use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class SelectWindowFunctionAnalyzerTest method test_over_references_window_that_references_subsequent_window.
@Test
public void test_over_references_window_that_references_subsequent_window() {
AnalyzedRelation relation = e.analyze("SELECT AVG(x) OVER w2 " + "FROM t WINDOW w AS (PARTITION BY x)," + " w2 AS (w ORDER BY x)");
WindowFunction windowFunction = (WindowFunction) relation.outputs().get(0);
WindowDefinition windowDefinition = windowFunction.windowDefinition();
assertThat(windowDefinition.partitions(), contains(isReference("x")));
OrderBy orderBy = windowDefinition.orderBy();
assertThat(orderBy, not(nullValue()));
assertThat(orderBy.orderBySymbols().size(), is(1));
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class SelectWindowFunctionAnalyzerTest method test_over_with_order_by_references_window_with_partition_by.
@Test
public void test_over_with_order_by_references_window_with_partition_by() {
AnalyzedRelation relation = e.analyze("SELECT AVG(x) OVER (w ORDER BY x) " + "FROM t " + "WINDOW w AS (PARTITION BY x)");
WindowFunction windowFunction = (WindowFunction) relation.outputs().get(0);
WindowDefinition windowDefinition = windowFunction.windowDefinition();
assertThat(windowDefinition.partitions(), contains(isReference("x")));
OrderBy orderBy = windowDefinition.orderBy();
assertThat(orderBy, not(nullValue()));
assertThat(orderBy.orderBySymbols().size(), is(1));
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class SelectWindowFunctionAnalyzerTest method testEmptyOverClause.
@Test
public void testEmptyOverClause() {
QueriedSelectRelation analysis = e.analyze("select avg(x) OVER () from t");
List<Symbol> outputSymbols = analysis.outputs();
assertThat(outputSymbols.size(), is(1));
assertThat(outputSymbols.get(0), instanceOf(WindowFunction.class));
WindowFunction windowFunction = (WindowFunction) outputSymbols.get(0);
assertThat(windowFunction.arguments().size(), is(1));
WindowDefinition windowDefinition = windowFunction.windowDefinition();
assertThat(windowDefinition.partitions().isEmpty(), is(true));
assertThat(windowDefinition.orderBy(), is(nullValue()));
assertThat(windowDefinition.windowFrameDefinition(), is(WindowDefinition.RANGE_UNBOUNDED_PRECEDING_CURRENT_ROW));
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class WindowAgg method pruneOutputsExcept.
@Override
public LogicalPlan pruneOutputsExcept(TableStats tableStats, Collection<Symbol> outputsToKeep) {
HashSet<Symbol> toKeep = new HashSet<>();
ArrayList<WindowFunction> newWindowFunctions = new ArrayList<>();
for (Symbol outputToKeep : outputsToKeep) {
SymbolVisitors.intersection(outputToKeep, windowFunctions, newWindowFunctions::add);
SymbolVisitors.intersection(outputToKeep, standalone, toKeep::add);
}
for (WindowFunction newWindowFunction : newWindowFunctions) {
SymbolVisitors.intersection(newWindowFunction, source.outputs(), toKeep::add);
}
LogicalPlan newSource = source.pruneOutputsExcept(tableStats, toKeep);
if (newSource == source) {
return this;
}
if (newWindowFunctions.isEmpty()) {
return newSource;
} else {
return new WindowAgg(newSource, windowDefinition, List.copyOf(newWindowFunctions), newSource.outputs());
}
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class WindowAgg method create.
@VisibleForTesting
public static LogicalPlan create(LogicalPlan source, List<WindowFunction> windowFunctions) {
if (windowFunctions.isEmpty()) {
return source;
}
LinkedHashMap<WindowDefinition, ArrayList<WindowFunction>> groupedFunctions = new LinkedHashMap<>();
for (WindowFunction windowFunction : windowFunctions) {
WindowDefinition windowDefinition = windowFunction.windowDefinition();
ArrayList<WindowFunction> functions = groupedFunctions.computeIfAbsent(windowDefinition, w -> new ArrayList<>());
functions.add(windowFunction);
}
LogicalPlan lastWindowAgg = source;
for (Map.Entry<WindowDefinition, ArrayList<WindowFunction>> entry : groupedFunctions.entrySet()) {
/*
* Pass along the source outputs as standalone symbols as they might be required in cases like:
* select x, avg(x) OVER() from t;
*/
ArrayList<WindowFunction> functions = entry.getValue();
WindowDefinition windowDefinition = entry.getKey();
OrderBy orderBy = windowDefinition.orderBy();
if (orderBy == null || lastWindowAgg.outputs().containsAll(orderBy.orderBySymbols())) {
lastWindowAgg = new WindowAgg(lastWindowAgg, windowDefinition, functions, lastWindowAgg.outputs());
} else {
// ``WindowProjector.createUpdateProbeValueFunction` expects that all OrderBY symbols are `InputColumn`
// Here we have a case where there is a function or something in the orderBy expression that is *not*
// already provided by the source.
// -> Inject `eval` so that the `orderBy` of the window-function will turn into a `InputColumn`
Eval eval = new Eval(lastWindowAgg, Lists2.concatUnique(lastWindowAgg.outputs(), orderBy.orderBySymbols()));
lastWindowAgg = new WindowAgg(eval, windowDefinition, functions, eval.outputs());
}
}
return lastWindowAgg;
}
Aggregations