-
Notifications
You must be signed in to change notification settings - Fork 139
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Backport 2.x] Push down limit through eval (#2927)
(cherry picked from commit 4a735ea) Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
e679df5
commit 89f8191
Showing
6 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
core/src/main/java/org/opensearch/sql/planner/optimizer/rule/EvalPushDown.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.opensearch.sql.planner.optimizer.rule; | ||
|
||
import static org.opensearch.sql.planner.optimizer.pattern.Patterns.evalCapture; | ||
import static org.opensearch.sql.planner.optimizer.pattern.Patterns.limit; | ||
import static org.opensearch.sql.planner.optimizer.rule.EvalPushDown.EvalPushDownBuilder.match; | ||
|
||
import com.facebook.presto.matching.Capture; | ||
import com.facebook.presto.matching.Captures; | ||
import com.facebook.presto.matching.Pattern; | ||
import com.facebook.presto.matching.pattern.CapturePattern; | ||
import com.facebook.presto.matching.pattern.WithPattern; | ||
import java.util.List; | ||
import java.util.function.BiFunction; | ||
import lombok.Getter; | ||
import lombok.experimental.Accessors; | ||
import org.opensearch.sql.planner.logical.LogicalEval; | ||
import org.opensearch.sql.planner.logical.LogicalLimit; | ||
import org.opensearch.sql.planner.logical.LogicalPlan; | ||
import org.opensearch.sql.planner.optimizer.Rule; | ||
|
||
/** | ||
* Rule template for all rules related to push down logical plans under eval, so these plans can | ||
* avoid blocking by eval and may have chances to be pushed down into table scan by rules in {@link | ||
* org.opensearch.sql.planner.optimizer.rule.read.TableScanPushDown}. | ||
*/ | ||
public class EvalPushDown<T extends LogicalPlan> implements Rule<T> { | ||
|
||
// TODO: Add more rules to push down sort and project | ||
/** Push down optimize rule for limit operator. Transform `limit -> eval` to `eval -> limit` */ | ||
public static final Rule<LogicalLimit> PUSH_DOWN_LIMIT = | ||
match(limit(evalCapture())) | ||
.apply( | ||
(limit, logicalEval) -> { | ||
List<LogicalPlan> child = logicalEval.getChild(); | ||
limit.replaceChildPlans(child); | ||
logicalEval.replaceChildPlans(List.of(limit)); | ||
return logicalEval; | ||
}); | ||
|
||
private final Capture<LogicalEval> capture; | ||
|
||
@Accessors(fluent = true) | ||
@Getter | ||
private final Pattern<T> pattern; | ||
|
||
private final BiFunction<T, LogicalEval, LogicalPlan> pushDownFunction; | ||
|
||
@SuppressWarnings("unchecked") | ||
public EvalPushDown( | ||
WithPattern<T> pattern, BiFunction<T, LogicalEval, LogicalPlan> pushDownFunction) { | ||
this.pattern = pattern; | ||
this.capture = ((CapturePattern<LogicalEval>) pattern.getPattern()).capture(); | ||
this.pushDownFunction = pushDownFunction; | ||
} | ||
|
||
@Override | ||
public LogicalPlan apply(T plan, Captures captures) { | ||
LogicalEval logicalEval = captures.get(capture); | ||
return pushDownFunction.apply(plan, logicalEval); | ||
} | ||
|
||
static class EvalPushDownBuilder<T extends LogicalPlan> { | ||
|
||
private WithPattern<T> pattern; | ||
|
||
public static <T extends LogicalPlan> EvalPushDown.EvalPushDownBuilder<T> match( | ||
Pattern<T> pattern) { | ||
EvalPushDown.EvalPushDownBuilder<T> builder = new EvalPushDown.EvalPushDownBuilder<>(); | ||
builder.pattern = (WithPattern<T>) pattern; | ||
return builder; | ||
} | ||
|
||
public EvalPushDown<T> apply(BiFunction<T, LogicalEval, LogicalPlan> pushDownFunction) { | ||
return new EvalPushDown<>(pattern, pushDownFunction); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
integ-test/src/test/resources/expectedOutput/ppl/explain_limit_push.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"root": { | ||
"name": "ProjectOperator", | ||
"description": { | ||
"fields": "[ageMinus]" | ||
}, | ||
"children": [ | ||
{ | ||
"name": "EvalOperator", | ||
"description": { | ||
"expressions": { | ||
"ageMinus": "-(age, 30)" | ||
} | ||
}, | ||
"children": [ | ||
{ | ||
"name": "OpenSearchIndexScan", | ||
"description": { | ||
"request": "OpenSearchQueryRequest(indexName=opensearch-sql_test_index_account, sourceBuilder={\"from\":0,\"size\":5,\"timeout\":\"1m\"}, searchDone=false)" | ||
}, | ||
"children": [] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |