-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ESQL: Refactor Join inside the planner #115813
Changes from 6 commits
bc21eca
2f0a3d5
038cc81
fe0cdeb
894e0f3
86f6cd9
1486dff
863b02d
b0d261a
8ffc167
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commented tests are failing - the plan is to revisit them once lookup join is properly added. Right now this is not a priority... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a comment so that these tests can easily be found later. As they are now, it's just an ignored set of tests. |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only two tests are failing and the issue is name collision/merging in join.
during physical planning we know k is available on both l and r but have no idea whether a comes from l or r and thus cannot determine on what branch to place the field extractors. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,7 @@ | |
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.In; | ||
import org.elasticsearch.xpack.esql.index.EsIndex; | ||
import org.elasticsearch.xpack.esql.plan.TableIdentifier; | ||
import org.elasticsearch.xpack.esql.plan.logical.Aggregate; | ||
import org.elasticsearch.xpack.esql.plan.logical.Drop; | ||
import org.elasticsearch.xpack.esql.plan.logical.Enrich; | ||
import org.elasticsearch.xpack.esql.plan.logical.EsRelation; | ||
|
@@ -72,7 +73,6 @@ | |
import org.elasticsearch.xpack.esql.plan.logical.MvExpand; | ||
import org.elasticsearch.xpack.esql.plan.logical.Project; | ||
import org.elasticsearch.xpack.esql.plan.logical.Rename; | ||
import org.elasticsearch.xpack.esql.plan.logical.Stats; | ||
import org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation; | ||
import org.elasticsearch.xpack.esql.plan.logical.local.EsqlProject; | ||
import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; | ||
|
@@ -405,8 +405,8 @@ protected LogicalPlan doRule(LogicalPlan plan) { | |
childrenOutput.addAll(output); | ||
} | ||
|
||
if (plan instanceof Stats stats) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By exposing the Aggregate, there's no reason to have the Stats interface anymore. |
||
return resolveStats(stats, childrenOutput); | ||
if (plan instanceof Aggregate aggregate) { | ||
return resolveAggregate(aggregate, childrenOutput); | ||
} | ||
|
||
if (plan instanceof Drop d) { | ||
|
@@ -440,12 +440,12 @@ protected LogicalPlan doRule(LogicalPlan plan) { | |
return plan.transformExpressionsOnly(UnresolvedAttribute.class, ua -> maybeResolveAttribute(ua, childrenOutput)); | ||
} | ||
|
||
private LogicalPlan resolveStats(Stats stats, List<Attribute> childrenOutput) { | ||
private Aggregate resolveAggregate(Aggregate aggregate, List<Attribute> childrenOutput) { | ||
// if the grouping is resolved but the aggs are not, use the former to resolve the latter | ||
// e.g. STATS a ... GROUP BY a = x + 1 | ||
Holder<Boolean> changed = new Holder<>(false); | ||
List<Expression> groupings = stats.groupings(); | ||
List<? extends NamedExpression> aggregates = stats.aggregates(); | ||
List<Expression> groupings = aggregate.groupings(); | ||
List<? extends NamedExpression> aggregates = aggregate.aggregates(); | ||
// first resolve groupings since the aggs might refer to them | ||
// trying to globally resolve unresolved attributes will lead to some being marked as unresolvable | ||
if (Resolvables.resolved(groupings) == false) { | ||
|
@@ -459,7 +459,7 @@ private LogicalPlan resolveStats(Stats stats, List<Attribute> childrenOutput) { | |
} | ||
groupings = newGroupings; | ||
if (changed.get()) { | ||
stats = stats.with(stats.child(), newGroupings, stats.aggregates()); | ||
aggregate = aggregate.with(aggregate.child(), newGroupings, aggregate.aggregates()); | ||
changed.set(false); | ||
} | ||
} | ||
|
@@ -475,8 +475,8 @@ private LogicalPlan resolveStats(Stats stats, List<Attribute> childrenOutput) { | |
List<Attribute> resolvedList = NamedExpressions.mergeOutputAttributes(resolved, childrenOutput); | ||
|
||
List<NamedExpression> newAggregates = new ArrayList<>(); | ||
for (NamedExpression aggregate : stats.aggregates()) { | ||
var agg = (NamedExpression) aggregate.transformUp(UnresolvedAttribute.class, ua -> { | ||
for (NamedExpression ag : aggregate.aggregates()) { | ||
var agg = (NamedExpression) ag.transformUp(UnresolvedAttribute.class, ua -> { | ||
Expression ne = ua; | ||
Attribute maybeResolved = maybeResolveAttribute(ua, resolvedList); | ||
if (maybeResolved != null) { | ||
|
@@ -489,10 +489,10 @@ private LogicalPlan resolveStats(Stats stats, List<Attribute> childrenOutput) { | |
} | ||
|
||
// TODO: remove this when Stats interface is removed | ||
stats = changed.get() ? stats.with(stats.child(), groupings, newAggregates) : stats; | ||
aggregate = changed.get() ? aggregate.with(aggregate.child(), groupings, newAggregates) : aggregate; | ||
} | ||
|
||
return (LogicalPlan) stats; | ||
return aggregate; | ||
} | ||
|
||
private LogicalPlan resolveMvExpand(MvExpand p, List<Attribute> childrenOutput) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,8 +18,7 @@ | |
import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; | ||
import org.elasticsearch.xpack.esql.optimizer.LogicalOptimizerContext; | ||
import org.elasticsearch.xpack.esql.optimizer.LogicalPlanOptimizer; | ||
import org.elasticsearch.xpack.esql.plan.physical.PhysicalPlan; | ||
import org.elasticsearch.xpack.esql.planner.Mapper; | ||
import org.elasticsearch.xpack.esql.planner.mapper.Mapper; | ||
import org.elasticsearch.xpack.esql.session.Configuration; | ||
import org.elasticsearch.xpack.esql.session.EsqlSession; | ||
import org.elasticsearch.xpack.esql.session.IndexResolver; | ||
|
@@ -29,8 +28,6 @@ | |
import org.elasticsearch.xpack.esql.stats.PlanningMetricsManager; | ||
import org.elasticsearch.xpack.esql.stats.QueryMetric; | ||
|
||
import java.util.function.BiConsumer; | ||
|
||
import static org.elasticsearch.action.ActionListener.wrap; | ||
|
||
public class PlanExecutor { | ||
|
@@ -47,7 +44,7 @@ public PlanExecutor(IndexResolver indexResolver, MeterRegistry meterRegistry) { | |
this.indexResolver = indexResolver; | ||
this.preAnalyzer = new PreAnalyzer(); | ||
this.functionRegistry = new EsqlFunctionRegistry(); | ||
this.mapper = new Mapper(functionRegistry); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. functionRegistry is not used inside the Mapper. |
||
this.mapper = new Mapper(); | ||
this.metrics = new Metrics(functionRegistry); | ||
this.verifier = new Verifier(metrics); | ||
this.planningMetricsManager = new PlanningMetricsManager(meterRegistry); | ||
|
@@ -60,7 +57,7 @@ public void esql( | |
EnrichPolicyResolver enrichPolicyResolver, | ||
EsqlExecutionInfo executionInfo, | ||
IndicesExpressionGrouper indicesExpressionGrouper, | ||
BiConsumer<PhysicalPlan, ActionListener<Result>> runPhase, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Introduced a interface inside the generic BiConsumer to preserve the generics signature. |
||
EsqlSession.PlanRunner planRunner, | ||
ActionListener<Result> listener | ||
) { | ||
final PlanningMetrics planningMetrics = new PlanningMetrics(); | ||
|
@@ -79,7 +76,7 @@ public void esql( | |
); | ||
QueryMetric clientId = QueryMetric.fromString("rest"); | ||
metrics.total(clientId); | ||
session.execute(request, executionInfo, runPhase, wrap(x -> { | ||
session.execute(request, executionInfo, planRunner, wrap(x -> { | ||
planningMetricsManager.publish(planningMetrics, true); | ||
listener.onResponse(x); | ||
}, ex -> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just renames |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix to make CsvTests work inside the IDE against individual files ("lookup.csv-spec" vs "*.csv-spec)