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 3c73319898e..e72537c7da5 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 @@ -284,10 +284,10 @@ public class BaseCalciteQueryTest extends CalciteTestBase private static SqlTestFramework queryFramework; final boolean useDefault = NullHandling.replaceWithDefault(); - @Rule + @Rule(order = 1) public ExpectedException expectedException = ExpectedException.none(); - @Rule + @Rule(order = 2) public TemporaryFolder temporaryFolder = new TemporaryFolder(); public boolean cannotVectorize = false; 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 85c690ebba7..99b974aa711 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 @@ -108,6 +108,7 @@ import org.apache.druid.segment.VirtualColumns; import org.apache.druid.segment.column.ColumnType; import org.apache.druid.segment.column.RowSignature; import org.apache.druid.segment.join.JoinType; +import org.apache.druid.sql.calcite.DecoupledIgnore.Modes; import org.apache.druid.sql.calcite.expression.DruidExpression; import org.apache.druid.sql.calcite.filtration.Filtration; import org.apache.druid.sql.calcite.planner.Calcites; @@ -2680,6 +2681,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testGroupByWithSelectAndOrderByProjections() { @@ -2731,6 +2733,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testTopNWithSelectProjections() { @@ -2764,7 +2767,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } - + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testTopNWithSelectAndOrderByProjections() { @@ -2802,6 +2805,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore @Test public void testUnionAllQueries() { @@ -2835,6 +2839,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testUnionAllQueriesWithLimit() { @@ -2863,6 +2868,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore @Test public void testUnionAllDifferentTablesWithMapping() { @@ -2906,6 +2912,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testJoinUnionAllDifferentTablesWithMapping() { @@ -2969,6 +2976,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest } } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testUnionAllTablesColumnTypeMismatchFloatLong() { @@ -3016,6 +3024,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnionAllTablesColumnTypeMismatchStringLong() { @@ -3033,6 +3042,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnionAllTablesWhenMappingIsRequired() { @@ -3049,6 +3059,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnionIsUnplannable() { @@ -3059,6 +3070,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnionAllTablesWhenCastAndMappingIsRequired() { @@ -3074,6 +3086,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore @Test public void testUnionAllSameTableTwice() { @@ -3117,6 +3130,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testUnionAllSameTableTwiceWithSameMapping() { @@ -3160,6 +3174,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnionAllSameTableTwiceWithDifferentMapping() { @@ -3173,7 +3188,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest "SQL requires union between two tables and column names queried for each table are different Left: [dim1, dim2, m1], Right: [dim2, dim1, m1]." ); } - + @DecoupledIgnore @Test public void testUnionAllSameTableThreeTimes() { @@ -3278,6 +3293,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest } } + @DecoupledIgnore @Test public void testUnionAllSameTableThreeTimesWithSameMapping() { @@ -5000,6 +5016,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testGroupByWithSortOnPostAggregationDefault() { @@ -5031,6 +5048,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testGroupByWithSortOnPostAggregationNoTopNConfig() { @@ -5074,6 +5092,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testGroupByWithSortOnPostAggregationNoTopNContext() { @@ -5661,6 +5680,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnplannableScanOrderByNonTime() { @@ -5715,6 +5735,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testUnplannableExactCountDistinctOnSketch() { @@ -6709,6 +6730,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testExactCountDistinctWithGroupingAndOtherAggregators() { @@ -6763,6 +6785,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testMultipleExactCountDistinctWithGroupingAndOtherAggregatorsUsingJoin() { @@ -7284,6 +7307,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testExactCountDistinctUsingSubqueryOnUnionAllTables() { @@ -7458,6 +7482,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testExactCountDistinctUsingSubqueryWithWherePushDown() { @@ -8188,6 +8213,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testFilterOnCurrentTimestampWithIntervalArithmetic() { @@ -8235,6 +8261,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testFilterOnCurrentTimestampOnView() { @@ -10426,6 +10453,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testGroupByTimeFloorAndDimOnGroupByTimeFloorAndDim() { @@ -11592,7 +11620,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } - + @DecoupledIgnore(mode = Modes.CANNOT_CONVERT) @Test public void testPostAggWithTimeseries() { @@ -11636,6 +11664,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testPostAggWithTopN() { @@ -11875,6 +11904,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore @Test public void testRequireTimeConditionPositive() { @@ -12078,6 +12108,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.ERROR_HANDLING) @Test public void testRequireTimeConditionSemiJoinNegative() { @@ -14056,6 +14087,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.PLAN_MISMATCH) @Test public void testPlanWithInFilterLessThanInSubQueryThreshold() { @@ -14376,7 +14408,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ) ); } - + @DecoupledIgnore @Test public void testOrderByAlongWithInternalScanQuery() { @@ -14419,6 +14451,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest ); } + @DecoupledIgnore(mode = Modes.NOT_ENOUGH_RULES) @Test public void testOrderByAlongWithInternalScanQueryNoDistinct() { diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledIgnore.java b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledIgnore.java new file mode 100644 index 00000000000..0c30432d3d6 --- /dev/null +++ b/sql/src/test/java/org/apache/druid/sql/calcite/DecoupledIgnore.java @@ -0,0 +1,111 @@ +/* + * 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.base.Throwables; +import org.apache.druid.error.DruidException; +import org.junit.AssumptionViolatedException; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertThrows; + +/** + * Can be used to mark tests which are not-yet supported in decoupled mode. + * + * In case a testcase marked with this annotation fails - it may mean that the + * testcase no longer needs that annotation. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface DecoupledIgnore +{ + Modes mode() default Modes.NOT_ENOUGH_RULES; + + enum Modes + { + PLAN_MISMATCH(AssertionError.class, "AssertionError: query #"), + NOT_ENOUGH_RULES(DruidException.class, "not enough rules"), + CANNOT_CONVERT(DruidException.class, "Cannot convert query parts"), + ERROR_HANDLING(AssertionError.class, "(is was |is was |with message a string containing)"); + + public Class throwableClass; + public String regex; + + Modes(Class cl, String regex) + { + this.throwableClass = cl; + this.regex = regex; + } + + Pattern getPattern() + { + return Pattern.compile(regex); + } + }; + + /** + * Processes {@link DecoupledIgnore} annotations. + * + * Ensures that test cases disabled with that annotation can still not pass. + * If the error is as expected; the testcase is marked as "ignored". + */ + class DecoupledIgnoreProcessor implements TestRule + { + @Override + public Statement apply(Statement base, Description description) + { + DecoupledIgnore annotation = description.getAnnotation(DecoupledIgnore.class); + if (annotation == null) { + return base; + } + return new Statement() + { + @Override + public void evaluate() + { + Throwable e = assertThrows( + "Expected that this testcase will fail - it might got fixed?", + annotation.mode().throwableClass, + base::evaluate + ); + + String trace = Throwables.getStackTraceAsString(e); + Matcher m = annotation.mode().getPattern().matcher(trace); + + if (!m.find()) { + throw new AssertionError("Exception stactrace doesn't match regex: " + annotation.mode().regex, e); + } + throw new AssumptionViolatedException("Test is not-yet supported in Decoupled mode"); + } + }; + } + } + + +} 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 67a1c0ccd43..c07a9b4e0d4 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 @@ -22,16 +22,20 @@ package org.apache.druid.sql.calcite; import com.google.common.collect.ImmutableMap; import org.apache.druid.query.QueryContexts; import org.apache.druid.server.security.AuthConfig; +import org.apache.druid.sql.calcite.DecoupledIgnore.DecoupledIgnoreProcessor; import org.apache.druid.sql.calcite.planner.PlannerConfig; import org.apache.druid.sql.calcite.util.SqlTestFramework; -import org.junit.Ignore; +import org.junit.Rule; public class DecoupledPlanningCalciteQueryTest extends CalciteQueryTest { + + @Rule(order = 0) + public DecoupledIgnoreProcessor decoupledIgnoreProcessor = new DecoupledIgnoreProcessor(); + private static final ImmutableMap CONTEXT_OVERRIDES = ImmutableMap.of( PlannerConfig.CTX_NATIVE_QUERY_SQL_PLANNING_MODE, PlannerConfig.NATIVE_QUERY_SQL_PLANNING_MODE_DECOUPLED, - QueryContexts.ENABLE_DEBUG, true - ); + QueryContexts.ENABLE_DEBUG, true); @Override protected QueryTestBuilder testBuilder() @@ -49,266 +53,4 @@ public class DecoupledPlanningCalciteQueryTest extends CalciteQueryTest .cannotVectorize(cannotVectorize) .skipVectorize(skipVectorize); } - - - @Override - @Ignore - public void testGroupByWithSelectAndOrderByProjections() - { - - } - - @Override - @Ignore - public void testTopNWithSelectAndOrderByProjections() - { - - } - - @Override - @Ignore - public void testUnionAllQueries() - { - - } - - @Override - @Ignore - public void testUnionAllQueriesWithLimit() - { - - } - - @Override - @Ignore - public void testUnionAllDifferentTablesWithMapping() - { - - } - - @Override - @Ignore - public void testJoinUnionAllDifferentTablesWithMapping() - { - - } - - @Override - @Ignore - public void testUnionAllTablesColumnTypeMismatchFloatLong() - { - - } - - @Override - @Ignore - public void testUnionAllTablesColumnTypeMismatchStringLong() - { - - } - - @Override - @Ignore - public void testUnionAllTablesWhenMappingIsRequired() - { - - } - - @Override - @Ignore - public void testUnionIsUnplannable() - { - - } - - @Override - @Ignore - public void testUnionAllTablesWhenCastAndMappingIsRequired() - { - - } - - @Override - @Ignore - public void testUnionAllSameTableTwice() - { - - } - - @Override - @Ignore - public void testUnionAllSameTableTwiceWithSameMapping() - { - - } - - @Override - @Ignore - public void testUnionAllSameTableTwiceWithDifferentMapping() - { - - } - - @Override - @Ignore - public void testUnionAllSameTableThreeTimes() - { - - } - - @Override - @Ignore - public void testUnionAllSameTableThreeTimesWithSameMapping() - { - - } - - @Override - @Ignore - public void testGroupByWithSortOnPostAggregationDefault() - { - - } - - @Override - @Ignore - public void testGroupByWithSortOnPostAggregationNoTopNConfig() - { - - } - - @Override - @Ignore - public void testGroupByWithSortOnPostAggregationNoTopNContext() - { - - } - - @Override - @Ignore - public void testMultipleExactCountDistinctWithGroupingAndOtherAggregatorsUsingJoin() - { - - } - - @Override - @Ignore - public void testUnplannableExactCountDistinctOnSketch() - { - - } - - @Override - @Ignore - public void testUnplannableScanOrderByNonTime() - { - - } - - @Override - @Ignore - public void testExactCountDistinctUsingSubqueryOnUnionAllTables() - { - - } - - @Override - @Ignore - public void testExactCountDistinctUsingSubqueryWithWherePushDown() - { - - } - - @Override - @Ignore - public void testGroupByTimeFloorAndDimOnGroupByTimeFloorAndDim() - { - - } - - @Override - @Ignore - public void testPostAggWithTimeseries() - { - - } - - @Override - @Ignore - public void testPostAggWithTopN() - { - - } - - @Override - @Ignore - public void testRequireTimeConditionPositive() - { - - } - - @Override - public void testRequireTimeConditionSemiJoinNegative() - { - - } - - @Override - @Ignore - public void testOrderByAlongWithInternalScanQuery() - { - - } - - @Override - @Ignore - public void testOrderByAlongWithInternalScanQueryNoDistinct() - { - - } - - @Override - @Ignore - public void testFilterOnCurrentTimestampWithIntervalArithmetic() - { - - } - - @Override - @Ignore - public void testFilterOnCurrentTimestampOnView() - { - - } - - // When run through decoupled, it expects - // dimensions=[DefaultDimensionSpec{dimension='dim2', outputName='d0', outputType='STRING'}, - // DefaultDimensionSpec{dimension='dim1', outputName='d1', outputType='STRING'}] - // - // but gets - // dimensions=[DefaultDimensionSpec{dimension='dim1', outputName='d0', outputType='STRING'}, - // DefaultDimensionSpec{dimension='dim2', outputName='d1', outputType='STRING'}] - // - // The change in the ordering fails the query plan exact match. This needs to be revisited - // when we make more advancements into the decoupled planner - @Override - @Ignore - public void testExactCountDistinctWithGroupingAndOtherAggregators() - { - - } - - @Override - @Ignore - public void testTopNWithSelectProjections() - { - - } - - @Override - @Ignore - public void testPlanWithInFilterLessThanInSubQueryThreshold() - { - - } }