This is an automated email from the ASF dual-hosted git repository.
cheddar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 65c3b4d31aa Support join in decoupled mode (#15957)
65c3b4d31aa is described below
commit 65c3b4d31aa4aba775fc78d5dbd3facbbc7c8776
Author: Zoltan Haindrich <[email protected]>
AuthorDate: Wed Mar 6 02:10:13 2024 +0100
Support join in decoupled mode (#15957)
* plan join(s) in decoupled mode
* configure DecoupledPlanningCalciteJoinQueryTest
the test has 593 cases; however there are quite a few parameterized
from the 107 methods annotated with @Test - 42 is not yet working
* replace the isRoot hack in DruidQueryGenerator with a logic that instead
looks ahead for the next node; and doesn't let the previous node do the Project
- this makes it plan more likely than the existing planner
---
sql/pom.xml | 10 ++
.../druid/sql/calcite/planner/QueryHandler.java | 3 +-
.../planner/querygen/DruidQueryGenerator.java | 137 ++++++++++++---------
...utDescProducer.java => SourceDescProducer.java} | 20 ++-
.../druid/sql/calcite/rel/DruidJoinQueryRel.java | 96 ++++++++++-----
.../druid/sql/calcite/rel/logical/DruidJoin.java | 79 ++++++++++++
.../sql/calcite/rel/logical/DruidTableScan.java | 8 +-
.../druid/sql/calcite/rel/logical/DruidUnion.java | 20 +--
.../druid/sql/calcite/rel/logical/DruidValues.java | 8 +-
.../druid/sql/calcite/rule/DruidJoinRule.java | 57 ++++++---
.../sql/calcite/rule/logical/DruidJoinRule.java | 76 ++++++++++++
.../calcite/rule/logical/DruidLogicalRules.java | 7 ++
.../druid/sql/calcite/BaseCalciteQueryTest.java | 22 ++--
.../druid/sql/calcite/CalciteJoinQueryTest.java | 71 ++++++++++-
.../apache/druid/sql/calcite/CalciteQueryTest.java | 26 ++--
... => DecoupledPlanningCalciteJoinQueryTest.java} | 19 ++-
.../calcite/DecoupledPlanningCalciteQueryTest.java | 2 +-
.../DecoupledPlanningCalciteUnionQueryTest.java | 2 +-
.../druid/sql/calcite/DecoupledTestConfig.java | 40 +++++-
.../apache/druid/sql/calcite/NotYetSupported.java | 58 ++++++++-
.../druid/sql/calcite/SqlTestFrameworkConfig.java | 9 +-
.../apache/druid/sql/http/ResultFormatTest.java | 28 ++---
22 files changed, 610 insertions(+), 188 deletions(-)
diff --git a/sql/pom.xml b/sql/pom.xml
index 7b062b11834..1941df02be5 100644
--- a/sql/pom.xml
+++ b/sql/pom.xml
@@ -207,6 +207,16 @@
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
index 3e7f58ec067..dfbded5281b 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
@@ -71,6 +71,7 @@ import org.apache.druid.sql.calcite.rel.DruidQuery;
import org.apache.druid.sql.calcite.rel.DruidRel;
import org.apache.druid.sql.calcite.rel.DruidUnionRel;
import org.apache.druid.sql.calcite.rel.logical.DruidLogicalConvention;
+import org.apache.druid.sql.calcite.rel.logical.DruidLogicalNode;
import org.apache.druid.sql.calcite.run.EngineFeature;
import org.apache.druid.sql.calcite.run.QueryMaker;
import org.apache.druid.sql.calcite.table.DruidTable;
@@ -561,7 +562,7 @@ public abstract class QueryHandler extends
SqlStatementHandler.BaseStatementHand
newRoot
);
- DruidQueryGenerator generator = new DruidQueryGenerator(plannerContext,
newRoot, rexBuilder);
+ DruidQueryGenerator generator = new DruidQueryGenerator(plannerContext,
(DruidLogicalNode) newRoot, rexBuilder);
DruidQuery baseQuery = generator.buildQuery();
try {
log.info(
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/DruidQueryGenerator.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/DruidQueryGenerator.java
index d10c9d3a65b..0047cc0ad4d 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/DruidQueryGenerator.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/DruidQueryGenerator.java
@@ -31,25 +31,28 @@ import org.apache.druid.error.DruidException;
import org.apache.druid.query.QueryDataSource;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import
org.apache.druid.sql.calcite.planner.querygen.DruidQueryGenerator.PDQVertexFactory.PDQVertex;
-import
org.apache.druid.sql.calcite.planner.querygen.InputDescProducer.InputDesc;
+import
org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer.SourceDesc;
import org.apache.druid.sql.calcite.rel.DruidQuery;
import org.apache.druid.sql.calcite.rel.PartialDruidQuery;
import org.apache.druid.sql.calcite.rel.PartialDruidQuery.Stage;
+import org.apache.druid.sql.calcite.rel.logical.DruidAggregate;
+import org.apache.druid.sql.calcite.rel.logical.DruidLogicalNode;
+import org.apache.druid.sql.calcite.rel.logical.DruidSort;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import java.util.Stack;
/**
- * Converts a DAG of {@link
org.apache.druid.sql.calcite.rel.logical.DruidLogicalNode} convention to a
native
- * {@link DruidQuery} for execution.
+ * Converts a DAG of {@link DruidLogicalNode} convention to a native {@link
DruidQuery} for execution.
*/
public class DruidQueryGenerator
{
- private final RelNode relRoot;
+ private final DruidLogicalNode relRoot;
private final PDQVertexFactory vertexFactory;
- public DruidQueryGenerator(PlannerContext plannerContext, RelNode relRoot,
RexBuilder rexBuilder)
+ public DruidQueryGenerator(PlannerContext plannerContext, DruidLogicalNode
relRoot, RexBuilder rexBuilder)
{
this.relRoot = relRoot;
this.vertexFactory = new PDQVertexFactory(plannerContext, rexBuilder);
@@ -57,28 +60,34 @@ public class DruidQueryGenerator
public DruidQuery buildQuery()
{
- Vertex vertex = buildVertexFor(relRoot, true);
+ Stack<DruidLogicalNode> stack = new Stack<>();
+ stack.push(relRoot);
+ Vertex vertex = buildVertexFor(stack);
return vertex.buildQuery(true);
}
- private Vertex buildVertexFor(RelNode node, boolean isRoot)
+ private Vertex buildVertexFor(Stack<DruidLogicalNode> stack)
{
List<Vertex> newInputs = new ArrayList<>();
- for (RelNode input : node.getInputs()) {
- newInputs.add(buildVertexFor(input, false));
+
+ for (RelNode input : stack.peek().getInputs()) {
+ stack.push((DruidLogicalNode) input);
+ newInputs.add(buildVertexFor(stack));
+ stack.pop();
}
- Vertex vertex = processNodeWithInputs(node, newInputs, isRoot);
+ Vertex vertex = processNodeWithInputs(stack, newInputs);
return vertex;
}
- private Vertex processNodeWithInputs(RelNode node, List<Vertex> newInputs,
boolean isRoot)
+ private Vertex processNodeWithInputs(Stack<DruidLogicalNode> stack,
List<Vertex> newInputs)
{
- if (node instanceof InputDescProducer) {
+ DruidLogicalNode node = stack.peek();
+ if (node instanceof SourceDescProducer) {
return vertexFactory.createVertex(PartialDruidQuery.create(node),
newInputs);
}
if (newInputs.size() == 1) {
Vertex inputVertex = newInputs.get(0);
- Optional<Vertex> newVertex = inputVertex.extendWith(node, isRoot);
+ Optional<Vertex> newVertex = inputVertex.extendWith(stack);
if (newVertex.isPresent()) {
return newVertex.get();
}
@@ -86,7 +95,7 @@ public class DruidQueryGenerator
PartialDruidQuery.createOuterQuery(((PDQVertex)
inputVertex).partialDruidQuery),
ImmutableList.of(inputVertex)
);
- newVertex = inputVertex.extendWith(node, false);
+ newVertex = inputVertex.extendWith(stack);
if (newVertex.isPresent()) {
return newVertex.get();
}
@@ -107,21 +116,21 @@ public class DruidQueryGenerator
/**
* Extends the current vertex to include the specified parent.
*/
- Optional<Vertex> extendWith(RelNode parentNode, boolean isRoot);
+ Optional<Vertex> extendWith(Stack<DruidLogicalNode> stack);
/**
- * Decides wether this {@link Vertex} can be unwrapped into an {@link
InputDesc}.
+ * Decides wether this {@link Vertex} can be unwrapped into an {@link
SourceDesc}.
*/
- boolean canUnwrapInput();
+ boolean canUnwrapSourceDesc();
/**
- * Unwraps this {@link Vertex} into an {@link InputDesc}.
+ * Unwraps this {@link Vertex} into an {@link SourceDesc}.
*
- * Unwraps the input of this vertex - if it doesn't do anything beyond
reading its input.
+ * Unwraps the source of this vertex - if it doesn't do anything beyond
reading its input.
*
* @throws DruidException if unwrap is not possible.
*/
- InputDesc unwrapInputDesc();
+ SourceDesc unwrapSourceDesc();
}
/**
@@ -157,10 +166,10 @@ public class DruidQueryGenerator
@Override
public DruidQuery buildQuery(boolean topLevel)
{
- InputDesc input = getInput();
+ SourceDesc source = getSource();
return partialDruidQuery.build(
- input.dataSource,
- input.rowSignature,
+ source.dataSource,
+ source.rowSignature,
plannerContext,
rexBuilder,
!topLevel
@@ -168,39 +177,39 @@ public class DruidQueryGenerator
}
/**
- * Creates the {@link InputDesc} for the current {@link Vertex}.
+ * Creates the {@link SourceDesc} for the current {@link Vertex}.
*/
- private InputDesc getInput()
+ private SourceDesc getSource()
{
- List<InputDesc> inputDescs = new ArrayList<>();
+ List<SourceDesc> sourceDescs = new ArrayList<>();
for (Vertex inputVertex : inputs) {
- final InputDesc desc;
- if (inputVertex.canUnwrapInput()) {
- desc = inputVertex.unwrapInputDesc();
+ final SourceDesc desc;
+ if (inputVertex.canUnwrapSourceDesc()) {
+ desc = inputVertex.unwrapSourceDesc();
} else {
DruidQuery inputQuery = inputVertex.buildQuery(false);
- desc = new InputDesc(new QueryDataSource(inputQuery.getQuery()),
inputQuery.getOutputRowSignature());
+ desc = new SourceDesc(new QueryDataSource(inputQuery.getQuery()),
inputQuery.getOutputRowSignature());
}
- inputDescs.add(desc);
+ sourceDescs.add(desc);
}
RelNode scan = partialDruidQuery.getScan();
- if (scan instanceof InputDescProducer) {
- InputDescProducer inp = (InputDescProducer) scan;
- return inp.getInputDesc(plannerContext, inputDescs);
+ if (scan instanceof SourceDescProducer) {
+ SourceDescProducer inp = (SourceDescProducer) scan;
+ return inp.getSourceDesc(plannerContext, sourceDescs);
}
if (inputs.size() == 1) {
- return inputDescs.get(0);
+ return sourceDescs.get(0);
}
- throw DruidException.defensive("Unable to create InputDesc for
Operator [%s]", scan);
+ throw DruidException.defensive("Unable to create SourceDesc for
Operator [%s]", scan);
}
/**
* Extends the the current partial query with the new parent if possible.
*/
@Override
- public Optional<Vertex> extendWith(RelNode parentNode, boolean isRoot)
+ public Optional<Vertex> extendWith(Stack<DruidLogicalNode> stack)
{
- Optional<PartialDruidQuery> newPartialQuery =
extendPartialDruidQuery(parentNode, isRoot);
+ Optional<PartialDruidQuery> newPartialQuery =
extendPartialDruidQuery(stack);
if (!newPartialQuery.isPresent()) {
return Optional.empty();
}
@@ -210,65 +219,81 @@ public class DruidQueryGenerator
/**
* Merges the given {@link RelNode} into the current {@link
PartialDruidQuery}.
*/
- private Optional<PartialDruidQuery> extendPartialDruidQuery(RelNode
parentNode, boolean isRoot)
+ private Optional<PartialDruidQuery>
extendPartialDruidQuery(Stack<DruidLogicalNode> stack)
{
- if (accepts(parentNode, Stage.WHERE_FILTER, Filter.class)) {
+ DruidLogicalNode parentNode = stack.peek();
+ if (accepts(stack, Stage.WHERE_FILTER, Filter.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withWhereFilter((Filter) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.SELECT_PROJECT, Project.class)) {
+ if (accepts(stack, Stage.SELECT_PROJECT, Project.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withSelectProject((Project) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.AGGREGATE, Aggregate.class)) {
+ if (accepts(stack, Stage.AGGREGATE, Aggregate.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withAggregate((Aggregate) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.AGGREGATE_PROJECT, Project.class) &&
isRoot) {
+ if (accepts(stack, Stage.AGGREGATE_PROJECT, Project.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withAggregateProject((Project) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.HAVING_FILTER, Filter.class)) {
+ if (accepts(stack, Stage.HAVING_FILTER, Filter.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withHavingFilter((Filter) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.SORT, Sort.class)) {
+ if (accepts(stack, Stage.SORT, Sort.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withSort((Sort) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.SORT_PROJECT, Project.class)) {
+ if (accepts(stack, Stage.SORT_PROJECT, Project.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withSortProject((Project) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.WINDOW, Window.class)) {
+ if (accepts(stack, Stage.WINDOW, Window.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withWindow((Window) parentNode);
return Optional.of(newPartialQuery);
}
- if (accepts(parentNode, Stage.WINDOW_PROJECT, Project.class)) {
+ if (accepts(stack, Stage.WINDOW_PROJECT, Project.class)) {
PartialDruidQuery newPartialQuery =
partialDruidQuery.withWindowProject((Project) parentNode);
return Optional.of(newPartialQuery);
}
return Optional.empty();
}
- private boolean accepts(RelNode node, Stage whereFilter, Class<? extends
RelNode> class1)
+ private boolean accepts(Stack<DruidLogicalNode> stack, Stage stage,
Class<? extends RelNode> clazz)
{
- return partialDruidQuery.canAccept(whereFilter) &&
class1.isInstance(node);
+ DruidLogicalNode currentNode = stack.peek();
+ if (Project.class == clazz && stack.size() >= 2) {
+ // peek at parent and postpone project for next query stage
+ DruidLogicalNode parentNode = stack.get(stack.size() - 2);
+ if (stage.ordinal() > Stage.AGGREGATE.ordinal()
+ && parentNode instanceof DruidAggregate
+ && !partialDruidQuery.canAccept(Stage.AGGREGATE)) {
+ return false;
+ }
+ if (stage.ordinal() > Stage.SORT.ordinal()
+ && parentNode instanceof DruidSort
+ && !partialDruidQuery.canAccept(Stage.SORT)) {
+ return false;
+ }
+ }
+ return partialDruidQuery.canAccept(stage) &&
clazz.isInstance(currentNode);
}
@Override
- public InputDesc unwrapInputDesc()
+ public SourceDesc unwrapSourceDesc()
{
- if (canUnwrapInput()) {
+ if (canUnwrapSourceDesc()) {
DruidQuery q = buildQuery(false);
- InputDesc origInput = getInput();
- return new InputDesc(origInput.dataSource,
q.getOutputRowSignature());
+ SourceDesc origInput = getSource();
+ return new SourceDesc(origInput.dataSource,
q.getOutputRowSignature());
}
- throw DruidException.defensive("Can't unwrap input of vertex[%s]",
partialDruidQuery);
+ throw DruidException.defensive("Can't unwrap source of vertex[%s]",
partialDruidQuery);
}
@Override
- public boolean canUnwrapInput()
+ public boolean canUnwrapSourceDesc()
{
if (partialDruidQuery.stage() == Stage.SCAN) {
return true;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/InputDescProducer.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/SourceDescProducer.java
similarity index 68%
rename from
sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/InputDescProducer.java
rename to
sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/SourceDescProducer.java
index 412ac4d1a28..5e2fa2dc4d0 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/InputDescProducer.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/querygen/SourceDescProducer.java
@@ -22,6 +22,7 @@ package org.apache.druid.sql.calcite.planner.querygen;
import org.apache.druid.query.DataSource;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.sql.calcite.planner.PlannerContext;
+import org.apache.druid.sql.calcite.rel.VirtualColumnRegistry;
import java.util.List;
@@ -30,24 +31,31 @@ import java.util.List;
*
* Example: TableScan ; Union; Join.
*/
-public interface InputDescProducer
+public interface SourceDescProducer
{
/**
* Utility class to input related things details.
*
* Main reason to have this was that {@link DataSource} doesn't contain the
{@link RowSignature}.
*/
- class InputDesc
+ class SourceDesc
{
- public DataSource dataSource;
- public RowSignature rowSignature;
+ public final DataSource dataSource;
+ public final RowSignature rowSignature;
+ public final VirtualColumnRegistry virtualColumnRegistry;
- public InputDesc(DataSource dataSource, RowSignature rowSignature)
+ public SourceDesc(DataSource dataSource, RowSignature rowSignature)
+ {
+ this(dataSource, rowSignature, null);
+ }
+
+ public SourceDesc(DataSource dataSource, RowSignature rowSignature,
VirtualColumnRegistry virtualColumnRegistry)
{
this.dataSource = dataSource;
this.rowSignature = rowSignature;
+ this.virtualColumnRegistry = virtualColumnRegistry;
}
}
- InputDesc getInputDesc(PlannerContext plannerContext, List<InputDesc>
inputs);
+ SourceDesc getSourceDesc(PlannerContext plannerContext, List<SourceDesc>
sources);
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/DruidJoinQueryRel.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/DruidJoinQueryRel.java
index 6a8f1529966..677a697a52a 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/rel/DruidJoinQueryRel.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/rel/DruidJoinQueryRel.java
@@ -55,9 +55,11 @@ import org.apache.druid.sql.calcite.expression.Expressions;
import org.apache.druid.sql.calcite.planner.Calcites;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
+import
org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer.SourceDesc;
import org.apache.druid.sql.calcite.table.RowSignatures;
import javax.annotation.Nullable;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -142,19 +144,13 @@ public class DruidJoinQueryRel extends
DruidRel<DruidJoinQueryRel>
);
}
- @Override
- public DruidQuery toDruidQuery(final boolean finalizeAggregations)
+ private SourceDesc buildLeftSourceDesc()
{
+ final SourceDesc leftDesc;
final DruidRel<?> leftDruidRel = (DruidRel<?>) left;
final DruidQuery leftQuery =
Preconditions.checkNotNull(leftDruidRel.toDruidQuery(false), "leftQuery");
final RowSignature leftSignature = leftQuery.getOutputRowSignature();
final DataSource leftDataSource;
-
- final DruidRel<?> rightDruidRel = (DruidRel<?>) right;
- final DruidQuery rightQuery =
Preconditions.checkNotNull(rightDruidRel.toDruidQuery(false), "rightQuery");
- final RowSignature rightSignature = rightQuery.getOutputRowSignature();
- final DataSource rightDataSource;
-
if (computeLeftRequiresSubquery(getPlannerContext(), leftDruidRel)) {
leftDataSource = new QueryDataSource(leftQuery.getQuery());
if (leftFilter != null) {
@@ -163,37 +159,54 @@ public class DruidJoinQueryRel extends
DruidRel<DruidJoinQueryRel>
} else {
leftDataSource = leftQuery.getDataSource();
}
+ leftDesc = new SourceDesc(leftDataSource, leftSignature);
+ return leftDesc;
+ }
+ private SourceDesc buildRightSourceDesc()
+ {
+ final SourceDesc rightDesc;
+ final DruidRel<?> rightDruidRel = (DruidRel<?>) right;
+ final DruidQuery rightQuery =
Preconditions.checkNotNull(rightDruidRel.toDruidQuery(false), "rightQuery");
+ final RowSignature rightSignature = rightQuery.getOutputRowSignature();
+ final DataSource rightDataSource;
if (computeRightRequiresSubquery(getPlannerContext(), rightDruidRel)) {
rightDataSource = new QueryDataSource(rightQuery.getQuery());
} else {
rightDataSource = rightQuery.getDataSource();
}
+ rightDesc = new SourceDesc(rightDataSource, rightSignature);
+ return rightDesc;
+ }
-
+ public static SourceDesc buildJoinSourceDesc(final SourceDesc leftDesc,
final SourceDesc rightDesc, PlannerContext plannerContext, Join joinRel, Filter
leftFilter)
+ {
final Pair<String, RowSignature> prefixSignaturePair =
computeJoinRowSignature(
- leftSignature,
- rightSignature,
- findExistingJoinPrefixes(leftDataSource, rightDataSource)
+ leftDesc.rowSignature,
+ rightDesc.rowSignature,
+ findExistingJoinPrefixes(leftDesc.dataSource, rightDesc.dataSource)
);
+ String prefix = prefixSignaturePair.lhs;
+ RowSignature signature = prefixSignaturePair.rhs;
+
VirtualColumnRegistry virtualColumnRegistry = VirtualColumnRegistry.create(
- prefixSignaturePair.rhs,
- getPlannerContext().getExpressionParser(),
-
getPlannerContext().getPlannerConfig().isForceExpressionVirtualColumns()
+ signature,
+ plannerContext.getExpressionParser(),
+ plannerContext.getPlannerConfig().isForceExpressionVirtualColumns()
);
-
getPlannerContext().setJoinExpressionVirtualColumnRegistry(virtualColumnRegistry);
+
plannerContext.setJoinExpressionVirtualColumnRegistry(virtualColumnRegistry);
// Generate the condition for this join as a Druid expression.
final DruidExpression condition = Expressions.toDruidExpression(
- getPlannerContext(),
- prefixSignaturePair.rhs,
+ plannerContext,
+ signature,
joinRel.getCondition()
);
// Unsetting it to avoid any VC Registry leaks incase there are multiple
druid quries for the SQL
// It should be fixed soon with changes in interface for
SqlOperatorConversion and Expressions bridge class
- getPlannerContext().setJoinExpressionVirtualColumnRegistry(null);
+ plannerContext.setJoinExpressionVirtualColumnRegistry(null);
// DruidJoinRule should not have created us if "condition" is null. Check
defensively anyway, which also
// quiets static code analysis.
@@ -201,25 +214,40 @@ public class DruidJoinQueryRel extends
DruidRel<DruidJoinQueryRel>
throw new CannotBuildQueryException(joinRel, joinRel.getCondition());
}
- return partialQuery.build(
- JoinDataSource.create(
- leftDataSource,
- rightDataSource,
- prefixSignaturePair.lhs,
- JoinConditionAnalysis.forExpression(
- condition.getExpression(),
- getPlannerContext().parseExpression(condition.getExpression()),
- prefixSignaturePair.lhs
- ),
- toDruidJoinType(joinRel.getJoinType()),
- getDimFilter(getPlannerContext(), leftSignature, leftFilter),
- getPlannerContext().getJoinableFactoryWrapper()
+ JoinDataSource joinDataSource = JoinDataSource.create(
+ leftDesc.dataSource,
+ rightDesc.dataSource,
+ prefix,
+ JoinConditionAnalysis.forExpression(
+ condition.getExpression(),
+ plannerContext.parseExpression(condition.getExpression()),
+ prefix
),
- prefixSignaturePair.rhs,
+ toDruidJoinType(joinRel.getJoinType()),
+ getDimFilter(plannerContext, leftDesc.rowSignature, leftFilter),
+ plannerContext.getJoinableFactoryWrapper()
+ );
+
+ SourceDesc sourceDesc = new SourceDesc(joinDataSource, signature,
virtualColumnRegistry);
+ return sourceDesc;
+ }
+
+
+ @Override
+ public DruidQuery toDruidQuery(final boolean finalizeAggregations)
+ {
+ final SourceDesc leftDesc = buildLeftSourceDesc();
+ final SourceDesc rightDesc = buildRightSourceDesc();
+
+ SourceDesc sourceDesc = buildJoinSourceDesc(leftDesc, rightDesc,
getPlannerContext(), joinRel, leftFilter);
+
+ return partialQuery.build(
+ sourceDesc.dataSource,
+ sourceDesc.rowSignature,
getPlannerContext(),
getCluster().getRexBuilder(),
finalizeAggregations,
- virtualColumnRegistry
+ sourceDesc.virtualColumnRegistry
);
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidJoin.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidJoin.java
new file mode 100644
index 00000000000..5d531bfde80
--- /dev/null
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidJoin.java
@@ -0,0 +1,79 @@
+/*
+ * 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.rel.logical;
+
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.core.Join;
+import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.hint.RelHint;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexNode;
+import org.apache.druid.sql.calcite.planner.PlannerContext;
+import org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer;
+import org.apache.druid.sql.calcite.rel.DruidJoinQueryRel;
+
+import java.util.List;
+import java.util.Set;
+
+public class DruidJoin extends Join implements DruidLogicalNode,
SourceDescProducer
+{
+ public DruidJoin(RelOptCluster cluster,
+ RelTraitSet traitSet,
+ List<RelHint> hints,
+ RelNode left,
+ RelNode right,
+ RexNode condition,
+ Set<CorrelationId> variablesSet,
+ JoinRelType joinType)
+ {
+ super(cluster, traitSet, hints, left, right, condition, variablesSet,
joinType);
+ }
+
+ @Override
+ public Join copy(
+ RelTraitSet traitSet,
+ RexNode conditionExpr,
+ RelNode left,
+ RelNode right,
+ JoinRelType joinType,
+ boolean semiJoinDone)
+ {
+ return new DruidJoin(getCluster(), traitSet, hints, left, right,
conditionExpr, variablesSet, joinType);
+ }
+
+ @Override
+ public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq)
+ {
+ return planner.getCostFactory().makeCost(mq.getRowCount(this), 0, 0);
+ }
+
+ @Override
+ public SourceDesc getSourceDesc(PlannerContext plannerContext,
List<SourceDesc> sources)
+ {
+ SourceDesc leftDesc = sources.get(0);
+ SourceDesc rightDesc = sources.get(1);
+ return DruidJoinQueryRel.buildJoinSourceDesc(leftDesc, rightDesc,
plannerContext, this, null);
+ }
+}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidTableScan.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidTableScan.java
index b3bc5ba782a..45d97b04f32 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidTableScan.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidTableScan.java
@@ -34,7 +34,7 @@ import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.schema.Table;
import org.apache.druid.sql.calcite.planner.PlannerContext;
-import org.apache.druid.sql.calcite.planner.querygen.InputDescProducer;
+import org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer;
import org.apache.druid.sql.calcite.table.DruidTable;
import java.util.List;
@@ -42,7 +42,7 @@ import java.util.List;
/**
* {@link DruidLogicalNode} convention node for {@link TableScan} plan node.
*/
-public class DruidTableScan extends TableScan implements DruidLogicalNode,
InputDescProducer
+public class DruidTableScan extends TableScan implements DruidLogicalNode,
SourceDescProducer
{
public DruidTableScan(
RelOptCluster cluster,
@@ -98,10 +98,10 @@ public class DruidTableScan extends TableScan implements
DruidLogicalNode, Input
}
@Override
- public InputDesc getInputDesc(PlannerContext plannerContext, List<InputDesc>
inputs)
+ public SourceDesc getSourceDesc(PlannerContext plannerContext,
List<SourceDesc> sources)
{
final DruidTable druidTable = getDruidTable();
- return new InputDesc(druidTable.getDataSource(),
druidTable.getRowSignature());
+ return new SourceDesc(druidTable.getDataSource(),
druidTable.getRowSignature());
}
private DruidTable getDruidTable()
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidUnion.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidUnion.java
index daab1708cb0..96981a751e6 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidUnion.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidUnion.java
@@ -35,11 +35,11 @@ import org.apache.druid.query.TableDataSource;
import org.apache.druid.query.UnionDataSource;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.sql.calcite.planner.PlannerContext;
-import org.apache.druid.sql.calcite.planner.querygen.InputDescProducer;
+import org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer;
import java.util.ArrayList;
import java.util.List;
-public class DruidUnion extends Union implements DruidLogicalNode,
InputDescProducer
+public class DruidUnion extends Union implements DruidLogicalNode,
SourceDescProducer
{
public DruidUnion(
RelOptCluster cluster,
@@ -64,26 +64,26 @@ public class DruidUnion extends Union implements
DruidLogicalNode, InputDescProd
}
@Override
- public InputDesc getInputDesc(PlannerContext plannerContext, List<InputDesc>
inputs)
+ public SourceDesc getSourceDesc(PlannerContext plannerContext,
List<SourceDesc> sources)
{
List<DataSource> dataSources = new ArrayList<>();
RowSignature signature = null;
- for (InputDesc inputDesc : inputs) {
- checkDataSourceSupported(inputDesc.dataSource);
- dataSources.add(inputDesc.dataSource);
+ for (SourceDesc sourceDesc : sources) {
+ checkDataSourceSupported(sourceDesc.dataSource);
+ dataSources.add(sourceDesc.dataSource);
if (signature == null) {
- signature = inputDesc.rowSignature;
+ signature = sourceDesc.rowSignature;
} else {
- if (!signature.equals(inputDesc.rowSignature)) {
+ if (!signature.equals(sourceDesc.rowSignature)) {
throw DruidException.defensive(
"Row signature mismatch in Union inputs [%s] and [%s]",
signature,
- inputDesc.rowSignature
+ sourceDesc.rowSignature
);
}
}
}
- return new InputDesc(new UnionDataSource(dataSources), signature);
+ return new SourceDesc(new UnionDataSource(dataSources), signature);
}
private void checkDataSourceSupported(DataSource dataSource)
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidValues.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidValues.java
index fea4e5f610d..c6fa2180161 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidValues.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/rel/logical/DruidValues.java
@@ -32,7 +32,7 @@ import org.apache.calcite.rex.RexLiteral;
import org.apache.druid.query.InlineDataSource;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.sql.calcite.planner.PlannerContext;
-import org.apache.druid.sql.calcite.planner.querygen.InputDescProducer;
+import org.apache.druid.sql.calcite.planner.querygen.SourceDescProducer;
import org.apache.druid.sql.calcite.rel.CostEstimates;
import org.apache.druid.sql.calcite.rule.DruidLogicalValuesRule;
import org.apache.druid.sql.calcite.table.InlineTable;
@@ -44,7 +44,7 @@ import java.util.stream.Collectors;
/**
* {@link DruidLogicalNode} convention node for {@link LogicalValues} plan
node.
*/
-public class DruidValues extends LogicalValues implements DruidLogicalNode,
InputDescProducer
+public class DruidValues extends LogicalValues implements DruidLogicalNode,
SourceDescProducer
{
private InlineTable inlineTable;
@@ -72,12 +72,12 @@ public class DruidValues extends LogicalValues implements
DruidLogicalNode, Inpu
}
@Override
- public InputDesc getInputDesc(PlannerContext plannerContext, List<InputDesc>
inputs)
+ public SourceDesc getSourceDesc(PlannerContext plannerContext,
List<SourceDesc> sources)
{
if (inlineTable == null) {
inlineTable = buildInlineTable(plannerContext);
}
- return new InputDesc(inlineTable.getDataSource(),
inlineTable.getRowSignature());
+ return new SourceDesc(inlineTable.getDataSource(),
inlineTable.getRowSignature());
}
private InlineTable buildInlineTable(PlannerContext plannerContext)
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rule/DruidJoinRule.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/DruidJoinRule.java
index d5a307bc54f..66f5accfcc6 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/rule/DruidJoinRule.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/rule/DruidJoinRule.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite.rule;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import org.apache.calcite.plan.RelOptRule;
@@ -47,6 +48,7 @@ import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.error.DruidException;
+import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.query.LookupDataSource;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.rel.DruidJoinQueryRel;
@@ -84,7 +86,7 @@ public class DruidJoinRule extends RelOptRule
{
return new DruidJoinRule(plannerContext);
}
-
+
@Override
public boolean matches(RelOptRuleCall call)
{
@@ -125,6 +127,7 @@ public class DruidJoinRule extends RelOptRule
join.getLeft().getRowType(),
rexBuilder
);
+ plannerContext.setPlanningError(conditionAnalysis.errorStr);
final boolean isLeftDirectAccessPossible = enableLeftScanDirect && (left
instanceof DruidQueryRel);
if (!plannerContext.getJoinAlgorithm().requiresSubquery()
@@ -247,6 +250,7 @@ public class DruidJoinRule extends RelOptRule
)
{
ConditionAnalysis conditionAnalysis = analyzeCondition(condition,
leftRowType, rexBuilder);
+ plannerContext.setPlanningError(conditionAnalysis.errorStr);
// if the right side requires a subquery, then even lookup will be
transformed to a QueryDataSource
// thereby allowing join conditions on both k and v columns of the lookup
if (right != null
@@ -275,7 +279,7 @@ public class DruidJoinRule extends RelOptRule
// for an example.
return conditionAnalysis.getUnsupportedOnSubConditions().isEmpty();
}
-
+
return true;
}
@@ -304,12 +308,15 @@ public class DruidJoinRule extends RelOptRule
private final Set<RexInputRef> rightColumns;
+ public final String errorStr;
+
ConditionAnalysis(
int numLeftFields,
List<RexEquality> equalitySubConditions,
List<RexLiteral> literalSubConditions,
List<RexNode> unsupportedOnSubConditions,
- Set<RexInputRef> rightColumns
+ Set<RexInputRef> rightColumns,
+ String errorStr
)
{
this.numLeftFields = numLeftFields;
@@ -317,6 +324,7 @@ public class DruidJoinRule extends RelOptRule
this.literalSubConditions = literalSubConditions;
this.unsupportedOnSubConditions = unsupportedOnSubConditions;
this.rightColumns = rightColumns;
+ this.errorStr = errorStr;
}
public ConditionAnalysis pushThroughLeftProject(final Project leftProject)
@@ -340,7 +348,8 @@ public class DruidJoinRule extends RelOptRule
.collect(Collectors.toList()),
literalSubConditions,
unsupportedOnSubConditions,
- rightColumns
+ rightColumns,
+ null
);
}
@@ -369,7 +378,8 @@ public class DruidJoinRule extends RelOptRule
.collect(Collectors.toList()),
literalSubConditions,
unsupportedOnSubConditions,
- rightColumns
+ rightColumns,
+ null
);
}
@@ -429,7 +439,7 @@ public class DruidJoinRule extends RelOptRule
* that can be extracted into post join filter.
* {@code f(LeftRel) = RightColumn}, then return a {@link ConditionAnalysis}.
*/
- public ConditionAnalysis analyzeCondition(
+ public static ConditionAnalysis analyzeCondition(
final RexNode condition,
final RelDataType leftRowType,
final RexBuilder rexBuilder
@@ -441,6 +451,7 @@ public class DruidJoinRule extends RelOptRule
final List<RexNode> unSupportedSubConditions = new ArrayList<>();
final Set<RexInputRef> rightColumns = new HashSet<>();
final int numLeftFields = leftRowType.getFieldCount();
+ final List<String> errors = new ArrayList<String>();
for (RexNode subCondition : subConditions) {
if (RexUtil.isLiteral(subCondition, true)) {
@@ -475,10 +486,12 @@ public class DruidJoinRule extends RelOptRule
comparisonKind = SqlKind.EQUALS;
if
(!SqlTypeName.BOOLEAN_TYPES.contains(secondOperand.getType().getSqlTypeName()))
{
- plannerContext.setPlanningError(
- "SQL requires a join with '%s' condition where the column is of
the type %s, that is not supported",
- subCondition.getKind(),
- secondOperand.getType().getSqlTypeName()
+ errors.add(
+ StringUtils.format(
+ "SQL requires a join with '%s' condition where the column is
of the type %s, that is not supported",
+ subCondition.getKind(),
+ secondOperand.getType().getSqlTypeName()
+ )
);
unSupportedSubConditions.add(subCondition);
continue;
@@ -492,9 +505,11 @@ public class DruidJoinRule extends RelOptRule
comparisonKind = subCondition.getKind();
} else {
// If it's not EQUALS or a BOOLEAN input ref, it's not supported.
- plannerContext.setPlanningError(
- "SQL requires a join with '%s' condition that is not supported.",
- subCondition.getKind()
+ errors.add(
+ StringUtils.format(
+ "SQL requires a join with '%s' condition that is not
supported.",
+ subCondition.getKind()
+ )
);
unSupportedSubConditions.add(subCondition);
continue;
@@ -509,17 +524,27 @@ public class DruidJoinRule extends RelOptRule
rightColumns.add((RexInputRef) firstOperand);
} else {
// Cannot handle this condition.
- plannerContext.setPlanningError("SQL is resulting in a join that has
unsupported operand types.");
+ errors.add(
+ StringUtils.format(
+ "SQL is resulting in a join that has unsupported operand
types."
+ )
+ );
unSupportedSubConditions.add(subCondition);
}
}
-
+ final String errorStr;
+ if (errors.size() > 0) {
+ errorStr = Joiner.on('\n').join(errors);
+ } else {
+ errorStr = null;
+ }
return new ConditionAnalysis(
numLeftFields,
equalitySubConditions,
literalSubConditions,
unSupportedSubConditions,
- rightColumns
+ rightColumns,
+ errorStr
);
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidJoinRule.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidJoinRule.java
new file mode 100644
index 00000000000..ded383cbefb
--- /dev/null
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidJoinRule.java
@@ -0,0 +1,76 @@
+/*
+ * 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.rule.logical;
+
+import org.apache.calcite.plan.RelTrait;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.core.Join;
+import org.apache.druid.error.InvalidSqlInput;
+import org.apache.druid.sql.calcite.rel.logical.DruidJoin;
+import org.apache.druid.sql.calcite.rel.logical.DruidLogicalConvention;
+import org.apache.druid.sql.calcite.rule.DruidJoinRule.ConditionAnalysis;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public class DruidJoinRule extends ConverterRule
+{
+
+ public DruidJoinRule(Class<? extends RelNode> clazz, RelTrait in, RelTrait
out, String descriptionPrefix)
+ {
+ super(Config.INSTANCE.withConversion(clazz, in, out, descriptionPrefix));
+ }
+
+ @Override
+ public @Nullable RelNode convert(RelNode rel)
+ {
+ Join join = (Join) rel;
+ RelTraitSet newTrait =
join.getTraitSet().replace(DruidLogicalConvention.instance());
+
+ ConditionAnalysis analysis =
org.apache.druid.sql.calcite.rule.DruidJoinRule.analyzeCondition(
+ join.getCondition(),
+ join.getLeft().getRowType(),
+ join.getCluster().getRexBuilder()
+ );
+
+ if (analysis.errorStr != null) {
+ // reject the query in case the anaysis detected any issues
+ throw InvalidSqlInput.exception(analysis.errorStr);
+ }
+
+ return new DruidJoin(
+ join.getCluster(),
+ newTrait,
+ join.getHints(),
+ convert(
+ join.getLeft(),
+ DruidLogicalConvention.instance()
+ ),
+ convert(
+ join.getRight(),
+ DruidLogicalConvention.instance()
+ ),
+ join.getCondition(),
+ join.getVariablesSet(),
+ join.getJoinType()
+ );
+ }
+
+}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidLogicalRules.java
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidLogicalRules.java
index 5fe939d3e7c..a7d1a2c8c68 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidLogicalRules.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/logical/DruidLogicalRules.java
@@ -25,6 +25,7 @@ import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rel.logical.LogicalAggregate;
import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalJoin;
import org.apache.calcite.rel.logical.LogicalProject;
import org.apache.calcite.rel.logical.LogicalSort;
import org.apache.calcite.rel.logical.LogicalTableScan;
@@ -98,6 +99,12 @@ public class DruidLogicalRules
Convention.NONE,
DruidLogicalConvention.instance(),
DruidUnionRule.class.getSimpleName()
+ ),
+ new DruidJoinRule(
+ LogicalJoin.class,
+ Convention.NONE,
+ DruidLogicalConvention.instance(),
+ DruidJoinRule.class.getSimpleName()
)
)
);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
index 8e8f3287e6e..d9569d31615 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
@@ -31,6 +31,8 @@ import org.apache.commons.text.StringEscapeUtils;
import org.apache.druid.annotations.UsedByJUnitParamsRunner;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.error.DruidException;
+import org.apache.druid.error.DruidException.Category;
+import org.apache.druid.error.DruidException.Persona;
import org.apache.druid.error.DruidExceptionMatcher;
import org.apache.druid.guice.DruidInjectorBuilder;
import org.apache.druid.hll.VersionOneHyperLogLogCollector;
@@ -126,6 +128,7 @@ import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import javax.annotation.Nullable;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -770,18 +773,21 @@ public class BaseCalciteQueryTest extends CalciteTestBase
catch (DruidException e) {
MatcherAssert.assertThat(
e,
- new DruidExceptionMatcher(DruidException.Persona.ADMIN,
DruidException.Category.INVALID_INPUT, "general")
- .expectMessageIs(
- StringUtils.format(
- "Query could not be planned. A possible reason is [%s]",
- expectedError
- )
- )
+
buildUnplannableExceptionMatcher().expectMessageContains(expectedError)
);
}
catch (Exception e) {
log.error(e, "Expected DruidException for query: %s", sql);
- Assert.fail(sql);
+ throw e;
+ }
+ }
+
+ private DruidExceptionMatcher buildUnplannableExceptionMatcher()
+ {
+ if (testBuilder().isDecoupledMode()) {
+ return new DruidExceptionMatcher(Persona.USER, Category.INVALID_INPUT,
"invalidInput");
+ } else {
+ return new DruidExceptionMatcher(Persona.ADMIN, Category.INVALID_INPUT,
"general");
}
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
index 5420be74e7f..ac59234576c 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteJoinQueryTest.java
@@ -85,6 +85,8 @@ import org.apache.druid.segment.join.JoinType;
import org.apache.druid.segment.virtual.ListFilteredVirtualColumn;
import org.apache.druid.server.QueryLifecycle;
import org.apache.druid.server.security.Access;
+import org.apache.druid.sql.calcite.DecoupledTestConfig.NativeQueryIgnore;
+import org.apache.druid.sql.calcite.NotYetSupported.Modes;
import org.apache.druid.sql.calcite.expression.DruidExpression;
import org.apache.druid.sql.calcite.filtration.Filtration;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
@@ -188,6 +190,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
// to compute the query with limit 1.
@SqlTestFrameworkConfig(minTopNThreshold = 1)
@Test
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testExactTopNOnInnerJoinWithLimit()
{
Map<String, Object> context = new HashMap<>(QUERY_CONTEXT_DEFAULT);
@@ -236,6 +239,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.STACK_OVERFLOW)
public void testJoinOuterGroupByAndSubqueryHasLimit()
{
// Cannot vectorize JOIN operator.
@@ -323,6 +327,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testJoinOuterGroupByAndSubqueryNoLimit(Map<String, Object>
queryContext)
{
// Fully removing the join allows this query to vectorize.
@@ -406,6 +411,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testJoinWithLimitBeforeJoining()
{
// Cannot vectorize JOIN operator.
@@ -492,6 +498,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testJoinOnTimeseriesWithFloorOnTime()
{
// Cannot vectorize JOIN operator.
@@ -546,6 +553,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testJoinOnGroupByInsteadOfTimeseriesWithFloorOnTime()
{
// Cannot vectorize JOIN operator.
@@ -612,6 +620,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void
testJoinOnGroupByInsteadOfTimeseriesWithFloorOnTimeWithNoAggregateMultipleValues()
{
// Cannot vectorize JOIN operator.
@@ -679,6 +688,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.CANNOT_JOIN_LOOKUP_NON_KEY)
public void
testFilterAndGroupByLookupUsingJoinOperatorWithValueFilterPushdownMatchesNothing(Map<String,
Object> queryContext)
{
@@ -760,6 +770,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testFilterAndGroupByLookupUsingJoinOperatorBackwards(Map<String,
Object> queryContext)
{
// Like "testFilterAndGroupByLookupUsingJoinOperator", but with the table
and lookup reversed.
@@ -815,6 +826,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void
testFilterAndGroupByLookupUsingJoinOperatorWithNotFilter(Map<String, Object>
queryContext)
{
@@ -857,6 +869,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
);
}
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
@Test
@Parameters(source = QueryContextForJoinProvider.class)
public void testJoinUnionTablesOnLookup(Map<String, Object> queryContext)
@@ -911,6 +924,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.CANNOT_JOIN_LOOKUP_NON_KEY)
public void testFilterAndGroupByLookupUsingJoinOperator(Map<String, Object>
queryContext)
{
// Cannot vectorize JOIN operator.
@@ -1120,6 +1134,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void
testInnerJoinTableLookupLookupWithFilterWithOuterLimit(Map<String, Object>
queryContext)
{
testQuery(
@@ -1163,6 +1178,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void testInnerJoinTableLookupLookupWithFilterWithoutLimit(Map<String,
Object> queryContext)
{
testQuery(
@@ -1204,6 +1220,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void
testInnerJoinTableLookupLookupWithFilterWithOuterLimitWithAllColumns(Map<String,
Object> queryContext)
{
@@ -1248,6 +1265,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void
testInnerJoinTableLookupLookupWithFilterWithoutLimitWithAllColumns(Map<String,
Object> queryContext)
{
testQuery(
@@ -1289,6 +1307,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void testManyManyInnerJoinOnManyManyLookup(Map<String, Object>
queryContext)
{
testQuery(
@@ -1518,6 +1537,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.FINALIZING_FIELD_ACCESS)
public void testInnerJoinQueryOfLookup(Map<String, Object> queryContext)
{
// Cannot vectorize the subquery.
@@ -1597,6 +1617,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.DEFINETLY_WORSE_PLAN)
public void testInnerJoinQueryOfLookupRemovable(Map<String, Object>
queryContext)
{
// Like "testInnerJoinQueryOfLookup", but the subquery is removable.
@@ -1635,6 +1656,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testInnerJoinTwoLookupsToTableUsingNumericColumn(Map<String,
Object> queryContext)
{
// Regression test for https://github.com/apache/druid/issues/9646.
@@ -1696,6 +1718,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void
testInnerJoinTwoLookupsToTableUsingNumericColumnInReverse(Map<String, Object>
queryContext)
{
@@ -1753,6 +1776,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testInnerJoinLookupTableTable(Map<String, Object> queryContext)
{
// Regression test for https://github.com/apache/druid/issues/9646.
@@ -1835,6 +1859,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testInnerJoinLookupTableTableChained(Map<String, Object>
queryContext)
{
// Cannot vectorize JOIN operator.
@@ -1957,6 +1982,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testCommaJoinLeftFunction()
{
testQuery(
@@ -1995,6 +2021,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
// Hence, comma join will result in a cross join with filter on outermost
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void testCommaJoinTableLookupTableMismatchedTypes(Map<String, Object>
queryContext)
{
// Regression test for https://github.com/apache/druid/issues/9646.
@@ -2061,6 +2088,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testJoinTableLookupTableMismatchedTypesWithoutComma(Map<String,
Object> queryContext)
{
// Empty-dataset aggregation queries in MSQ return an empty row, rather
than a single row as SQL requires.
@@ -2131,6 +2159,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testInnerJoinCastLeft(Map<String, Object> queryContext)
{
// foo.m1 is FLOAT, l.k is STRING.
@@ -2259,6 +2288,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testInnerJoinLeftFunction(Map<String, Object> queryContext)
{
testQuery(
@@ -2711,6 +2741,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testUsingSubqueryWithExtractionFns(Map<String, Object>
queryContext)
{
// Cannot vectorize JOIN operator.
@@ -2771,6 +2802,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testInnerJoinWithIsNullFilter(Map<String, Object> queryContext)
{
testQuery(
@@ -2913,6 +2945,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_LEFT_DIRECT_ACCESS)
public void
testLeftJoinOnTwoInlineDataSourcesWithTimeFilter_withLeftDirectAccess(Map<String,
Object> queryContext)
{
queryContext = withLeftDirectAccessEnabled(queryContext);
@@ -3024,6 +3057,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_LEFT_DIRECT_ACCESS)
public void
testLeftJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String,
Object> queryContext)
{
queryContext = withLeftDirectAccessEnabled(queryContext);
@@ -3125,6 +3159,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_LEFT_DIRECT_ACCESS)
public void
testLeftJoinOnTwoInlineDataSources_withLeftDirectAccess(Map<String, Object>
queryContext)
{
queryContext = withLeftDirectAccessEnabled(queryContext);
@@ -3226,6 +3261,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_LEFT_DIRECT_ACCESS)
public void
testInnerJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String,
Object> queryContext)
{
queryContext = withLeftDirectAccessEnabled(queryContext);
@@ -3327,6 +3363,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void
testGroupByOverGroupByOverInnerJoinOnTwoInlineDataSources(Map<String, Object>
queryContext)
{
skipVectorize();
@@ -3412,6 +3449,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_LEFT_DIRECT_ACCESS)
public void
testInnerJoinOnTwoInlineDataSources_withLeftDirectAccess(Map<String, Object>
queryContext)
{
queryContext = withLeftDirectAccessEnabled(queryContext);
@@ -3640,6 +3678,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testLeftJoinSubqueryWithSelectorFilter(Map<String, Object>
queryContext)
{
// Cannot vectorize due to 'concat' expression.
@@ -3693,6 +3732,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testLeftJoinWithNotNullFilter(Map<String, Object> queryContext)
{
testQuery(
@@ -3740,6 +3780,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testInnerJoin(Map<String, Object> queryContext)
{
testQuery(
@@ -3794,6 +3835,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testJoinWithExplicitIsNotDistinctFromCondition(Map<String,
Object> queryContext)
{
// Like "testInnerJoin", but uses IS NOT DISTINCT FROM instead of equals.
@@ -3839,6 +3881,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testInnerJoinSubqueryWithSelectorFilter(Map<String, Object>
queryContext)
{
if (sortBasedJoin) {
@@ -3898,6 +3941,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testSemiJoinWithOuterTimeExtractScan()
{
testQuery(
@@ -3946,6 +3990,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testTwoSemiJoinsSimultaneously(Map<String, Object> queryContext)
{
// Fully removing the join allows this query to vectorize.
@@ -4117,6 +4162,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testSemiAndAntiJoinSimultaneouslyUsingExplicitJoins(Map<String,
Object> queryContext)
{
cannotVectorize();
@@ -4184,6 +4230,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testSemiJoinWithOuterTimeExtractAggregateWithOrderBy()
{
// Cannot vectorize due to virtual columns.
@@ -4278,6 +4325,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.UNION_WITH_COMPLEX_OPERAND)
public void testUnionAllTwoQueriesLeftQueryIsJoin(Map<String, Object>
queryContext)
{
// MSQ does not support UNION ALL.
@@ -4322,6 +4370,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.UNION_WITH_COMPLEX_OPERAND)
public void testUnionAllTwoQueriesRightQueryIsJoin(Map<String, Object>
queryContext)
{
// MSQ does not support UNION ALL.
@@ -4364,6 +4413,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
);
}
+ @NotYetSupported(Modes.UNION_WITH_COMPLEX_OPERAND)
@Test
public void testUnionAllTwoQueriesBothQueriesAreJoin()
{
@@ -4636,6 +4686,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testJoinWithNonEquiCondition(Map<String, Object> queryContext)
{
// Native JOIN operator cannot handle the condition, so a SQL JOIN with
greater-than is translated into a
@@ -4698,6 +4749,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void testJoinWithEquiAndNonEquiCondition(Map<String, Object>
queryContext)
{
// Native JOIN operator cannot handle the condition, so a SQL JOIN with
greater-than is translated into a
@@ -4743,6 +4795,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testUsingSubqueryAsPartOfAndFilter(Map<String, Object>
queryContext)
{
// Fully removing the join allows this query to vectorize.
@@ -4902,6 +4955,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_UNSUPORTED_OPERAND)
public void testNestedGroupByOnInlineDataSourceWithFilter(Map<String,
Object> queryContext)
{
// Cannot vectorize due to virtual columns.
@@ -5094,6 +5148,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void testTopNOnStringWithNonSortedOrUniqueDictionary(Map<String,
Object> queryContext)
{
testQuery(
@@ -5134,6 +5189,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.EQUIV_PLAN)
public void
testTopNOnStringWithNonSortedOrUniqueDictionaryOrderByDim(Map<String, Object>
queryContext)
{
@@ -5174,6 +5230,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.SLIGHTLY_WORSE_PLAN)
public void testVirtualColumnOnMVFilterJoinExpression(Map<String, Object>
queryContext)
{
// Doesn't work in MSQ, although it's not really MSQ's fault. In MSQ, the
second field (foo2.dim3) is returned as
@@ -5230,6 +5287,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.DEFINETLY_WORSE_PLAN)
public void testVirtualColumnOnMVFilterMultiJoinExpression(Map<String,
Object> queryContext)
{
// Doesn't work in MSQ, although it's not really MSQ's fault. In MSQ, the
second field (foo2.dim3) is returned as
@@ -5309,6 +5367,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void
testInnerJoinWithFilterPushdownAndManyFiltersEmptyResults(Map<String, Object>
queryContext)
{
// create the query we expect
@@ -5416,6 +5475,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void
testInnerJoinWithFilterPushdownAndManyFiltersNonEmptyResults(Map<String,
Object> queryContext)
{
// create the query we expect
@@ -5584,6 +5644,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@Test
@Parameters(source = QueryContextForJoinProvider.class)
+ @NotYetSupported(Modes.SORT_REMOVE_TROUBLE)
public void testRegressionFilteredAggregatorsSubqueryJoins(Map<String,
Object> queryContext)
{
cannotVectorize();
@@ -5778,6 +5839,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
@SqlTestFrameworkConfig(minTopNThreshold = 1)
@Test
+ @NotYetSupported(Modes.JOIN_TABLE_TABLE)
public void testJoinWithAliasAndOrderByNoGroupBy()
{
Map<String, Object> context = new HashMap<>(QUERY_CONTEXT_DEFAULT);
@@ -5796,8 +5858,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
new QueryDataSource(
newScanQueryBuilder()
.dataSource(CalciteTests.DATASOURCE3)
- .intervals(querySegmentSpec(Intervals.of(
-
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z")))
+
.intervals(querySegmentSpec(Filtration.eternity()))
.columns("dim2")
.context(context)
.build()
@@ -5970,6 +6031,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @DecoupledTestConfig(nativeQueryIgnore =
NativeQueryIgnore.JOIN_FILTER_LOCATIONS)
public void testJoinWithInputRefCondition()
{
cannotVectorize();
@@ -6088,6 +6150,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.CORRELATE_CONVERSION)
public void testJoinsWithUnnestOnLeft()
{
// Segment map function of MSQ needs some work
@@ -6143,6 +6206,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.CORRELATE_CONVERSION)
public void testJoinsWithUnnestOverFilteredDSOnLeft()
{
// Segment map function of MSQ needs some work
@@ -6201,6 +6265,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.CORRELATE_CONVERSION)
public void testJoinsWithUnnestOverJoin()
{
// Segment map function of MSQ needs some work
@@ -6287,6 +6352,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.CORRELATE_CONVERSION)
public void testSelfJoinsWithUnnestOnLeftAndRight()
{
// Segment map function of MSQ needs some work
@@ -6356,6 +6422,7 @@ public class CalciteJoinQueryTest extends
BaseCalciteQueryTest
}
@Test
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
public void testJoinsOverUnnestOverFilterDSOverJoin()
{
// Segment map function of MSQ needs some work
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index d513387cfe9..0a3cd0c7a54 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -2817,7 +2817,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
@Test
public void testGroupByWithSelectAndOrderByProjections()
{
@@ -2902,7 +2901,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
@Test
public void testTopNWithSelectAndOrderByProjections()
{
@@ -4868,7 +4866,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
@Test
public void testGroupByWithSortOnPostAggregationDefault()
{
@@ -4900,7 +4897,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
@Test
public void testGroupByWithSortOnPostAggregationNoTopNConfig()
{
@@ -4944,7 +4940,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
@Test
public void testGroupByWithSortOnPostAggregationNoTopNContext()
{
@@ -5784,7 +5779,6 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.ERROR_HANDLING)
@Test
public void testUnplannableJoinQueriesInNonSQLCompatibleMode()
{
@@ -6931,7 +6925,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.AGG_COL_EXCHANGE)
@Test
public void testExactCountDistinctWithGroupingAndOtherAggregators()
{
@@ -6986,7 +6980,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.MISSING_JOIN_CONVERSION)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.AGG_COL_EXCHANGE)
@Test
public void
testMultipleExactCountDistinctWithGroupingAndOtherAggregatorsUsingJoin()
{
@@ -10515,7 +10509,7 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.PLAN_MISMATCH)
+ @DecoupledTestConfig(nativeQueryIgnore = NativeQueryIgnore.IMPROVED_PLAN)
@Test
public void testGroupByTimeFloorAndDimOnGroupByTimeFloorAndDim()
{
@@ -12149,7 +12143,6 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.MISSING_JOIN_CONVERSION)
@Test
public void testRequireTimeConditionPositive()
{
@@ -12178,7 +12171,11 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
new Object[]{3L, timestamp("2001-01-01")}
)
);
+ }
+ @Test
+ public void testRequireTimeConditionPositive2()
+ {
// nested GROUP BY only requires time condition for inner most query
testQuery(
PLANNER_CONFIG_REQUIRE_TIME_CONDITION,
@@ -12221,7 +12218,13 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
new Object[]{6L, 4L}
)
);
+ }
+ // __time >= x remains in the join condition
+ @NotYetSupported(Modes.JOIN_CONDITION_NOT_PUSHED_CONDITION)
+ @Test
+ public void testRequireTimeConditionPositive3()
+ {
// Cannot vectorize next test due to extraction dimension spec.
cannotVectorize();
@@ -12353,7 +12356,6 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.MISSING_JOIN_CONVERSION2)
@Test
public void testRequireTimeConditionSemiJoinNegative()
{
@@ -14648,7 +14650,6 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.MISSING_JOIN_CONVERSION)
@Test
public void testOrderByAlongWithInternalScanQuery()
{
@@ -14691,7 +14692,6 @@ public class CalciteQueryTest extends
BaseCalciteQueryTest
);
}
- @NotYetSupported(Modes.MISSING_JOIN_CONVERSION)
@Test
public void testOrderByAlongWithInternalScanQueryNoDistinct()
{
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteJoinQueryTest.java
similarity index 81%
copy from
sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
copy to
sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteJoinQueryTest.java
index e150ba52f30..9787f046be8 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteJoinQueryTest.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite;
import com.google.common.collect.ImmutableMap;
+import junitparams.Parameters;
import org.apache.druid.query.QueryContexts;
import org.apache.druid.server.security.AuthConfig;
import org.apache.druid.sql.calcite.NotYetSupported.NotYetSupportedProcessor;
@@ -27,8 +28,13 @@ import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.util.SqlTestFramework;
import
org.apache.druid.sql.calcite.util.SqlTestFramework.PlannerComponentSupplier;
import org.junit.Rule;
+import org.junit.Test;
-public class DecoupledPlanningCalciteUnionQueryTest extends
CalciteUnionQueryTest
+import java.util.Map;
+
+import static org.junit.Assert.assertNotNull;
+
+public class DecoupledPlanningCalciteJoinQueryTest extends CalciteJoinQueryTest
{
@Rule(order = 0)
@@ -59,7 +65,7 @@ public class DecoupledPlanningCalciteUnionQueryTest extends
CalciteUnionQueryTes
.cannotVectorize(cannotVectorize)
.skipVectorize(skipVectorize);
- DecoupledTestConfig decTestConfig =
queryFrameworkRule.getDescription().getAnnotation(DecoupledTestConfig.class);
+ DecoupledTestConfig decTestConfig =
queryFrameworkRule.getAnnotation(DecoupledTestConfig.class);
if (decTestConfig != null &&
decTestConfig.nativeQueryIgnore().isPresent()) {
builder.verifyNativeQueries(x -> false);
@@ -67,4 +73,13 @@ public class DecoupledPlanningCalciteUnionQueryTest extends
CalciteUnionQueryTes
return builder;
}
+
+ @Test
+ @Parameters(source = QueryContextForJoinProvider.class)
+ @DecoupledTestConfig
+ public void ensureDecoupledTestConfigAnnotationWorks(Map<String, Object>
queryContext)
+ {
+ assertNotNull(queryFrameworkRule.getAnnotation(DecoupledTestConfig.class));
+ assertNotNull(queryContext);
+ }
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteQueryTest.java
index 6dbfe4277bf..cf7d47ee084 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteQueryTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteQueryTest.java
@@ -59,7 +59,7 @@ public class DecoupledPlanningCalciteQueryTest extends
CalciteQueryTest
.cannotVectorize(cannotVectorize)
.skipVectorize(skipVectorize);
- DecoupledTestConfig decTestConfig =
queryFrameworkRule.getDescription().getAnnotation(DecoupledTestConfig.class);
+ DecoupledTestConfig decTestConfig =
queryFrameworkRule.getAnnotation(DecoupledTestConfig.class);
if (decTestConfig != null &&
decTestConfig.nativeQueryIgnore().isPresent()) {
builder.verifyNativeQueries(x -> false);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
index e150ba52f30..1e8c3d0b37d 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledPlanningCalciteUnionQueryTest.java
@@ -59,7 +59,7 @@ public class DecoupledPlanningCalciteUnionQueryTest extends
CalciteUnionQueryTes
.cannotVectorize(cannotVectorize)
.skipVectorize(skipVectorize);
- DecoupledTestConfig decTestConfig =
queryFrameworkRule.getDescription().getAnnotation(DecoupledTestConfig.class);
+ DecoupledTestConfig decTestConfig =
queryFrameworkRule.getAnnotation(DecoupledTestConfig.class);
if (decTestConfig != null &&
decTestConfig.nativeQueryIgnore().isPresent()) {
builder.verifyNativeQueries(x -> false);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledTestConfig.java
b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledTestConfig.java
index bc1bb9362f2..511db82b76b 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledTestConfig.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledTestConfig.java
@@ -20,6 +20,10 @@
package org.apache.druid.sql.calcite;
import org.apache.calcite.rel.rules.CoreRules;
+import org.apache.druid.query.QueryContexts;
+import
org.apache.druid.query.aggregation.post.FinalizingFieldAccessPostAggregator;
+import org.apache.druid.query.scan.ScanQuery;
+import org.apache.druid.query.timeseries.TimeseriesQuery;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -63,7 +67,41 @@ public @interface DecoupledTestConfig
/**
* Worse plan; may loose vectorization; but no extra queries
*/
- SLIGHTLY_WORSE_PLAN;
+ SLIGHTLY_WORSE_PLAN,
+ /**
+ * {@link TimeseriesQuery} to {@link ScanQuery} change.
+ *
+ * Not yet sure if this is improvement; or some issue
+ */
+ TS_TO_SCAN,
+ /**
+ * GroupBy doesn't sorted?!
+ */
+ GBY_DOESNT_SORT,
+ /**
+ * Equvivalent plan.
+ *
+ * Renamed variable
+ */
+ EQUIV_PLAN,
+ /**
+ * {@link QueryContexts#SQL_JOIN_LEFT_SCAN_DIRECT} not supported.
+ */
+ JOIN_LEFT_DIRECT_ACCESS,
+ /**
+ * Different filter layout.
+ *
+ * Filter is pushed below join to the left.
+ */
+ JOIN_FILTER_LOCATIONS,
+ /**
+ * New scans / etc.
+ */
+ DEFINETLY_WORSE_PLAN,
+ /**
+ * A new {@link FinalizingFieldAccessPostAggregator} appeared in the plan.
+ */
+ FINALIZING_FIELD_ACCESS;
public boolean isPresent()
{
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
b/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
index 31ff6fd079d..4fe39234fad 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
@@ -20,18 +20,27 @@
package org.apache.druid.sql.calcite;
import com.google.common.base.Throwables;
+import junitparams.JUnitParamsRunner;
+import org.apache.commons.lang3.RegExUtils;
import org.apache.druid.error.DruidException;
+import org.apache.druid.java.util.common.ISE;
import org.junit.AssumptionViolatedException;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
+import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
+import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.junit.Assert.assertThrows;
@@ -68,7 +77,6 @@ public @interface NotYetSupported
enum Modes
{
- PLAN_MISMATCH(AssertionError.class, "AssertionError: query #"),
NOT_ENOUGH_RULES(DruidException.class, "not enough rules"),
ERROR_HANDLING(AssertionError.class, "targetPersona: is <[A-Z]+> and
category: is <[A-Z_]+> and errorCode: is"),
EXPRESSION_NOT_GROUPED(DruidException.class, "Expression '[a-z]+' is not
being grouped"),
@@ -83,12 +91,17 @@ public @interface NotYetSupported
INCORRECT_SYNTAX(DruidException.class, "Incorrect syntax near the
keyword"),
// at least c7 is represented oddly in the parquet file
T_ALLTYPES_ISSUES(AssertionError.class,
"(t_alltype|allTypsUniq|fewRowsAllData).parquet.*Verifier.verify"),
- RESULT_MISMATCH(AssertionError.class,
"(assertResultsEquals|AssertionError: column content mismatch)"),
+ RESULT_MISMATCH(AssertionError.class, "(assertResulEquals|AssertionError:
column content mismatch)"),
UNSUPPORTED_NULL_ORDERING(DruidException.class, "(A|DE)SCENDING ordering
with NULLS (LAST|FIRST)"),
- MISSING_JOIN_CONVERSION(DruidException.class, "Missing conversions?
(was|is) (Logical)?Join"),
- MISSING_JOIN_CONVERSION2(AssertionError.class, "Missing conversions?
(was|is) (Logical)?Join"),
UNION_WITH_COMPLEX_OPERAND(DruidException.class, "Only Table and Values
are supported as inputs for Union"),
- UNION_MORE_STRICT_ROWTYPE_CHECK(DruidException.class, "Row signature
mismatch in Union inputs");
+ UNION_MORE_STRICT_ROWTYPE_CHECK(DruidException.class, "Row signature
mismatch in Union inputs"),
+ JOIN_CONDITION_NOT_PUSHED_CONDITION(DruidException.class, "SQL requires a
join with '.*' condition"),
+ JOIN_CONDITION_UNSUPORTED_OPERAND(DruidException.class, "SQL .*
unsupported operand type"),
+ JOIN_TABLE_TABLE(ISE.class, "Cannot handle subquery structure for
dataSource: JoinDataSource"),
+ CORRELATE_CONVERSION(DruidException.class, "Missing conversion( is|s are)
LogicalCorrelate"),
+ SORT_REMOVE_TROUBLE(DruidException.class, "Calcite assertion
violated.*Sort\\.<init>"),
+ STACK_OVERFLOW(StackOverflowError.class, ""),
+ CANNOT_JOIN_LOOKUP_NON_KEY(RuntimeException.class, "Cannot join lookup
with condition referring to non-key");
public Class<? extends Throwable> throwableClass;
public String regex;
@@ -116,7 +129,7 @@ public @interface NotYetSupported
@Override
public Statement apply(Statement base, Description description)
{
- NotYetSupported annotation =
description.getAnnotation(NotYetSupported.class);
+ NotYetSupported annotation = getAnnotation(description,
NotYetSupported.class);
if (annotation == null) {
return base;
@@ -159,5 +172,38 @@ public @interface NotYetSupported
}
};
}
+
+ private static Method getMethodForName(Class<?> testClass, String
realMethodName)
+ {
+ List<Method> matches = Stream.of(testClass.getMethods())
+ .filter(m -> realMethodName.equals(m.getName()))
+ .collect(Collectors.toList());
+ switch (matches.size()) {
+ case 0:
+ throw new IllegalArgumentException("Expected to find method...but
there is none?");
+ case 1:
+ return matches.get(0);
+ default:
+ throw new IllegalArgumentException("method overrides are not
supported");
+ }
+ }
+
+ public static <T extends Annotation> T getAnnotation(Description
description, Class<T> annotationType)
+ {
+ T annotation = description.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ Class<?> testClass = description.getTestClass();
+ RunWith runWith = testClass.getAnnotation(RunWith.class);
+ if (runWith == null || !runWith.value().equals(JUnitParamsRunner.class))
{
+ return null;
+ }
+ String mehodName = description.getMethodName();
+ String realMethodName = RegExUtils.replaceAll(mehodName, "\\(.*", "");
+
+ Method m = getMethodForName(testClass, realMethodName);
+ return m.getAnnotation(annotationType);
+ }
}
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/SqlTestFrameworkConfig.java
b/sql/src/test/java/org/apache/druid/sql/calcite/SqlTestFrameworkConfig.java
index 3a169560b6e..cb66572c53b 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/SqlTestFrameworkConfig.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/SqlTestFrameworkConfig.java
@@ -20,6 +20,7 @@
package org.apache.druid.sql.calcite;
import org.apache.druid.query.topn.TopNQueryConfig;
+import org.apache.druid.sql.calcite.NotYetSupported.NotYetSupportedProcessor;
import org.apache.druid.sql.calcite.util.CacheTestHelperModule.ResultCacheMode;
import org.apache.druid.sql.calcite.util.SqlTestFramework;
import
org.apache.druid.sql.calcite.util.SqlTestFramework.QueryComponentSupplier;
@@ -27,6 +28,7 @@ import org.junit.rules.ExternalResource;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
+import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -119,9 +121,9 @@ public @interface SqlTestFrameworkConfig
return getConfigurationInstance().framework;
}
- public Description getDescription()
+ public <T extends Annotation> T getAnnotation(Class<T> annotationType)
{
- return description;
+ return NotYetSupportedProcessor.getAnnotation(description,
annotationType);
}
private ConfigurationInstance getConfigurationInstance()
@@ -133,12 +135,10 @@ public @interface SqlTestFrameworkConfig
{
return new ConfigurationInstance(config, testHost);
}
-
}
class ConfigurationInstance
{
-
public SqlTestFramework framework;
ConfigurationInstance(SqlTestFrameworkConfig config,
QueryComponentSupplier testHost)
@@ -156,5 +156,4 @@ public @interface SqlTestFrameworkConfig
framework.close();
}
}
-
}
diff --git a/sql/src/test/java/org/apache/druid/sql/http/ResultFormatTest.java
b/sql/src/test/java/org/apache/druid/sql/http/ResultFormatTest.java
index 9f9f8400ffd..37ee6de032a 100644
--- a/sql/src/test/java/org/apache/druid/sql/http/ResultFormatTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/http/ResultFormatTest.java
@@ -21,25 +21,21 @@ package org.apache.druid.sql.http;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import junitparams.JUnitParamsRunner;
-import junitparams.Parameters;
-import org.apache.druid.annotations.UsedByJUnitParamsRunner;
import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.StringUtils;
import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import java.util.EnumSet;
-@RunWith(JUnitParamsRunner.class)
public class ResultFormatTest
{
-
private final ObjectMapper jsonMapper = new DefaultObjectMapper();
- @Test
- @Parameters(source = ResultFormatTypeProvider.class)
+ @ParameterizedTest
+ @MethodSource("provideResultFormats")
public void testSerde(ResultFormat target) throws JsonProcessingException
{
final String json = jsonMapper.writeValueAsString(target);
@@ -56,15 +52,11 @@ public class ResultFormatTest
Assert.assertEquals(ResultFormat.OBJECTLINES,
jsonMapper.readValue("\"oBjEcTlInEs\"", ResultFormat.class));
}
- public static class ResultFormatTypeProvider
+ public static Object[] provideResultFormats()
{
- @UsedByJUnitParamsRunner
- public static Object[] provideResultFormats()
- {
- return EnumSet.allOf(ResultFormat.class)
- .stream()
- .map(format -> new Object[]{format})
- .toArray(Object[]::new);
- }
+ return EnumSet.allOf(ResultFormat.class)
+ .stream()
+ .map(format -> new Object[] {format})
+ .toArray(Object[]::new);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]