[fix](planner)fix bug of pushing conjuncts into inlineview (#21962)

1. markConstantConjunct method shouldn't change the input conjunct
2. Use Expr's comeFrom method to check if the pushed expr is one of the group by exprs, this is the correct way to check if the conjunct can be pushed down through the agg node.
3. migrateConstantConjuncts should substitute the conjuncts using inlineViewRef's analyzer to make the analyzer recognize the column in the conjuncts in the following analyze phase
This commit is contained in:
starocean999
2023-07-21 11:34:56 +08:00
committed by GitHub
parent b09c4d490a
commit fb5b412698
3 changed files with 68 additions and 4 deletions

View File

@ -1891,7 +1891,9 @@ public class Analyzer {
// aliases and having it analyzed is needed for the following EvalPredicate() call
conjunct.analyze(this);
}
Expr newConjunct = conjunct.getResultValue(true);
// getResultValue will modify the conjunct internally
// we have to use a clone to keep conjunct unchanged
Expr newConjunct = conjunct.clone().getResultValue(true);
newConjunct = FoldConstantsRule.INSTANCE.apply(newConjunct, this, null);
if (newConjunct instanceof BoolLiteral || newConjunct instanceof NullLiteral) {
boolean evalResult = true;

View File

@ -1860,15 +1860,21 @@ public class SingleNodePlanner {
return;
}
List<Expr> newConjuncts = cloneExprs(conjuncts);
final QueryStmt stmt = inlineViewRef.getViewStmt();
final Analyzer viewAnalyzer = inlineViewRef.getAnalyzer();
viewAnalyzer.markConjunctsAssigned(conjuncts);
// even if the conjuncts are constant, they may contains slotRef
// for example: case when slotRef is null then 0 else 1
// we need substitute the conjuncts using inlineViewRef's analyzer
// otherwise, when analyzing the conjunct in the inline view
// the analyzer is not able to find the column because it comes from outside
List<Expr> newConjuncts =
Expr.substituteList(conjuncts, inlineViewRef.getSmap(), viewAnalyzer, false);
if (stmt instanceof SelectStmt) {
final SelectStmt select = (SelectStmt) stmt;
if (select.getAggInfo() != null) {
viewAnalyzer.registerConjuncts(newConjuncts, select.getAggInfo().getOutputTupleId().asList());
} else if (select.getTableRefs().size() > 1) {
} else if (select.getTableRefs().size() > 0) {
for (int i = select.getTableRefs().size() - 1; i >= 0; i--) {
viewAnalyzer.registerConjuncts(newConjuncts,
select.getTableRefs().get(i).getDesc().getId().asList());
@ -2799,7 +2805,9 @@ public class SingleNodePlanner {
}
GroupByClause groupByClause = stmt.getGroupByClause();
List<Expr> exprs = groupByClause.getGroupingExprs();
if (!exprs.contains(sourceExpr)) {
final Expr srcExpr = sourceExpr;
if (!exprs.stream().anyMatch(expr -> expr.comeFrom(srcExpr))) {
// the sourceExpr doesn't come from any of the group by exprs
isAllSlotReferToGroupBys = false;
break;
}

View File

@ -60,6 +60,60 @@ suite("test_push_conjuncts_inlineview") {
contains "4:VSELECT"
}
explain {
sql("""SELECT *
FROM
(SELECT `a_key` AS `a_key`
FROM
(SELECT `b`.`a_key` AS `a_key`
FROM
(SELECT `a`.`a_key` AS `a_key`
FROM `push_conjunct_table` a) b
GROUP BY 1 ) t2 ) t1
WHERE a_key = '123';""")
notContains "having"
contains "= '123'"
}
sql """
WITH ttt AS
(SELECT c1,
c2,
c3,
c4,
c5,
c6,
c7
FROM
(SELECT '10000003' c1, '0816ffk' c2, '1' c3, 1416.0800 c4, '0816ffk' c5, '2023-07-03 15:36:36' c6, 1 c7 ) a
WHERE c7 = 1 )
SELECT dd.c1,
dd.d1
FROM
(SELECT src.c1,
CASE
WHEN IFNULL(src.c3,'') = ''
OR src.c3 = '3' THEN
'-1'
WHEN src.c4 = 0 THEN
'0'
WHEN src.c4 <= 200 THEN
'1'
WHEN src.c4 > 200
AND src.c4 <= 500 THEN
'2'
WHEN src.c4 > 500
AND src.c4 <= 1000 THEN
'3'
ELSE '4'
END AS d1
FROM ttt src
WHERE src.c1 = '10000003'
GROUP BY src.c1, d1 ) dd
WHERE dd.d1 IN ('-1');
"""
sql """ DROP TABLE IF EXISTS `push_conjunct_table` """
}