[fix](Nereids) do not push down topn-filter through right/full outer join if the first orderkey is nulls first (#32633)

* do not push down topn-filter through right/full outer join if the first order key is nulls first
This commit is contained in:
minghong
2024-03-22 20:53:30 +08:00
committed by yiguolei
parent 3d14d9e379
commit f62cdecc08
2 changed files with 28 additions and 3 deletions

View File

@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.SortPhase;
import org.apache.doris.nereids.trees.plans.algebra.Join;
import org.apache.doris.nereids.trees.plans.algebra.OlapScan;
import org.apache.doris.nereids.trees.plans.physical.PhysicalCatalogRelation;
import org.apache.doris.nereids.trees.plans.physical.PhysicalDeferMaterializeTopN;
@ -89,7 +90,9 @@ public class TopNScanOpt extends PlanPostProcessor {
if (! (firstKey instanceof SlotReference)) {
return Optional.empty();
}
OlapScan olapScan = findScanNodeBySlotReference(topN, (SlotReference) firstKey);
boolean nullsFirst = topN.getOrderKeys().get(0).isNullFirst();
OlapScan olapScan = findScanNodeBySlotReference(topN, (SlotReference) firstKey, nullsFirst);
if (olapScan != null
&& olapScan.getTable().isDupKeysOrMergeOnWrite()
&& olapScan instanceof PhysicalCatalogRelation) {
@ -99,7 +102,14 @@ public class TopNScanOpt extends PlanPostProcessor {
return Optional.empty();
}
private OlapScan findScanNodeBySlotReference(Plan root, SlotReference slot) {
private OlapScan findScanNodeBySlotReference(Plan root, SlotReference slot, boolean nullsFirst) {
// topn-filter cannot be pushed through right/full outer join if the first orderKey is nulls first
if (nullsFirst && root instanceof Join) {
Join join = (Join) root;
if (join.getJoinType().isRightOuterJoin() || join.getJoinType().isFullOuterJoin()) {
return null;
}
}
OlapScan target = null;
if (root instanceof OlapScan && root.getOutputSet().contains(slot)) {
return (OlapScan) root;
@ -109,7 +119,7 @@ public class TopNScanOpt extends PlanPostProcessor {
// TODO for union, topn-filter can be pushed down to all of its children.
Plan child = root.child(0);
if (!(child instanceof PhysicalWindow) && child.getOutputSet().contains(slot)) {
target = findScanNodeBySlotReference(child, slot);
target = findScanNodeBySlotReference(child, slot, nullsFirst);
if (target != null) {
return target;
}

View File

@ -116,6 +116,21 @@ suite("topn-filter") {
}
qt_groupingsets "select n_regionkey, sum(n_nationkey) from nation group by grouping sets((n_regionkey)) order by n_regionkey limit 2;"
explain {
sql "select * from nation right outer join region on r_regionkey = n_regionkey order by n_regionkey nulls first limit 1; "
notContains "TOPN OPT:"
}
explain {
sql "select * from nation right outer join region on r_regionkey = n_regionkey order by n_regionkey nulls last limit 1; "
contains "TOPN OPT:"
}
explain {
sql "select * from nation right outer join region on r_regionkey = n_regionkey order by n_regionkey nulls last, n_name nulls first limit 1; "
contains "TOPN OPT:"
}
sql "set enable_pipeline_engine=false;"
sql "set enable_pipeline_x_engine=false;"