| /* |
| * 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.sql.calcite; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.calcite.avatica.SqlType; |
| import org.apache.druid.common.config.NullHandling; |
| import org.apache.druid.guice.DruidInjectorBuilder; |
| import org.apache.druid.guice.NestedDataModule; |
| import org.apache.druid.java.util.common.HumanReadableBytes; |
| import org.apache.druid.java.util.common.Intervals; |
| import org.apache.druid.java.util.common.StringUtils; |
| import org.apache.druid.java.util.common.granularity.Granularities; |
| import org.apache.druid.math.expr.ExprEval; |
| import org.apache.druid.math.expr.ExprMacroTable; |
| import org.apache.druid.math.expr.ExpressionType; |
| import org.apache.druid.query.Druids; |
| import org.apache.druid.query.FilteredDataSource; |
| import org.apache.druid.query.InlineDataSource; |
| import org.apache.druid.query.LookupDataSource; |
| import org.apache.druid.query.Query; |
| import org.apache.druid.query.QueryContexts; |
| import org.apache.druid.query.QueryDataSource; |
| import org.apache.druid.query.TableDataSource; |
| import org.apache.druid.query.UnnestDataSource; |
| import org.apache.druid.query.aggregation.CountAggregatorFactory; |
| import org.apache.druid.query.aggregation.DoubleSumAggregatorFactory; |
| import org.apache.druid.query.aggregation.ExpressionLambdaAggregatorFactory; |
| import org.apache.druid.query.aggregation.FilteredAggregatorFactory; |
| import org.apache.druid.query.aggregation.LongSumAggregatorFactory; |
| import org.apache.druid.query.aggregation.post.ExpressionPostAggregator; |
| import org.apache.druid.query.dimension.DefaultDimensionSpec; |
| import org.apache.druid.query.expression.TestExprMacroTable; |
| import org.apache.druid.query.extraction.SubstringDimExtractionFn; |
| import org.apache.druid.query.filter.ArrayContainsElementFilter; |
| import org.apache.druid.query.filter.ExpressionDimFilter; |
| import org.apache.druid.query.filter.InDimFilter; |
| import org.apache.druid.query.filter.LikeDimFilter; |
| import org.apache.druid.query.groupby.GroupByQuery; |
| import org.apache.druid.query.groupby.having.DimFilterHavingSpec; |
| import org.apache.druid.query.groupby.orderby.DefaultLimitSpec; |
| import org.apache.druid.query.groupby.orderby.NoopLimitSpec; |
| import org.apache.druid.query.groupby.orderby.OrderByColumnSpec; |
| import org.apache.druid.query.ordering.StringComparators; |
| import org.apache.druid.query.scan.ScanQuery; |
| import org.apache.druid.query.spec.MultipleIntervalSegmentSpec; |
| import org.apache.druid.query.topn.DimensionTopNMetricSpec; |
| import org.apache.druid.query.topn.TopNQueryBuilder; |
| import org.apache.druid.segment.column.ColumnType; |
| import org.apache.druid.segment.column.RowSignature; |
| import org.apache.druid.segment.join.JoinType; |
| import org.apache.druid.segment.virtual.ExpressionVirtualColumn; |
| import org.apache.druid.sql.calcite.filtration.Filtration; |
| import org.apache.druid.sql.calcite.util.CalciteTests; |
| import org.apache.druid.sql.http.SqlParameter; |
| import org.junit.Assert; |
| import org.junit.jupiter.api.Test; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * Tests for array functions and array types |
| */ |
| public class CalciteArraysQueryTest extends BaseCalciteQueryTest |
| { |
| private static final Map<String, Object> QUERY_CONTEXT_UNNEST = |
| ImmutableMap.<String, Object>builder() |
| .putAll(QUERY_CONTEXT_DEFAULT) |
| .put(QueryContexts.CTX_SQL_STRINGIFY_ARRAYS, false) |
| .build(); |
| |
| public static void assertResultsDeepEquals(String sql, List<Object[]> expected, List<Object[]> results) |
| { |
| for (int row = 0; row < results.size(); row++) { |
| for (int col = 0; col < results.get(row).length; col++) { |
| final String rowString = StringUtils.format("result #%d: %s", row + 1, sql); |
| assertDeepEquals(rowString + " - column: " + col + ":", expected.get(row)[col], results.get(row)[col]); |
| } |
| } |
| } |
| |
| public static void assertDeepEquals(String path, Object expected, Object actual) |
| { |
| if (expected instanceof List && actual instanceof List) { |
| List expectedList = (List) expected; |
| List actualList = (List) actual; |
| Assert.assertEquals(path + " arrays length mismatch", expectedList.size(), actualList.size()); |
| for (int i = 0; i < expectedList.size(); i++) { |
| assertDeepEquals(path + "[" + i + "]", expectedList.get(i), actualList.get(i)); |
| } |
| } else { |
| Assert.assertEquals(path, expected, actual); |
| } |
| } |
| |
| @Override |
| public void configureGuice(DruidInjectorBuilder builder) |
| { |
| super.configureGuice(builder); |
| builder.addModule(new NestedDataModule()); |
| } |
| |
| // test some query stuffs, sort of limited since no native array column types so either need to use constructor or |
| // array aggregator |
| @Test |
| public void testSelectConstantArrayExpressionFromTable() |
| { |
| testQuery( |
| "SELECT ARRAY[1,2] as arr, dim1 FROM foo LIMIT 1", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn("v0", "array(1,2)", ColumnType.LONG_ARRAY)) |
| .columns("dim1", "v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(1) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1,2]", ""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testGroupByArrayFromCase() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT CASE WHEN dim4 = 'a' THEN ARRAY['foo','bar','baz'] END as mv_value, count(1) from numfoo GROUP BY 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "case_searched((\"dim4\" == 'a'),array('foo','bar','baz'),null)", |
| ColumnType.STRING_ARRAY |
| )) |
| .setDimensions(new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING_ARRAY)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{ImmutableList.of("foo", "bar", "baz"), 3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testGroupByArrayColumnFromCase() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT CASE WHEN arrayStringNulls = ARRAY['a', 'b'] THEN arrayLongNulls END as arr, count(1) from arrays GROUP BY 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "case_searched((\"arrayStringNulls\" == array('a','b')),\"arrayLongNulls\",null)", |
| ColumnType.LONG_ARRAY |
| )) |
| .setDimensions(new DefaultDimensionSpec("v0", "d0", ColumnType.LONG_ARRAY)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null, 11L}, |
| new Object[]{Arrays.asList(1L, null, 3L), 1L}, |
| new Object[]{Arrays.asList(2L, 3L), 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testSelectNonConstantArrayExpressionFromTable() |
| { |
| testQuery( |
| "SELECT ARRAY[CONCAT(dim1, 'word'),'up'] as arr, dim1 FROM foo LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(concat(\"dim1\",'word'),'up')", |
| ColumnType.STRING_ARRAY |
| )) |
| .columns("dim1", "v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"word\",\"up\"]", ""}, |
| new Object[]{"[\"10.1word\",\"up\"]", "10.1"}, |
| new Object[]{"[\"2word\",\"up\"]", "2"}, |
| new Object[]{"[\"1word\",\"up\"]", "1"}, |
| new Object[]{"[\"defword\",\"up\"]", "def"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testSelectNonConstantArrayExpressionFromTableForMultival() |
| { |
| // Produces nested string array, that MSQ can't infer from the selector |
| msqIncompatible(); |
| final String sql = "SELECT ARRAY[CONCAT(dim3, 'word'),'up'] as arr, dim1 FROM foo LIMIT 5"; |
| final Query<?> scanQuery = newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn("v0", "array(concat(\"dim3\",'word'),'up')", ColumnType.STRING_ARRAY)) |
| .columns("dim1", "v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build(); |
| |
| // dim3 is a multi-valued string column, so the automatic translation will turn this |
| // expression into |
| // |
| // `map((dim3) -> array(concat(dim3,'word'),'up'), dim3)` |
| // |
| // this works, but we still translate the output into a string since that is the current output type |
| // in some future this might not auto-convert to a string type (when we support grouping on arrays maybe?) |
| |
| testQuery( |
| sql, |
| ImmutableList.of(scanQuery), |
| ImmutableList.of( |
| new Object[]{"[[\"aword\",\"up\"],[\"bword\",\"up\"]]", ""}, |
| new Object[]{"[[\"bword\",\"up\"],[\"cword\",\"up\"]]", "10.1"}, |
| new Object[]{"[[\"dword\",\"up\"]]", "2"}, |
| new Object[]{"[[\"word\",\"up\"]]", "1"}, |
| useDefault ? new Object[]{"[[\"word\",\"up\"]]", "def"} : new Object[]{"[[null,\"up\"]]", "def"} |
| ) |
| ); |
| |
| } |
| |
| @Test |
| public void testSomeArrayFunctionsWithScanQuery() |
| { |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{ |
| "", |
| "a", |
| "[\"a\",\"b\"]", |
| 7L, |
| 0L, |
| 1.0, |
| 0.0, |
| "[\"a\",\"b\",\"c\"]", |
| "[1,2,3]", |
| "[1.9,2.2,4.3]", |
| "[\"a\",\"b\",\"foo\"]", |
| "[\"foo\",\"a\"]", |
| "[1,2,7]", |
| "[0,1,2]", |
| "[1.2,2.2,1.0]", |
| "[0.0,1.1,2.2]", |
| "[\"a\",\"a\",\"b\"]", |
| "[7,0]", |
| "[1.0,0.0]", |
| 7L, |
| 1.0, |
| 7L, |
| 1.0 |
| } |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{ |
| "", |
| "a", |
| "[\"a\",\"b\"]", |
| 7L, |
| null, |
| 1.0, |
| null, |
| "[\"a\",\"b\",\"c\"]", |
| "[1,2,3]", |
| "[1.9,2.2,4.3]", |
| "[\"a\",\"b\",\"foo\"]", |
| "[\"foo\",\"a\"]", |
| "[1,2,7]", |
| "[null,1,2]", |
| "[1.2,2.2,1.0]", |
| "[null,1.1,2.2]", |
| "[\"a\",\"a\",\"b\"]", |
| "[7,null]", |
| "[1.0,null]", |
| 7L, |
| 1.0, |
| 7L, |
| 1.0 |
| } |
| ); |
| } |
| testQuery( |
| "SELECT" |
| + " dim1," |
| + " dim2," |
| + " dim3," |
| + " l1," |
| + " l2," |
| + " d1," |
| + " d2," |
| + " ARRAY['a', 'b', 'c']," |
| + " ARRAY[1,2,3]," |
| + " ARRAY[1.9, 2.2, 4.3]," |
| + " ARRAY_APPEND(dim3, 'foo')," |
| + " ARRAY_PREPEND('foo', ARRAY[dim2])," |
| + " ARRAY_APPEND(ARRAY[1,2], l1)," |
| + " ARRAY_PREPEND(l2, ARRAY[1,2])," |
| + " ARRAY_APPEND(ARRAY[1.2,2.2], d1)," |
| + " ARRAY_PREPEND(d2, ARRAY[1.1,2.2])," |
| + " ARRAY_CONCAT(dim2,dim3)," |
| + " ARRAY_CONCAT(ARRAY[l1],ARRAY[l2])," |
| + " ARRAY_CONCAT(ARRAY[d1],ARRAY[d2])," |
| + " ARRAY_OFFSET(ARRAY[l1],0)," |
| + " ARRAY_OFFSET(ARRAY[d1],0)," |
| + " ARRAY_ORDINAL(ARRAY[l1],1)," |
| + " ARRAY_ORDINAL(ARRAY[d1],1)" |
| + " FROM druid.numfoo" |
| + " LIMIT 1", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| // these report as strings even though they are not, someday this will not be so |
| expressionVirtualColumn("v0", "array('a','b','c')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v1", "array(1,2,3)", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v10", "array_concat(array(\"l1\"),array(\"l2\"))", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn( |
| "v11", |
| "array_concat(array(\"d1\"),array(\"d2\"))", |
| ColumnType.DOUBLE_ARRAY |
| ), |
| expressionVirtualColumn("v12", "array_offset(array(\"l1\"),0)", ColumnType.LONG), |
| expressionVirtualColumn("v13", "array_offset(array(\"d1\"),0)", ColumnType.DOUBLE), |
| expressionVirtualColumn("v14", "array_ordinal(array(\"l1\"),1)", ColumnType.LONG), |
| expressionVirtualColumn("v15", "array_ordinal(array(\"d1\"),1)", ColumnType.DOUBLE), |
| expressionVirtualColumn("v2", "array(1.9,2.2,4.3)", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v3", "array_append(\"dim3\",'foo')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v4", "array_prepend('foo',array(\"dim2\"))", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v5", "array_append(array(1,2),\"l1\")", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v6", "array_prepend(\"l2\",array(1,2))", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v7", "array_append(array(1.2,2.2),\"d1\")", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v8", "array_prepend(\"d2\",array(1.1,2.2))", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v9", "array_concat(\"dim2\",\"dim3\")", ColumnType.STRING_ARRAY) |
| ) |
| .columns( |
| "d1", |
| "d2", |
| "dim1", |
| "dim2", |
| "dim3", |
| "l1", |
| "l2", |
| "v0", |
| "v1", |
| "v10", |
| "v11", |
| "v12", |
| "v13", |
| "v14", |
| "v15", |
| "v2", |
| "v3", |
| "v4", |
| "v5", |
| "v6", |
| "v7", |
| "v8", |
| "v9" |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(1) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| expectedResults, |
| RowSignature.builder() |
| .add("dim1", ColumnType.STRING) |
| .add("dim2", ColumnType.STRING) |
| .add("dim3", ColumnType.STRING) |
| .add("l1", ColumnType.LONG) |
| .add("l2", ColumnType.LONG) |
| .add("d1", ColumnType.DOUBLE) |
| .add("d2", ColumnType.DOUBLE) |
| .add("EXPR$7", ColumnType.STRING_ARRAY) |
| .add("EXPR$8", ColumnType.LONG_ARRAY) |
| .add("EXPR$9", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$10", ColumnType.STRING_ARRAY) |
| .add("EXPR$11", ColumnType.STRING_ARRAY) |
| .add("EXPR$12", ColumnType.LONG_ARRAY) |
| .add("EXPR$13", ColumnType.LONG_ARRAY) |
| .add("EXPR$14", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$15", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$16", ColumnType.STRING_ARRAY) |
| .add("EXPR$17", ColumnType.LONG_ARRAY) |
| .add("EXPR$18", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$19", ColumnType.LONG) |
| .add("EXPR$20", ColumnType.DOUBLE) |
| .add("EXPR$21", ColumnType.LONG) |
| .add("EXPR$22", ColumnType.DOUBLE) |
| .build() |
| ); |
| } |
| |
| @Test |
| public void testSomeArrayFunctionsWithScanQueryArrayColumns() |
| { |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{null, "[]", null, null, null, "[1]", "[2]", null, null, null, "[1,2,3]", null, "", null, null, "", null, null}, |
| new Object[]{"[\"a\",\"b\"]", "[2,3]", "[null]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[2,3,1]", "[2,2,3]", "[null,1.1]", "[2.2,null]", null, null, null, "a", 2L, 0.0D, "a", 2L, 0.0D}, |
| new Object[]{"[\"b\",\"b\"]", "[1]", null, "[\"b\",\"b\",\"foo\"]", "[\"foo\",\"b\",\"b\"]", "[1,1]", "[2,1]", null, null, "[\"d\",\"e\",\"b\",\"b\"]", "[1,4,1]", null, "b", 1L, null, "b", 1L, null}, |
| new Object[]{null, "[null,2,9]", "[999.0,5.5,null]", null, null, "[null,2,9,1]", "[2,null,2,9]", "[999.0,5.5,null,1.1]", "[2.2,999.0,5.5,null]", null, null, null, "", 0L, 999.0D, "", 0L, 999.0D}, |
| new Object[]{"[\"a\",\"b\"]", "[1,null,3]", "[1.1,2.2,null]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[1,null,3,1]", "[2,1,null,3]", "[1.1,2.2,null,1.1]", "[2.2,1.1,2.2,null]", "[\"a\",\"b\",\"a\",\"b\"]", "[1,2,3,1,null,3]", "[1.1,2.2,3.3,1.1,2.2,null]", "a", 1L, 1.1D, "a", 1L, 1.1D}, |
| new Object[]{"[\"d\",null,\"b\"]", "[1,2,3]", "[null,2.2,null]", "[\"d\",null,\"b\",\"foo\"]", "[\"foo\",\"d\",null,\"b\"]", "[1,2,3,1]", "[2,1,2,3]", "[null,2.2,null,1.1]", "[2.2,null,2.2,null]", "[\"b\",\"c\",\"d\",null,\"b\"]", "[1,2,3,4,1,2,3]", "[1.1,3.3,null,2.2,null]", "d", 1L, 0.0D, "d", 1L, 0.0D}, |
| new Object[]{"[null,\"b\"]", null, "[999.0,null,5.5]", "[null,\"b\",\"foo\"]", "[\"foo\",null,\"b\"]", null, null, "[999.0,null,5.5,1.1]", "[2.2,999.0,null,5.5]", "[\"a\",\"b\",\"c\",null,\"b\"]", null, "[3.3,4.4,5.5,999.0,null,5.5]", "", null, 999.0D, "", null, 999.0D}, |
| new Object[]{null, null, "[]", null, null, null, null, "[1.1]", "[2.2]", null, null, "[1.1,2.2,3.3]", "", null, null, "", null, null}, |
| new Object[]{"[\"a\",\"b\"]", "[2,3]", "[null,1.1]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[2,3,1]", "[2,2,3]", "[null,1.1,1.1]", "[2.2,null,1.1]", null, null, null, "a", 2L, 0.0D, "a", 2L, 0.0D}, |
| new Object[]{"[\"b\",\"b\"]", "[null]", null, "[\"b\",\"b\",\"foo\"]", "[\"foo\",\"b\",\"b\"]", "[null,1]", "[2,null]", null, null, "[\"d\",\"e\",\"b\",\"b\"]", "[1,4,null]", null, "b", 0L, null, "b", 0L, null}, |
| new Object[]{"[null]", "[null,2,9]", "[999.0,5.5,null]", "[null,\"foo\"]", "[\"foo\",null]", "[null,2,9,1]", "[2,null,2,9]", "[999.0,5.5,null,1.1]", "[2.2,999.0,5.5,null]", "[\"a\",\"b\",null]", null, null, "", 0L, 999.0D, "", 0L, 999.0D}, |
| new Object[]{"[]", "[1,null,3]", "[1.1,2.2,null]", "[\"foo\"]", "[\"foo\"]", "[1,null,3,1]", "[2,1,null,3]", "[1.1,2.2,null,1.1]", "[2.2,1.1,2.2,null]", "[\"a\",\"b\"]", "[1,2,3,1,null,3]", "[1.1,2.2,3.3,1.1,2.2,null]", "", 1L, 1.1D, "", 1L, 1.1D}, |
| new Object[]{"[\"d\",null,\"b\"]", "[1,2,3]", "[null,2.2,null]", "[\"d\",null,\"b\",\"foo\"]", "[\"foo\",\"d\",null,\"b\"]", "[1,2,3,1]", "[2,1,2,3]", "[null,2.2,null,1.1]", "[2.2,null,2.2,null]", "[\"b\",\"c\",\"d\",null,\"b\"]", "[1,2,3,4,1,2,3]", "[1.1,3.3,null,2.2,null]", "d", 1L, 0.0D, "d", 1L, 0.0D}, |
| new Object[]{"[null,\"b\"]", null, "[999.0,null,5.5]", "[null,\"b\",\"foo\"]", "[\"foo\",null,\"b\"]", null, null, "[999.0,null,5.5,1.1]", "[2.2,999.0,null,5.5]", "[\"a\",\"b\",\"c\",null,\"b\"]", null, "[3.3,4.4,5.5,999.0,null,5.5]", "", null, 999.0D, "", null, 999.0D} |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{null, "[]", null, null, null, "[1]", "[2]", null, null, null, "[1,2,3]", null, null, null, null, null, null, null}, |
| new Object[]{"[\"a\",\"b\"]", "[2,3]", "[null]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[2,3,1]", "[2,2,3]", "[null,1.1]", "[2.2,null]", null, null, null, "a", 2L, null, "a", 2L, null}, |
| new Object[]{"[\"b\",\"b\"]", "[1]", null, "[\"b\",\"b\",\"foo\"]", "[\"foo\",\"b\",\"b\"]", "[1,1]", "[2,1]", null, null, "[\"d\",\"e\",\"b\",\"b\"]", "[1,4,1]", null, "b", 1L, null, "b", 1L, null}, |
| new Object[]{null, "[null,2,9]", "[999.0,5.5,null]", null, null, "[null,2,9,1]", "[2,null,2,9]", "[999.0,5.5,null,1.1]", "[2.2,999.0,5.5,null]", null, null, null, null, null, 999.0D, null, null, 999.0D}, |
| new Object[]{"[\"a\",\"b\"]", "[1,null,3]", "[1.1,2.2,null]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[1,null,3,1]", "[2,1,null,3]", "[1.1,2.2,null,1.1]", "[2.2,1.1,2.2,null]", "[\"a\",\"b\",\"a\",\"b\"]", "[1,2,3,1,null,3]", "[1.1,2.2,3.3,1.1,2.2,null]", "a", 1L, 1.1D, "a", 1L, 1.1D}, |
| new Object[]{"[\"d\",null,\"b\"]", "[1,2,3]", "[null,2.2,null]", "[\"d\",null,\"b\",\"foo\"]", "[\"foo\",\"d\",null,\"b\"]", "[1,2,3,1]", "[2,1,2,3]", "[null,2.2,null,1.1]", "[2.2,null,2.2,null]", "[\"b\",\"c\",\"d\",null,\"b\"]", "[1,2,3,4,1,2,3]", "[1.1,3.3,null,2.2,null]", "d", 1L, null, "d", 1L, null}, |
| new Object[]{"[null,\"b\"]", null, "[999.0,null,5.5]", "[null,\"b\",\"foo\"]", "[\"foo\",null,\"b\"]", null, null, "[999.0,null,5.5,1.1]", "[2.2,999.0,null,5.5]", "[\"a\",\"b\",\"c\",null,\"b\"]", null, "[3.3,4.4,5.5,999.0,null,5.5]", null, null, 999.0D, null, null, 999.0D}, |
| new Object[]{null, null, "[]", null, null, null, null, "[1.1]", "[2.2]", null, null, "[1.1,2.2,3.3]", null, null, null, null, null, null}, |
| new Object[]{"[\"a\",\"b\"]", "[2,3]", "[null,1.1]", "[\"a\",\"b\",\"foo\"]", "[\"foo\",\"a\",\"b\"]", "[2,3,1]", "[2,2,3]", "[null,1.1,1.1]", "[2.2,null,1.1]", null, null, null, "a", 2L, null, "a", 2L, null}, |
| new Object[]{"[\"b\",\"b\"]", "[null]", null, "[\"b\",\"b\",\"foo\"]", "[\"foo\",\"b\",\"b\"]", "[null,1]", "[2,null]", null, null, "[\"d\",\"e\",\"b\",\"b\"]", "[1,4,null]", null, "b", null, null, "b", null, null}, |
| new Object[]{"[null]", "[null,2,9]", "[999.0,5.5,null]", "[null,\"foo\"]", "[\"foo\",null]", "[null,2,9,1]", "[2,null,2,9]", "[999.0,5.5,null,1.1]", "[2.2,999.0,5.5,null]", "[\"a\",\"b\",null]", null, null, null, null, 999.0D, null, null, 999.0D}, |
| new Object[]{"[]", "[1,null,3]", "[1.1,2.2,null]", "[\"foo\"]", "[\"foo\"]", "[1,null,3,1]", "[2,1,null,3]", "[1.1,2.2,null,1.1]", "[2.2,1.1,2.2,null]", "[\"a\",\"b\"]", "[1,2,3,1,null,3]", "[1.1,2.2,3.3,1.1,2.2,null]", null, 1L, 1.1D, null, 1L, 1.1D}, |
| new Object[]{"[\"d\",null,\"b\"]", "[1,2,3]", "[null,2.2,null]", "[\"d\",null,\"b\",\"foo\"]", "[\"foo\",\"d\",null,\"b\"]", "[1,2,3,1]", "[2,1,2,3]", "[null,2.2,null,1.1]", "[2.2,null,2.2,null]", "[\"b\",\"c\",\"d\",null,\"b\"]", "[1,2,3,4,1,2,3]", "[1.1,3.3,null,2.2,null]", "d", 1L, null, "d", 1L, null}, |
| new Object[]{"[null,\"b\"]", null, "[999.0,null,5.5]", "[null,\"b\",\"foo\"]", "[\"foo\",null,\"b\"]", null, null, "[999.0,null,5.5,1.1]", "[2.2,999.0,null,5.5]", "[\"a\",\"b\",\"c\",null,\"b\"]", null, "[3.3,4.4,5.5,999.0,null,5.5]", null, null, 999.0D, null, null, 999.0D} |
| ); |
| } |
| testQuery( |
| "SELECT" |
| + " arrayStringNulls," |
| + " arrayLongNulls," |
| + " arrayDoubleNulls," |
| + " ARRAY_APPEND(arrayStringNulls, 'foo')," |
| + " ARRAY_PREPEND('foo', arrayStringNulls)," |
| + " ARRAY_APPEND(arrayLongNulls, 1)," |
| + " ARRAY_PREPEND(2, arrayLongNulls)," |
| + " ARRAY_APPEND(arrayDoubleNulls, 1.1)," |
| + " ARRAY_PREPEND(2.2, arrayDoubleNulls)," |
| + " ARRAY_CONCAT(arrayString,arrayStringNulls)," |
| + " ARRAY_CONCAT(arrayLong,arrayLongNulls)," |
| + " ARRAY_CONCAT(arrayDouble,arrayDoubleNulls)," |
| + " ARRAY_OFFSET(arrayStringNulls,0)," |
| + " ARRAY_OFFSET(arrayLongNulls,0)," |
| + " ARRAY_OFFSET(arrayDoubleNulls,0)," |
| + " ARRAY_ORDINAL(arrayStringNulls,1)," |
| + " ARRAY_ORDINAL(arrayLongNulls,1)," |
| + " ARRAY_ORDINAL(arrayDoubleNulls,1)" |
| + " FROM druid.arrays", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| // these report as strings even though they are not, someday this will not be so |
| expressionVirtualColumn("v0", "array_append(\"arrayStringNulls\",'foo')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v1", "array_prepend('foo',\"arrayStringNulls\")", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v10", "array_offset(\"arrayLongNulls\",0)", ColumnType.LONG), |
| expressionVirtualColumn("v11", "array_offset(\"arrayDoubleNulls\",0)", ColumnType.DOUBLE), |
| expressionVirtualColumn("v12", "array_ordinal(\"arrayStringNulls\",1)", ColumnType.STRING), |
| expressionVirtualColumn("v13", "array_ordinal(\"arrayLongNulls\",1)", ColumnType.LONG), |
| expressionVirtualColumn("v14", "array_ordinal(\"arrayDoubleNulls\",1)", ColumnType.DOUBLE), |
| expressionVirtualColumn("v2", "array_append(\"arrayLongNulls\",1)", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v3", "array_prepend(2,\"arrayLongNulls\")", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v4", "array_append(\"arrayDoubleNulls\",1.1)", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v5", "array_prepend(2.2,\"arrayDoubleNulls\")", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v6", "array_concat(\"arrayString\",\"arrayStringNulls\")", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v7", "array_concat(\"arrayLong\",\"arrayLongNulls\")", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v8", "array_concat(\"arrayDouble\",\"arrayDoubleNulls\")", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v9", "array_offset(\"arrayStringNulls\",0)", ColumnType.STRING) |
| ) |
| .columns( |
| "arrayDoubleNulls", |
| "arrayLongNulls", |
| "arrayStringNulls", |
| "v0", |
| "v1", |
| "v10", |
| "v11", |
| "v12", |
| "v13", |
| "v14", |
| "v2", |
| "v3", |
| "v4", |
| "v5", |
| "v6", |
| "v7", |
| "v8", |
| "v9" |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| expectedResults, |
| RowSignature.builder() |
| .add("arrayStringNulls", ColumnType.STRING_ARRAY) |
| .add("arrayLongNulls", ColumnType.LONG_ARRAY) |
| .add("arrayDoubleNulls", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$3", ColumnType.STRING_ARRAY) |
| .add("EXPR$4", ColumnType.STRING_ARRAY) |
| .add("EXPR$5", ColumnType.LONG_ARRAY) |
| .add("EXPR$6", ColumnType.LONG_ARRAY) |
| .add("EXPR$7", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$8", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$9", ColumnType.STRING_ARRAY) |
| .add("EXPR$10", ColumnType.LONG_ARRAY) |
| .add("EXPR$11", ColumnType.DOUBLE_ARRAY) |
| .add("EXPR$12", ColumnType.STRING) |
| .add("EXPR$13", ColumnType.LONG) |
| .add("EXPR$14", ColumnType.DOUBLE) |
| .add("EXPR$15", ColumnType.STRING) |
| .add("EXPR$16", ColumnType.LONG) |
| .add("EXPR$17", ColumnType.DOUBLE) |
| .build() |
| ); |
| } |
| |
| @Test |
| public void testSomeArrayFunctionsWithScanQueryNoStringify() |
| { |
| // when not stringifying arrays, some things are still stringified, because they are inferred to be typed as strings |
| // the planner context which controls stringification of arrays does not apply to multi-valued string columns, |
| // which will still always be stringified to ultimately adhere to the varchar type |
| // as array support increases in the engine this will likely change since using explict array functions should |
| // probably kick it into an array |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{ |
| "", |
| "a", |
| "[\"a\",\"b\"]", |
| Arrays.asList("a", "b", "c"), |
| Arrays.asList(1L, 2L, 3L), |
| Arrays.asList(1.9, 2.2, 4.3), |
| Arrays.asList("a", "b", "foo"), |
| Arrays.asList("foo", "a"), |
| Arrays.asList(1L, 2L, 7L), |
| Arrays.asList(0L, 1L, 2L), |
| Arrays.asList(1.2, 2.2, 1.0), |
| Arrays.asList(0.0, 1.1, 2.2), |
| Arrays.asList("a", "a", "b"), |
| Arrays.asList(7L, 0L), |
| Arrays.asList(1.0, 0.0) |
| } |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{ |
| "", |
| "a", |
| "[\"a\",\"b\"]", |
| Arrays.asList("a", "b", "c"), |
| Arrays.asList(1L, 2L, 3L), |
| Arrays.asList(1.9, 2.2, 4.3), |
| Arrays.asList("a", "b", "foo"), |
| Arrays.asList("foo", "a"), |
| Arrays.asList(1L, 2L, 7L), |
| Arrays.asList(null, 1L, 2L), |
| Arrays.asList(1.2, 2.2, 1.0), |
| Arrays.asList(null, 1.1, 2.2), |
| Arrays.asList("a", "a", "b"), |
| Arrays.asList(7L, null), |
| Arrays.asList(1.0, null) |
| } |
| ); |
| } |
| testQuery( |
| "SELECT" |
| + " dim1," |
| + " dim2," |
| + " dim3," |
| + " ARRAY['a', 'b', 'c']," |
| + " ARRAY[1,2,3]," |
| + " ARRAY[1.9, 2.2, 4.3]," |
| + " ARRAY_APPEND(dim3, 'foo')," |
| + " ARRAY_PREPEND('foo', ARRAY[dim2])," |
| + " ARRAY_APPEND(ARRAY[1,2], l1)," |
| + " ARRAY_PREPEND(l2, ARRAY[1,2])," |
| + " ARRAY_APPEND(ARRAY[1.2,2.2], d1)," |
| + " ARRAY_PREPEND(d2, ARRAY[1.1,2.2])," |
| + " ARRAY_CONCAT(dim2,dim3)," |
| + " ARRAY_CONCAT(ARRAY[l1],ARRAY[l2])," |
| + " ARRAY_CONCAT(ARRAY[d1],ARRAY[d2])" |
| + " FROM druid.numfoo" |
| + " LIMIT 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array('a','b','c')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v1", "array(1,2,3)", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v10", "array_concat(array(\"l1\"),array(\"l2\"))", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn( |
| "v11", |
| "array_concat(array(\"d1\"),array(\"d2\"))", |
| ColumnType.DOUBLE_ARRAY |
| ), |
| expressionVirtualColumn("v2", "array(1.9,2.2,4.3)", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v3", "array_append(\"dim3\",'foo')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v4", "array_prepend('foo',array(\"dim2\"))", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v5", "array_append(array(1,2),\"l1\")", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v6", "array_prepend(\"l2\",array(1,2))", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v7", "array_append(array(1.2,2.2),\"d1\")", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v8", "array_prepend(\"d2\",array(1.1,2.2))", ColumnType.DOUBLE_ARRAY), |
| expressionVirtualColumn("v9", "array_concat(\"dim2\",\"dim3\")", ColumnType.STRING_ARRAY) |
| ) |
| .columns( |
| "dim1", |
| "dim2", |
| "dim3", |
| "v0", |
| "v1", |
| "v10", |
| "v11", |
| "v2", |
| "v3", |
| "v4", |
| "v5", |
| "v6", |
| "v7", |
| "v8", |
| "v9" |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(1) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilter() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_OVERLAP(dim3, ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(in("dim3", ImmutableList.of("a", "b"))) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"b\",\"c\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterStringArrayColumn() |
| { |
| testQuery( |
| "SELECT arrayStringNulls FROM druid.arrays WHERE ARRAY_OVERLAP(arrayStringNulls, ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| or( |
| new ArrayContainsElementFilter("arrayStringNulls", ColumnType.STRING, "a", null), |
| new ArrayContainsElementFilter("arrayStringNulls", ColumnType.STRING, "b", null) |
| ) |
| ) |
| .columns("arrayStringNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"b\",\"b\"]"}, |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"d\",null,\"b\"]"}, |
| new Object[]{"[null,\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterLongArrayColumn() |
| { |
| testQuery( |
| "SELECT arrayLongNulls FROM druid.arrays WHERE ARRAY_OVERLAP(arrayLongNulls, ARRAY[1, 2]) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| or( |
| new ArrayContainsElementFilter("arrayLongNulls", ColumnType.LONG, 1L, null), |
| new ArrayContainsElementFilter("arrayLongNulls", ColumnType.LONG, 2L, null) |
| ) |
| ) |
| .columns("arrayLongNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[2,3]"}, |
| new Object[]{"[1]"}, |
| new Object[]{"[null,2,9]"}, |
| new Object[]{"[1,null,3]"}, |
| new Object[]{"[1,2,3]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterDoubleArrayColumn() |
| { |
| testQuery( |
| "SELECT arrayDoubleNulls FROM druid.arrays WHERE ARRAY_OVERLAP(arrayDoubleNulls, ARRAY[1.1, 2.2]) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| or( |
| new ArrayContainsElementFilter("arrayDoubleNulls", ColumnType.DOUBLE, 1.1, null), |
| new ArrayContainsElementFilter("arrayDoubleNulls", ColumnType.DOUBLE, 2.2, null) |
| ) |
| ) |
| .columns("arrayDoubleNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1.1,2.2,null]"}, |
| new Object[]{"[null,2.2,null]"}, |
| new Object[]{"[null,1.1]"}, |
| new Object[]{"[1.1,2.2,null]"}, |
| new Object[]{"[null,2.2,null]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterWithExtractionFn() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_OVERLAP(SUBSTRING(dim3, 1, 1), ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| new InDimFilter("dim3", ImmutableList.of("a", "b"), new SubstringDimExtractionFn(0, 1)) |
| ) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"b\",\"c\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterNonLiteral() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_OVERLAP(dim3, ARRAY[dim2]) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_overlap(\"dim3\",array(\"dim2\"))")) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterArrayStringColumns() |
| { |
| testQuery( |
| "SELECT arrayStringNulls, arrayString FROM druid.arrays WHERE ARRAY_OVERLAP(arrayStringNulls, arrayString) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_overlap(\"arrayStringNulls\",\"arrayString\")")) |
| .columns("arrayString", "arrayStringNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]", "[\"a\",\"b\"]"}, |
| new Object[]{"[\"d\",null,\"b\"]", "[\"b\",\"c\"]"}, |
| new Object[]{"[null,\"b\"]", "[\"a\",\"b\",\"c\"]"}, |
| new Object[]{"[\"d\",null,\"b\"]", "[\"b\",\"c\"]"}, |
| new Object[]{"[null,\"b\"]", "[\"a\",\"b\",\"c\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterArrayLongColumns() |
| { |
| testQuery( |
| "SELECT arrayLongNulls, arrayLong FROM druid.arrays WHERE ARRAY_OVERLAP(arrayLongNulls, arrayLong) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_overlap(\"arrayLongNulls\",\"arrayLong\")")) |
| .columns("arrayLong", "arrayLongNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1]", "[1,4]"}, |
| new Object[]{"[1,null,3]", "[1,2,3]"}, |
| new Object[]{"[1,2,3]", "[1,2,3,4]"}, |
| new Object[]{"[1,null,3]", "[1,2,3]"}, |
| new Object[]{"[1,2,3]", "[1,2,3,4]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterArrayDoubleColumns() |
| { |
| testQuery( |
| "SELECT arrayDoubleNulls, arrayDouble FROM druid.arrays WHERE ARRAY_OVERLAP(arrayDoubleNulls, arrayDouble) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_overlap(\"arrayDoubleNulls\",\"arrayDouble\")")) |
| .columns("arrayDouble", "arrayDoubleNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1.1,2.2,null]", "[1.1,2.2,3.3]"}, |
| new Object[]{"[999.0,null,5.5]", "[3.3,4.4,5.5]"}, |
| new Object[]{"[1.1,2.2,null]", "[1.1,2.2,3.3]"}, |
| new Object[]{"[999.0,null,5.5]", "[3.3,4.4,5.5]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOverlapFilterWithDynamicParameter() |
| { |
| Druids.ScanQueryBuilder builder = newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_overlap(array(1.0,1.7,null),array(\"d1\"))")) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT); |
| |
| testQuery( |
| PLANNER_CONFIG_DEFAULT, |
| QUERY_CONTEXT_DEFAULT, |
| ImmutableList.of( |
| new SqlParameter(SqlType.ARRAY, Arrays.asList(1.0, 1.7, null)) |
| ), |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_OVERLAP(?, ARRAY[d1]) LIMIT 5", |
| CalciteTests.REGULAR_USER_AUTH_RESULT, |
| ImmutableList.of(builder.build()), |
| NullHandling.sqlCompatible() ? ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"b\",\"c\"]"}, |
| new Object[]{""}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) : ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"b\",\"c\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilter() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(dim3, ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| and( |
| equality("dim3", "a", ColumnType.STRING), |
| equality("dim3", "b", ColumnType.STRING) |
| ) |
| ) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayStringColumn() |
| { |
| testQuery( |
| "SELECT arrayStringNulls FROM druid.arrays WHERE ARRAY_CONTAINS(arrayStringNulls, ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| and( |
| new ArrayContainsElementFilter("arrayStringNulls", ColumnType.STRING, "a", null), |
| new ArrayContainsElementFilter("arrayStringNulls", ColumnType.STRING, "b", null) |
| ) |
| |
| ) |
| .columns("arrayStringNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"a\",\"b\"]"}, |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayLongColumn() |
| { |
| testQuery( |
| "SELECT arrayLongNulls FROM druid.arrays WHERE ARRAY_CONTAINS(arrayLongNulls, ARRAY[1, null]) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| and( |
| new ArrayContainsElementFilter("arrayLongNulls", ColumnType.LONG, 1L, null), |
| new ArrayContainsElementFilter("arrayLongNulls", ColumnType.LONG, null, null) |
| ) |
| ) |
| .columns("arrayLongNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1,null,3]"}, |
| new Object[]{"[1,null,3]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayDoubleColumn() |
| { |
| testQuery( |
| "SELECT arrayDoubleNulls FROM druid.arrays WHERE ARRAY_CONTAINS(arrayDoubleNulls, ARRAY[1.1, null]) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| and( |
| new ArrayContainsElementFilter("arrayDoubleNulls", ColumnType.DOUBLE, 1.1, null), |
| new ArrayContainsElementFilter("arrayDoubleNulls", ColumnType.DOUBLE, null, null) |
| ) |
| ) |
| .columns("arrayDoubleNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1.1,2.2,null]"}, |
| new Object[]{"[null,1.1]"}, |
| new Object[]{"[1.1,2.2,null]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterWithExtractionFn() |
| { |
| Druids.ScanQueryBuilder builder = newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT); |
| |
| if (NullHandling.sqlCompatible()) { |
| builder = builder.virtualColumns(expressionVirtualColumn("v0", "substring(\"dim3\", 0, 1)", ColumnType.STRING)) |
| .filters( |
| and( |
| equality("v0", "a", ColumnType.STRING), |
| equality("v0", "b", ColumnType.STRING) |
| ) |
| ); |
| } else { |
| builder = builder.filters( |
| and( |
| selector("dim3", "a", new SubstringDimExtractionFn(0, 1)), |
| selector("dim3", "b", new SubstringDimExtractionFn(0, 1)) |
| ) |
| ); |
| } |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(SUBSTRING(dim3, 1, 1), ARRAY['a','b']) LIMIT 5", |
| ImmutableList.of(builder.build()), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsArrayOfOneElement() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(dim3, ARRAY['a']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(equality("dim3", "a", ColumnType.STRING)) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsArrayOfNonLiteral() |
| { |
| testQuery( |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(dim3, ARRAY[dim2]) LIMIT 5", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_contains(\"dim3\",array(\"dim2\"))")) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayStringColumns() |
| { |
| testQuery( |
| "SELECT arrayStringNulls, arrayString FROM druid.arrays WHERE ARRAY_CONTAINS(arrayStringNulls, arrayString) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| expressionFilter("array_contains(\"arrayStringNulls\",\"arrayString\")") |
| ) |
| .columns("arrayString", "arrayStringNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]", "[\"a\",\"b\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsArrayStringColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_CONTAINS(arrayStringNulls, ARRAY['a', 'b']), ARRAY_CONTAINS(arrayStringNulls, arrayString) FROM druid.arrays LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .columns("v0", "v1") |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array_contains(\"arrayStringNulls\",array('a','b'))", ColumnType.LONG), |
| expressionVirtualColumn("v1", "array_contains(\"arrayStringNulls\",\"arrayString\")", ColumnType.LONG) |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{NullHandling.sqlCompatible() ? null : false, NullHandling.sqlCompatible() ? null : false}, |
| new Object[]{true, false}, |
| new Object[]{false, false}, |
| new Object[]{NullHandling.sqlCompatible() ? null : false, NullHandling.sqlCompatible() ? null : false}, |
| new Object[]{true, true} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayLongColumns() |
| { |
| testQuery( |
| "SELECT arrayLong, arrayLongNulls FROM druid.arrays WHERE ARRAY_CONTAINS(arrayLong, arrayLongNulls) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| expressionFilter("array_contains(\"arrayLong\",\"arrayLongNulls\")") |
| ) |
| .columns("arrayLong", "arrayLongNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1,2,3]", "[]"}, |
| new Object[]{"[1,4]", "[1]"}, |
| new Object[]{"[1,2,3,4]", "[1,2,3]"}, |
| new Object[]{"[1,2,3,4]", "[1,2,3]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterArrayDoubleColumns() |
| { |
| testQuery( |
| "SELECT arrayDoubleNulls, arrayDouble FROM druid.arrays WHERE ARRAY_CONTAINS(arrayDoubleNulls, arrayDouble) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| expressionFilter("array_contains(\"arrayDoubleNulls\",\"arrayDouble\")") |
| ) |
| .columns("arrayDouble", "arrayDoubleNulls") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of() |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsConstantNull() |
| { |
| testQuery( |
| "SELECT ARRAY_CONTAINS(null, ARRAY['a','b'])", |
| ImmutableList.of( |
| NullHandling.sqlCompatible() |
| ? newScanQueryBuilder() |
| .dataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of(new Object[]{NullHandling.defaultLongValue()}), |
| RowSignature.builder().add("EXPR$0", ColumnType.LONG).build() |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .columns("EXPR$0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| : newScanQueryBuilder() |
| .dataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of(new Object[]{0L}), |
| RowSignature.builder().add("ZERO", ColumnType.LONG).build() |
| ) |
| ) |
| .virtualColumns(expressionVirtualColumn("v0", "0", ColumnType.LONG)) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .columns("v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{NullHandling.sqlCompatible() ? null : false} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayContainsFilterWithDynamicParameter() |
| { |
| Druids.ScanQueryBuilder builder = newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters(expressionFilter("array_contains(array(1,null),array((\"d1\" > 1)))")) |
| .columns("dim3") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT); |
| |
| testQuery( |
| PLANNER_CONFIG_DEFAULT, |
| QUERY_CONTEXT_DEFAULT, |
| ImmutableList.of( |
| new SqlParameter(SqlType.ARRAY, Arrays.asList(true, null)) |
| ), |
| "SELECT dim3 FROM druid.numfoo WHERE ARRAY_CONTAINS(?, ARRAY[d1>1]) LIMIT 5", |
| CalciteTests.REGULAR_USER_AUTH_RESULT, |
| ImmutableList.of(builder.build()), |
| NullHandling.sqlCompatible() ? ImmutableList.of( |
| new Object[]{"[\"b\",\"c\"]"}, |
| new Object[]{""}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) : ImmutableList.of( |
| new Object[]{"[\"b\",\"c\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testScalarInArrayFilter() |
| { |
| msqIncompatible(); |
| testQuery( |
| "SELECT dim2 FROM druid.numfoo WHERE SCALAR_IN_ARRAY(dim2, ARRAY['a', 'd']) LIMIT 5", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| new ExpressionDimFilter("scalar_in_array(\"dim2\",array('a','d'))", ExprMacroTable.nil()) |
| ) |
| .columns("dim2") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(5) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"a"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayScalarInFilter_MVD() |
| { |
| msqIncompatible(); |
| testBuilder() |
| .sql( |
| "SELECT dim3, (CASE WHEN scalar_in_array(dim3, Array['a', 'b', 'd']) THEN 'abd' ELSE 'not abd' END) " + |
| "FROM druid.numfoo" |
| ) |
| .expectedQueries( |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| new ExpressionVirtualColumn( |
| "v0", |
| "case_searched(scalar_in_array(\"dim3\",array('a','b','d')),'abd','not abd')", |
| ColumnType.STRING, |
| ExprMacroTable.nil() |
| ) |
| ) |
| .columns("dim3", "v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ) |
| ) |
| .expectedResults(ResultMatchMode.RELAX_NULLS, |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]", "[\"abd\",\"abd\"]"}, |
| new Object[]{"[\"b\",\"c\"]", "[\"abd\",\"not abd\"]"}, |
| new Object[]{"d", "abd"}, |
| new Object[]{"", "not abd"}, |
| new Object[]{null, "not abd"}, |
| new Object[]{null, "not abd"} |
| ) |
| ) |
| .run(); |
| |
| } |
| |
| @Test |
| public void testArraySlice() |
| { |
| testQuery( |
| "SELECT ARRAY_SLICE(dim3, 1) FROM druid.numfoo", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| new Druids.ScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn("v0", "array_slice(\"dim3\",1)", ColumnType.STRING_ARRAY)) |
| .columns(ImmutableList.of("v0")) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{Collections.singletonList("b")}, |
| new Object[]{Collections.singletonList("c")}, |
| new Object[]{Collections.emptyList()}, |
| new Object[]{useDefault ? null : Collections.emptyList()}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArraySliceArrayColumns() |
| { |
| testQuery( |
| "SELECT ARRAY_SLICE(arrayString, 1), ARRAY_SLICE(arrayLong, 2), ARRAY_SLICE(arrayDoubleNulls, 1) FROM druid.arrays", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| new Druids.ScanQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array_slice(\"arrayString\",1)", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v1", "array_slice(\"arrayLong\",2)", ColumnType.LONG_ARRAY), |
| expressionVirtualColumn("v2", "array_slice(\"arrayDoubleNulls\",1)", ColumnType.DOUBLE_ARRAY) |
| ) |
| .columns("v0", "v1", "v2") |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null, Collections.singletonList(3L), null}, |
| new Object[]{null, null, Collections.emptyList()}, |
| new Object[]{ImmutableList.of("e"), Collections.emptyList(), null}, |
| new Object[]{ImmutableList.of("b"), null, Arrays.asList(5.5D, null)}, |
| new Object[]{ImmutableList.of("b"), Collections.singletonList(3L), Arrays.asList(2.2D, null)}, |
| new Object[]{ImmutableList.of("c"), Arrays.asList(3L, 4L), Arrays.asList(2.2D, null)}, |
| new Object[]{ImmutableList.of("b", "c"), Collections.emptyList(), Arrays.asList(null, 5.5D)}, |
| new Object[]{null, Collections.singletonList(3L), null}, |
| new Object[]{null, null, Collections.singletonList(1.1D)}, |
| new Object[]{ImmutableList.of("e"), Collections.emptyList(), null}, |
| new Object[]{ImmutableList.of("b"), null, Arrays.asList(5.5D, null)}, |
| new Object[]{ImmutableList.of("b"), Collections.singletonList(3L), Arrays.asList(2.2D, null)}, |
| new Object[]{ImmutableList.of("c"), Arrays.asList(3L, 4L), Arrays.asList(2.2D, null)}, |
| new Object[]{ImmutableList.of("b", "c"), Collections.emptyList(), Arrays.asList(null, 5.5D)} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayLength() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT dim1, ARRAY_LENGTH(dim3), SUM(cnt) FROM druid.numfoo GROUP BY 1, 2 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn("v0", "array_length(\"dim3\")", ColumnType.LONG)) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("dim1", "_d0", ColumnType.STRING), |
| new DefaultDimensionSpec("v0", "_d1", ColumnType.LONG) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "_d1", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"", 2, 1L}, |
| new Object[]{"10.1", 2, 1L}, |
| useDefault ? new Object[]{"2", 1, 1L} : new Object[]{"1", 1, 1L}, |
| useDefault ? new Object[]{"1", 0, 1L} : new Object[]{"2", 1, 1L}, |
| new Object[]{"abc", useDefault ? 0 : null, 1L}, |
| new Object[]{"def", useDefault ? 0 : null, 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayLengthArrayColumn() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT arrayStringNulls, ARRAY_LENGTH(arrayStringNulls), SUM(cnt) FROM druid.arrays GROUP BY 1, 2 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn("v0", "array_length(\"arrayStringNulls\")", ColumnType.LONG)) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("arrayStringNulls", "d0", ColumnType.STRING_ARRAY), |
| new DefaultDimensionSpec("v0", "d1", ColumnType.LONG) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec( |
| new DefaultLimitSpec( |
| ImmutableList.of( |
| new OrderByColumnSpec( |
| "d1", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| ) |
| ), |
| Integer.MAX_VALUE |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| NullHandling.sqlCompatible() |
| ? ImmutableList.of( |
| new Object[]{"[\"d\",null,\"b\"]", 3, 2L}, |
| new Object[]{"[null,\"b\"]", 2, 2L}, |
| new Object[]{"[\"a\",\"b\"]", 2, 3L}, |
| new Object[]{"[\"b\",\"b\"]", 2, 2L}, |
| new Object[]{"[null]", 1, 1L}, |
| new Object[]{"[]", 0, 1L}, |
| new Object[]{null, null, 3L} |
| ) |
| : ImmutableList.of( |
| new Object[]{"[\"d\",null,\"b\"]", 3, 2L}, |
| new Object[]{"[null,\"b\"]", 2, 2L}, |
| new Object[]{"[\"a\",\"b\"]", 2, 3L}, |
| new Object[]{"[\"b\",\"b\"]", 2, 2L}, |
| new Object[]{"[null]", 1, 1L}, |
| new Object[]{null, 0, 3L}, |
| new Object[]{"[]", 0, 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAppend() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{ImmutableList.of("a", "b", "foo"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "foo"), 1L}, |
| new Object[]{ImmutableList.of("d", "foo"), 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{ImmutableList.of("", "foo"), 1L}, |
| new Object[]{ImmutableList.of("a", "b", "foo"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "foo"), 1L}, |
| new Object[]{ImmutableList.of("d", "foo"), 1L} |
| ); |
| } |
| testQuery( |
| "SELECT ARRAY_APPEND(dim3, 'foo'), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_append(\"dim3\",'foo')", |
| ColumnType.STRING_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayPrepend() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{ImmutableList.of("foo", "a", "b"), 1L}, |
| new Object[]{ImmutableList.of("foo", "b", "c"), 1L}, |
| new Object[]{ImmutableList.of("foo", "d"), 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{ImmutableList.of("foo", ""), 1L}, |
| new Object[]{ImmutableList.of("foo", "a", "b"), 1L}, |
| new Object[]{ImmutableList.of("foo", "b", "c"), 1L}, |
| new Object[]{ImmutableList.of("foo", "d"), 1L} |
| ); |
| } |
| testQuery( |
| "SELECT ARRAY_PREPEND('foo', dim3), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_prepend('foo',\"dim3\")", |
| ColumnType.STRING_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayPrependAppend() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{"", "", 3L}, |
| new Object[]{"foo,a,b", "a,b,foo", 1L}, |
| new Object[]{"foo,b,c", "b,c,foo", 1L}, |
| new Object[]{"foo,d", "d,foo", 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{null, null, 2L}, |
| new Object[]{"foo,", ",foo", 1L}, |
| new Object[]{"foo,a,b", "a,b,foo", 1L}, |
| new Object[]{"foo,b,c", "b,c,foo", 1L}, |
| new Object[]{"foo,d", "d,foo", 1L} |
| ); |
| } |
| testQuery( |
| "SELECT ARRAY_TO_STRING(ARRAY_PREPEND('foo', dim3), ','), ARRAY_TO_STRING(ARRAY_APPEND(dim3, 'foo'), ','), SUM(cnt) FROM druid.numfoo GROUP BY 1,2 ORDER BY 3 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns( |
| expressionVirtualColumn( |
| "v0", |
| "array_to_string(array_prepend('foo',\"dim3\"),',')", |
| ColumnType.STRING |
| ), |
| expressionVirtualColumn( |
| "v1", |
| "array_to_string(array_append(\"dim3\",'foo'),',')", |
| ColumnType.STRING |
| ) |
| ) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING), |
| new DefaultDimensionSpec("v1", "_d1", ColumnType.STRING) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayConcat() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{ImmutableList.of("a", "b", "a", "b"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "b", "c"), 1L}, |
| new Object[]{ImmutableList.of("d", "d"), 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{ImmutableList.of("", ""), 1L}, |
| new Object[]{ImmutableList.of("a", "b", "a", "b"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "b", "c"), 1L}, |
| new Object[]{ImmutableList.of("d", "d"), 1L} |
| ); |
| } |
| testQuery( |
| "SELECT ARRAY_CONCAT(dim3, dim3), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_concat(\"dim3\",\"dim3\")", |
| ColumnType.STRING_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayOffset() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT ARRAY_OFFSET(dim3, 1), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn("v0", "array_offset(\"dim3\",1)", ColumnType.STRING)) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{NullHandling.defaultStringValue(), 4L}, |
| new Object[]{"b", 1L}, |
| new Object[]{"c", 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayGroupAsLongArray() |
| { |
| // Cannot vectorize as we donot have support in native query subsytem for grouping on arrays |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY[l1], SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(\"l1\")", |
| ColumnType.LONG_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.LONG_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| useDefault ? ImmutableList.of( |
| new Object[]{ImmutableList.of(0L), 4L}, |
| new Object[]{ImmutableList.of(7L), 1L}, |
| new Object[]{ImmutableList.of(325323L), 1L} |
| ) : ImmutableList.of( |
| new Object[]{Collections.singletonList(null), 3L}, |
| new Object[]{ImmutableList.of(0L), 1L}, |
| new Object[]{ImmutableList.of(7L), 1L}, |
| new Object[]{ImmutableList.of(325323L), 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayGroupAsLongArrayColumn() |
| { |
| // Cannot vectorize as we donot have support in native query subsytem for grouping on arrays |
| cannotVectorize(); |
| testQuery( |
| "SELECT arrayLongNulls, SUM(cnt) FROM druid.arrays GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("arrayLongNulls", "d0", ColumnType.LONG_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec( |
| new DefaultLimitSpec( |
| ImmutableList.of( |
| new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| ) |
| ), |
| Integer.MAX_VALUE |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{Arrays.asList(null, 2L, 9L), 2L}, |
| new Object[]{Arrays.asList(1L, null, 3L), 2L}, |
| new Object[]{Arrays.asList(1L, 2L, 3L), 2L}, |
| new Object[]{Arrays.asList(2L, 3L), 2L}, |
| new Object[]{Collections.emptyList(), 1L}, |
| new Object[]{Collections.singletonList(null), 1L}, |
| new Object[]{Collections.singletonList(1L), 1L} |
| ) |
| ); |
| } |
| |
| |
| @Test |
| public void testArrayGroupAsDoubleArray() |
| { |
| // Cannot vectorize as we donot have support in native query subsytem for grouping on arrays as keys |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY[d1], SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(\"d1\")", |
| ColumnType.DOUBLE_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.DOUBLE_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| useDefault ? ImmutableList.of( |
| new Object[]{ImmutableList.of(0.0), 4L}, |
| new Object[]{ImmutableList.of(1.0), 1L}, |
| new Object[]{ImmutableList.of(1.7), 1L} |
| ) : |
| ImmutableList.of( |
| new Object[]{Collections.singletonList(null), 3L}, |
| new Object[]{ImmutableList.of(0.0), 1L}, |
| new Object[]{ImmutableList.of(1.0), 1L}, |
| new Object[]{ImmutableList.of(1.7), 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayGroupAsDoubleArrayColumn() |
| { |
| // Cannot vectorize as we donot have support in native query subsytem for grouping on arrays |
| cannotVectorize(); |
| testQuery( |
| "SELECT arrayDoubleNulls, SUM(cnt) FROM druid.arrays GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("arrayDoubleNulls", "d0", ColumnType.DOUBLE_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec( |
| new DefaultLimitSpec( |
| ImmutableList.of( |
| new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| ) |
| ), |
| Integer.MAX_VALUE |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null, 3L}, |
| new Object[]{Arrays.asList(null, 2.2D, null), 2L}, |
| new Object[]{Arrays.asList(1.1D, 2.2D, null), 2L}, |
| new Object[]{Arrays.asList(999.0D, null, 5.5D), 2L}, |
| new Object[]{Arrays.asList(999.0D, 5.5D, null), 2L}, |
| new Object[]{Collections.emptyList(), 1L}, |
| new Object[]{Collections.singletonList(null), 1L}, |
| new Object[]{Arrays.asList(null, 1.1D), 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayGroupAsFloatArray() |
| { |
| // Cannot vectorize as we donot have support in native query subsytem for grouping on arrays as keys |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY[f1], SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(\"f1\")", |
| ColumnType.ofArray(ColumnType.FLOAT) |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.ofArray(ColumnType.FLOAT)) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| useDefault ? ImmutableList.of( |
| new Object[]{ImmutableList.of(0.0F), 4L}, |
| new Object[]{ImmutableList.of(0.10000000149011612F), 1L}, |
| new Object[]{ImmutableList.of(1.0F), 1L} |
| ) : |
| ImmutableList.of( |
| new Object[]{Collections.singletonList(null), 3L}, |
| new Object[]{ImmutableList.of(0.0F), 1L}, |
| new Object[]{ImmutableList.of(0.10000000149011612F), 1L}, |
| new Object[]{ImmutableList.of(1.0F), 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayGroupAsArrayWithFunction() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY[ARRAY_ORDINAL(dim3, 2)], SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(array_ordinal(\"dim3\",2))", |
| ColumnType.STRING_ARRAY |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{Collections.singletonList(null), 4L}, |
| new Object[]{ImmutableList.of("b"), 1L}, |
| new Object[]{ImmutableList.of("c"), 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOrdinal() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT ARRAY_ORDINAL(dim3, 2), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_ordinal(\"dim3\",2)", |
| ColumnType.STRING |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{NullHandling.defaultStringValue(), 4L}, |
| new Object[]{"b", 1L}, |
| new Object[]{"c", 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOffsetOf() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT ARRAY_OFFSET_OF(dim3, 'b'), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_offset_of(\"dim3\",'b')", |
| ColumnType.LONG |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.LONG) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| useDefault |
| ? ImmutableList.of( |
| new Object[]{0, 4L}, |
| new Object[]{-1, 1L}, |
| new Object[]{1, 1L} |
| ) |
| : ImmutableList.of( |
| new Object[]{null, 4L}, |
| new Object[]{0, 1L}, |
| new Object[]{1, 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayOrdinalOf() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT ARRAY_ORDINAL_OF(dim3, 'b'), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_ordinal_of(\"dim3\",'b')", |
| ColumnType.LONG |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.LONG) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| useDefault |
| ? ImmutableList.of( |
| new Object[]{0, 3L}, |
| new Object[]{-1, 1L}, |
| new Object[]{1, 1L}, |
| new Object[]{2, 1L} |
| ) |
| : ImmutableList.of( |
| new Object[]{null, 4L}, |
| new Object[]{1, 1L}, |
| new Object[]{2, 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayToString() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{"", 3L}, |
| new Object[]{"a,b", 1L}, |
| new Object[]{"b,c", 1L}, |
| new Object[]{"d", 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{"", 1L}, |
| new Object[]{"a,b", 1L}, |
| new Object[]{"b,c", 1L}, |
| new Object[]{"d", 1L} |
| ); |
| } |
| testQuery( |
| "SELECT ARRAY_TO_STRING(dim3, ','), SUM(cnt) FROM druid.numfoo GROUP BY 1 ORDER BY 2 DESC", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array_to_string(\"dim3\",',')", |
| ColumnType.STRING |
| )) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v0", "_d0", ColumnType.STRING) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayToStringToMultiValueString() |
| { |
| // Cannot vectorize due to usage of expressions. |
| cannotVectorize(); |
| |
| ImmutableList<Object[]> results; |
| if (useDefault) { |
| results = ImmutableList.of( |
| new Object[]{ImmutableList.of("a", "b", "d"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "d"), 1L}, |
| new Object[]{ImmutableList.of("d", "d"), 1L} |
| ); |
| } else { |
| results = ImmutableList.of( |
| new Object[]{ImmutableList.of("", "d"), 1L}, |
| new Object[]{ImmutableList.of("a", "b", "d"), 1L}, |
| new Object[]{ImmutableList.of("b", "c", "d"), 1L}, |
| new Object[]{ImmutableList.of("d", "d"), 1L} |
| ); |
| } |
| testQuery( |
| "SELECT STRING_TO_ARRAY(CONCAT(ARRAY_TO_STRING(dim3, ','), ',d'), ','), SUM(cnt) FROM druid.numfoo WHERE ARRAY_LENGTH(dim3) > 0 GROUP BY 1 ORDER BY 2 DESC", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns( |
| expressionVirtualColumn("v0", "array_length(\"dim3\")", ColumnType.LONG), |
| expressionVirtualColumn( |
| "v1", |
| "string_to_array(concat(array_to_string(\"dim3\",','),',d'),',')", |
| ColumnType.STRING_ARRAY |
| ) |
| ) |
| .setDimFilter(range("v0", ColumnType.LONG, 0L, null, true, false)) |
| .setDimensions( |
| dimensions( |
| new DefaultDimensionSpec("v1", "_d0", ColumnType.STRING_ARRAY) |
| ) |
| ) |
| .setAggregatorSpecs(aggregators(new LongSumAggregatorFactory("a0", "cnt"))) |
| .setLimitSpec(new DefaultLimitSpec( |
| ImmutableList.of(new OrderByColumnSpec( |
| "a0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.NUMERIC |
| )), |
| Integer.MAX_VALUE |
| )) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| results |
| ); |
| } |
| |
| @Test |
| public void testArrayAgg() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(dim1), ARRAY_AGG(DISTINCT dim1), ARRAY_AGG(DISTINCT dim1) FILTER(WHERE dim1 = 'shazbot') FROM foo WHERE dim1 is not null", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("dim1")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"dim1\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new FilteredAggregatorFactory( |
| new ExpressionLambdaAggregatorFactory( |
| "a2", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a2\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| equality("dim1", "shazbot", ColumnType.STRING) |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{"[\"10.1\",\"2\",\"1\",\"def\",\"abc\"]", "[\"1\",\"10.1\",\"2\",\"abc\",\"def\"]", null} |
| : new Object[]{ |
| "[\"\",\"10.1\",\"2\",\"1\",\"def\",\"abc\"]", |
| "[\"\",\"1\",\"10.1\",\"2\",\"abc\",\"def\"]", |
| null |
| } |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggMultiValue() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(dim3), ARRAY_AGG(DISTINCT dim3) FROM foo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim3"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"dim3\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("dim3"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim3\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{"[\"a\",\"b\",\"b\",\"c\",\"d\",null,null,null]", "[null,\"a\",\"b\",\"c\",\"d\"]"} |
| : new Object[]{"[\"a\",\"b\",\"b\",\"c\",\"d\",\"\",null,null]", "[null,\"\",\"a\",\"b\",\"c\",\"d\"]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggNumeric() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(l1), ARRAY_AGG(DISTINCT l1), ARRAY_AGG(d1), ARRAY_AGG(DISTINCT d1), ARRAY_AGG(f1), ARRAY_AGG(DISTINCT f1) FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("l1"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"l1\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("l1"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"l1\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a2", |
| ImmutableSet.of("d1"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"d1\")", |
| "array_concat(\"__acc\", \"a2\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a3", |
| ImmutableSet.of("d1"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"d1\")", |
| "array_set_add_all(\"__acc\", \"a3\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a4", |
| ImmutableSet.of("f1"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"f1\")", |
| "array_concat(\"__acc\", \"a4\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a5", |
| ImmutableSet.of("f1"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"f1\")", |
| "array_set_add_all(\"__acc\", \"a5\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{ |
| "[7,325323,0,0,0,0]", |
| "[0,7,325323]", |
| "[1.0,1.7,0.0,0.0,0.0,0.0]", |
| "[0.0,1.0,1.7]", |
| "[1.0,0.10000000149011612,0.0,0.0,0.0,0.0]", |
| "[0.0,0.10000000149011612,1.0]" |
| } |
| : new Object[]{ |
| "[7,325323,0,null,null,null]", |
| "[null,0,7,325323]", |
| "[1.0,1.7,0.0,null,null,null]", |
| "[null,0.0,1.0,1.7]", |
| "[1.0,0.10000000149011612,0.0,null,null,null]", |
| "[null,0.0,0.10000000149011612,1.0]" |
| } |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggQuantile() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_QUANTILE(ARRAY_AGG(l1), 0.9) FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("l1"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"l1\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .postAggregators( |
| expressionPostAgg("p0", "array_quantile(\"a0\",0.9)", ColumnType.DOUBLE) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| // Different results because there are some nulls in the column. In SQL-compatible mode we ignore them; |
| // in replace-with-default mode we treat them as zeroes. |
| ImmutableList.of(new Object[]{NullHandling.sqlCompatible() ? 260259.80000000002 : 162665.0}) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggArrays() |
| { |
| // Produces nested array - ARRAY<ARRAY<LONG>>, which frame writers don't support. A way to get this query |
| // to run would be to use nested columns. |
| msqIncompatible(); |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(ARRAY[l1, l2]), ARRAY_AGG(DISTINCT ARRAY[l1, l2]) FROM numfoo", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array(\"l1\",\"l2\")", ColumnType.LONG_ARRAY) |
| ) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"v0\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| (sql, queryResults) -> { |
| // ordering is not stable in array_agg and array_concat_agg |
| List<Object[]> expected = ImmutableList.of( |
| useDefault ? |
| new Object[]{ |
| Arrays.asList( |
| Arrays.asList(7L, 0L), |
| Arrays.asList(325323L, 325323L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L) |
| ), |
| Arrays.asList( |
| Arrays.asList(0L, 0L), |
| Arrays.asList(7L, 0L), |
| Arrays.asList(325323L, 325323L) |
| ) |
| } |
| : |
| new Object[]{ |
| Arrays.asList( |
| Arrays.asList(7L, null), |
| Arrays.asList(325323L, 325323L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(null, null), |
| Arrays.asList(null, null), |
| Arrays.asList(null, null) |
| ), |
| Arrays.asList( |
| Arrays.asList(null, null), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(7L, null), |
| Arrays.asList(325323L, 325323L) |
| ) |
| } |
| ); |
| assertResultsDeepEquals(sql, expected, queryResults.results); |
| } |
| ); |
| } |
| |
| @Test |
| public void testArrayAggArraysWithMaxSizeBytes() |
| { |
| // Produces nested array - ARRAY<ARRAY<LONG>>, which frame writers don't support. A way to get this query |
| // to run would be to use nested columns. |
| msqIncompatible(); |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(ARRAY[l1, l2], 10000), ARRAY_AGG(DISTINCT ARRAY[l1, l2], CAST(10000 AS INTEGER)) FROM numfoo", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array(\"l1\",\"l2\")", ColumnType.LONG_ARRAY) |
| ) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| new HumanReadableBytes(10000), |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"v0\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| new HumanReadableBytes(10000), |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .build() |
| ), |
| (sql, queryResults) -> { |
| // ordering is not stable in array_agg and array_concat_agg |
| List<Object[]> expected = ImmutableList.of( |
| useDefault ? |
| new Object[]{ |
| Arrays.asList( |
| Arrays.asList(7L, 0L), |
| Arrays.asList(325323L, 325323L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(0L, 0L) |
| ), |
| Arrays.asList( |
| Arrays.asList(0L, 0L), |
| Arrays.asList(7L, 0L), |
| Arrays.asList(325323L, 325323L) |
| ) |
| } |
| : |
| new Object[]{ |
| Arrays.asList( |
| Arrays.asList(7L, null), |
| Arrays.asList(325323L, 325323L), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(null, null), |
| Arrays.asList(null, null), |
| Arrays.asList(null, null) |
| ), |
| Arrays.asList( |
| Arrays.asList(null, null), |
| Arrays.asList(0L, 0L), |
| Arrays.asList(7L, null), |
| Arrays.asList(325323L, 325323L) |
| ) |
| } |
| ); |
| assertResultsDeepEquals(sql, expected, queryResults.results); |
| } |
| ); |
| } |
| |
| |
| @Test |
| public void testArrayConcatAggArrays() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_CONCAT_AGG(ARRAY[l1, l2]), ARRAY_CONCAT_AGG(DISTINCT ARRAY[l1, l2]) FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array(\"l1\",\"l2\")", ColumnType.LONG_ARRAY) |
| ) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| false, |
| false, |
| "array_concat(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| false, |
| false, |
| "array_set_add_all(\"__acc\", \"v0\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{"[7,0,325323,325323,0,0,0,0,0,0,0,0]", "[0,7,325323]"} |
| : new Object[]{"[7,null,325323,325323,0,0,null,null,null,null,null,null]", "[null,0,7,325323]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayConcatAggArraysWithMaxSizeBytes() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_CONCAT_AGG(ARRAY[l1, l2], 10000), ARRAY_CONCAT_AGG(DISTINCT ARRAY[l1, l2], CAST(10000 AS INTEGER)) " |
| + "FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array(\"l1\",\"l2\")", ColumnType.LONG_ARRAY) |
| ) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| false, |
| false, |
| "array_concat(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| new HumanReadableBytes(10000), |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| false, |
| false, |
| "array_set_add_all(\"__acc\", \"v0\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| new HumanReadableBytes(10000), |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{"[7,0,325323,325323,0,0,0,0,0,0,0,0]", "[0,7,325323]"} |
| : new Object[]{"[7,null,325323,325323,0,0,null,null,null,null,null,null]", "[null,0,7,325323]"} |
| ) |
| ); |
| } |
| |
| |
| |
| @Test |
| public void testArrayAggArrayColumns() |
| { |
| msqIncompatible(); |
| // nested array party |
| cannotVectorize(); |
| if (NullHandling.replaceWithDefault()) { |
| // default value mode plans to selector filters for equality, which do not support array filtering |
| return; |
| } |
| testQuery( |
| "SELECT ARRAY_AGG(arrayLongNulls), ARRAY_AGG(DISTINCT arrayDouble), ARRAY_AGG(DISTINCT arrayStringNulls) FILTER(WHERE arrayLong = ARRAY[2,3]) FROM arrays WHERE arrayDoubleNulls is not null", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("arrayDoubleNulls")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("arrayLongNulls"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"arrayLongNulls\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("arrayDouble"), |
| "__acc", |
| "ARRAY<ARRAY<DOUBLE>>[]", |
| "ARRAY<ARRAY<DOUBLE>>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"arrayDouble\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new FilteredAggregatorFactory( |
| new ExpressionLambdaAggregatorFactory( |
| "a2", |
| ImmutableSet.of("arrayStringNulls"), |
| "__acc", |
| "ARRAY<ARRAY<STRING>>[]", |
| "ARRAY<ARRAY<STRING>>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"arrayStringNulls\")", |
| "array_set_add_all(\"__acc\", \"a2\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| equality("arrayLong", ImmutableList.of(2, 3), ColumnType.LONG_ARRAY) |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ |
| "[[2,3],[null,2,9],[1,null,3],[1,2,3],null,null,[2,3],[null,2,9],[1,null,3],[1,2,3],null]", |
| "[null,[1.1,2.2,3.3],[1.1,3.3],[3.3,4.4,5.5]]", |
| "[[null,\"b\"]]" |
| } |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayConcatAggArrayColumns() |
| { |
| cannotVectorize(); |
| if (NullHandling.replaceWithDefault()) { |
| // default value mode plans to selector filters for equality, which do not support array filtering |
| return; |
| } |
| testQuery( |
| "SELECT ARRAY_CONCAT_AGG(arrayLongNulls), ARRAY_CONCAT_AGG(DISTINCT arrayDouble), ARRAY_CONCAT_AGG(DISTINCT arrayStringNulls) FILTER(WHERE arrayLong = ARRAY[2,3]) FROM arrays WHERE arrayDoubleNulls is not null", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.ARRAYS_DATASOURCE) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("arrayDoubleNulls")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("arrayLongNulls"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| false, |
| false, |
| "array_concat(\"__acc\", \"arrayLongNulls\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("arrayDouble"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| false, |
| false, |
| "array_set_add_all(\"__acc\", \"arrayDouble\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| new FilteredAggregatorFactory( |
| new ExpressionLambdaAggregatorFactory( |
| "a2", |
| ImmutableSet.of("arrayStringNulls"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| false, |
| false, |
| "array_set_add_all(\"__acc\", \"arrayStringNulls\")", |
| "array_set_add_all(\"__acc\", \"a2\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ), |
| equality("arrayLong", ImmutableList.of(2, 3), ColumnType.LONG_ARRAY) |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ |
| "[2,3,null,2,9,1,null,3,1,2,3,2,3,null,2,9,1,null,3,1,2,3]", |
| "[1.1,2.2,3.3,4.4,5.5]", |
| "[null,\"b\"]" |
| } |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggToString() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_TO_STRING(ARRAY_AGG(DISTINCT dim1), ',') FROM foo WHERE dim1 is not null", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("dim1")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .postAggregators(expressionPostAgg("p0", "array_to_string(\"a0\",',')", ColumnType.STRING)) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault ? new Object[]{"1,10.1,2,abc,def"} : new Object[]{",1,10.1,2,abc,def"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggExpression() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_TO_STRING(ARRAY_AGG(DISTINCT CONCAT(dim1, dim2)), ',') FROM foo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "concat(\"dim1\",\"dim2\")", ColumnType.STRING) |
| ) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"v0\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .postAggregators(expressionPostAgg("p0", "array_to_string(\"a0\",',')", ColumnType.STRING)) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault ? new Object[]{"10.1,1a,2,a,abc,defabc"} : new Object[]{"null,1a,2,a,defabc"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggMaxBytes() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT ARRAY_AGG(l1, 128), ARRAY_AGG(DISTINCT l1, CAST(128 AS INTEGER)) FROM numfoo", |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("l1"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"l1\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| new HumanReadableBytes(128), |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionLambdaAggregatorFactory( |
| "a1", |
| ImmutableSet.of("l1"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"l1\")", |
| "array_set_add_all(\"__acc\", \"a1\")", |
| null, |
| null, |
| new HumanReadableBytes(128), |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| useDefault |
| ? new Object[]{"[7,325323,0,0,0,0]", "[0,7,325323]"} |
| : new Object[]{"[7,325323,0,null,null,null]", "[null,0,7,325323]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggAsArrayFromJoin() |
| { |
| cannotVectorize(); |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{"a", "[\"10.1\",\"2\"]", "10.1,2"}, |
| new Object[]{"a", "[\"10.1\",\"2\"]", "10.1,2"}, |
| new Object[]{"a", "[\"10.1\",\"2\"]", "10.1,2"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"} |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{"a", "[\"\",\"10.1\",\"2\"]", ",10.1,2"}, |
| new Object[]{"a", "[\"\",\"10.1\",\"2\"]", ",10.1,2"}, |
| new Object[]{"a", "[\"\",\"10.1\",\"2\"]", ",10.1,2"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"}, |
| new Object[]{"b", "[\"1\",\"abc\",\"def\"]", "1,abc,def"} |
| ); |
| } |
| testQuery( |
| "SELECT numfoo.dim4, j.arr, ARRAY_TO_STRING(j.arr, ',') FROM numfoo INNER JOIN (SELECT dim4, ARRAY_AGG(DISTINCT dim1) as arr FROM numfoo WHERE dim1 is not null GROUP BY 1) as j ON numfoo.dim4 = j.dim4", |
| QUERY_CONTEXT_DEFAULT, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| join( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE3) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimFilter(notNull("dim1")) |
| .setDimensions(new DefaultDimensionSpec("dim4", "_d0")) |
| .setAggregatorSpecs( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| "j0.", |
| "(\"dim4\" == \"j0._d0\")", |
| JoinType.INNER, |
| null |
| ) |
| ) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array_to_string(\"j0.a0\",',')", ColumnType.STRING) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .columns("dim4", "j0.a0", "v0") |
| .context(QUERY_CONTEXT_DEFAULT) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .build() |
| |
| ), |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testArrayAggGroupByArrayAggFromSubquery() |
| { |
| cannotVectorize(); |
| |
| testQuery( |
| "SELECT dim2, arr, COUNT(*) FROM (SELECT dim2, ARRAY_AGG(DISTINCT dim1) as arr FROM foo WHERE dim1 is not null GROUP BY 1 LIMIT 5) GROUP BY 1,2", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| new TopNQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .dimension(new DefaultDimensionSpec( |
| "dim2", |
| "d0", |
| ColumnType.STRING |
| )) |
| .metric(new DimensionTopNMetricSpec( |
| null, |
| StringComparators.LEXICOGRAPHIC |
| )) |
| .filters(notNull("dim1")) |
| .threshold(5) |
| .aggregators(new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| new HumanReadableBytes(1024), |
| ExprMacroTable.nil() |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .context(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .postAggregators(expressionPostAgg("s0", "1", ColumnType.LONG)) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"", ImmutableList.of("10.1", "2", "abc"), 1L}, |
| new Object[]{"a", ImmutableList.of("1"), 1L}, |
| new Object[]{"abc", ImmutableList.of("def"), 1L} |
| ) : |
| ImmutableList.of( |
| new Object[]{null, ImmutableList.of("10.1", "abc"), 1L}, |
| new Object[]{"", ImmutableList.of("2"), 1L}, |
| new Object[]{"a", ImmutableList.of("", "1"), 1L}, |
| new Object[]{"abc", ImmutableList.of("def"), 1L} |
| ) |
| ); |
| } |
| |
| @SqlTestFrameworkConfig(numMergeBuffers = 3) |
| @Test |
| public void testArrayAggGroupByArrayAggOfLongsFromSubquery() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select cntarray, count(*) from ( select dim1, dim2, ARRAY_AGG(cnt) as cntarray from ( select dim1, dim2, dim3, count(*) as cnt from foo group by 1, 2, 3 ) group by 1, 2 ) group by 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new TableDataSource(CalciteTests.DATASOURCE1)) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions( |
| new DefaultDimensionSpec("dim1", "d0"), |
| new DefaultDimensionSpec("dim2", "d1"), |
| new DefaultDimensionSpec("dim3", "d2" |
| ) |
| ) |
| .setAggregatorSpecs( |
| new CountAggregatorFactory("a0")) |
| .build())) |
| .setQuerySegmentSpec( |
| querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimensions( |
| new DefaultDimensionSpec( |
| "d0", |
| "_d0" |
| ), |
| new DefaultDimensionSpec( |
| "d1", |
| "_d1" |
| ) |
| ) |
| .setAggregatorSpecs(new ExpressionLambdaAggregatorFactory( |
| "_a0", |
| ImmutableSet.of("a0"), |
| "__acc", |
| "ARRAY<LONG>[]", |
| "ARRAY<LONG>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"a0\")", |
| "array_concat(\"__acc\", \"_a0\")", |
| null, |
| null, |
| new HumanReadableBytes(1024), |
| ExprMacroTable.nil() |
| )) |
| .build())) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions(new DefaultDimensionSpec("_a0", "d0", ColumnType.LONG_ARRAY)) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ImmutableList.of(1L), 4L}, |
| new Object[]{ImmutableList.of(1L, 1L), 2L} |
| ) |
| ); |
| } |
| |
| @SqlTestFrameworkConfig(numMergeBuffers = 3) |
| @Test |
| public void testArrayAggGroupByArrayAggOfStringsFromSubquery() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select cntarray, count(*) from ( select dim1, dim2, ARRAY_AGG(cnt) as cntarray from ( select dim1, dim2, dim3, cast( count(*) as VARCHAR ) as cnt from foo group by 1, 2, 3 ) group by 1, 2 ) group by 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new TableDataSource(CalciteTests.DATASOURCE1)) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions( |
| new DefaultDimensionSpec("dim1", "d0"), |
| new DefaultDimensionSpec("dim2", "d1"), |
| new DefaultDimensionSpec("dim3", "d2" |
| ) |
| ) |
| .setAggregatorSpecs( |
| new CountAggregatorFactory("a0")) |
| .build())) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimensions( |
| new DefaultDimensionSpec("d0", "_d0"), |
| new DefaultDimensionSpec("d1", "_d1") |
| ) |
| .setAggregatorSpecs(new ExpressionLambdaAggregatorFactory( |
| "_a0", |
| ImmutableSet.of("a0"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"a0\")", |
| "array_concat(\"__acc\", \"_a0\")", |
| null, |
| null, |
| new HumanReadableBytes(1024), |
| ExprMacroTable.nil() |
| )) |
| .build())) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions(new DefaultDimensionSpec("_a0", "d0", ColumnType.STRING_ARRAY)) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ImmutableList.of("1"), 4L}, |
| new Object[]{ImmutableList.of("1", "1"), 2L} |
| ) |
| ); |
| } |
| |
| @SqlTestFrameworkConfig(numMergeBuffers = 3) |
| @Test |
| public void testArrayAggGroupByArrayAggOfDoubleFromSubquery() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select cntarray, count(*) from ( select dim1, dim2, ARRAY_AGG(cnt) as cntarray from ( select dim1, dim2, dim3, cast( count(*) as DOUBLE ) as cnt from foo group by 1, 2, 3 ) group by 1, 2 ) group by 1", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery |
| .builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(new TableDataSource(CalciteTests.DATASOURCE1)) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions( |
| new DefaultDimensionSpec("dim1", "d0"), |
| new DefaultDimensionSpec("dim2", "d1"), |
| new DefaultDimensionSpec("dim3", "d2" |
| ) |
| ) |
| .setAggregatorSpecs( |
| new CountAggregatorFactory("a0")) |
| .build())) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setDimensions( |
| new DefaultDimensionSpec("d0", "_d0"), |
| new DefaultDimensionSpec("d1", "_d1") |
| ) |
| .setAggregatorSpecs(new ExpressionLambdaAggregatorFactory( |
| "_a0", |
| ImmutableSet.of("a0"), |
| "__acc", |
| "ARRAY<DOUBLE>[]", |
| "ARRAY<DOUBLE>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"a0\")", |
| "array_concat(\"__acc\", \"_a0\")", |
| null, |
| null, |
| new HumanReadableBytes(1024), |
| ExprMacroTable.nil() |
| )) |
| .build())) |
| .setQuerySegmentSpec(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_NO_STRINGIFY_ARRAY) |
| .setDimensions(new DefaultDimensionSpec("_a0", "d0", ColumnType.DOUBLE_ARRAY)) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ImmutableList.of(1.0), 4L}, |
| new Object[]{ImmutableList.of(1.0, 1.0), 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayAggArrayContainsSubquery() |
| { |
| cannotVectorize(); |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{"10.1", ""}, |
| new Object[]{"2", ""}, |
| new Object[]{"1", "a"}, |
| new Object[]{"def", "abc"}, |
| new Object[]{"abc", ""} |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{"", "a"}, |
| new Object[]{"10.1", null}, |
| new Object[]{"2", ""}, |
| new Object[]{"1", "a"}, |
| new Object[]{"def", "abc"}, |
| new Object[]{"abc", null} |
| ); |
| } |
| testQuery( |
| "SELECT dim1,dim2 FROM foo WHERE ARRAY_CONTAINS((SELECT ARRAY_AGG(DISTINCT dim1) FROM foo WHERE dim1 is not null), dim1)", |
| QUERY_CONTEXT_DEFAULT, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| join( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| new QueryDataSource( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("dim1")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| "j0.", |
| "1", |
| JoinType.LEFT, |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| new ExpressionDimFilter( |
| "array_contains(\"j0.a0\",\"dim1\")", |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .columns("dim1", "dim2") |
| .context(QUERY_CONTEXT_DEFAULT) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .build() |
| |
| ), |
| expectedResults |
| ); |
| } |
| |
| @Test |
| public void testArrayAggGroupByArrayContainsSubquery() |
| { |
| cannotVectorize(); |
| List<Object[]> expectedResults; |
| if (useDefault) { |
| expectedResults = ImmutableList.of( |
| new Object[]{"", 3L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"abc", 1L} |
| ); |
| } else { |
| expectedResults = ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{"", 1L}, |
| new Object[]{"a", 2L}, |
| new Object[]{"abc", 1L} |
| ); |
| } |
| testQuery( |
| "SELECT dim2, COUNT(*) FROM foo WHERE ARRAY_CONTAINS((SELECT ARRAY_AGG(DISTINCT dim1) FROM foo WHERE dim1 is not null), dim1) GROUP BY 1", |
| QUERY_CONTEXT_DEFAULT, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource( |
| join( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| new QueryDataSource( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE1) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .granularity(Granularities.ALL) |
| .filters(notNull("dim1")) |
| .aggregators( |
| aggregators( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("dim1"), |
| "__acc", |
| "ARRAY<STRING>[]", |
| "ARRAY<STRING>[]", |
| true, |
| true, |
| false, |
| "array_set_add(\"__acc\", \"dim1\")", |
| "array_set_add_all(\"__acc\", \"a0\")", |
| null, |
| null, |
| ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| ) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| "j0.", |
| "1", |
| JoinType.LEFT, |
| null |
| ) |
| ) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setDimFilter( |
| new ExpressionDimFilter( |
| "array_contains(\"j0.a0\",\"dim1\")", |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0"))) |
| .setAggregatorSpecs(aggregators(new CountAggregatorFactory("a0"))) |
| .setGranularity(Granularities.ALL) |
| .setLimitSpec(NoopLimitSpec.instance()) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| |
| ), |
| expectedResults |
| ); |
| |
| } |
| |
| @Test |
| public void testUnnestInline() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT * FROM UNNEST(ARRAY[1,2,3])", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of( |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L} |
| ), |
| RowSignature.builder().add("EXPR$0", ColumnType.LONG).build() |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of( |
| "EXPR$0" |
| )) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestInlineWithCount() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT COUNT(*) FROM (select c from UNNEST(ARRAY[1,2,3]) as unnested(c))", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of( |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L} |
| ), |
| RowSignature.builder().add("EXPR$0", ColumnType.LONG).build() |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .context(QUERY_CONTEXT_UNNEST) |
| .aggregators(aggregators(new CountAggregatorFactory("a0"))) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnest() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsString() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayString) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayString\"", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"d"}, |
| new Object[]{"e"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{"e"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"c"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsStringNulls() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayStringNulls) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayStringNulls\"", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"d"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"d"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsLong() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayLong) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayLong\"", ColumnType.LONG_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{4L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{4L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{4L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{4L}, |
| new Object[]{2L}, |
| new Object[]{3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsLongNulls() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayLongNulls) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayLongNulls\"", ColumnType.LONG_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{null}, |
| new Object[]{2L}, |
| new Object[]{9L}, |
| new Object[]{1L}, |
| new Object[]{null}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{2L}, |
| new Object[]{3L}, |
| new Object[]{null}, |
| new Object[]{null}, |
| new Object[]{2L}, |
| new Object[]{9L}, |
| new Object[]{1L}, |
| new Object[]{null}, |
| new Object[]{3L}, |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsDouble() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayDouble) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayDouble\"", ColumnType.DOUBLE_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{4.0D}, |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{1.1D}, |
| new Object[]{3.3D}, |
| new Object[]{3.3D}, |
| new Object[]{4.4D}, |
| new Object[]{5.5D}, |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{4.0D}, |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{3.3D}, |
| new Object[]{1.1D}, |
| new Object[]{3.3D}, |
| new Object[]{3.3D}, |
| new Object[]{4.4D}, |
| new Object[]{5.5D} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestArrayColumnsDoubleNulls() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT a FROM druid.arrays, UNNEST(arrayDoubleNulls) as unnested (a)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayDoubleNulls\"", ColumnType.DOUBLE_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{null}, |
| new Object[]{999.0D}, |
| new Object[]{5.5D}, |
| new Object[]{null}, |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{null}, |
| new Object[]{null}, |
| new Object[]{2.2D}, |
| new Object[]{null}, |
| new Object[]{999.0D}, |
| new Object[]{null}, |
| new Object[]{5.5D}, |
| new Object[]{null}, |
| new Object[]{1.1D}, |
| new Object[]{999.0D}, |
| new Object[]{5.5D}, |
| new Object[]{null}, |
| new Object[]{1.1D}, |
| new Object[]{2.2D}, |
| new Object[]{null}, |
| new Object[]{null}, |
| new Object[]{2.2D}, |
| new Object[]{null}, |
| new Object[]{999.0D}, |
| new Object[]{null}, |
| new Object[]{5.5D} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestTwice() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT dim1, MV_TO_ARRAY(dim3), STRING_TO_ARRAY(dim1, U&'\\005C.') AS dim1_split, dim1_split_unnest, dim3_unnest\n" |
| + "FROM\n" |
| + " druid.numfoo,\n" |
| + " UNNEST(STRING_TO_ARRAY(dim1, U&'\\005C.')) as t2 (dim1_split_unnest),\n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as t3 (dim3_unnest)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "string_to_array(\"dim1\",'\\u005C.')", |
| ColumnType.STRING_ARRAY |
| ), |
| null |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| expressionVirtualColumn( |
| "v0", |
| "mv_to_array(\"dim3\")", |
| ColumnType.STRING_ARRAY |
| ), |
| expressionVirtualColumn( |
| "v1", |
| "string_to_array(\"dim1\",'\\u005C.')", |
| ColumnType.STRING_ARRAY |
| ) |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("_j0.unnest", "dim1", "j0.unnest", "v0", "v1")) |
| .build() |
| ), |
| NullHandling.replaceWithDefault() ? |
| ImmutableList.of( |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "10", "b"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "10", "c"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "b"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "c"}, |
| new Object[]{"2", ImmutableList.of("d"), ImmutableList.of("2"), "2", "d"}, |
| new Object[]{"1", useDefault ? null : ImmutableList.of(""), ImmutableList.of("1"), "1", ""}, |
| new Object[]{"def", null, ImmutableList.of("def"), "def", NullHandling.defaultStringValue()}, |
| new Object[]{"abc", null, ImmutableList.of("abc"), "abc", NullHandling.defaultStringValue()} |
| ) : |
| ImmutableList.of( |
| new Object[]{"", ImmutableList.of("a", "b"), ImmutableList.of(""), "", "a"}, |
| new Object[]{"", ImmutableList.of("a", "b"), ImmutableList.of(""), "", "b"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "10", "b"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "10", "c"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "b"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "c"}, |
| new Object[]{"2", ImmutableList.of("d"), ImmutableList.of("2"), "2", "d"}, |
| new Object[]{"1", ImmutableList.of(""), ImmutableList.of("1"), "1", ""}, |
| new Object[]{"def", null, ImmutableList.of("def"), "def", null}, |
| new Object[]{"abc", null, ImmutableList.of("abc"), "abc", null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestTwiceArrayColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT arrayStringNulls, arrayLongNulls, usn, uln" |
| + " FROM\n" |
| + " druid.arrays,\n" |
| + " UNNEST(arrayStringNulls) as t2 (usn),\n" |
| + " UNNEST(arrayLongNulls) as t3 (uln)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"arrayStringNulls\"", |
| ColumnType.STRING_ARRAY |
| ), |
| null |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"arrayLongNulls\"", |
| ColumnType.LONG_ARRAY |
| ), |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("_j0.unnest", "arrayLongNulls", "arrayStringNulls", "j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "a", 2L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "a", 3L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "b", 2L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "b", 3L}, |
| new Object[]{Arrays.asList("b", "b"), Collections.singletonList(1L), "b", 1L}, |
| new Object[]{Arrays.asList("b", "b"), Collections.singletonList(1L), "b", 1L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "a", 1L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "a", null}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "a", 3L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "b", 1L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "b", null}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(1L, null, 3L), "b", 3L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 3L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 3L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 3L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "a", 2L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "a", 3L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "b", 2L}, |
| new Object[]{Arrays.asList("a", "b"), Arrays.asList(2L, 3L), "b", 3L}, |
| new Object[]{Arrays.asList("b", "b"), Collections.singletonList(null), "b", null}, |
| new Object[]{Arrays.asList("b", "b"), Collections.singletonList(null), "b", null}, |
| new Object[]{Collections.singletonList(null), Arrays.asList(null, 2L, 9L), NullHandling.defaultStringValue(), null}, |
| new Object[]{Collections.singletonList(null), Arrays.asList(null, 2L, 9L), NullHandling.defaultStringValue(), 2L}, |
| new Object[]{Collections.singletonList(null), Arrays.asList(null, 2L, 9L), NullHandling.defaultStringValue(), 9L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "d", 3L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), NullHandling.defaultStringValue(), 3L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 1L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 2L}, |
| new Object[]{Arrays.asList("d", null, "b"), Arrays.asList(1L, 2L, 3L), "b", 3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestTwiceWithFiltersAndExpressions() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT dim1, MV_TO_ARRAY(dim3), STRING_TO_ARRAY(dim1, U&'\\005C.') AS dim1_split, dim1_split_unnest, dim3_unnest || 'xx'\n" |
| + "FROM\n" |
| + " druid.numfoo,\n" |
| + " UNNEST(STRING_TO_ARRAY(dim1, U&'\\005C.')) as t2 (dim1_split_unnest),\n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as t3 (dim3_unnest)" |
| + "WHERE dim1_split_unnest IN ('1', '2') AND dim3_unnest LIKE '_'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "string_to_array(\"dim1\",'\\u005C.')", |
| ColumnType.STRING_ARRAY |
| ), |
| in("j0.unnest", ImmutableList.of("1", "2")) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| new LikeDimFilter("_j0.unnest", "_", null, null) |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns( |
| expressionVirtualColumn( |
| "v0", |
| "mv_to_array(\"dim3\")", |
| ColumnType.STRING_ARRAY |
| ), |
| expressionVirtualColumn( |
| "v1", |
| "string_to_array(\"dim1\",'\\u005C.')", |
| ColumnType.STRING_ARRAY |
| ), |
| expressionVirtualColumn( |
| "v2", |
| "concat(\"_j0.unnest\",'xx')", |
| ColumnType.STRING |
| ) |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("dim1", "j0.unnest", "v0", "v1", "v2")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "bxx"}, |
| new Object[]{"10.1", ImmutableList.of("b", "c"), ImmutableList.of("10", "1"), "1", "cxx"}, |
| new Object[]{"2", ImmutableList.of("d"), ImmutableList.of("2"), "2", "dxx"} |
| ) |
| ); |
| } |
| |
| |
| @Test |
| public void testUnnestThriceWithFiltersOnDimAndUnnestCol() |
| { |
| cannotVectorize(); |
| String sql = " SELECT dimZipf, dim3_unnest1, dim3_unnest2, dim3_unnest3 FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM lotsocolumns, UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest1) )" |
| + " ,UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest2) \n" |
| + " ), UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest3) " |
| + " WHERE dimZipf=27 AND dim3_unnest1='Baz'"; |
| List<Query<?>> expectedQuerySc = ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE5), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| and( |
| NullHandling.sqlCompatible() |
| ? equality("dimZipf", "27", ColumnType.LONG) |
| : bound("dimZipf", "27", "27", false, false, null, StringComparators.NUMERIC), |
| equality("j0.unnest", "Baz", ColumnType.STRING) |
| ) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), null |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .virtualColumns(expressionVirtualColumn( |
| "v0", |
| "'Baz'", |
| ColumnType.STRING |
| )) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "dimZipf", "v0")) |
| .build() |
| ); |
| testQuery( |
| sql, |
| QUERY_CONTEXT_UNNEST, |
| expectedQuerySc, |
| ImmutableList.of( |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Hello"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Hello"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Hello", "Baz"}, |
| new Object[]{"27", "Baz", "Hello", "Baz"}, |
| new Object[]{"27", "Baz", "Hello", "Hello"}, |
| new Object[]{"27", "Baz", "Hello", "World"}, |
| new Object[]{"27", "Baz", "World", "Baz"}, |
| new Object[]{"27", "Baz", "World", "Baz"}, |
| new Object[]{"27", "Baz", "World", "Hello"}, |
| new Object[]{"27", "Baz", "World", "World"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Hello"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Baz"}, |
| new Object[]{"27", "Baz", "Baz", "Hello"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Hello", "Baz"}, |
| new Object[]{"27", "Baz", "Hello", "Baz"}, |
| new Object[]{"27", "Baz", "Hello", "Hello"}, |
| new Object[]{"27", "Baz", "Hello", "World"}, |
| new Object[]{"27", "Baz", "World", "Baz"}, |
| new Object[]{"27", "Baz", "World", "Baz"}, |
| new Object[]{"27", "Baz", "World", "Hello"}, |
| new Object[]{"27", "Baz", "World", "World"} |
| ) |
| ); |
| } |
| @Test |
| public void testUnnestThriceWithFiltersOnDimAndAllUnnestColumns() |
| { |
| cannotVectorize(); |
| String sql = " SELECT dimZipf, dim3_unnest1, dim3_unnest2, dim3_unnest3 FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM lotsocolumns, UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest1) )" |
| + " ,UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest2) \n" |
| + " ), UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest3) " |
| + " WHERE dimZipf=27 AND dim3_unnest1='Baz' AND dim3_unnest2='Hello' AND dim3_unnest3='World'"; |
| List<Query<?>> expectedQuerySc = ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE5), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| and( |
| NullHandling.sqlCompatible() |
| ? equality("dimZipf", "27", ColumnType.LONG) |
| : bound("dimZipf", "27", "27", false, false, null, StringComparators.NUMERIC), |
| equality("j0.unnest", "Baz", ColumnType.STRING) |
| ) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), equality("_j0.unnest", "Hello", ColumnType.STRING) |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| equality("__j0.unnest", "World", ColumnType.STRING) |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .virtualColumns(expressionVirtualColumn( |
| "v0", |
| "'Baz'", |
| ColumnType.STRING |
| )) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "dimZipf", "v0")) |
| .build() |
| ); |
| testQuery( |
| sql, |
| QUERY_CONTEXT_UNNEST, |
| expectedQuerySc, |
| ImmutableList.of( |
| new Object[]{"27", "Baz", "Hello", "World"}, |
| new Object[]{"27", "Baz", "Hello", "World"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestThriceWithFiltersOnDimAndAllUnnestColumnsArrayColumns() |
| { |
| cannotVectorize(); |
| String sql = " SELECT arrayString, uln, udn, usn FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM arrays, UNNEST(arrayLongNulls) as ut(uln))" |
| + " ,UNNEST(arrayDoubleNulls) as ut(udn) \n" |
| + " ), UNNEST(arrayStringNulls) as ut(usn) " |
| + " WHERE arrayString = ARRAY['a','b'] AND uln = 1 AND udn = 2.2 AND usn = 'a'"; |
| List<Query<?>> expectedQuerySc = ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"arrayLongNulls\"", |
| ColumnType.LONG_ARRAY |
| ), |
| null |
| ), |
| and( |
| NullHandling.sqlCompatible() |
| ? equality("arrayString", ImmutableList.of("a", "b"), ColumnType.STRING_ARRAY) |
| : expressionFilter("(\"arrayString\" == array('a','b'))"), |
| equality("j0.unnest", 1, ColumnType.LONG) |
| ) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"arrayDoubleNulls\"", |
| ColumnType.DOUBLE_ARRAY |
| ), |
| equality("_j0.unnest", 2.2, ColumnType.DOUBLE) |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"arrayStringNulls\"", |
| ColumnType.STRING_ARRAY |
| ), |
| equality("__j0.unnest", "a", ColumnType.STRING) |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array('a','b')", ColumnType.STRING_ARRAY), |
| expressionVirtualColumn("v1", "1", ColumnType.LONG) |
| ) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "v0", "v1")) |
| .build() |
| ); |
| testQuery( |
| sql, |
| QUERY_CONTEXT_UNNEST, |
| expectedQuerySc, |
| ImmutableList.of( |
| new Object[]{ImmutableList.of("a", "b"), 1L, 2.2D, "a"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestThriceWithFiltersOnDimAndUnnestColumnsORCombinations() |
| { |
| cannotVectorize(); |
| String sql = " SELECT dimZipf, dim3_unnest1, dim3_unnest2, dim3_unnest3 FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM lotsocolumns, UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest1) )" |
| + " ,UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest2) \n" |
| + " ), UNNEST(MV_TO_ARRAY(dimMultivalEnumerated)) as ut(dim3_unnest3) " |
| + " WHERE dimZipf=27 AND (dim3_unnest1='Baz' OR dim3_unnest2='Hello') AND dim3_unnest3='World'"; |
| List<Query<?>> expectedQuerySqlCom = ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE5), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| NullHandling.sqlCompatible() ? equality("dimZipf", "27", ColumnType.LONG) : range( |
| "dimZipf", |
| ColumnType.LONG, |
| "27", |
| "27", |
| false, |
| false |
| ) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| or( |
| equality("j0.unnest", "Baz", ColumnType.STRING), |
| equality("_j0.unnest", "Hello", ColumnType.STRING) |
| ) // (j0.unnest = Baz || _j0.unnest = Hello) |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"dimMultivalEnumerated\"", |
| ColumnType.STRING |
| ), |
| equality("__j0.unnest", "World", ColumnType.STRING) |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "dimZipf", "j0.unnest")) |
| .build() |
| ); |
| testQuery( |
| sql, |
| QUERY_CONTEXT_UNNEST, expectedQuerySqlCom, |
| ImmutableList.of( |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Hello", "World"}, |
| new Object[]{"27", "Baz", "World", "World"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Baz", "World"}, |
| new Object[]{"27", "Baz", "Hello", "World"}, |
| new Object[]{"27", "Baz", "World", "World"}, |
| new Object[]{"27", "Hello", "Hello", "World"}, |
| new Object[]{"27", "World", "Hello", "World"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestThriceWithFiltersOnDimAndAllUnnestColumnsArrayColumnsOrFilters() |
| { |
| cannotVectorize(); |
| String sql = " SELECT arrayString, uln, udn, usn FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM arrays, UNNEST(arrayLongNulls) as ut(uln))" |
| + " ,UNNEST(arrayDoubleNulls) as ut(udn) \n" |
| + " ), UNNEST(arrayStringNulls) as ut(usn) " |
| + " WHERE arrayString = ARRAY['a','b'] AND (uln = 1 OR udn = 2.2) AND usn = 'a'"; |
| List<Query<?>> expectedQuerySc = ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"arrayLongNulls\"", |
| ColumnType.LONG_ARRAY |
| ), |
| null |
| ), |
| NullHandling.sqlCompatible() |
| ? equality("arrayString", ImmutableList.of("a", "b"), ColumnType.STRING_ARRAY) |
| : expressionFilter("(\"arrayString\" == array('a','b'))") |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"arrayDoubleNulls\"", |
| ColumnType.DOUBLE_ARRAY |
| ), |
| null |
| ), |
| or( |
| equality("j0.unnest", 1, ColumnType.LONG), |
| equality("_j0.unnest", 2.2, ColumnType.DOUBLE) |
| ) |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"arrayStringNulls\"", |
| ColumnType.STRING_ARRAY |
| ), |
| equality("__j0.unnest", "a", ColumnType.STRING) |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .virtualColumns( |
| expressionVirtualColumn("v0", "array('a','b')", ColumnType.STRING_ARRAY) |
| ) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "j0.unnest", "v0")) |
| .build() |
| ); |
| testQuery( |
| sql, |
| QUERY_CONTEXT_UNNEST, |
| expectedQuerySc, |
| ImmutableList.of( |
| new Object[]{ImmutableList.of("a", "b"), 1L, 1.1D, "a"}, |
| new Object[]{ImmutableList.of("a", "b"), 1L, 2.2D, "a"}, |
| new Object[]{ImmutableList.of("a", "b"), 1L, null, "a"}, |
| new Object[]{ImmutableList.of("a", "b"), null, 2.2D, "a"}, |
| new Object[]{ImmutableList.of("a", "b"), 3L, 2.2D, "a"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupBy() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) GROUP BY d3 ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{""}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) : |
| ImmutableList.of( |
| new Object[]{null}, |
| new Object[]{""}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByArrayColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT usn FROM druid.arrays, UNNEST(arrayStringNulls) as u (usn) GROUP BY usn ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayStringNulls\"", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByOrderBy() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) GROUP BY d3 ORDER BY d3 DESC ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setLimitSpec( |
| DefaultLimitSpec |
| .builder() |
| .orderBy(new OrderByColumnSpec( |
| "_d0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.LEXICOGRAPHIC |
| )) |
| .build() |
| ) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"d", 1L}, |
| new Object[]{"c", 1L}, |
| new Object[]{"b", 2L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"", 3L} |
| ) : |
| ImmutableList.of( |
| new Object[]{"d", 1L}, |
| new Object[]{"c", 1L}, |
| new Object[]{"b", 2L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"", 1L}, |
| new Object[]{null, 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByOrderByWithLimit() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) GROUP BY d3 ORDER BY d3 ASC LIMIT 4 ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| new TopNQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .dimension(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .metric(new DimensionTopNMetricSpec(null, StringComparators.LEXICOGRAPHIC)) |
| .threshold(4) |
| .aggregators(aggregators(new CountAggregatorFactory("a0"))) |
| .context(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"", 3L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"b", 2L}, |
| new Object[]{"c", 1L} |
| ) : |
| ImmutableList.of( |
| new Object[]{null, 2L}, |
| new Object[]{"", 1L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"b", 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByHaving() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) GROUP BY d3 HAVING COUNT(*) = 1", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setHavingSpec(new DimFilterHavingSpec(equality("a0", 1L, ColumnType.LONG), true)) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a", 1L}, |
| new Object[]{"c", 1L}, |
| new Object[]{"d", 1L} |
| ) : |
| ImmutableList.of( |
| new Object[]{"", 1L}, |
| new Object[]{"a", 1L}, |
| new Object[]{"c", 1L}, |
| new Object[]{"d", 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithLimit() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) LIMIT 3", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .limit(3) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestFirstQueryOnSelect() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM (select dim1, dim2, dim3 from druid.numfoo), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestVirtualWithColumns1() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT strings, m1 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (strings) where (strings='a' and (m1<=10 or strings='b'))", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of(Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| equality("j0.unnest", "a", ColumnType.STRING) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .filters(or( |
| NullHandling.sqlCompatible() |
| ? range("m1", ColumnType.LONG, null, "10", false, false) |
| : bound( |
| "m1", |
| null, |
| "10", |
| false, |
| false, |
| null, |
| StringComparators.NUMERIC |
| ), |
| equality("j0.unnest", "b", ColumnType.STRING) |
| )) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "m1")) |
| .build()), |
| ImmutableList.of(new Object[]{"a", 1.0f}) |
| ); |
| } |
| |
| @Test |
| public void testUnnestVirtualWithColumns2() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT strings, m1 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (strings) where (strings='a' or (m1=2 and strings='b'))", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of(Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) // (j0.unnest = a || (m1 = 2 && j0.unnest = b)) |
| .filters(or( |
| equality("j0.unnest", "a", ColumnType.STRING), |
| and( |
| NullHandling.sqlCompatible() |
| ? equality("m1", "2", ColumnType.FLOAT) |
| : equality("m1", "2", ColumnType.STRING), |
| equality("j0.unnest", "b", ColumnType.STRING) |
| ) |
| )) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "m1")) |
| .build()), |
| ImmutableList.of( |
| new Object[]{"a", 1.0f}, |
| new Object[]{"b", 2.0f} |
| ) |
| ); |
| } |
| @Test |
| public void testUnnestWithFilters() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM (select * from druid.numfoo where dim2='a'), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| equality("dim2", "a", ColumnType.STRING) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFiltersWithExpressionInInnerQuery() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT t,d3 FROM (select FLOOR(__time to hour) t, dim3 from druid.numfoo where dim2='a'), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| equality("dim2", "a", ColumnType.STRING) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn( |
| "v0", |
| "timestamp_floor(\"__time\",'PT1H',null,'UTC')", |
| ColumnType.LONG |
| )) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "v0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{946684800000L, "a"}, |
| new Object[]{946684800000L, "b"}, |
| new Object[]{978307200000L, ""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithInFiltersWithExpressionInInnerQuery() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT t,d3 FROM (select FLOOR(__time to hour) t, dim3 from druid.numfoo where dim2 IN ('a','b')), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| in("dim2", ImmutableList.of("a", "b")) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn("v0", |
| "timestamp_floor(\"__time\",'PT1H',null,'UTC')", |
| ColumnType.LONG)) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "v0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{946684800000L, "a"}, |
| new Object[]{946684800000L, "b"}, |
| new Object[]{978307200000L, ""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFiltersInnerLimit() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM (select dim2,dim3 from druid.numfoo where dim2='a' LIMIT 2), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new QueryDataSource( |
| newScanQueryBuilder() |
| .dataSource( |
| new TableDataSource(CalciteTests.DATASOURCE3) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .filters(equality("dim2", "a", ColumnType.STRING)) |
| .columns("dim3") |
| .limit(2) |
| .context(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| NullHandling.replaceWithDefault() ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFiltersInsideAndOutside() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM\n" |
| + " (select * from druid.numfoo where dim2='a') as t,\n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)\n" |
| + "WHERE t.dim1 <> 'foo'\n" |
| + "AND unnested.d3 <> 'b'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| and( |
| equality("dim2", "a", ColumnType.STRING), |
| not(equality("dim1", "foo", ColumnType.STRING)) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| not(equality("j0.unnest", "b", ColumnType.STRING)) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFiltersInsideAndOutside1() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM\n" |
| + " (select * from druid.numfoo where dim2='a'),\n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)\n" |
| + "WHERE dim1 <> 'foo'\n" |
| + "AND (unnested.d3 IN ('a', 'c') OR unnested.d3 LIKE '_')", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| and( |
| equality("dim2", "a", ColumnType.STRING), |
| not(equality("dim1", "foo", ColumnType.STRING)) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| or( |
| in("j0.unnest", ImmutableList.of("a", "c")), |
| new LikeDimFilter("j0.unnest", "_", null, null) |
| ) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFiltersOutside() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM\n" |
| + " druid.numfoo t,\n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)\n" |
| + "WHERE t.dim2='a'\n" |
| + "AND t.dim1 <> 'foo'\n" |
| + "AND (unnested.d3 IN ('a', 'c') OR unnested.d3 LIKE '_')", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| and( |
| equality("dim2", "a", ColumnType.STRING), |
| not(equality("dim1", "foo", ColumnType.STRING)) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| or( |
| in("j0.unnest", ImmutableList.of("a", "c")), |
| new LikeDimFilter("j0.unnest", "_", null, null) |
| ) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithInFilters() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM (select * from druid.numfoo where dim2 IN ('a','b','ab','abc')), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| in("dim2", ImmutableList.of("a", "b", "ab", "abc")) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{""}, |
| useDefault ? |
| new Object[]{""} : new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestVirtualWithColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT strings FROM druid.numfoo, UNNEST(ARRAY[dim4, dim5]) as unnested (strings)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"dim4\",\"dim5\")", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"aa"}, |
| new Object[]{"a"}, |
| new Object[]{"ab"}, |
| new Object[]{"a"}, |
| new Object[]{"ba"}, |
| new Object[]{"b"}, |
| new Object[]{"ad"}, |
| new Object[]{"b"}, |
| new Object[]{"aa"}, |
| new Object[]{"b"}, |
| new Object[]{"ab"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByOrderByOnVirtualColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d24, COUNT(*) FROM druid.numfoo, UNNEST(ARRAY[dim2, dim4]) AS unnested(d24) GROUP BY d24 ORDER BY d24 DESC ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "array(\"dim2\",\"dim4\")", |
| ColumnType.STRING_ARRAY |
| ), |
| null |
| ) |
| ) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setLimitSpec( |
| DefaultLimitSpec |
| .builder() |
| .orderBy(new OrderByColumnSpec( |
| "_d0", |
| OrderByColumnSpec.Direction.DESCENDING, |
| StringComparators.LEXICOGRAPHIC |
| )) |
| .build() |
| ) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"b", 3L}, |
| new Object[]{"abc", 1L}, |
| new Object[]{"a", 5L}, |
| new Object[]{"", 3L} |
| ) : |
| ImmutableList.of( |
| new Object[]{"b", 3L}, |
| new Object[]{"abc", 1L}, |
| new Object[]{"a", 5L}, |
| new Object[]{"", 1L}, |
| new Object[]{null, 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithJoinOnTheLeft() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 from (SELECT * from druid.numfoo JOIN (select dim2 as t from druid.numfoo where dim2 IN ('a','b','ab','abc')) ON dim2=t), UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| join( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| new QueryDataSource( |
| newScanQueryBuilder() |
| .dataSource( |
| new TableDataSource(CalciteTests.DATASOURCE3) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .filters(in("dim2", ImmutableList.of("a", "b", "ab", "abc"))) |
| .columns("dim2") |
| .context(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| "j0.", |
| "(\"dim2\" == \"j0.dim2\")", |
| JoinType.INNER |
| ), |
| expressionVirtualColumn("_j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("_j0.unnest")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithConstant() |
| { |
| // Since there is a constant on the right, |
| // Druid will plan this as a join query |
| // as there is nothing to correlate between left and right |
| cannotVectorize(); |
| testQuery( |
| "SELECT longs FROM druid.numfoo, UNNEST(ARRAY[1,2,3]) as unnested (longs)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| join( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| InlineDataSource.fromIterable( |
| ImmutableList.of( |
| new Object[]{1L}, |
| new Object[]{2L}, |
| new Object[]{3L} |
| ), |
| RowSignature.builder().add("EXPR$0", ColumnType.LONG).build() |
| ), |
| "j0.", |
| "1", |
| JoinType.INNER |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.EXPR$0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3}, |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3}, |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3}, |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3}, |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3}, |
| new Object[]{1}, |
| new Object[]{2}, |
| new Object[]{3} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSQLFunctionOnUnnestedColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT strlen(d3) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .virtualColumns(expressionVirtualColumn("v0", "strlen(\"j0.unnest\")", ColumnType.LONG)) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("v0")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{0}, |
| new Object[]{0}, |
| new Object[]{0} |
| ) : |
| ImmutableList.of( |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{1}, |
| new Object[]{0}, |
| new Object[]{null}, |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithINFiltersWithLeftRewrite() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3 IN ('a','b') and m1 < 10", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| range("m1", ColumnType.LONG, null, 10L, false, true) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("a", "b")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithINFiltersWithNoLeftRewrite() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d45 FROM druid.numfoo, UNNEST(ARRAY[dim4,dim5]) as unnested (d45) where d45 IN ('a','b')", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"dim4\",\"dim5\")", ColumnType.STRING_ARRAY), |
| in("j0.unnest", ImmutableSet.of("a", "b")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"a"}, |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithInvalidINFiltersOnUnnestedColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3 IN ('foo','bar')", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("foo", "bar")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of() |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithNotFiltersOnUnnestedColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3!='d' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| not(equality("j0.unnest", "d", ColumnType.STRING)) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSelectorFiltersOnSelectedColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3='b'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| equality("j0.unnest", "b", ColumnType.STRING) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSelectorFiltersOnVirtualColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d12 FROM druid.numfoo, UNNEST(ARRAY[m1,m2]) as unnested (d12) where d12=1", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"m1\",\"m2\")", ColumnType.FLOAT_ARRAY), |
| NullHandling.replaceWithDefault() |
| ? selector("j0.unnest", "1") |
| : equality("j0.unnest", 1.0, ColumnType.FLOAT) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1.0f}, |
| new Object[]{1.0f} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSelectorFiltersOnVirtualStringColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d45 FROM druid.numfoo, UNNEST(ARRAY[dim4,dim5]) as unnested (d45) where d45 IN ('a','ab')", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"dim4\",\"dim5\")", ColumnType.STRING_ARRAY), |
| in("j0.unnest", ImmutableSet.of("a", "ab")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"a"}, |
| new Object[]{"ab"}, |
| new Object[]{"a"}, |
| new Object[]{"ab"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleAndFiltersOnSelectedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3='b' and m1 < 10 and m2 < 10", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| and( |
| range("m1", ColumnType.LONG, null, 10L, false, true), |
| range("m2", ColumnType.LONG, null, 10L, false, true) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| equality("j0.unnest", "b", ColumnType.STRING) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnSelectedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3='b' or m1 < 2 ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .filters( |
| or( |
| equality("j0.unnest", "b", ColumnType.STRING), |
| range("m1", ColumnType.LONG, null, 2L, false, true) |
| ) |
| ) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleAndFiltersOnSelectedUnnestedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3 IN ('a','b') and d3 < 'e' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("a", "b")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnUnnestedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3='b' or d3='d' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("b", "d")) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnVariationsOfUnnestedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where strlen(d3) < 2 or d3='d' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| or( |
| expressionFilter("(strlen(\"j0.unnest\") < 2)"), |
| equality("j0.unnest", "d", ColumnType.STRING) |
| ) |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnSelectedNonUnnestedColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where m1 < 2 or m2 < 2 ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| or( |
| range("m1", ColumnType.LONG, null, 2L, false, true), |
| range("m2", ColumnType.LONG, null, 2L, false, true) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnSelectedVirtualColumns() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d45 FROM druid.numfoo, UNNEST(ARRAY[dim4,dim5]) as unnested (d45) where d45 IN ('a','aa') or m1 < 2 ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"dim4\",\"dim5\")", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .filters( |
| or( |
| in("j0.unnest", ImmutableSet.of("a", "aa")), |
| range("m1", ColumnType.LONG, null, 2L, false, true) |
| ) |
| ) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"aa"}, |
| new Object[]{"a"}, |
| new Object[]{"a"}, |
| new Object[]{"aa"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnUnnestedColumnsAndOnOriginalColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where d3='b' or dim3='d' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .filters( |
| or( |
| equality("j0.unnest", "b", ColumnType.STRING), |
| equality("dim3", "d", ColumnType.STRING) |
| ) |
| ) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithMultipleOrFiltersOnUnnestedColumnsAndOnOriginalColumnDiffOrdering() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT dim3, d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) where dim3='b' or d3='a' ", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .filters( |
| or( |
| equality("dim3", "b", ColumnType.STRING), |
| equality("j0.unnest", "a", ColumnType.STRING) |
| ) |
| ) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("dim3", "j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"a\",\"b\"]", "a"}, |
| new Object[]{"[\"a\",\"b\"]", "b"}, |
| new Object[]{"[\"b\",\"c\"]", "b"}, |
| new Object[]{"[\"b\",\"c\"]", "c"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithCountOnColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT count(*) d3 FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .context(QUERY_CONTEXT_UNNEST) |
| .aggregators(aggregators(new CountAggregatorFactory("a0"))) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{8L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByHavingSelector() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) GROUP BY d3 HAVING d3='b'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setDimFilter(equality("j0.unnest", "b", ColumnType.STRING)) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b", 2L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSumOnUnnestedVirtualColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select sum(c) col from druid.numfoo, unnest(ARRAY[m1,m2]) as u(c)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "array(\"m1\",\"m2\")", ColumnType.FLOAT_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .context(QUERY_CONTEXT_UNNEST) |
| .aggregators(aggregators(new DoubleSumAggregatorFactory("a0", "j0.unnest"))) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{42.0} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSumOnUnnestedColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select sum(c) col from druid.numfoo, unnest(mv_to_array(dim3)) as u(c)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(expressionVirtualColumn("v0", "CAST(\"j0.unnest\", 'DOUBLE')", ColumnType.DOUBLE)) |
| .context(QUERY_CONTEXT_UNNEST) |
| .aggregators(aggregators(new DoubleSumAggregatorFactory("a0", "v0"))) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{0.0} |
| ) : |
| ImmutableList.of( |
| new Object[]{null} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithSumOnUnnestedArrayColumn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select sum(c) col from druid.arrays, unnest(arrayDoubleNulls) as u(c)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newTimeseriesQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayDoubleNulls\"", ColumnType.DOUBLE_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .context(QUERY_CONTEXT_UNNEST) |
| .aggregators(aggregators(new DoubleSumAggregatorFactory("a0", "j0.unnest"))) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{4030.0999999999995} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByHavingWithWhereOnAggCol() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) WHERE d3 IN ('a','c') GROUP BY d3 HAVING COUNT(*) = 1", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("a", "c")) |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setHavingSpec(new DimFilterHavingSpec(equality("a0", 1L, ColumnType.LONG), true)) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a", 1L}, |
| new Object[]{"c", 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByHavingWithWhereOnUnnestCol() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT d3, COUNT(*) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) AS unnested(d3) WHERE d3 IN ('a','c') GROUP BY d3 HAVING d3='a'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| in("j0.unnest", ImmutableSet.of("a", "c")) |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "_d0", ColumnType.STRING)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setDimFilter(equality("j0.unnest", "a", ColumnType.STRING)) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a", 1L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByWithWhereOnUnnestArrayCol() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT uln, COUNT(*) FROM druid.arrays, UNNEST(arrayLongNulls) AS unnested(uln) WHERE uln IN (1, 2, 3) GROUP BY uln", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayLongNulls\"", ColumnType.LONG_ARRAY), |
| in("j0.unnest", ColumnType.LONG, ImmutableList.of(1L, 2L, 3L)) |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "d0", ColumnType.LONG)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1L, 5L}, |
| new Object[]{2L, 6L}, |
| new Object[]{3L, 6L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByHavingWithWhereOnUnnestArrayCol() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT uln, COUNT(*) FROM druid.arrays, UNNEST(arrayLongNulls) AS unnested(uln) WHERE uln IN (1, 2, 3) GROUP BY uln HAVING uln=1", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| expressionVirtualColumn("j0.unnest", "\"arrayLongNulls\"", ColumnType.LONG_ARRAY), |
| in("j0.unnest", ColumnType.LONG, ImmutableList.of(1L, 2L, 3L)) |
| )) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .setDimensions(new DefaultDimensionSpec("j0.unnest", "d0", ColumnType.LONG)) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("a0")) |
| .setDimFilter(equality("j0.unnest", 1L, ColumnType.LONG)) |
| .setContext(QUERY_CONTEXT_UNNEST) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1L, 5L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestVirtualWithColumnsAndNullIf() |
| { |
| cannotVectorize(); |
| testQuery( |
| "select c,m2 from druid.foo, unnest(ARRAY[\"m1\", \"m2\"]) as u(c) where NULLIF(c,m2) IS NULL", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| expressionVirtualColumn("j0.unnest", "array(\"m1\",\"m2\")", ColumnType.FLOAT_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .filters( |
| useDefault ? expressionFilter("(\"j0.unnest\" == \"m2\")") : |
| or( |
| expressionFilter("(\"j0.unnest\" == \"m2\")"), |
| and( |
| isNull("j0.unnest"), |
| NullHandling.sqlCompatible() |
| ? not(istrue(expressionFilter("(\"j0.unnest\" == \"m2\")"))) |
| : not(expressionFilter("(\"j0.unnest\" == \"m2\")")) |
| ) |
| )) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "m2")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1.0f, 1.0D}, |
| new Object[]{1.0f, 1.0D}, |
| new Object[]{2.0f, 2.0D}, |
| new Object[]{2.0f, 2.0D}, |
| new Object[]{3.0f, 3.0D}, |
| new Object[]{3.0f, 3.0D}, |
| new Object[]{4.0f, 4.0D}, |
| new Object[]{4.0f, 4.0D}, |
| new Object[]{5.0f, 5.0D}, |
| new Object[]{5.0f, 5.0D}, |
| new Object[]{6.0f, 6.0D}, |
| new Object[]{6.0f, 6.0D} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterOnly() |
| { |
| testQuery( |
| "select c from foo, unnest(MV_TO_ARRAY(dim3)) as u(c)" |
| + " where __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Intervals.of("2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterOnlyArrayColumn() |
| { |
| testQuery( |
| "select c from arrays, unnest(arrayStringNulls) as u(c)" |
| + " where __time >= TIMESTAMP '2023-01-02 00:00:00' and __time <= TIMESTAMP '2023-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| range("__time", ColumnType.LONG, 1672617600000L, 1672704600000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"arrayStringNulls\"", ColumnType.STRING_ARRAY), |
| null |
| )) |
| .intervals(querySegmentSpec(Intervals.of("2023-01-02T00:00:00.000Z/2023-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"d"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"}, |
| new Object[]{NullHandling.defaultStringValue()}, |
| new Object[]{"b"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterAndAnotherFilter() |
| { |
| testQuery( |
| "select c from foo, unnest(MV_TO_ARRAY(dim3)) as u(c) " |
| + " where m1=2 and __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| and( |
| useDefault ? equality("m1", 2, ColumnType.FLOAT) : |
| equality("m1", 2.0, ColumnType.FLOAT), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Intervals.of("2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterOrAnotherFilter() |
| { |
| testQuery( |
| "select c from foo, unnest(MV_TO_ARRAY(dim3)) as u(c) " |
| + " where m1=2 or __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| or( |
| useDefault ? equality("m1", 2, ColumnType.FLOAT) : |
| equality("m1", 2.0, ColumnType.FLOAT), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterOnlyNested() |
| { |
| testQuery( |
| "select c from foo CROSS JOIN UNNEST(ARRAY[m1,m2]) as un(d) CROSS JOIN unnest(MV_TO_ARRAY(dim3)) as u(c)" |
| + " where __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "array(\"m1\",\"m2\")", ColumnType.FLOAT_ARRAY), |
| null |
| ), |
| expressionVirtualColumn("_j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Intervals.of("2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("_j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterOnlyNestedAndNestedAgain() |
| { |
| testQuery( |
| "select c from foo CROSS JOIN UNNEST(ARRAY[m1,m2]) as un(d) CROSS JOIN UNNEST(ARRAY[dim1,dim2]) as ud(a) " |
| + " CROSS JOIN unnest(MV_TO_ARRAY(dim3)) as u(c)" |
| + " where __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| UnnestDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "array(\"m1\",\"m2\")", ColumnType.FLOAT_ARRAY), |
| null |
| ), |
| expressionVirtualColumn("_j0.unnest", "array(\"dim1\",\"dim2\")", ColumnType.STRING_ARRAY), |
| null |
| ), |
| expressionVirtualColumn("__j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Intervals.of("2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{"d"}, |
| new Object[]{"d"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterInsideSubquery() |
| { |
| testQuery( |
| "select d3 from (select * from foo, UNNEST(MV_TO_ARRAY(dim3)) as u(d3)" |
| + " where __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00' LIMIT 2) \n" |
| + " where m1 IN (1,2)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| new QueryDataSource( |
| newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Intervals.of( |
| "2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .columns("j0.unnest", "m1") |
| .limit(2) |
| .context(QUERY_CONTEXT_UNNEST) |
| .build() |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| NullHandling.sqlCompatible() |
| ? in("m1", ColumnType.FLOAT, ImmutableList.of(1.0f, 2.0f)) |
| : in("m1", ImmutableList.of("1", "2")) |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"b"}, |
| new Object[]{"c"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithTimeFilterInsideSubqueryArrayColumns() |
| { |
| testQuery( |
| "select uln from (select * from arrays, UNNEST(arrayLongNulls) as u(uln)" |
| + " where __time >= TIMESTAMP '2023-01-02 00:00:00' and __time <= TIMESTAMP '2023-01-03 00:10:00' LIMIT 2) \n" |
| + " where ARRAY_CONTAINS(arrayLongNulls, ARRAY[2])", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| new QueryDataSource( |
| newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| new TableDataSource(CalciteTests.ARRAYS_DATASOURCE), |
| range("__time", ColumnType.LONG, 1672617600000L, 1672704600000L, false, false) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"arrayLongNulls\"", ColumnType.LONG_ARRAY), |
| null |
| ) |
| ) |
| .intervals(querySegmentSpec(Intervals.of( |
| "2023-01-02T00:00:00.000Z/2023-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .columns("arrayLongNulls", "j0.unnest") |
| .limit(2) |
| .context(QUERY_CONTEXT_UNNEST) |
| .build() |
| ) |
| ) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .filters( |
| new ArrayContainsElementFilter("arrayLongNulls", ColumnType.LONG, 2L, null) |
| ) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{2L}, |
| new Object[]{3L} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithFilterAndUnnestNestedBackToBack() |
| { |
| testQuery( |
| "SELECT m1, dim3_unnest1, dim3_unnest2, dim3_unnest3 FROM \n" |
| + " ( SELECT * FROM \n" |
| + " ( SELECT * FROM foo, UNNEST(MV_TO_ARRAY(dim3)) as ut(dim3_unnest1) ), \n" |
| + " UNNEST(MV_TO_ARRAY(dim3)) as ut(dim3_unnest2) \n" |
| + " ), UNNEST(MV_TO_ARRAY(dim3)) as ut(dim3_unnest3) " |
| + " WHERE m1=2 AND (dim3_unnest1='a' OR dim3_unnest2='b') AND dim3_unnest3='c' " |
| + " AND __time >= TIMESTAMP '2000-01-02 00:00:00' and __time <= TIMESTAMP '2000-01-03 00:10:00'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| FilteredDataSource.create( |
| UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE1), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| NullHandling.sqlCompatible() ? |
| and( |
| equality("m1", 2.0f, ColumnType.FLOAT), |
| range("__time", ColumnType.LONG, 946771200000L, 946858200000L, false, false) |
| ) : |
| and( |
| selector("m1", "2", null), |
| bound( |
| "__time", |
| "946771200000", |
| "946858200000", |
| false, |
| false, |
| null, |
| StringComparators.NUMERIC |
| ) |
| ) |
| ), |
| expressionVirtualColumn( |
| "_j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| null |
| ), |
| or( |
| equality("j0.unnest", "a", ColumnType.STRING), |
| equality("_j0.unnest", "b", ColumnType.STRING) |
| ) |
| ), |
| expressionVirtualColumn( |
| "__j0.unnest", |
| "\"dim3\"", |
| ColumnType.STRING |
| ), |
| equality("__j0.unnest", "c", ColumnType.STRING) |
| ) |
| ) |
| .intervals(querySegmentSpec(Intervals.of("2000-01-02T00:00:00.000Z/2000-01-03T00:10:00.001Z"))) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .virtualColumns(expressionVirtualColumn("v0", "2.0", ColumnType.FLOAT)) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("__j0.unnest", "_j0.unnest", "j0.unnest", "v0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{2.0f, "b", "b", "c"}, |
| new Object[]{2.0f, "c", "b", "c"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithLookup() |
| { |
| testQuery( |
| "SELECT * FROM lookup.lookyloo, unnest(mv_to_array(v)) as u(d) where k='a'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| FilteredDataSource.create( |
| new LookupDataSource("lookyloo"), |
| equality("k", "a", ColumnType.STRING) |
| ), |
| expressionVirtualColumn("j0.unnest", "\"v\"", ColumnType.STRING), |
| null |
| )) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .virtualColumns(expressionVirtualColumn("v0", "'a'", ColumnType.STRING)) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("j0.unnest", "v", "v0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a", "xa", "xa"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestWithGroupByOnExpression() |
| { |
| cannotVectorize(); |
| testQuery( |
| "WITH X as \n" |
| + "(\n" |
| + "SELECT\n" |
| + "ARRAY[1,2,3] as allNums\n" |
| + "FROM foo\n" |
| + "GROUP BY 1\n" |
| + ")\n" |
| + "select * from X CROSS JOIN UNNEST(X.allNums) as ud(num)", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new QueryDataSource( |
| GroupByQuery.builder() |
| .setDataSource(CalciteTests.DATASOURCE1) |
| .setInterval(new MultipleIntervalSegmentSpec(ImmutableList.of( |
| Filtration.eternity()))) |
| .setVirtualColumns(expressionVirtualColumn( |
| "v0", |
| "array(1,2,3)", |
| ColumnType.LONG_ARRAY |
| )) |
| .setDimensions(dimensions( |
| new DefaultDimensionSpec( |
| "v0", |
| "d0", |
| ColumnType.LONG_ARRAY |
| ) |
| )) |
| .setGranularity(Granularities.ALL) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build()), |
| expressionVirtualColumn( |
| "j0.unnest", |
| "array(1,2,3)", |
| ColumnType.LONG_ARRAY |
| ), |
| null |
| ) |
| ) |
| .eternityInterval() |
| .columns("d0", "j0.unnest") |
| .legacy(false) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{ImmutableList.of(1L, 2L, 3L), 1}, |
| new Object[]{ImmutableList.of(1L, 2L, 3L), 2}, |
| new Object[]{ImmutableList.of(1L, 2L, 3L), 3} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testArrayToMvPostaggInline() |
| { |
| cannotVectorize(); |
| testQuery( |
| "WITH \"ext\" AS (\n" |
| + " SELECT\n" |
| + " CAST(\"c0\" AS TIMESTAMP) AS \"__time\",\n" |
| + " STRING_TO_ARRAY(\"c1\", '<#>') AS \"strings\",\n" |
| + " CAST(STRING_TO_ARRAY(\"c2\", '<#>') AS BIGINT ARRAY) AS \"longs\"\n" |
| + " FROM (\n" |
| + " VALUES\n" |
| + " (0, 'A<#>B', '1<#>2'),\n" |
| + " (0, 'C<#>D', '3<#>4')\n" |
| + " ) AS \"t\" (\"c0\", \"c1\", \"c2\")\n" |
| + ")\n" |
| + "SELECT\n" |
| + " ARRAY_TO_MV(\"strings\") AS \"strings\",\n" |
| + " ARRAY_TO_MV(\"longs\") AS \"longs\",\n" |
| + " COUNT(*) AS \"count\"\n" |
| + "FROM \"ext\"\n" |
| + "GROUP BY \"strings\", \"longs\"", |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource( |
| InlineDataSource.fromIterable( |
| Arrays.asList( |
| new Object[]{0L, "A<#>B", "1<#>2"}, |
| new Object[]{0L, "C<#>D", "3<#>4"} |
| ), |
| RowSignature.builder() |
| .add("c0", ColumnType.LONG) |
| .add("c1", ColumnType.STRING) |
| .add("c2", ColumnType.STRING) |
| .build() |
| ) |
| ) |
| .setQuerySegmentSpec(new MultipleIntervalSegmentSpec(ImmutableList.of(Intervals.ETERNITY))) |
| .setDimensions( |
| new DefaultDimensionSpec("v0", "d0", ColumnType.STRING_ARRAY), |
| new DefaultDimensionSpec("v1", "d1", ColumnType.LONG_ARRAY) |
| ) |
| .setVirtualColumns( |
| new ExpressionVirtualColumn( |
| "v0", |
| "string_to_array(\"c1\",'<#>')", |
| ColumnType.STRING_ARRAY, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionVirtualColumn( |
| "v1", |
| "CAST(string_to_array(\"c2\",'<#>'), 'ARRAY<LONG>')", |
| ColumnType.LONG_ARRAY, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .setAggregatorSpecs( |
| new CountAggregatorFactory("a0") |
| ) |
| .setPostAggregatorSpecs( |
| new ExpressionPostAggregator( |
| "p0", |
| "array_to_mv(\"d0\")", |
| null, |
| ColumnType.STRING, |
| TestExprMacroTable.INSTANCE |
| ), |
| new ExpressionPostAggregator( |
| "p1", |
| "array_to_mv(\"d1\")", |
| null, |
| ColumnType.STRING, |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .setGranularity(Granularities.ALL) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[\"A\",\"B\"]", "[\"1\",\"2\"]", 1L}, |
| new Object[]{"[\"C\",\"D\"]", "[\"3\",\"4\"]", 1L} |
| ), |
| RowSignature.builder() |
| .add("strings", ColumnType.STRING) |
| .add("longs", ColumnType.STRING) |
| .add("count", ColumnType.LONG) |
| .build() |
| ); |
| } |
| |
| @Test |
| public void testUnnestExtractionFn() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT substring(d3,1) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) WHERE substring(d3,1) <> 'b'", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| NullHandling.sqlCompatible() |
| ? expressionFilter("(substring(\"j0.unnest\", 0, -1) != 'b')") |
| : not(selector("j0.unnest", "b", new SubstringDimExtractionFn(0, null))) |
| )) |
| .virtualColumns(expressionVirtualColumn("v0", "substring(\"j0.unnest\", 0, -1)", ColumnType.STRING)) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("v0")) |
| .build() |
| ), |
| useDefault ? |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"c"}, |
| new Object[]{"d"}, |
| new Object[]{""}, |
| new Object[]{""}, |
| new Object[]{""} |
| ) : |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testUnnestExtractionFnNull() |
| { |
| cannotVectorize(); |
| testQuery( |
| "SELECT substring(d3,1) FROM druid.numfoo, UNNEST(MV_TO_ARRAY(dim3)) as unnested (d3) WHERE substring(d3,1) is not null", |
| QUERY_CONTEXT_UNNEST, |
| ImmutableList.of( |
| Druids.newScanQueryBuilder() |
| .dataSource(UnnestDataSource.create( |
| new TableDataSource(CalciteTests.DATASOURCE3), |
| expressionVirtualColumn("j0.unnest", "\"dim3\"", ColumnType.STRING), |
| NullHandling.sqlCompatible() |
| ? expressionFilter("notnull(substring(\"j0.unnest\", 0, -1))") |
| : not(selector("j0.unnest", null, new SubstringDimExtractionFn(0, null))) |
| )) |
| .virtualColumns(expressionVirtualColumn("v0", "substring(\"j0.unnest\", 0, -1)", ColumnType.STRING)) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .legacy(false) |
| .context(QUERY_CONTEXT_UNNEST) |
| .columns(ImmutableList.of("v0")) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"a"}, |
| new Object[]{"b"}, |
| new Object[]{"b"}, |
| new Object[]{"c"}, |
| new Object[]{"d"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testBooleanConstExprArray() |
| { |
| ExprEval exprEval = ExprEval.ofArray(ExpressionType.LONG_ARRAY, new Long[]{1L, 0L, null}); |
| testQuery( |
| "SELECT ARRAY[true, false, null] FROM druid.numfoo LIMIT 1", |
| ImmutableList.of( |
| newScanQueryBuilder() |
| .dataSource(CalciteTests.DATASOURCE3) |
| .intervals(querySegmentSpec(Filtration.eternity())) |
| .virtualColumns(new ExpressionVirtualColumn( |
| "v0", |
| "array(1,0,null)", |
| exprEval.toExpr(), |
| ColumnType.LONG_ARRAY |
| )) |
| .columns("v0") |
| .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST) |
| .limit(1) |
| .context(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{"[1,0,null]"} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testGroupByNestedArrayInline() |
| { |
| cannotVectorize(); |
| // msq does not support nested arrays currently |
| msqIncompatible(); |
| testQuery( |
| "SELECT c1, ARRAY_PREPEND('1', ARRAY_AGG(ARRAY[1,c2], 100000)) c5 \n" |
| + "FROM (VALUES (1,1),(2,2),(3,3)) t(c1,c2)\n" |
| + "GROUP BY 1 \n" |
| + "HAVING ARRAY_PREPEND('1', ARRAY_AGG(ARRAY[1,c2], 100000)) <> ARRAY_PREPEND('0', ARRAY_AGG(ARRAY[1,c2], 100000))", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of( |
| new Object[]{1L, 1L}, |
| new Object[]{2L, 2L}, |
| new Object[]{3L, 3L} |
| ), |
| RowSignature.builder() |
| .add("c1", ColumnType.LONG) |
| .add("c2", ColumnType.LONG) |
| .build() |
| ) |
| ) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns( |
| expressionVirtualColumn( |
| "v0", |
| "array(1,\"c2\")", |
| ColumnType.LONG_ARRAY |
| ) |
| ) |
| .setDimensions(new DefaultDimensionSpec("c1", "d0", ColumnType.LONG)) |
| .setAggregatorSpecs( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| HumanReadableBytes.valueOf(100000), |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .setPostAggregatorSpecs( |
| expressionPostAgg( |
| "p0", |
| "array_prepend('1',\"a0\")", |
| ColumnType.ofArray(ColumnType.LONG_ARRAY) |
| ) |
| ) |
| .setHavingSpec( |
| new DimFilterHavingSpec( |
| expressionFilter("(array_prepend('1',\"a0\") != array_prepend('0',\"a0\"))"), |
| true |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{1, ImmutableList.of(ImmutableList.of(1L), ImmutableList.of(1L, 1L))}, |
| new Object[]{2, ImmutableList.of(ImmutableList.of(1L), ImmutableList.of(1L, 2L))}, |
| new Object[]{3, ImmutableList.of(ImmutableList.of(1L), ImmutableList.of(1L, 3L))} |
| ) |
| ); |
| } |
| |
| @Test |
| public void testGroupByNestedArrayInlineCount() |
| { |
| cannotVectorize(); |
| // msq does not support nested arrays currently |
| msqIncompatible(); |
| testQuery( |
| "SELECT COUNT(*) c FROM (\n" |
| + "SELECT c1, ARRAY_PREPEND('1', ARRAY_AGG(ARRAY[1,c2], 100000)) c5 \n" |
| + "FROM (VALUES (1,1),(2,2),(3,3)) t(c1,c2)\n" |
| + "GROUP BY 1 \n" |
| + "HAVING ARRAY_PREPEND('1', ARRAY_AGG(ARRAY[1,c2], 100000)) <> ARRAY_PREPEND('0', ARRAY_AGG(ARRAY[1,c2], 100000))\n" |
| + ")", |
| QUERY_CONTEXT_NO_STRINGIFY_ARRAY, |
| ImmutableList.of( |
| GroupByQuery.builder() |
| .setDataSource( |
| GroupByQuery.builder() |
| .setDataSource( |
| InlineDataSource.fromIterable( |
| ImmutableList.of( |
| new Object[]{1L, 1L}, |
| new Object[]{2L, 2L}, |
| new Object[]{3L, 3L} |
| ), |
| RowSignature.builder() |
| .add("c1", ColumnType.LONG) |
| .add("c2", ColumnType.LONG) |
| .build() |
| ) |
| ) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setVirtualColumns( |
| expressionVirtualColumn( |
| "v0", |
| "array(1,\"c2\")", |
| ColumnType.LONG_ARRAY |
| ) |
| ) |
| .setDimensions(new DefaultDimensionSpec("c1", "d0", ColumnType.LONG)) |
| .setAggregatorSpecs( |
| new ExpressionLambdaAggregatorFactory( |
| "a0", |
| ImmutableSet.of("v0"), |
| "__acc", |
| "ARRAY<ARRAY<LONG>>[]", |
| "ARRAY<ARRAY<LONG>>[]", |
| true, |
| true, |
| false, |
| "array_append(\"__acc\", \"v0\")", |
| "array_concat(\"__acc\", \"a0\")", |
| null, |
| null, |
| HumanReadableBytes.valueOf(100000), |
| TestExprMacroTable.INSTANCE |
| ) |
| ) |
| .setHavingSpec( |
| new DimFilterHavingSpec( |
| expressionFilter( |
| "(array_prepend('1',\"a0\") != array_prepend('0',\"a0\"))"), |
| true |
| ) |
| ) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ) |
| .setInterval(querySegmentSpec(Filtration.eternity())) |
| .setGranularity(Granularities.ALL) |
| .setAggregatorSpecs(new CountAggregatorFactory("_a0")) |
| .setContext(QUERY_CONTEXT_DEFAULT) |
| .build() |
| ), |
| ImmutableList.of( |
| new Object[]{3L} |
| ) |
| ); |
| } |
| } |