use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class MoveFilterBeneathWindowAggTest method test_filter_on_containing_windows_function_is_not_moved.
@Test
public void test_filter_on_containing_windows_function_is_not_moved() {
var collect = e.logicalPlan("SELECT id FROM t1");
WindowFunction windowFunction = (WindowFunction) e.asSymbol("ROW_NUMBER() OVER(PARTITION by id)");
WindowAgg windowAgg = (WindowAgg) WindowAgg.create(collect, List.of(windowFunction));
Symbol query = e.asSymbol("ROW_NUMBER() OVER(PARTITION by id) = 2");
Filter filter = new Filter(windowAgg, query);
var rule = new MoveFilterBeneathWindowAgg();
Match<Filter> match = rule.pattern().accept(filter, Captures.empty());
assertThat(match.isPresent(), is(true));
assertThat(match.value(), Matchers.sameInstance(filter));
LogicalPlan newPlan = rule.apply(match.value(), match.captures(), new TableStats(), CoordinatorTxnCtx.systemTransactionContext(), e.nodeCtx);
assertThat(newPlan, nullValue());
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class ExpressionAnalyzer method allocateBuiltinOrUdfFunction.
/**
* Creates a function symbol and tries to normalize the new function's
* {@link FunctionImplementation} iff only Literals are supplied as arguments.
* This folds any constant expressions like '1 + 1' => '2'.
* @param schema The schema for udf functions
* @param functionName The function name of the new function.
* @param arguments The arguments to provide to the {@link Function}.
* @param filter The filter clause to filter {@link Function}'s input values.
* @param context Context holding the state for the current translation.
* @param windowDefinition The definition of the window the allocated function will be executed against.
* @param coordinatorTxnCtx {@link CoordinatorTxnCtx} for this transaction.
* @param nodeCtx The {@link NodeContext} to normalize constant expressions.
* @return The supplied {@link Function} or a {@link Literal} in case of constant folding.
*/
private static Symbol allocateBuiltinOrUdfFunction(@Nullable String schema, String functionName, List<Symbol> arguments, @Nullable Symbol filter, @Nullable Boolean ignoreNulls, ExpressionAnalysisContext context, @Nullable WindowDefinition windowDefinition, CoordinatorTxnCtx coordinatorTxnCtx, NodeContext nodeCtx) {
FunctionImplementation funcImpl = nodeCtx.functions().get(schema, functionName, arguments, coordinatorTxnCtx.sessionContext().searchPath());
Signature signature = funcImpl.signature();
Signature boundSignature = funcImpl.boundSignature();
List<Symbol> castArguments = cast(arguments, boundSignature.getArgumentDataTypes());
Function newFunction;
if (windowDefinition == null) {
if (signature.getKind() == FunctionType.AGGREGATE) {
context.indicateAggregates();
} else if (filter != null) {
throw new UnsupportedOperationException("Only aggregate functions allow a FILTER clause");
}
if (ignoreNulls != null) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "%s cannot accept RESPECT or IGNORE NULLS flag.", functionName));
}
newFunction = new Function(signature, castArguments, boundSignature.getReturnType().createType(), filter);
} else {
if (signature.getKind() != FunctionType.WINDOW) {
if (signature.getKind() != FunctionType.AGGREGATE) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "OVER clause was specified, but %s is neither a window nor an aggregate function.", functionName));
} else {
if (ignoreNulls != null) {
throw new IllegalArgumentException(String.format(Locale.ENGLISH, "%s cannot accept RESPECT or IGNORE NULLS flag.", functionName));
}
}
}
newFunction = new WindowFunction(signature, castArguments, boundSignature.getReturnType().createType(), filter, windowDefinition, ignoreNulls);
}
return newFunction;
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class WindowDefinitionTest method testUnboundedPrecedingUnboundedFollowingFrameIsAllowed.
@Test
public void testUnboundedPrecedingUnboundedFollowingFrameIsAllowed() {
Collect collect = e.plan("select sum(col1) over(RANGE BETWEEN UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING) FROM " + "unnest([1, 2, 1, 1, 1, 4])");
List<Projection> projections = collect.collectPhase().projections();
assertThat(projections.size(), is(2));
WindowAggProjection windowProjection = null;
for (Projection projection : projections) {
if (projection instanceof WindowAggProjection) {
windowProjection = (WindowAggProjection) projection;
break;
}
}
assertThat(windowProjection, is(notNullValue()));
List<? extends Symbol> outputs = windowProjection.outputs();
// IC and window function
assertThat(outputs.size(), is(2));
WindowFunction windowFunction = null;
for (Symbol output : outputs) {
if (output instanceof WindowFunction) {
windowFunction = (WindowFunction) output;
}
}
assertThat(windowFunction, is(notNullValue()));
assertThat(windowFunction.windowDefinition().windowFrameDefinition().start().type(), is(UNBOUNDED_PRECEDING));
assertThat(windowFunction.windowDefinition().windowFrameDefinition().end().type(), is(UNBOUNDED_FOLLOWING));
}
use of io.crate.expression.symbol.WindowFunction in project crate by crate.
the class WindowDefinitionTest method testFrameEndDefaultsToCurrentRowIfNotSpecified.
@Test
public void testFrameEndDefaultsToCurrentRowIfNotSpecified() {
AnalyzedRelation analyze = e.analyze("select sum(col1) over(RANGE UNBOUNDED PRECEDING) FROM " + "unnest([1, 2, 1, 1, 1, 4])");
assertThat(analyze, is(instanceOf(QueriedSelectRelation.class)));
List<Symbol> outputs = analyze.outputs();
assertThat(outputs.size(), is(1));
WindowFunction windowFunction = (WindowFunction) outputs.get(0);
assertThat(windowFunction.windowDefinition().windowFrameDefinition().end().type(), is(CURRENT_ROW));
}
Aggregations