use of io.prestosql.sql.tree.Window in project hetu-core by openlookeng.
the class ImpalaAstBuilder method visitFunctionCall.
@Override
public Node visitFunctionCall(ImpalaSqlParser.FunctionCallContext context) {
Optional<Expression> filter = visitIfPresent(context.filter(), Expression.class);
Optional<Window> window = visitIfPresent(context.over(), Window.class);
Optional<OrderBy> orderBy = Optional.empty();
if (context.ORDER() != null) {
orderBy = Optional.of(new OrderBy(visit(context.sortItem(), SortItem.class)));
}
QualifiedName name = getQualifiedName(context.qualifiedName());
boolean distinct = isDistinct(context.setQuantifier());
if (name.toString().equalsIgnoreCase("if")) {
check(context.expression().size() == 2 || context.expression().size() == 3, "Invalid number of arguments for 'if' function", context);
check(!window.isPresent(), "OVER clause not valid for 'if' function", context);
check(!distinct, "DISTINCT not valid for 'if' function", context);
check(!filter.isPresent(), "FILTER not valid for 'if' function", context);
Expression elseExpression = null;
if (context.expression().size() == 3) {
elseExpression = (Expression) visit(context.expression(2));
}
return new IfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)), elseExpression);
}
if (name.toString().equalsIgnoreCase("nullif")) {
check(context.expression().size() == 2, "Invalid number of arguments for 'nullif' function", context);
check(!window.isPresent(), "OVER clause not valid for 'nullif' function", context);
check(!distinct, "DISTINCT not valid for 'nullif' function", context);
check(!filter.isPresent(), "FILTER not valid for 'nullif' function", context);
return new NullIfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)));
}
if (name.toString().equalsIgnoreCase("coalesce")) {
check(context.expression().size() >= 2, "The 'coalesce' function must have at least two arguments", context);
check(!window.isPresent(), "OVER clause not valid for 'coalesce' function", context);
check(!distinct, "DISTINCT not valid for 'coalesce' function", context);
check(!filter.isPresent(), "FILTER not valid for 'coalesce' function", context);
return new CoalesceExpression(getLocation(context), visit(context.expression(), Expression.class));
}
return new FunctionCall(Optional.of(getLocation(context)), getQualifiedName(context.qualifiedName()), window, filter, orderBy, distinct, false, visit(context.expression(), Expression.class));
}
use of io.prestosql.sql.tree.Window in project hetu-core by openlookeng.
the class QueryPlanner method window.
private PlanBuilder window(PlanBuilder inputSubPlan, List<FunctionCall> windowFunctions) {
PlanBuilder subPlan = inputSubPlan;
if (windowFunctions.isEmpty()) {
return subPlan;
}
for (FunctionCall windowFunction : windowFunctions) {
Window window = windowFunction.getWindow().get();
// Extract frame
WindowFrameType frameType = RANGE;
FrameBoundType frameStartType = UNBOUNDED_PRECEDING;
FrameBoundType frameEndType = CURRENT_ROW;
Expression frameStart = null;
Expression frameEnd = null;
if (window.getFrame().isPresent()) {
WindowFrame frame = window.getFrame().get();
frameType = frame.getType();
frameStartType = frame.getStart().getType();
frameStart = frame.getStart().getValue().orElse(null);
if (frame.getEnd().isPresent()) {
frameEndType = frame.getEnd().get().getType();
frameEnd = frame.getEnd().get().getValue().orElse(null);
}
}
// Pre-project inputs
ImmutableList.Builder<Expression> inputs = ImmutableList.<Expression>builder().addAll(windowFunction.getArguments()).addAll(window.getPartitionBy()).addAll(Iterables.transform(getSortItemsFromOrderBy(window.getOrderBy()), SortItem::getSortKey));
if (frameStart != null) {
inputs.add(frameStart);
}
if (frameEnd != null) {
inputs.add(frameEnd);
}
subPlan = subPlan.appendProjections(inputs.build(), planSymbolAllocator, idAllocator);
// Rewrite PARTITION BY in terms of pre-projected inputs
ImmutableList.Builder<Symbol> partitionBySymbols = ImmutableList.builder();
for (Expression expression : window.getPartitionBy()) {
partitionBySymbols.add(subPlan.translate(expression));
}
// Rewrite ORDER BY in terms of pre-projected inputs
LinkedHashMap<Symbol, SortOrder> orderings = new LinkedHashMap<>();
for (SortItem item : getSortItemsFromOrderBy(window.getOrderBy())) {
Symbol symbol = subPlan.translate(item.getSortKey());
// don't override existing keys, i.e. when "ORDER BY a ASC, a DESC" is specified
orderings.putIfAbsent(symbol, sortItemToSortOrder(item));
}
// Rewrite frame bounds in terms of pre-projected inputs
Optional<Symbol> frameStartSymbol = Optional.empty();
Optional<Symbol> frameEndSymbol = Optional.empty();
if (frameStart != null) {
frameStartSymbol = Optional.of(subPlan.translate(frameStart));
}
if (frameEnd != null) {
frameEndSymbol = Optional.of(subPlan.translate(frameEnd));
}
WindowNode.Frame frame = new WindowNode.Frame(frameType, frameStartType, frameStartSymbol, frameEndType, frameEndSymbol, Optional.ofNullable(frameStart).map(Expression::toString), Optional.ofNullable(frameEnd).map(Expression::toString));
TranslationMap outputTranslations = subPlan.copyTranslations();
// Rewrite function call in terms of pre-projected inputs
Expression rewritten = subPlan.rewrite(windowFunction);
boolean needCoercion = rewritten instanceof Cast;
// Strip out the cast and add it back as a post-projection
if (rewritten instanceof Cast) {
rewritten = ((Cast) rewritten).getExpression();
}
// If refers to existing symbol, don't create another PlanNode
if (rewritten instanceof SymbolReference) {
if (needCoercion) {
subPlan = explicitCoercionSymbols(subPlan, subPlan.getRoot().getOutputSymbols(), ImmutableList.of(windowFunction));
}
continue;
}
Type returnType = analysis.getType(windowFunction);
Symbol newSymbol = planSymbolAllocator.newSymbol(rewritten, analysis.getType(windowFunction));
outputTranslations.put(windowFunction, newSymbol);
List<RowExpression> arguments = new ArrayList<>();
for (int i = 0; i < ((FunctionCall) rewritten).getArguments().size(); i++) {
arguments.add(castToRowExpression(((FunctionCall) rewritten).getArguments().get(i)));
}
WindowNode.Function function = new WindowNode.Function(call(windowFunction.getName().toString(), analysis.getFunctionHandle(windowFunction), returnType, ((FunctionCall) rewritten).getArguments().stream().map(OriginalExpressionUtils::castToRowExpression).collect(toImmutableList())), arguments, frame);
List<Symbol> sourceSymbols = subPlan.getRoot().getOutputSymbols();
ImmutableList.Builder<Symbol> orderBySymbols = ImmutableList.builder();
orderBySymbols.addAll(orderings.keySet());
Optional<OrderingScheme> orderingScheme = Optional.empty();
if (!orderings.isEmpty()) {
orderingScheme = Optional.of(new OrderingScheme(orderBySymbols.build(), orderings));
}
// create window node
subPlan = new PlanBuilder(outputTranslations, new WindowNode(idAllocator.getNextId(), subPlan.getRoot(), new WindowNode.Specification(partitionBySymbols.build(), orderingScheme), ImmutableMap.of(newSymbol, function), Optional.empty(), ImmutableSet.of(), 0));
if (needCoercion) {
subPlan = explicitCoercionSymbols(subPlan, sourceSymbols, ImmutableList.of(windowFunction));
}
}
return subPlan;
}
use of io.prestosql.sql.tree.Window in project hetu-core by openlookeng.
the class HiveAstBuilder method visitFunctionCall.
@Override
public Node visitFunctionCall(HiveSqlParser.FunctionCallContext context) {
Optional<Expression> filter = Optional.empty();
Optional<OrderBy> orderBy = Optional.empty();
Optional<Window> window = visitIfPresent(context.over(), Window.class);
boolean distinct = isDistinct(context.setQuantifier());
QualifiedName name = getQualifiedName(context.qualifiedName());
if (name.toString().equalsIgnoreCase("if")) {
check(context.expression().size() == 3, "Illegal arguments for 'if' function", context);
check(!window.isPresent(), "OVER not valid for 'if' function", context);
check(!distinct, "DISTINCT not valid for 'if' function", context);
Expression elseExpression = (Expression) visit(context.expression(2));
return new IfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)), elseExpression);
}
if (name.toString().equalsIgnoreCase("nullif")) {
check(context.expression().size() == 2, "Illegal arguments for 'nullif' function", context);
check(!window.isPresent(), "OVER not valid for 'nullif' function", context);
check(!distinct, "DISTINCT not valid for 'nullif' function", context);
return new NullIfExpression(getLocation(context), (Expression) visit(context.expression(0)), (Expression) visit(context.expression(1)));
}
if (name.toString().equalsIgnoreCase("coalesce")) {
check(context.expression().size() > 0, "The 'coalesce' function must have at least one argument", context);
check(!window.isPresent(), "OVER not valid for 'coalesce' function", context);
check(!distinct, "DISTINCT not valid for 'coalesce' function", context);
return new CoalesceExpression(getLocation(context), visit(context.expression(), Expression.class));
}
return new FunctionCall(Optional.of(getLocation(context)), getQualifiedName(context.qualifiedName()), window, filter, orderBy, distinct, false, visit(context.expression(), Expression.class));
}
use of io.prestosql.sql.tree.Window in project hetu-core by openlookeng.
the class TestSwapAdjacentWindowsBySpecifications method subsetComesFirst.
@Test
public void subsetComesFirst() {
String columnAAlias = "ALIAS_A";
String columnBAlias = "ALIAS_B";
ExpectedValueProvider<WindowNode.Specification> specificationA = specification(ImmutableList.of(columnAAlias), ImmutableList.of(), ImmutableMap.of());
ExpectedValueProvider<WindowNode.Specification> specificationAB = specification(ImmutableList.of(columnAAlias, columnBAlias), ImmutableList.of(), ImmutableMap.of());
Optional<Window> windowAB = Optional.of(new Window(ImmutableList.of(new SymbolReference("a"), new SymbolReference("b")), Optional.empty(), Optional.empty()));
Optional<Window> windowA = Optional.of(new Window(ImmutableList.of(new SymbolReference("a")), Optional.empty(), Optional.empty()));
tester().assertThat(new GatherAndMergeWindows.SwapAdjacentWindowsBySpecifications(0)).on(p -> p.window(new WindowNode.Specification(ImmutableList.of(p.symbol("a")), Optional.empty()), ImmutableMap.of(p.symbol("avg_1", DOUBLE), newWindowNodeFunction(ImmutableList.of(p.variable("a")))), p.window(new WindowNode.Specification(ImmutableList.of(p.symbol("a"), p.symbol("b")), Optional.empty()), ImmutableMap.of(p.symbol("avg_2", DOUBLE), newWindowNodeFunction(ImmutableList.of(p.variable("b")))), p.values(p.symbol("a"), p.symbol("b"))))).matches(window(windowMatcherBuilder -> windowMatcherBuilder.specification(specificationAB).addFunction(functionCall("avg", Optional.empty(), ImmutableList.of(columnBAlias))), window(windowMatcherBuilder -> windowMatcherBuilder.specification(specificationA).addFunction(functionCall("avg", Optional.empty(), ImmutableList.of(columnAAlias))), values(ImmutableMap.of(columnAAlias, 0, columnBAlias, 1)))));
}
use of io.prestosql.sql.tree.Window in project hetu-core by openlookeng.
the class TestSwapAdjacentWindowsBySpecifications method dependentWindowsAreNotReordered.
@Test
public void dependentWindowsAreNotReordered() {
Optional<Window> windowA = Optional.of(new Window(ImmutableList.of(new SymbolReference("a")), Optional.empty(), Optional.empty()));
tester().assertThat(new GatherAndMergeWindows.SwapAdjacentWindowsBySpecifications(0)).on(p -> p.window(new WindowNode.Specification(ImmutableList.of(p.symbol("a")), Optional.empty()), ImmutableMap.of(p.symbol("avg_1"), newWindowNodeFunction(ImmutableList.of(p.variable("avg_2")))), p.window(new WindowNode.Specification(ImmutableList.of(p.symbol("a"), p.symbol("b")), Optional.empty()), ImmutableMap.of(p.symbol("avg_2"), newWindowNodeFunction(ImmutableList.of(p.variable("a")))), p.values(p.symbol("a"), p.symbol("b"))))).doesNotFire();
}
Aggregations