-
Notifications
You must be signed in to change notification settings - Fork 25.9k
ESQL: INLINESTATS #109583
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: INLINESTATS #109583
Changes from 1 commit
e2d9da7
14017d6
355905a
a634f90
8f04e1b
3a3939b
5483426
7695f67
64f858b
141a63f
d0dc736
6947e1c
cc44421
8466a4e
cc20b73
2f9b8af
c4f1d87
1408824
2a38bc8
b786c1c
547e5a5
0eb2958
32a03b2
966c860
83252cf
40d3fe9
50fc6e2
d33a445
a868e7e
0bbdef4
e19c769
5d019f4
434bd9b
0d5d0da
e7eb532
908dfc9
2386fa8
887b9ce
2e028ce
1dfe527
ab350c4
2d90569
c937834
0a9332c
c30230c
9d12a29
6f690b7
18d30f0
9ff0024
c142d61
76998b7
40b13df
48253a4
674d93d
4489b27
8074a95
10b1fcd
fdb43d8
cbb1e60
8fbe301
09d226a
0e454f7
a6ec9be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,23 +7,40 @@ | |
|
|
||
| package org.elasticsearch.xpack.esql.plan.logical; | ||
|
|
||
| import org.elasticsearch.common.collect.Iterators; | ||
| import org.elasticsearch.compute.data.Block; | ||
| import org.elasticsearch.compute.data.Page; | ||
| import org.elasticsearch.core.Releasables; | ||
| import org.elasticsearch.xpack.esql.core.capabilities.Resolvables; | ||
| import org.elasticsearch.xpack.esql.core.expression.Attribute; | ||
| import org.elasticsearch.xpack.esql.core.expression.Expression; | ||
| import org.elasticsearch.xpack.esql.core.expression.Expressions; | ||
| import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; | ||
| import org.elasticsearch.xpack.esql.core.expression.NamedExpression; | ||
| import org.elasticsearch.xpack.esql.core.expression.ReferenceAttribute; | ||
| import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan; | ||
| import org.elasticsearch.xpack.esql.core.plan.logical.UnaryPlan; | ||
| import org.elasticsearch.xpack.esql.core.tree.NodeInfo; | ||
| import org.elasticsearch.xpack.esql.core.tree.Source; | ||
| import org.elasticsearch.xpack.esql.core.type.DataType; | ||
| import org.elasticsearch.xpack.esql.core.type.EsField; | ||
| import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; | ||
| import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier; | ||
| import org.elasticsearch.xpack.esql.planner.PlannerUtils; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class InlineStats extends UnaryPlan { | ||
| import static org.elasticsearch.xpack.esql.expression.NamedExpressions.mergeOutputAttributes; | ||
|
|
||
| public class InlineStats extends UnaryPlan implements Phased { | ||
|
|
||
| private final List<Expression> groupings; | ||
| private final List<? extends NamedExpression> aggregates; | ||
| private List<Attribute> output; | ||
|
|
||
| public InlineStats(Source source, LogicalPlan child, List<Expression> groupings, List<? extends NamedExpression> aggregates) { | ||
| super(source, child); | ||
|
|
@@ -56,7 +73,34 @@ public boolean expressionsResolved() { | |
|
|
||
| @Override | ||
| public List<Attribute> output() { | ||
| return Expressions.asAttributes(aggregates); | ||
| // NOCOMMIT when is this one called? | ||
| if (this.output == null) { | ||
| this.output = mergeOutputAttributes(Expressions.asAttributes(aggregates), child().output()); | ||
|
Contributor
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. I think this is subtly incorrect; the Unfortunately, when the groupings do not occur in This method is currently unused, but will become important if we move the phase subdivision after the logical optimization. I think the correct code should be We could try and update this right away or at least leave a TODO here.
Member
Author
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. I've updated it now. I can't make a test for it that passes, but I've made one that doesn't pass and added an
Contributor
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. Thanks! This will matter once we move the phasing past the logical optimization (instead of after analysis); currently, |
||
| } | ||
| return output; | ||
|
nik9000 marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| @Override | ||
| public LogicalPlan firstPhase() { | ||
| return new Aggregate(source(), child(), groupings, aggregates); | ||
| } | ||
|
|
||
| @Override | ||
| public LogicalPlan nextPhase(List<Attribute> layout, List<Page> firstPhaseResult) { | ||
| // NOCOMMIT memory tracking | ||
| if (firstPhaseResult.size() > 1) { | ||
| throw new UnsupportedOperationException(); | ||
| } | ||
| List<NamedExpression> namedGroupings = groupings.stream().map(Expressions::wrapAsNamed).toList(); | ||
| Page page = firstPhaseResult.get(0); | ||
| Block[] blocks = IntStream.range(0, page.getBlockCount()).mapToObj(b -> { | ||
| Block block = page.getBlock(b); | ||
| Block.Builder builder = block.elementType().newBlockBuilder(block.getPositionCount(), PlannerUtils.NON_BREAKING_BLOCK_FACTORY); | ||
| builder.copyFrom(block, 0, block.getPositionCount()); | ||
| return builder.build(); | ||
| }).toArray(Block[]::new); | ||
| LocalRelation local = new LocalRelation(source(), layout, LocalSupplier.of(blocks)); | ||
| return new Lookup(source(), child(), new ReferenceAttribute(source(), "unused", DataType.KEYWORD), namedGroupings, local); | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| package org.elasticsearch.xpack.esql.plan.logical; | ||
|
|
||
| import org.elasticsearch.compute.data.Page; | ||
| import org.elasticsearch.xpack.esql.core.expression.Attribute; | ||
| import org.elasticsearch.xpack.esql.core.plan.logical.LogicalPlan; | ||
| import org.elasticsearch.xpack.esql.core.util.Holder; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public interface Phased { | ||
| LogicalPlan firstPhase(); | ||
| LogicalPlan nextPhase(List<Attribute> layout, List<Page> firstPhaseResult); | ||
|
|
||
| static LogicalPlan extractNextPhase(LogicalPlan plan) { | ||
| var firstPhase = new Holder<LogicalPlan>(); | ||
| plan.forEachUp(t -> { | ||
| if (t instanceof Phased phased) { | ||
| firstPhase.set(phased.firstPhase()); | ||
| } | ||
| }); | ||
|
alex-spies marked this conversation as resolved.
|
||
| return firstPhase.get(); | ||
| } | ||
|
|
||
| static LogicalPlan applyResultsFromNextPhase(LogicalPlan plan, List<Attribute> layout, List<Page> result) { | ||
| return plan.transformUp(logicalPlan -> { | ||
| // NOCOMMIT make sure this stops after the first one. | ||
| if (logicalPlan instanceof Phased phased) { | ||
| return phased.nextPhase(layout, result); | ||
| } | ||
| return logicalPlan; | ||
| }); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.