mirror of https://github.com/apache/druid.git
Fix Stack overflow with infinite loop in ReduceExpressionsRule of HepProgram (#10120)
* Fix Stack overflow with SELECT ARRAY ['Hello', NULL] * address comments
This commit is contained in:
parent
477335abb4
commit
1676ba22e3
|
@ -26,10 +26,13 @@ import org.apache.calcite.plan.RelOptMaterialization;
|
||||||
import org.apache.calcite.plan.RelOptPlanner;
|
import org.apache.calcite.plan.RelOptPlanner;
|
||||||
import org.apache.calcite.plan.RelOptRule;
|
import org.apache.calcite.plan.RelOptRule;
|
||||||
import org.apache.calcite.plan.RelTraitSet;
|
import org.apache.calcite.plan.RelTraitSet;
|
||||||
|
import org.apache.calcite.plan.hep.HepProgram;
|
||||||
|
import org.apache.calcite.plan.hep.HepProgramBuilder;
|
||||||
import org.apache.calcite.plan.volcano.AbstractConverter;
|
import org.apache.calcite.plan.volcano.AbstractConverter;
|
||||||
import org.apache.calcite.rel.RelNode;
|
import org.apache.calcite.rel.RelNode;
|
||||||
import org.apache.calcite.rel.core.RelFactories;
|
import org.apache.calcite.rel.core.RelFactories;
|
||||||
import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
|
import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
|
||||||
|
import org.apache.calcite.rel.metadata.RelMetadataProvider;
|
||||||
import org.apache.calcite.rel.rules.AggregateCaseToFilterRule;
|
import org.apache.calcite.rel.rules.AggregateCaseToFilterRule;
|
||||||
import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
|
import org.apache.calcite.rel.rules.AggregateExpandDistinctAggregatesRule;
|
||||||
import org.apache.calcite.rel.rules.AggregateJoinTransposeRule;
|
import org.apache.calcite.rel.rules.AggregateJoinTransposeRule;
|
||||||
|
@ -85,6 +88,16 @@ public class Rules
|
||||||
public static final int DRUID_CONVENTION_RULES = 0;
|
public static final int DRUID_CONVENTION_RULES = 0;
|
||||||
public static final int BINDABLE_CONVENTION_RULES = 1;
|
public static final int BINDABLE_CONVENTION_RULES = 1;
|
||||||
|
|
||||||
|
// Due to Calcite bug (CALCITE-3845), ReduceExpressionsRule can considered expression which is the same as the
|
||||||
|
// previous input expression as reduced. Basically, the expression is actually not reduced but is still considered as
|
||||||
|
// reduced. Hence, this resulted in an infinite loop of Calcite trying to reducing the same expression over and over.
|
||||||
|
// Calcite 1.23.0 fixes this issue by not consider expression as reduced if this case happens. However, while
|
||||||
|
// we are still using Calcite 1.21.0, a workaround is to limit the number of pattern matches to avoid infinite loop.
|
||||||
|
private static final String HEP_DEFAULT_MATCH_LIMIT_CONFIG_STRING = "druid.sql.planner.hepMatchLimit";
|
||||||
|
private static final int HEP_DEFAULT_MATCH_LIMIT = Integer.valueOf(
|
||||||
|
System.getProperty(HEP_DEFAULT_MATCH_LIMIT_CONFIG_STRING, "1200")
|
||||||
|
);
|
||||||
|
|
||||||
// Rules from RelOptUtil's registerBaseRules, minus:
|
// Rules from RelOptUtil's registerBaseRules, minus:
|
||||||
//
|
//
|
||||||
// 1) AggregateExpandDistinctAggregatesRule (it'll be added back later if approximate count distinct is disabled)
|
// 1) AggregateExpandDistinctAggregatesRule (it'll be added back later if approximate count distinct is disabled)
|
||||||
|
@ -191,12 +204,14 @@ public class Rules
|
||||||
|
|
||||||
public static List<Program> programs(final PlannerContext plannerContext, final QueryMaker queryMaker)
|
public static List<Program> programs(final PlannerContext plannerContext, final QueryMaker queryMaker)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// Program that pre-processes the tree before letting the full-on VolcanoPlanner loose.
|
// Program that pre-processes the tree before letting the full-on VolcanoPlanner loose.
|
||||||
final Program preProgram =
|
final Program preProgram =
|
||||||
Programs.sequence(
|
Programs.sequence(
|
||||||
Programs.subQuery(DefaultRelMetadataProvider.INSTANCE),
|
Programs.subQuery(DefaultRelMetadataProvider.INSTANCE),
|
||||||
DecorrelateAndTrimFieldsProgram.INSTANCE,
|
DecorrelateAndTrimFieldsProgram.INSTANCE,
|
||||||
Programs.hep(REDUCTION_RULES, true, DefaultRelMetadataProvider.INSTANCE)
|
buildHepProgram(REDUCTION_RULES, true, DefaultRelMetadataProvider.INSTANCE, HEP_DEFAULT_MATCH_LIMIT)
|
||||||
);
|
);
|
||||||
|
|
||||||
return ImmutableList.of(
|
return ImmutableList.of(
|
||||||
|
@ -205,6 +220,19 @@ public class Rules
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Program buildHepProgram(Iterable<? extends RelOptRule> rules,
|
||||||
|
boolean noDag,
|
||||||
|
RelMetadataProvider metadataProvider,
|
||||||
|
int matchLimit)
|
||||||
|
{
|
||||||
|
final HepProgramBuilder builder = HepProgram.builder();
|
||||||
|
builder.addMatchLimit(matchLimit);
|
||||||
|
for (RelOptRule rule : rules) {
|
||||||
|
builder.addRuleInstance(rule);
|
||||||
|
}
|
||||||
|
return Programs.of(builder.build(), noDag, metadataProvider);
|
||||||
|
}
|
||||||
|
|
||||||
private static List<RelOptRule> druidConventionRuleSet(
|
private static List<RelOptRule> druidConventionRuleSet(
|
||||||
final PlannerContext plannerContext,
|
final PlannerContext plannerContext,
|
||||||
final QueryMaker queryMaker
|
final QueryMaker queryMaker
|
||||||
|
|
|
@ -139,6 +139,19 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpressionContainingNull() throws Exception
|
||||||
|
{
|
||||||
|
List<String> expectedResult = new ArrayList<>();
|
||||||
|
expectedResult.add("Hello");
|
||||||
|
expectedResult.add(null);
|
||||||
|
testQuery(
|
||||||
|
"SELECT ARRAY ['Hello', NULL]",
|
||||||
|
ImmutableList.of(),
|
||||||
|
ImmutableList.of(new Object[]{expectedResult})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectNonNumericNumberLiterals() throws Exception
|
public void testSelectNonNumericNumberLiterals() throws Exception
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue