mirror of https://github.com/apache/druid.git
Add query context param `forceExpressionVirtualColumns` to always use "expression"-type virtual columns in query plan (#12583)
SQL expressions such as those containing `MV_FILTER_ONLY` and `MV_FILTER_NONE` are planned as specialized virtual columns instead of the default `expression`-type virtual columns. This commit adds a new context parameter to force the `expression`-type virtual columns. Changes - Add query context param `forceExpressionVirtualColumns` - Use context param to determine if specialized virtual columns should be used or not - Moved some tests into `CalciteExplainQueryTest`
This commit is contained in:
parent
6bcb778eeb
commit
b6f8d7a1b3
|
@ -387,6 +387,15 @@ public class DruidExpression
|
|||
return virtualColumnCreator.create(name, outputType, expression.get(), macroTable);
|
||||
}
|
||||
|
||||
public VirtualColumn toExpressionVirtualColumn(
|
||||
final String name,
|
||||
final ColumnType outputType,
|
||||
final ExprMacroTable macroTable
|
||||
)
|
||||
{
|
||||
return DEFAULT_VIRTUAL_COLUMN_BUILDER.create(name, outputType, expression.get(), macroTable);
|
||||
}
|
||||
|
||||
public NodeType getType()
|
||||
{
|
||||
return nodeType;
|
||||
|
|
|
@ -34,6 +34,7 @@ public class PlannerConfig
|
|||
public static final String CTX_KEY_USE_APPROXIMATE_TOPN = "useApproximateTopN";
|
||||
public static final String CTX_COMPUTE_INNER_JOIN_COST_AS_FILTER = "computeInnerJoinCostAsFilter";
|
||||
public static final String CTX_KEY_USE_NATIVE_QUERY_EXPLAIN = "useNativeQueryExplain";
|
||||
public static final String CTX_KEY_FORCE_EXPRESSION_VIRTUAL_COLUMNS = "forceExpressionVirtualColumns";
|
||||
public static final String CTX_MAX_NUMERIC_IN_FILTERS = "maxNumericInFilters";
|
||||
public static final int NUM_FILTER_NOT_USED = -1;
|
||||
|
||||
|
@ -76,6 +77,9 @@ public class PlannerConfig
|
|||
@JsonProperty
|
||||
private boolean useNativeQueryExplain = false;
|
||||
|
||||
@JsonProperty
|
||||
private boolean forceExpressionVirtualColumns = false;
|
||||
|
||||
@JsonProperty
|
||||
private int maxNumericInFilters = NUM_FILTER_NOT_USED;
|
||||
|
||||
|
@ -156,6 +160,15 @@ public class PlannerConfig
|
|||
return useNativeQueryExplain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if special virtual columns should not be optimized and should
|
||||
* always be of type "expressions", false otherwise.
|
||||
*/
|
||||
public boolean isForceExpressionVirtualColumns()
|
||||
{
|
||||
return forceExpressionVirtualColumns;
|
||||
}
|
||||
|
||||
public PlannerConfig withOverrides(final QueryContext queryContext)
|
||||
{
|
||||
if (queryContext.isEmpty()) {
|
||||
|
@ -185,6 +198,10 @@ public class PlannerConfig
|
|||
CTX_KEY_USE_NATIVE_QUERY_EXPLAIN,
|
||||
isUseNativeQueryExplain()
|
||||
);
|
||||
newConfig.forceExpressionVirtualColumns = queryContext.getAsBoolean(
|
||||
CTX_KEY_FORCE_EXPRESSION_VIRTUAL_COLUMNS,
|
||||
isForceExpressionVirtualColumns()
|
||||
);
|
||||
final int systemConfigMaxNumericInFilters = getMaxNumericInFilters();
|
||||
final int queryContextMaxNumericInFilters = queryContext.getAsInt(
|
||||
CTX_MAX_NUMERIC_IN_FILTERS,
|
||||
|
@ -244,7 +261,8 @@ public class PlannerConfig
|
|||
serializeComplexValues == that.serializeComplexValues &&
|
||||
Objects.equals(metadataRefreshPeriod, that.metadataRefreshPeriod) &&
|
||||
Objects.equals(sqlTimeZone, that.sqlTimeZone) &&
|
||||
useNativeQueryExplain == that.useNativeQueryExplain;
|
||||
useNativeQueryExplain == that.useNativeQueryExplain &&
|
||||
forceExpressionVirtualColumns == that.forceExpressionVirtualColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -262,7 +280,8 @@ public class PlannerConfig
|
|||
metadataSegmentCacheEnable,
|
||||
metadataSegmentPollPeriod,
|
||||
serializeComplexValues,
|
||||
useNativeQueryExplain
|
||||
useNativeQueryExplain,
|
||||
forceExpressionVirtualColumns
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -163,7 +163,11 @@ public class DruidJoinQueryRel extends DruidRel<DruidJoinQueryRel>
|
|||
|
||||
final Pair<String, RowSignature> prefixSignaturePair = computeJoinRowSignature(leftSignature, rightSignature);
|
||||
|
||||
VirtualColumnRegistry virtualColumnRegistry = VirtualColumnRegistry.create(prefixSignaturePair.rhs, getPlannerContext().getExprMacroTable());
|
||||
VirtualColumnRegistry virtualColumnRegistry = VirtualColumnRegistry.create(
|
||||
prefixSignaturePair.rhs,
|
||||
getPlannerContext().getExprMacroTable(),
|
||||
getPlannerContext().getPlannerConfig().isForceExpressionVirtualColumns()
|
||||
);
|
||||
getPlannerContext().setJoinExpressionVirtualColumnRegistry(virtualColumnRegistry);
|
||||
|
||||
// Generate the condition for this join as a Druid expression.
|
||||
|
|
|
@ -167,7 +167,11 @@ public class DruidQuery
|
|||
{
|
||||
final RelDataType outputRowType = partialQuery.leafRel().getRowType();
|
||||
if (virtualColumnRegistry == null) {
|
||||
virtualColumnRegistry = VirtualColumnRegistry.create(sourceRowSignature, plannerContext.getExprMacroTable());
|
||||
virtualColumnRegistry = VirtualColumnRegistry.create(
|
||||
sourceRowSignature,
|
||||
plannerContext.getExprMacroTable(),
|
||||
plannerContext.getPlannerConfig().isForceExpressionVirtualColumns()
|
||||
);
|
||||
}
|
||||
|
||||
// Now the fun begins.
|
||||
|
@ -634,24 +638,25 @@ public class DruidQuery
|
|||
// implementation can be used instead of being composed as part of some expression tree in an expresson virtual
|
||||
// column
|
||||
Set<String> specialized = new HashSet<>();
|
||||
final boolean forceExpressionVirtualColumns =
|
||||
plannerContext.getPlannerConfig().isForceExpressionVirtualColumns();
|
||||
virtualColumnRegistry.visitAllSubExpressions((expression) -> {
|
||||
switch (expression.getType()) {
|
||||
case SPECIALIZED:
|
||||
// add the expression to the top level of the registry as a standalone virtual column
|
||||
final String name = virtualColumnRegistry.getOrCreateVirtualColumnForExpression(
|
||||
expression,
|
||||
expression.getDruidType()
|
||||
);
|
||||
specialized.add(name);
|
||||
// replace with an identifier expression of the new virtual column name
|
||||
return DruidExpression.ofColumn(expression.getDruidType(), name);
|
||||
default:
|
||||
// do nothing
|
||||
return expression;
|
||||
if (!forceExpressionVirtualColumns
|
||||
&& expression.getType() == DruidExpression.NodeType.SPECIALIZED) {
|
||||
// add the expression to the top level of the registry as a standalone virtual column
|
||||
final String name = virtualColumnRegistry.getOrCreateVirtualColumnForExpression(
|
||||
expression,
|
||||
expression.getDruidType()
|
||||
);
|
||||
specialized.add(name);
|
||||
// replace with an identifier expression of the new virtual column name
|
||||
return DruidExpression.ofColumn(expression.getDruidType(), name);
|
||||
} else {
|
||||
// do nothing
|
||||
return expression;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// we always want to add any virtual columns used by the query level DimFilter
|
||||
if (filter != null) {
|
||||
for (String columnName : filter.getRequiredColumns()) {
|
||||
|
|
|
@ -49,11 +49,13 @@ public class VirtualColumnRegistry
|
|||
private final Map<String, ExpressionAndTypeHint> virtualColumnsByName;
|
||||
private final String virtualColumnPrefix;
|
||||
private int virtualColumnCounter;
|
||||
private boolean forceExpressionVirtualColumns;
|
||||
|
||||
private VirtualColumnRegistry(
|
||||
RowSignature baseRowSignature,
|
||||
ExprMacroTable macroTable,
|
||||
String virtualColumnPrefix,
|
||||
boolean forceExpressionVirtualColumns,
|
||||
Map<ExpressionAndTypeHint, String> virtualColumnsByExpression,
|
||||
Map<String, ExpressionAndTypeHint> virtualColumnsByName
|
||||
)
|
||||
|
@ -63,14 +65,20 @@ public class VirtualColumnRegistry
|
|||
this.virtualColumnPrefix = virtualColumnPrefix;
|
||||
this.virtualColumnsByExpression = virtualColumnsByExpression;
|
||||
this.virtualColumnsByName = virtualColumnsByName;
|
||||
this.forceExpressionVirtualColumns = forceExpressionVirtualColumns;
|
||||
}
|
||||
|
||||
public static VirtualColumnRegistry create(final RowSignature rowSignature, final ExprMacroTable macroTable)
|
||||
public static VirtualColumnRegistry create(
|
||||
final RowSignature rowSignature,
|
||||
final ExprMacroTable macroTable,
|
||||
final boolean forceExpressionVirtualColumns
|
||||
)
|
||||
{
|
||||
return new VirtualColumnRegistry(
|
||||
rowSignature,
|
||||
macroTable,
|
||||
Calcites.findUnusedPrefixForDigits("v", rowSignature.getColumnNames()),
|
||||
forceExpressionVirtualColumns,
|
||||
new HashMap<>(),
|
||||
new HashMap<>()
|
||||
);
|
||||
|
@ -124,14 +132,23 @@ public class VirtualColumnRegistry
|
|||
}
|
||||
|
||||
/**
|
||||
* Get existing virtual column by column name
|
||||
* Get existing virtual column by column name.
|
||||
*
|
||||
* @return null if a virtual column for the given name does not exist.
|
||||
*/
|
||||
@Nullable
|
||||
public VirtualColumn getVirtualColumn(String virtualColumnName)
|
||||
{
|
||||
return Optional.ofNullable(virtualColumnsByName.get(virtualColumnName))
|
||||
.map(v -> v.getExpression().toVirtualColumn(virtualColumnName, v.getTypeHint(), macroTable))
|
||||
.orElse(null);
|
||||
ExpressionAndTypeHint registeredColumn = virtualColumnsByName.get(virtualColumnName);
|
||||
if (registeredColumn == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DruidExpression expression = registeredColumn.getExpression();
|
||||
ColumnType columnType = registeredColumn.getTypeHint();
|
||||
return forceExpressionVirtualColumns
|
||||
? expression.toExpressionVirtualColumn(virtualColumnName, columnType, macroTable)
|
||||
: expression.toVirtualColumn(virtualColumnName, columnType, macroTable);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -223,7 +240,7 @@ public class VirtualColumnRegistry
|
|||
)
|
||||
{
|
||||
final String name = getOrCreateVirtualColumnForExpression(expression, valueType);
|
||||
return virtualColumnsByName.get(name).expression.toVirtualColumn(name, valueType, macroTable);
|
||||
return getVirtualColumn(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
* 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 org.apache.druid.sql.calcite.planner.PlannerConfig;
|
||||
import org.apache.druid.sql.calcite.util.CalciteTests;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Unit tests for EXPLAIN PLAN queries.
|
||||
*/
|
||||
public class CalciteExplainQueryTest extends BaseCalciteQueryTest
|
||||
{
|
||||
@Test
|
||||
public void testExplainCountStarOnView() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT COUNT(*) FROM view.aview WHERE dim1_firstchar <> 'z'";
|
||||
final String legacyExplanation = "DruidQueryRel(query=[{\"queryType\":\"timeseries\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":\"selector\",\"dimension\":\"dim2\",\"value\":\"a\"},{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"z\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}}]},\"granularity\":{\"type\":\"all\"},\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{a0:LONG}])\n";
|
||||
final String explanation = "[{"
|
||||
+ "\"query\":{\"queryType\":\"timeseries\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":\"selector\",\"dimension\":\"dim2\",\"value\":\"a\"},{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"z\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}}]},"
|
||||
+ "\"granularity\":{\"type\":\"all\"},"
|
||||
+ "\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}},"
|
||||
+ "\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"aview\",\"type\":\"VIEW\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{legacyExplanation, resources}
|
||||
)
|
||||
);
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainInformationSchemaColumns() throws Exception
|
||||
{
|
||||
final String explanation =
|
||||
"BindableProject(COLUMN_NAME=[$3], DATA_TYPE=[$7])\n"
|
||||
+ " BindableFilter(condition=[AND(=($1, 'druid'), =($2, 'foo'))])\n"
|
||||
+ " BindableTableScan(table=[[INFORMATION_SCHEMA, COLUMNS]])\n";
|
||||
|
||||
final String resources = "[]";
|
||||
|
||||
testQuery(
|
||||
"EXPLAIN PLAN FOR\n"
|
||||
+ "SELECT COLUMN_NAME, DATA_TYPE\n"
|
||||
+ "FROM INFORMATION_SCHEMA.COLUMNS\n"
|
||||
+ "WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = 'foo'",
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainExactCountDistinctOfSemiJoinResult() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT COUNT(*)\n"
|
||||
+ "FROM (\n"
|
||||
+ " SELECT DISTINCT dim2\n"
|
||||
+ " FROM druid.foo\n"
|
||||
+ " WHERE SUBSTRING(dim2, 1, 1) IN (\n"
|
||||
+ " SELECT SUBSTRING(dim1, 1, 1) FROM druid.foo WHERE dim1 IS NOT NULL\n"
|
||||
+ " )\n"
|
||||
+ ")";
|
||||
final String legacyExplanation =
|
||||
"DruidOuterQueryRel(query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"query\",\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"__subquery__\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"list\",\"granularity\":{\"type\":\"all\"}}},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[],\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{a0:LONG}])\n"
|
||||
+ " DruidJoinQueryRel(condition=[=(SUBSTRING($3, 1, 1), $8)], joinType=[inner], query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"__join__\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"default\",\"dimension\":\"dim2\",\"outputName\":\"d0\",\"outputType\":\"STRING\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{d0:STRING}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":null}},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"extraction\",\"dimension\":\"dim1\",\"outputName\":\"d0\",\"outputType\":\"STRING\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{d0:STRING}])\n";
|
||||
final String explanation = "["
|
||||
+ "{\"query\":{\"queryType\":\"groupBy\","
|
||||
+ "\"dataSource\":{\"type\":\"query\",\"query\":{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"join\",\"left\":{\"type\":\"table\",\"name\":\"foo\"},\"right\":{\"type\":\"query\",\"query\":{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":null}},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"extraction\",\"dimension\":\"dim1\",\"outputName\":\"d0\",\"outputType\":\"STRING\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}},\"rightPrefix\":\"j0.\",\"condition\":\"(substring(\\\"dim2\\\", 0, 1) == \\\"j0.d0\\\")\",\"joinType\":\"INNER\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"default\",\"dimension\":\"dim2\",\"outputName\":\"d0\",\"outputType\":\"STRING\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"granularity\":{\"type\":\"all\"},"
|
||||
+ "\"dimensions\":[],"
|
||||
+ "\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],"
|
||||
+ "\"limitSpec\":{\"type\":\"NoopLimitSpec\"},"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}},"
|
||||
+ "\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{legacyExplanation, resources})
|
||||
);
|
||||
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanation, resources})
|
||||
);
|
||||
}
|
||||
|
||||
// This testcase has been added here and not in CalciteSelectQueryTests since this checks if the overrides are working
|
||||
// properly when displaying the output of "EXPLAIN PLAN FOR ..." queries
|
||||
@Test
|
||||
public void testExplainSelectStarWithOverrides() throws Exception
|
||||
{
|
||||
Map<String, Object> useRegularExplainContext = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
useRegularExplainContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, false);
|
||||
|
||||
Map<String, Object> useNativeQueryExplain = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
useNativeQueryExplain.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, true);
|
||||
|
||||
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
String legacyExplanation = "DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n";
|
||||
String legacyExplanationWithContext = "DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":false},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n";
|
||||
String explanation = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]"
|
||||
+ "}]";
|
||||
|
||||
String explanationWithContext = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":true,\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]"
|
||||
+ "}]";
|
||||
String sql = "EXPLAIN PLAN FOR SELECT * FROM druid.foo";
|
||||
String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
// Test when default config and no overrides
|
||||
testQuery(sql, ImmutableList.of(), ImmutableList.of(new Object[]{legacyExplanation, resources}));
|
||||
|
||||
// Test when default config and useNativeQueryExplain is overridden in the context
|
||||
testQuery(
|
||||
sql,
|
||||
useNativeQueryExplain,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanationWithContext, resources})
|
||||
);
|
||||
|
||||
// Test when useNativeQueryExplain enabled by default and no overrides
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
sql,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanation, resources})
|
||||
);
|
||||
|
||||
// Test when useNativeQueryExplain enabled by default but is overriden in the context
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
useRegularExplainContext,
|
||||
sql,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{legacyExplanationWithContext, resources})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainMultipleTopLevelUnionAllQueries() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT dim1 FROM druid.foo\n"
|
||||
+ "UNION ALL (SELECT dim1 FROM druid.foo WHERE dim1 = '42'\n"
|
||||
+ "UNION ALL SELECT dim1 FROM druid.foo WHERE dim1 = '44')";
|
||||
final String legacyExplanation = "DruidUnionRel(limit=[-1])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n"
|
||||
+ " DruidUnionRel(limit=[-1])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"42\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"44\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n";
|
||||
final String explanation = "["
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "},"
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"42\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "},"
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"44\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{legacyExplanation, resources}
|
||||
)
|
||||
);
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainSelectMvfilterExpressions() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String explainSql = "EXPLAIN PLAN FOR SELECT"
|
||||
+ " MV_FILTER_ONLY(\"dim1\", ARRAY['true', 'false']),"
|
||||
+ " MV_FILTER_NONE(\"dim1\", ARRAY['true', 'false'])"
|
||||
+ " FROM druid.foo";
|
||||
|
||||
// Test plan as default expressions
|
||||
final Map<String, Object> defaultExprContext = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
defaultExprContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, true);
|
||||
defaultExprContext.put(PlannerConfig.CTX_KEY_FORCE_EXPRESSION_VIRTUAL_COLUMNS, true);
|
||||
|
||||
final String expectedPlanWithDefaultExpressions = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"virtualColumns\":["
|
||||
+ "{\"type\":\"expression\",\"name\":\"v0\",\"expression\":\"filter((x) -> array_contains(array('true','false'), x), \\\"dim1\\\")\",\"outputType\":\"STRING\"},"
|
||||
+ "{\"type\":\"expression\",\"name\":\"v1\",\"expression\":\"filter((x) -> !array_contains(array('true','false'), x), \\\"dim1\\\")\",\"outputType\":\"STRING\"}"
|
||||
+ "],"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"v0\",\"v1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"forceExpressionVirtualColumns\":true,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":true,\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"v0\",\"type\":\"STRING\"},{\"name\":\"v1\",\"type\":\"STRING\"}]"
|
||||
+ "}]";
|
||||
final String expectedResources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
testQuery(
|
||||
explainSql,
|
||||
defaultExprContext,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{expectedPlanWithDefaultExpressions, expectedResources})
|
||||
);
|
||||
|
||||
// Test plan as mv-filtered virtual columns
|
||||
final String expectedPlanWithMvfiltered = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"virtualColumns\":["
|
||||
+ "{\"type\":\"mv-filtered\",\"name\":\"v0\",\"delegate\":{\"type\":\"default\",\"dimension\":\"dim1\",\"outputName\":\"dim1\",\"outputType\":\"STRING\"},\"values\":[\"true\",\"false\"],\"isAllowList\":true},"
|
||||
+ "{\"type\":\"mv-filtered\",\"name\":\"v1\",\"delegate\":{\"type\":\"default\",\"dimension\":\"dim1\",\"outputName\":\"dim1\",\"outputType\":\"STRING\"},\"values\":[\"true\",\"false\"],\"isAllowList\":false}"
|
||||
+ "],"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"v0\",\"v1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":true,\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"v0\",\"type\":\"STRING\"},{\"name\":\"v1\",\"type\":\"STRING\"}]"
|
||||
+ "}]";
|
||||
|
||||
final Map<String, Object> mvFilteredContext = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
mvFilteredContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, true);
|
||||
|
||||
testQuery(
|
||||
explainSql,
|
||||
mvFilteredContext,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{expectedPlanWithMvfiltered, expectedResources})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainSelectTimestampExpression() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String explainSql = "EXPLAIN PLAN FOR SELECT"
|
||||
+ " TIME_PARSE(dim1)"
|
||||
+ " FROM druid.foo";
|
||||
|
||||
final Map<String, Object> queryContext = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
queryContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, true);
|
||||
|
||||
final String expectedPlan = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"virtualColumns\":["
|
||||
+ "{\"type\":\"expression\",\"name\":\"v0\",\"expression\":\"timestamp_parse(\\\"dim1\\\",null,'UTC')\",\"outputType\":\"LONG\"}"
|
||||
+ "],"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"v0\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":true,\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"v0\",\"type\":\"LONG\"}]"
|
||||
+ "}]";
|
||||
final String expectedResources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
// Verify the query plan
|
||||
testQuery(
|
||||
explainSql,
|
||||
queryContext,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{expectedPlan, expectedResources})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -353,28 +353,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainInformationSchemaColumns() throws Exception
|
||||
{
|
||||
final String explanation =
|
||||
"BindableProject(COLUMN_NAME=[$3], DATA_TYPE=[$7])\n"
|
||||
+ " BindableFilter(condition=[AND(=($1, 'druid'), =($2, 'foo'))])\n"
|
||||
+ " BindableTableScan(table=[[INFORMATION_SCHEMA, COLUMNS]])\n";
|
||||
|
||||
final String resources = "[]";
|
||||
|
||||
testQuery(
|
||||
"EXPLAIN PLAN FOR\n"
|
||||
+ "SELECT COLUMN_NAME, DATA_TYPE\n"
|
||||
+ "FROM INFORMATION_SCHEMA.COLUMNS\n"
|
||||
+ "WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = 'foo'",
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAggregatorsOnInformationSchemaColumns() throws Exception
|
||||
{
|
||||
|
@ -4361,44 +4339,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainCountStarOnView() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT COUNT(*) FROM view.aview WHERE dim1_firstchar <> 'z'";
|
||||
final String legacyExplanation = "DruidQueryRel(query=[{\"queryType\":\"timeseries\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":\"selector\",\"dimension\":\"dim2\",\"value\":\"a\"},{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"z\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}}]},\"granularity\":{\"type\":\"all\"},\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{a0:LONG}])\n";
|
||||
final String explanation = "[{"
|
||||
+ "\"query\":{\"queryType\":\"timeseries\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"filter\":{\"type\":\"and\",\"fields\":[{\"type\":\"selector\",\"dimension\":\"dim2\",\"value\":\"a\"},{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"z\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}}]},"
|
||||
+ "\"granularity\":{\"type\":\"all\"},"
|
||||
+ "\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}},"
|
||||
+ "\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"aview\",\"type\":\"VIEW\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{legacyExplanation, resources}
|
||||
)
|
||||
);
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountStarWithLikeFilter() throws Exception
|
||||
{
|
||||
|
@ -7193,173 +7133,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainExactCountDistinctOfSemiJoinResult() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT COUNT(*)\n"
|
||||
+ "FROM (\n"
|
||||
+ " SELECT DISTINCT dim2\n"
|
||||
+ " FROM druid.foo\n"
|
||||
+ " WHERE SUBSTRING(dim2, 1, 1) IN (\n"
|
||||
+ " SELECT SUBSTRING(dim1, 1, 1) FROM druid.foo WHERE dim1 IS NOT NULL\n"
|
||||
+ " )\n"
|
||||
+ ")";
|
||||
final String legacyExplanation =
|
||||
"DruidOuterQueryRel(query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"query\",\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"__subquery__\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"list\",\"granularity\":{\"type\":\"all\"}}},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[],\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{a0:LONG}])\n"
|
||||
+ " DruidJoinQueryRel(condition=[=(SUBSTRING($3, 1, 1), $8)], joinType=[inner], query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"__join__\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"default\",\"dimension\":\"dim2\",\"outputName\":\"d0\",\"outputType\":\"STRING\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{d0:STRING}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":null}},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"extraction\",\"dimension\":\"dim1\",\"outputName\":\"d0\",\"outputType\":\"STRING\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}], signature=[{d0:STRING}])\n";
|
||||
final String explanation = "["
|
||||
+ "{\"query\":{\"queryType\":\"groupBy\","
|
||||
+ "\"dataSource\":{\"type\":\"query\",\"query\":{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"join\",\"left\":{\"type\":\"table\",\"name\":\"foo\"},\"right\":{\"type\":\"query\",\"query\":{\"queryType\":\"groupBy\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"filter\":{\"type\":\"not\",\"field\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":null}},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"extraction\",\"dimension\":\"dim1\",\"outputName\":\"d0\",\"outputType\":\"STRING\",\"extractionFn\":{\"type\":\"substring\",\"index\":0,\"length\":1}}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}},\"rightPrefix\":\"j0.\",\"condition\":\"(substring(\\\"dim2\\\", 0, 1) == \\\"j0.d0\\\")\",\"joinType\":\"INNER\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"granularity\":{\"type\":\"all\"},\"dimensions\":[{\"type\":\"default\",\"dimension\":\"dim2\",\"outputName\":\"d0\",\"outputType\":\"STRING\"}],\"limitSpec\":{\"type\":\"NoopLimitSpec\"},\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}}},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"granularity\":{\"type\":\"all\"},"
|
||||
+ "\"dimensions\":[],"
|
||||
+ "\"aggregations\":[{\"type\":\"count\",\"name\":\"a0\"}],"
|
||||
+ "\"limitSpec\":{\"type\":\"NoopLimitSpec\"},"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"}},"
|
||||
+ "\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{legacyExplanation, resources})
|
||||
);
|
||||
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanation, resources})
|
||||
);
|
||||
}
|
||||
|
||||
// This testcase has been added here and not in CalciteSelectQueryTests since this checks if the overrides are working
|
||||
// properly when displaying the output of "EXPLAIN PLAN FOR ..." queries
|
||||
@Test
|
||||
public void testExplainSelectStarWithOverrides() throws Exception
|
||||
{
|
||||
Map<String, Object> useRegularExplainContext = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
useRegularExplainContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, false);
|
||||
|
||||
Map<String, Object> useNativeQueryExplain = new HashMap<>(QUERY_CONTEXT_DEFAULT);
|
||||
useNativeQueryExplain.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN, true);
|
||||
|
||||
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
String legacyExplanation = "DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n";
|
||||
String legacyExplanationWithContext = "DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":false},\"granularity\":{\"type\":\"all\"}}], signature=[{__time:LONG, cnt:LONG, dim1:STRING, dim2:STRING, dim3:STRING, m1:FLOAT, m2:DOUBLE, unique_dim1:COMPLEX<hyperUnique>}])\n";
|
||||
String explanation = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]"
|
||||
+ "}]";
|
||||
|
||||
String explanationWithContext = "[{"
|
||||
+ "\"query\":{\"queryType\":\"scan\","
|
||||
+ "\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},"
|
||||
+ "\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
|
||||
+ "\"resultFormat\":\"compactedList\","
|
||||
+ "\"columns\":[\"__time\",\"cnt\",\"dim1\",\"dim2\",\"dim3\",\"m1\",\"m2\",\"unique_dim1\"],"
|
||||
+ "\"legacy\":false,"
|
||||
+ "\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"useNativeQueryExplain\":true,\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
|
||||
+ "\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]"
|
||||
+ "}]";
|
||||
String sql = "EXPLAIN PLAN FOR SELECT * FROM druid.foo";
|
||||
String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
// Test when default config and no overrides
|
||||
testQuery(sql, ImmutableList.of(), ImmutableList.of(new Object[]{legacyExplanation, resources}));
|
||||
|
||||
// Test when default config and useNativeQueryExplain is overridden in the context
|
||||
testQuery(
|
||||
sql,
|
||||
useNativeQueryExplain,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanationWithContext, resources})
|
||||
);
|
||||
|
||||
// Test when useNativeQueryExplain enabled by default and no overrides
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
sql,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{explanation, resources})
|
||||
);
|
||||
|
||||
// Test when useNativeQueryExplain enabled by default but is overriden in the context
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
useRegularExplainContext,
|
||||
sql,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(new Object[]{legacyExplanationWithContext, resources})
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplainMultipleTopLevelUnionAllQueries() throws Exception
|
||||
{
|
||||
// Skip vectorization since otherwise the "context" will change for each subtest.
|
||||
skipVectorize();
|
||||
|
||||
final String query = "EXPLAIN PLAN FOR SELECT dim1 FROM druid.foo\n"
|
||||
+ "UNION ALL (SELECT dim1 FROM druid.foo WHERE dim1 = '42'\n"
|
||||
+ "UNION ALL SELECT dim1 FROM druid.foo WHERE dim1 = '44')";
|
||||
final String legacyExplanation = "DruidUnionRel(limit=[-1])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n"
|
||||
+ " DruidUnionRel(limit=[-1])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"42\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n"
|
||||
+ " DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"44\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}}], signature=[{dim1:STRING}])\n";
|
||||
final String explanation = "["
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "},"
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"42\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "},"
|
||||
+ "{"
|
||||
+ "\"query\":{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"table\",\"name\":\"foo\"},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"filter\":{\"type\":\"selector\",\"dimension\":\"dim1\",\"value\":\"44\"},\"columns\":[\"dim1\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
|
||||
+ "\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
|
||||
+ "}]";
|
||||
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
|
||||
|
||||
testQuery(
|
||||
query,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{legacyExplanation, resources}
|
||||
)
|
||||
);
|
||||
testQuery(
|
||||
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
|
||||
query,
|
||||
CalciteTests.REGULAR_USER_AUTH_RESULT,
|
||||
ImmutableList.of(),
|
||||
ImmutableList.of(
|
||||
new Object[]{explanation, resources}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExactCountDistinctUsingSubqueryWithWherePushDown() throws Exception
|
||||
{
|
||||
|
|
|
@ -317,7 +317,7 @@ class ExpressionTestHelper
|
|||
)
|
||||
{
|
||||
final RexNode rexNode = rexBuilder.makeCall(op, exprs);
|
||||
final VirtualColumnRegistry virtualColumnRegistry = VirtualColumnRegistry.create(rowSignature, TestExprMacroTable.INSTANCE);
|
||||
final VirtualColumnRegistry virtualColumnRegistry = VirtualColumnRegistry.create(rowSignature, TestExprMacroTable.INSTANCE, false);
|
||||
|
||||
final DimFilter filter = Expressions.toFilter(PLANNER_CONTEXT, rowSignature, virtualColumnRegistry, rexNode);
|
||||
Assert.assertEquals("Filter for: " + rexNode, expectedFilter, filter);
|
||||
|
|
|
@ -62,7 +62,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
selectorFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, dataSource, selectorFilter, Intervals.ETERNITY);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
filterWithInterval,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, dataSource, selectorFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
filterWithInterval,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, dataSource, selectorFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
otherFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, expectedDataSource, otherFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
otherFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, expectedDataSource, otherFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
otherFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, expectedDataSource, otherFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
otherFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, expectedDataSource, otherFilter, Intervals.utc(100, 200));
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ public class DruidQueryTest
|
|||
Pair<DataSource, Filtration> pair = DruidQuery.getFiltration(
|
||||
dataSource,
|
||||
queryFilter,
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE)
|
||||
VirtualColumnRegistry.create(RowSignature.empty(), TestExprMacroTable.INSTANCE, false)
|
||||
);
|
||||
verify(pair, expectedDataSource, otherFilter, Intervals.utc(150, 200));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue