Skip to content

Commit 2de7856

Browse files
Vladsz83alex-plekhanov
authored andcommitted
IGNITE-27397 SQL Calcite: Add dynamic configuration to disable a rule globally - Fixes #12595.
Signed-off-by: Aleksey Plekhanov <[email protected]>
1 parent 71447db commit 2de7856

File tree

9 files changed

+476
-68
lines changed

9 files changed

+476
-68
lines changed

modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ public ExecutionService<Object[]> executionService() {
398398
/** {@inheritDoc} */
399399
@Override public void onKernalStart(boolean active) {
400400
onStart(ctx,
401+
distrCfg,
401402
executionSvc,
402403
mailboxRegistry,
403404
partSvc,
@@ -407,7 +408,8 @@ public ExecutionService<Object[]> executionService() {
407408
mappingSvc,
408409
qryPlanCache,
409410
exchangeSvc,
410-
qryReg
411+
qryReg,
412+
prepareSvc
411413
);
412414

413415
started = true;
@@ -419,6 +421,7 @@ public ExecutionService<Object[]> executionService() {
419421
started = false;
420422

421423
onStop(
424+
prepareSvc,
422425
qryReg,
423426
executionSvc,
424427
mailboxRegistry,
@@ -428,7 +431,8 @@ public ExecutionService<Object[]> executionService() {
428431
taskExecutor,
429432
mappingSvc,
430433
qryPlanCache,
431-
exchangeSvc
434+
exchangeSvc,
435+
distrCfg
432436
);
433437
}
434438
}

modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/DistributedCalciteConfiguration.java

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,109 @@
1717

1818
package org.apache.ignite.internal.processors.query.calcite;
1919

20+
import java.util.Objects;
21+
import java.util.stream.Stream;
2022
import org.apache.ignite.IgniteLogger;
2123
import org.apache.ignite.internal.GridKernalContext;
24+
import org.apache.ignite.internal.processors.configuration.distributed.DistributePropertyListener;
25+
import org.apache.ignite.internal.processors.configuration.distributed.DistributedChangeableProperty;
26+
import org.apache.ignite.internal.processors.configuration.distributed.DistributedPropertyDispatcher;
27+
import org.apache.ignite.internal.processors.configuration.distributed.SimpleDistributedProperty;
2228
import org.apache.ignite.internal.processors.query.DistributedSqlConfiguration;
29+
import org.apache.ignite.internal.processors.query.calcite.prepare.QueryPlanCache;
30+
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
31+
import org.apache.ignite.internal.processors.query.calcite.util.LifecycleAware;
32+
import org.apache.ignite.internal.processors.query.calcite.util.Service;
33+
import org.apache.ignite.internal.util.typedef.F;
34+
35+
import static org.apache.ignite.internal.cluster.DistributedConfigurationUtils.setDefaultValue;
2336

2437
/** Distributed Calcite-engine configuration. */
25-
public class DistributedCalciteConfiguration extends DistributedSqlConfiguration {
38+
public class DistributedCalciteConfiguration extends DistributedSqlConfiguration implements Service, LifecycleAware {
39+
/** Globally disabled rules property name. */
40+
public static final String DISABLED_RULES_PROPERTY_NAME = "sql.calcite.disabledRules";
41+
42+
/** Default value of the disabled rules. */
43+
public static final String[] DFLT_DISABLED_RULES = new String[0];
44+
45+
/** Globally disabled rules. */
46+
private volatile DistributedChangeableProperty<String[]> disabledRules;
47+
48+
/** */
49+
private QueryPlanCache qryPlanCache;
50+
2651
/** */
2752
public DistributedCalciteConfiguration(GridKernalContext ctx, IgniteLogger log) {
2853
super(ctx, log);
2954
}
55+
56+
/** {@inheritDoc} */
57+
@Override public void onStart(GridKernalContext ctx) {
58+
CalciteQueryProcessor proc = Objects.requireNonNull(Commons.lookupComponent(ctx, CalciteQueryProcessor.class));
59+
60+
assert proc != null;
61+
62+
qryPlanCache = proc.queryPlanCache();
63+
}
64+
65+
/** {@inheritDoc} */
66+
@Override public void onStop() {
67+
// No-op.
68+
}
69+
70+
/**
71+
* @return Globally disabled planning rules.
72+
* @see #DISABLED_RULES_PROPERTY_NAME
73+
*/
74+
public String[] disabledRules() {
75+
DistributedChangeableProperty<String[]> disabledRules = this.disabledRules;
76+
77+
String[] res = disabledRules == null ? DFLT_DISABLED_RULES : disabledRules.get();
78+
79+
return res != null ? res : DFLT_DISABLED_RULES;
80+
}
81+
82+
/** {@inheritDoc} */
83+
@Override protected void onReadyToRegister(DistributedPropertyDispatcher dispatcher) {
84+
super.onReadyToRegister(dispatcher);
85+
86+
registerProperty(
87+
dispatcher,
88+
DISABLED_RULES_PROPERTY_NAME,
89+
prop -> disabledRules = prop,
90+
() -> new SimpleDistributedProperty<>(
91+
DISABLED_RULES_PROPERTY_NAME,
92+
str -> Stream.of(str.split(",")).map(String::trim).filter(s -> !s.isBlank()).toArray(String[]::new),
93+
"Comma-separated list of Calcite's disabled planning rules. NOTE: cleans the planning cache on change."
94+
),
95+
log
96+
);
97+
98+
disabledRules.addListener(new DistributePropertyListener<>() {
99+
@Override public void onUpdate(String name, String[] oldVal, String[] newVal) {
100+
if (oldVal != null && F.compareArrays(oldVal, newVal) != 0) {
101+
if (qryPlanCache != null) {
102+
if (log.isInfoEnabled()) {
103+
log.info("Cleaning Calcite's cache plan by changing of the property '"
104+
+ DISABLED_RULES_PROPERTY_NAME + "'.");
105+
}
106+
107+
qryPlanCache.clear();
108+
}
109+
}
110+
}
111+
});
112+
}
113+
114+
/** {@inheritDoc} */
115+
@Override protected void onReadyToWrite() {
116+
super.onReadyToWrite();
117+
118+
setDefaultValue(disabledRules, DFLT_DISABLED_RULES, log);
119+
}
120+
121+
/** */
122+
DistributedChangeableProperty<String[]> disabledRulesProperty() {
123+
return disabledRules;
124+
}
30125
}

modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgnitePlanner.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.Reader;
2222
import java.io.StringWriter;
2323
import java.util.ArrayList;
24+
import java.util.Arrays;
2425
import java.util.Collection;
2526
import java.util.Collections;
2627
import java.util.HashMap;
@@ -29,6 +30,8 @@
2930
import java.util.Map;
3031
import java.util.Objects;
3132
import java.util.Set;
33+
import java.util.function.Function;
34+
import java.util.stream.Collectors;
3235
import com.google.common.collect.ImmutableList;
3336
import org.apache.calcite.plan.Context;
3437
import org.apache.calcite.plan.RelOptCluster;
@@ -80,6 +83,7 @@
8083
import org.apache.calcite.tools.FrameworkConfig;
8184
import org.apache.calcite.tools.Planner;
8285
import org.apache.calcite.tools.Program;
86+
import org.apache.calcite.tools.RuleSet;
8387
import org.apache.calcite.tools.RuleSets;
8488
import org.apache.calcite.tools.ValidationException;
8589
import org.apache.calcite.util.Pair;
@@ -724,16 +728,7 @@ public void addDisabledRules(Collection<String> disabledRuleNames) {
724728
if (F.isEmpty(disabledRuleNames))
725729
return;
726730

727-
ctx.addRulesFilter(rulesSet -> {
728-
List<RelOptRule> newSet = new ArrayList<>();
729-
730-
for (RelOptRule r : rulesSet) {
731-
if (!disabledRuleNames.contains(shortRuleName(r.toString())))
732-
newSet.add(r);
733-
}
734-
735-
return RuleSets.ofList(newSet);
736-
});
731+
ctx.addRulesFilter(new DisabledRuleFilter(disabledRuleNames));
737732
}
738733

739734
/** */
@@ -746,6 +741,34 @@ private static String shortRuleName(String ruleDesc) {
746741
return ruleDesc.substring(0, pos);
747742
}
748743

744+
/** */
745+
public static final class DisabledRuleFilter implements Function<RuleSet, RuleSet> {
746+
/** */
747+
private final Set<String> ruleNames;
748+
749+
/** */
750+
public DisabledRuleFilter(Collection<String> ruleNames) {
751+
this.ruleNames = ruleNames.stream().map(ruleName -> ruleName.trim().toUpperCase()).collect(Collectors.toSet());
752+
}
753+
754+
/** */
755+
public DisabledRuleFilter(String[] ruleNames) {
756+
this(Arrays.asList(ruleNames));
757+
}
758+
759+
/** {@inheritDoc} */
760+
@Override public RuleSet apply(RuleSet rules) {
761+
List<RelOptRule> newSet = new ArrayList<>();
762+
763+
for (RelOptRule r : rules) {
764+
if (!ruleNames.contains(shortRuleName(r.toString()).toUpperCase()))
765+
newSet.add(r);
766+
}
767+
768+
return RuleSets.ofList(newSet);
769+
}
770+
}
771+
749772
/** */
750773
private static class VolcanoPlannerExt extends VolcanoPlanner {
751774
/** */

modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PrepareServiceImpl.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
package org.apache.ignite.internal.processors.query.calcite.prepare;
1919

2020
import java.util.List;
21-
21+
import java.util.Objects;
2222
import org.apache.calcite.plan.RelOptPlanner;
2323
import org.apache.calcite.plan.RelOptUtil;
2424
import org.apache.calcite.rel.type.RelDataType;
@@ -35,11 +35,15 @@
3535
import org.apache.ignite.internal.GridKernalContext;
3636
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
3737
import org.apache.ignite.internal.processors.query.IgniteSQLException;
38+
import org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
39+
import org.apache.ignite.internal.processors.query.calcite.DistributedCalciteConfiguration;
3840
import org.apache.ignite.internal.processors.query.calcite.prepare.ddl.DdlSqlToCommandConverter;
3941
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
4042
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
4143
import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
44+
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
4245
import org.apache.ignite.internal.processors.query.calcite.util.TypeUtils;
46+
import org.apache.ignite.internal.util.typedef.F;
4347
import org.apache.ignite.internal.util.typedef.T2;
4448
import org.jetbrains.annotations.Nullable;
4549

@@ -58,6 +62,9 @@ public class PrepareServiceImpl extends AbstractService implements PrepareServic
5862
/** */
5963
private final PlanExtractor planExtractor;
6064

65+
/** */
66+
private DistributedCalciteConfiguration distrCfg;
67+
6168
/**
6269
* @param ctx Kernal.
6370
*/
@@ -71,6 +78,12 @@ public PrepareServiceImpl(GridKernalContext ctx) {
7178
/** {@inheritDoc} */
7279
@Override public void onStart(GridKernalContext ctx) {
7380
super.onStart(ctx);
81+
82+
CalciteQueryProcessor proc = Objects.requireNonNull(Commons.lookupComponent(ctx, CalciteQueryProcessor.class));
83+
84+
assert proc != null;
85+
86+
distrCfg = proc.distributedConfiguration();
7487
}
7588

7689
/** {@inheritDoc} */
@@ -80,6 +93,13 @@ public PrepareServiceImpl(GridKernalContext ctx) {
8093

8194
ctx.planner().reset();
8295

96+
assert distrCfg != null;
97+
98+
String[] disbledRules = distrCfg.disabledRules();
99+
100+
if (!F.isEmpty(disbledRules))
101+
ctx.addRulesFilter(new IgnitePlanner.DisabledRuleFilter(disbledRules));
102+
83103
if (SqlKind.DDL.contains(sqlNode.getKind()))
84104
return prepareDdl(sqlNode, ctx);
85105

0 commit comments

Comments
 (0)