[fix](planner) infer predicate could generate predicates in another scope (#13691)
* [fix](planner) infer predicate could generate predicates in another scope
This commit is contained in:
@ -239,6 +239,59 @@ public class Analyzer {
|
||||
return globalState.autoBroadcastJoinThreshold;
|
||||
}
|
||||
|
||||
private static class InferPredicateState {
|
||||
// map from two table tuple ids to JoinOperator between two tables.
|
||||
// NOTE: first tupleId's position in front of the second tupleId.
|
||||
public final Map<Pair<TupleId, TupleId>, JoinOperator> anyTwoTalesJoinOperator = Maps.newHashMap();
|
||||
|
||||
// slotEqSlotExpr: Record existing and infer equivalent connections
|
||||
private final List<Expr> onSlotEqSlotExpr = new ArrayList<>();
|
||||
|
||||
// slotEqSlotDeDuplication: De-Duplication for slotEqSlotExpr
|
||||
private final Set<Pair<Expr, Expr>> onSlotEqSlotDeDuplication = Sets.newHashSet();
|
||||
|
||||
// slotToLiteralExpr: Record existing and infer expr which slot and literal are equal
|
||||
private final List<Expr> onSlotToLiteralExpr = new ArrayList<>();
|
||||
|
||||
// slotToLiteralDeDuplication: De-Duplication for slotToLiteralExpr
|
||||
private final Set<Pair<Expr, Expr>> onSlotToLiteralDeDuplication = Sets.newHashSet();
|
||||
|
||||
// inExpr: Recoud existing and infer expr which in predicate
|
||||
private final List<Expr> onInExpr = new ArrayList<>();
|
||||
|
||||
// inExprDeDuplication: De-Duplication for inExpr
|
||||
private final Set<Expr> onInDeDuplication = Sets.newHashSet();
|
||||
|
||||
// isNullExpr: Record existing and infer not null predicate
|
||||
private final List<Expr> onIsNullExpr = new ArrayList<>();
|
||||
|
||||
//isNullDeDuplication: De-Duplication for isNullExpr
|
||||
private final Set<Expr> onIsNullDeDuplication = Sets.newHashSet();
|
||||
|
||||
// slotToLiteralDeDuplication: De-Duplication for slotToLiteralExpr. Contain on and where.
|
||||
private final Set<Pair<Expr, Expr>> globalSlotToLiteralDeDuplication = Sets.newHashSet();
|
||||
|
||||
// inExprDeDuplication: De-Duplication for inExpr. Contain on and where
|
||||
private final Set<Expr> globalInDeDuplication = Sets.newHashSet();
|
||||
|
||||
public InferPredicateState() {
|
||||
}
|
||||
|
||||
public InferPredicateState(InferPredicateState that) {
|
||||
anyTwoTalesJoinOperator.putAll(that.anyTwoTalesJoinOperator);
|
||||
onSlotEqSlotExpr.addAll(that.onSlotEqSlotExpr);
|
||||
onSlotEqSlotDeDuplication.addAll(that.onSlotEqSlotDeDuplication);
|
||||
onSlotToLiteralExpr.addAll(that.onSlotToLiteralExpr);
|
||||
onSlotToLiteralDeDuplication.addAll(that.onSlotToLiteralDeDuplication);
|
||||
onInExpr.addAll(that.onInExpr);
|
||||
onInDeDuplication.addAll(that.onInDeDuplication);
|
||||
onIsNullExpr.addAll(that.onIsNullExpr);
|
||||
onIsNullDeDuplication.addAll(that.onIsNullDeDuplication);
|
||||
globalSlotToLiteralDeDuplication.addAll(that.globalSlotToLiteralDeDuplication);
|
||||
globalInDeDuplication.addAll(that.globalInDeDuplication);
|
||||
}
|
||||
}
|
||||
|
||||
// state shared between all objects of an Analyzer tree
|
||||
// TODO: Many maps here contain properties about tuples, e.g., whether
|
||||
// a tuple is outer/semi joined, etc. Remove the maps in favor of making
|
||||
@ -322,40 +375,6 @@ public class Analyzer {
|
||||
// TODO chenhao16, to save conjuncts, which children are constant
|
||||
public final Map<TupleId, Set<Expr>> constantConjunct = Maps.newHashMap();
|
||||
|
||||
// map from two table tuple ids to JoinOperator between two tables.
|
||||
// NOTE: first tupleId's position in front of the second tupleId.
|
||||
public final Map<Pair<TupleId, TupleId>, JoinOperator> anyTwoTalesJoinOperator = Maps.newHashMap();
|
||||
|
||||
// slotEqSlotExpr: Record existing and infer equivalent connections
|
||||
private final List<Expr> onSlotEqSlotExpr = new ArrayList<>();
|
||||
|
||||
// slotEqSlotDeDuplication: De-Duplication for slotEqSlotExpr
|
||||
private final Set<Pair<Expr, Expr>> onSlotEqSlotDeDuplication = Sets.newHashSet();
|
||||
|
||||
// slotToLiteralExpr: Record existing and infer expr which slot and literal are equal
|
||||
private final List<Expr> onSlotToLiteralExpr = new ArrayList<>();
|
||||
|
||||
// slotToLiteralDeDuplication: De-Duplication for slotToLiteralExpr
|
||||
private final Set<Pair<Expr, Expr>> onSlotToLiteralDeDuplication = Sets.newHashSet();
|
||||
|
||||
// inExpr: Recoud existing and infer expr which in predicate
|
||||
private final List<Expr> onInExpr = new ArrayList<>();
|
||||
|
||||
// inExprDeDuplication: De-Duplication for inExpr
|
||||
private final Set<Expr> onInDeDuplication = Sets.newHashSet();
|
||||
|
||||
// isNullExpr: Record existing and infer not null predicate
|
||||
private final List<Expr> onIsNullExpr = new ArrayList<>();
|
||||
|
||||
//isNullDeDuplication: De-Duplication for isNullExpr
|
||||
private final Set<Expr> onIsNullDeDuplication = Sets.newHashSet();
|
||||
|
||||
// slotToLiteralDeDuplication: De-Duplication for slotToLiteralExpr. Contain on and where.
|
||||
private final Set<Pair<Expr, Expr>> globalSlotToLiteralDeDuplication = Sets.newHashSet();
|
||||
|
||||
// inExprDeDuplication: De-Duplication for inExpr. Contain on and where
|
||||
private final Set<Expr> globalInDeDuplication = Sets.newHashSet();
|
||||
|
||||
// map from slot id to the analyzer/block in which it was registered
|
||||
private final Map<SlotId, Analyzer> blockBySlot = Maps.newHashMap();
|
||||
|
||||
@ -426,6 +445,8 @@ public class Analyzer {
|
||||
|
||||
private final GlobalState globalState;
|
||||
|
||||
private final InferPredicateState inferPredicateState;
|
||||
|
||||
// An analyzer stores analysis state for a single select block. A select block can be
|
||||
// a top level select statement, or an inline view select block.
|
||||
// ancestors contains the Analyzers of the enclosing select blocks of 'this'
|
||||
@ -460,6 +481,7 @@ public class Analyzer {
|
||||
public Analyzer(Env env, ConnectContext context) {
|
||||
ancestors = Lists.newArrayList();
|
||||
globalState = new GlobalState(env, context);
|
||||
inferPredicateState = new InferPredicateState();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -469,7 +491,7 @@ public class Analyzer {
|
||||
* @param parentAnalyzer the analyzer of the enclosing select block
|
||||
*/
|
||||
public Analyzer(Analyzer parentAnalyzer) {
|
||||
this(parentAnalyzer, parentAnalyzer.globalState);
|
||||
this(parentAnalyzer, parentAnalyzer.globalState, parentAnalyzer.inferPredicateState);
|
||||
if (parentAnalyzer.isSubquery) {
|
||||
this.isSubquery = true;
|
||||
}
|
||||
@ -478,10 +500,11 @@ public class Analyzer {
|
||||
/**
|
||||
* Analyzer constructor for nested select block with the specified global state.
|
||||
*/
|
||||
private Analyzer(Analyzer parentAnalyzer, GlobalState globalState) {
|
||||
private Analyzer(Analyzer parentAnalyzer, GlobalState globalState, InferPredicateState inferPredicateState) {
|
||||
ancestors = Lists.newArrayList(parentAnalyzer);
|
||||
ancestors.addAll(parentAnalyzer.ancestors);
|
||||
this.globalState = globalState;
|
||||
this.inferPredicateState = new InferPredicateState(inferPredicateState);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -490,7 +513,7 @@ public class Analyzer {
|
||||
*/
|
||||
public static Analyzer createWithNewGlobalState(Analyzer parentAnalyzer) {
|
||||
GlobalState globalState = new GlobalState(parentAnalyzer.globalState.env, parentAnalyzer.getContext());
|
||||
return new Analyzer(parentAnalyzer, globalState);
|
||||
return new Analyzer(parentAnalyzer, globalState, new InferPredicateState());
|
||||
}
|
||||
|
||||
public void setIsExplain() {
|
||||
@ -1038,47 +1061,47 @@ public class Analyzer {
|
||||
if (joinOperator == null) {
|
||||
joinOperator = JoinOperator.INNER_JOIN;
|
||||
}
|
||||
globalState.anyTwoTalesJoinOperator.put(tids, joinOperator);
|
||||
inferPredicateState.anyTwoTalesJoinOperator.put(tids, joinOperator);
|
||||
}
|
||||
|
||||
public void registerOnSlotEqSlotExpr(Expr expr) {
|
||||
globalState.onSlotEqSlotExpr.add(expr);
|
||||
inferPredicateState.onSlotEqSlotExpr.add(expr);
|
||||
}
|
||||
|
||||
public void registerOnSlotEqSlotDeDuplication(Pair<Expr, Expr> pair) {
|
||||
globalState.onSlotEqSlotDeDuplication.add(pair);
|
||||
inferPredicateState.onSlotEqSlotDeDuplication.add(pair);
|
||||
}
|
||||
|
||||
public void registerOnSlotToLiteralExpr(Expr expr) {
|
||||
globalState.onSlotToLiteralExpr.add(expr);
|
||||
inferPredicateState.onSlotToLiteralExpr.add(expr);
|
||||
}
|
||||
|
||||
public void registerOnSlotToLiteralDeDuplication(Pair<Expr, Expr> pair) {
|
||||
globalState.onSlotToLiteralDeDuplication.add(pair);
|
||||
inferPredicateState.onSlotToLiteralDeDuplication.add(pair);
|
||||
}
|
||||
|
||||
public void registerInExpr(Expr expr) {
|
||||
globalState.onInExpr.add(expr);
|
||||
inferPredicateState.onInExpr.add(expr);
|
||||
}
|
||||
|
||||
public void registerInDeDuplication(Expr expr) {
|
||||
globalState.onInDeDuplication.add(expr);
|
||||
inferPredicateState.onInDeDuplication.add(expr);
|
||||
}
|
||||
|
||||
public void registerOnIsNullExpr(Expr expr) {
|
||||
globalState.onIsNullExpr.add(expr);
|
||||
inferPredicateState.onIsNullExpr.add(expr);
|
||||
}
|
||||
|
||||
public void registerOnIsNullDeDuplication(Expr expr) {
|
||||
globalState.onIsNullDeDuplication.add(expr);
|
||||
inferPredicateState.onIsNullDeDuplication.add(expr);
|
||||
}
|
||||
|
||||
public void registerGlobalSlotToLiteralDeDuplication(Pair<Expr, Expr> pair) {
|
||||
globalState.globalSlotToLiteralDeDuplication.add(pair);
|
||||
inferPredicateState.globalSlotToLiteralDeDuplication.add(pair);
|
||||
}
|
||||
|
||||
public void registerGlobalInDeDuplication(Expr expr) {
|
||||
globalState.globalInDeDuplication.add(expr);
|
||||
inferPredicateState.globalInDeDuplication.add(expr);
|
||||
}
|
||||
|
||||
public void registerConjunct(Expr e, TupleId tupleId) throws AnalysisException {
|
||||
@ -1417,11 +1440,11 @@ public class Analyzer {
|
||||
* Return JoinOperator between two tables
|
||||
*/
|
||||
public JoinOperator getAnyTwoTablesJoinOp(Pair<TupleId, TupleId> tids) {
|
||||
return globalState.anyTwoTalesJoinOperator.get(tids);
|
||||
return inferPredicateState.anyTwoTalesJoinOperator.get(tids);
|
||||
}
|
||||
|
||||
public boolean isContainTupleIds(Pair<TupleId, TupleId> tids) {
|
||||
return globalState.anyTwoTalesJoinOperator.containsKey(tids);
|
||||
return inferPredicateState.anyTwoTalesJoinOperator.containsKey(tids);
|
||||
}
|
||||
|
||||
public boolean isWhereClauseConjunct(Expr e) {
|
||||
@ -1518,43 +1541,43 @@ public class Analyzer {
|
||||
}
|
||||
|
||||
public List<Expr> getOnSlotEqSlotExpr() {
|
||||
return new ArrayList<>(globalState.onSlotEqSlotExpr);
|
||||
return new ArrayList<>(inferPredicateState.onSlotEqSlotExpr);
|
||||
}
|
||||
|
||||
public Set<Pair<Expr, Expr>> getOnSlotEqSlotDeDuplication() {
|
||||
return Sets.newHashSet(globalState.onSlotEqSlotDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.onSlotEqSlotDeDuplication);
|
||||
}
|
||||
|
||||
public List<Expr> getOnSlotToLiteralExpr() {
|
||||
return new ArrayList<>(globalState.onSlotToLiteralExpr);
|
||||
return new ArrayList<>(inferPredicateState.onSlotToLiteralExpr);
|
||||
}
|
||||
|
||||
public Set<Pair<Expr, Expr>> getOnSlotToLiteralDeDuplication() {
|
||||
return Sets.newHashSet(globalState.onSlotToLiteralDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.onSlotToLiteralDeDuplication);
|
||||
}
|
||||
|
||||
public List<Expr> getInExpr() {
|
||||
return new ArrayList<>(globalState.onInExpr);
|
||||
return new ArrayList<>(inferPredicateState.onInExpr);
|
||||
}
|
||||
|
||||
public Set<Expr> getInDeDuplication() {
|
||||
return Sets.newHashSet(globalState.onInDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.onInDeDuplication);
|
||||
}
|
||||
|
||||
public List<Expr> getOnIsNullExpr() {
|
||||
return new ArrayList<>(globalState.onIsNullExpr);
|
||||
return new ArrayList<>(inferPredicateState.onIsNullExpr);
|
||||
}
|
||||
|
||||
public Set<Expr> getOnIsNullDeDuplication() {
|
||||
return Sets.newHashSet(globalState.onIsNullDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.onIsNullDeDuplication);
|
||||
}
|
||||
|
||||
public Set<Pair<Expr, Expr>> getGlobalSlotToLiteralDeDuplication() {
|
||||
return Sets.newHashSet(globalState.globalSlotToLiteralDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.globalSlotToLiteralDeDuplication);
|
||||
}
|
||||
|
||||
public Set<Expr> getGlobalInDeDuplication() {
|
||||
return Sets.newHashSet(globalState.globalInDeDuplication);
|
||||
return Sets.newHashSet(inferPredicateState.globalInDeDuplication);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
114
regression-test/suites/correctness/test_infer_predicate.groovy
Normal file
114
regression-test/suites/correctness/test_infer_predicate.groovy
Normal file
@ -0,0 +1,114 @@
|
||||
// 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.
|
||||
|
||||
suite("test_infer_predicate") {
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t1 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t2 """
|
||||
sql """ DROP VIEW IF EXISTS infer_predicate_v1 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t4 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t5 """
|
||||
sql"""
|
||||
CREATE TABLE infer_predicate_t2 (
|
||||
a varchar(1) NULL COMMENT "",
|
||||
x varchar(1) NULL COMMENT "",
|
||||
c varchar(1) NULL COMMENT ""
|
||||
) ENGINE=OLAP
|
||||
UNIQUE KEY(a)
|
||||
DISTRIBUTED BY HASH(a) BUCKETS 8
|
||||
PROPERTIES (
|
||||
"replication_allocation" = "tag.location.default:1",
|
||||
"in_memory" = "false",
|
||||
"storage_format" = "V2"
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
sql"""
|
||||
CREATE TABLE infer_predicate_t5 (
|
||||
x varchar(5) NULL COMMENT "",
|
||||
d varchar(3) NULL COMMENT ""
|
||||
) ENGINE=OLAP
|
||||
UNIQUE KEY(x)
|
||||
DISTRIBUTED BY HASH(x) BUCKETS 8
|
||||
PROPERTIES (
|
||||
"replication_allocation" = "tag.location.default:1",
|
||||
"in_memory" = "false",
|
||||
"storage_format" = "V2"
|
||||
);
|
||||
"""
|
||||
|
||||
sql"""
|
||||
CREATE TABLE infer_predicate_t4 (
|
||||
a varchar(1) NULL COMMENT "",
|
||||
e varchar(1) NULL COMMENT ""
|
||||
) ENGINE=OLAP
|
||||
UNIQUE KEY(a)
|
||||
DISTRIBUTED BY HASH(a) BUCKETS 8
|
||||
PROPERTIES (
|
||||
"replication_allocation" = "tag.location.default:1",
|
||||
"in_memory" = "false",
|
||||
"storage_format" = "V2"
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
sql"""
|
||||
CREATE TABLE infer_predicate_t1 (
|
||||
k1 varchar(20) NULL COMMENT "",
|
||||
dt date NULL COMMENT ""
|
||||
) ENGINE=OLAP
|
||||
UNIQUE KEY(k1)
|
||||
DISTRIBUTED BY HASH(k1) BUCKETS 6
|
||||
PROPERTIES (
|
||||
"replication_allocation" = "tag.location.default:1",
|
||||
"in_memory" = "false",
|
||||
"storage_format" = "V2"
|
||||
);
|
||||
"""
|
||||
|
||||
sql"""
|
||||
CREATE VIEW infer_predicate_v1
|
||||
AS
|
||||
SELECT k1
|
||||
FROM infer_predicate_t1
|
||||
WHERE dt = (
|
||||
SELECT max(dt)
|
||||
FROM infer_predicate_t1
|
||||
);
|
||||
"""
|
||||
|
||||
try {
|
||||
sql """
|
||||
select
|
||||
f1.k1
|
||||
from (
|
||||
select
|
||||
infer_predicate_t2.c as k1
|
||||
from infer_predicate_t5
|
||||
inner join infer_predicate_t2 on infer_predicate_t2.x=infer_predicate_t5.x
|
||||
inner join infer_predicate_t4 on infer_predicate_t2.a=infer_predicate_t4.a and infer_predicate_t2.x in ('ZCR', 'ZDR')
|
||||
) f1
|
||||
left join infer_predicate_v1 on f1.k1=infer_predicate_v1.k1;
|
||||
"""
|
||||
} finally {
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t1 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t2 """
|
||||
sql """ DROP VIEW IF EXISTS infer_predicate_v1 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t4 """
|
||||
sql """ DROP TABLE IF EXISTS infer_predicate_t5 """
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user