Search in sources :

Example 6 with WindowNode

use of io.prestosql.spi.plan.WindowNode in project hetu-core by openlookeng.

the class WindowMatcher method detailMatches.

@Override
public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) {
    checkState(shapeMatches(node), "Plan testing framework error: shapeMatches returned false in detailMatches in %s", this.getClass().getName());
    WindowNode windowNode = (WindowNode) node;
    if (!prePartitionedInputs.map(expectedInputs -> expectedInputs.stream().map(alias -> alias.toSymbol(symbolAliases)).collect(toImmutableSet()).equals(windowNode.getPrePartitionedInputs())).orElse(true)) {
        return NO_MATCH;
    }
    if (!specification.map(expectedSpecification -> expectedSpecification.getExpectedValue(symbolAliases).equals(windowNode.getSpecification())).orElse(true)) {
        return NO_MATCH;
    }
    if (!preSortedOrderPrefix.map(Integer.valueOf(windowNode.getPreSortedOrderPrefix())::equals).orElse(true)) {
        return NO_MATCH;
    }
    if (!hashSymbol.map(expectedHashSymbol -> expectedHashSymbol.map(alias -> alias.toSymbol(symbolAliases)).equals(windowNode.getHashSymbol())).orElse(true)) {
        return NO_MATCH;
    }
    /*
         * Window functions produce a symbol (the result of the function call) that we might
         * want to bind to an alias so we can reference it further up the tree. As such,
         * they need to be matched with an Alias matcher so we can bind the symbol if desired.
         */
    return match();
}
Also used : StatsProvider(io.prestosql.cost.StatsProvider) MatchResult.match(io.prestosql.sql.planner.assertions.MatchResult.match) Set(java.util.Set) PlanNode(io.prestosql.spi.plan.PlanNode) Metadata(io.prestosql.metadata.Metadata) SortOrder(io.prestosql.spi.block.SortOrder) Preconditions.checkState(com.google.common.base.Preconditions.checkState) FunctionHandle(io.prestosql.spi.function.FunctionHandle) List(java.util.List) FunctionCall(io.prestosql.sql.tree.FunctionCall) WindowNode(io.prestosql.spi.plan.WindowNode) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) Session(io.prestosql.Session) Optional(java.util.Optional) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) PlanMatchPattern.node(io.prestosql.sql.planner.assertions.PlanMatchPattern.node) LinkedList(java.util.LinkedList) NO_MATCH(io.prestosql.sql.planner.assertions.MatchResult.NO_MATCH) MoreObjects.toStringHelper(com.google.common.base.MoreObjects.toStringHelper) WindowNode(io.prestosql.spi.plan.WindowNode)

Example 7 with WindowNode

use of io.prestosql.spi.plan.WindowNode 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;
}
Also used : Cast(io.prestosql.sql.tree.Cast) WindowFrame(io.prestosql.sql.tree.WindowFrame) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) Symbol(io.prestosql.spi.plan.Symbol) SymbolUtils.toSymbolReference(io.prestosql.sql.planner.SymbolUtils.toSymbolReference) SymbolReference(io.prestosql.sql.tree.SymbolReference) ArrayList(java.util.ArrayList) FrameBoundType(io.prestosql.spi.sql.expression.Types.FrameBoundType) LinkedHashMap(java.util.LinkedHashMap) SortItem(io.prestosql.sql.tree.SortItem) WindowFrame(io.prestosql.sql.tree.WindowFrame) FunctionCall(io.prestosql.sql.tree.FunctionCall) Window(io.prestosql.sql.tree.Window) WindowFrameType(io.prestosql.spi.sql.expression.Types.WindowFrameType) WindowNode(io.prestosql.spi.plan.WindowNode) OrderingScheme(io.prestosql.spi.plan.OrderingScheme) SortOrder(io.prestosql.spi.block.SortOrder) OrderingSchemeUtils.sortItemToSortOrder(io.prestosql.sql.planner.OrderingSchemeUtils.sortItemToSortOrder) OriginalExpressionUtils.castToRowExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression) RowExpression(io.prestosql.spi.relation.RowExpression) FrameBoundType(io.prestosql.spi.sql.expression.Types.FrameBoundType) Type(io.prestosql.spi.type.Type) WindowFrameType(io.prestosql.spi.sql.expression.Types.WindowFrameType) RelationType(io.prestosql.sql.analyzer.RelationType) OriginalExpressionUtils.castToRowExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression) LambdaExpression(io.prestosql.sql.tree.LambdaExpression) Expression(io.prestosql.sql.tree.Expression) RowExpression(io.prestosql.spi.relation.RowExpression)

Example 8 with WindowNode

use of io.prestosql.spi.plan.WindowNode in project hetu-core by openlookeng.

the class TestWindowNode method testSerializationRoundtrip.

@Test
public void testSerializationRoundtrip() throws Exception {
    Symbol windowSymbol = planSymbolAllocator.newSymbol("sum", BIGINT);
    FunctionHandle functionHandle = createTestMetadataManager().getFunctionAndTypeManager().lookupFunction("sum", fromTypes(BIGINT));
    WindowNode.Frame frame = new WindowNode.Frame(Types.WindowFrameType.RANGE, Types.FrameBoundType.UNBOUNDED_PRECEDING, Optional.empty(), Types.FrameBoundType.UNBOUNDED_FOLLOWING, Optional.empty(), Optional.empty(), Optional.empty());
    PlanNodeId id = newId();
    WindowNode.Specification specification = new WindowNode.Specification(ImmutableList.of(columnA), Optional.of(new OrderingScheme(ImmutableList.of(columnB), ImmutableMap.of(columnB, SortOrder.ASC_NULLS_FIRST))));
    CallExpression call = call("sum", functionHandle, BIGINT, ImmutableList.of(new VariableReferenceExpression(columnC.getName(), BIGINT)));
    Map<Symbol, WindowNode.Function> functions = ImmutableMap.of(windowSymbol, new WindowNode.Function(call, ImmutableList.of(new VariableReferenceExpression(columnC.getName(), BIGINT)), frame));
    Optional<Symbol> hashSymbol = Optional.of(columnB);
    Set<Symbol> prePartitionedInputs = ImmutableSet.of(columnA);
    WindowNode windowNode = new WindowNode(id, sourceNode, specification, functions, hashSymbol, prePartitionedInputs, 0);
    String json = codec.toJson(windowNode);
    WindowNode actualNode = codec.fromJson(json);
    assertEquals(actualNode.getId(), windowNode.getId());
    assertEquals(actualNode.getSpecification(), windowNode.getSpecification());
    assertEquals(actualNode.getWindowFunctions(), windowNode.getWindowFunctions());
    assertEquals(actualNode.getFrames(), windowNode.getFrames());
    assertEquals(actualNode.getHashSymbol(), windowNode.getHashSymbol());
    assertEquals(actualNode.getPrePartitionedInputs(), windowNode.getPrePartitionedInputs());
    assertEquals(actualNode.getPreSortedOrderPrefix(), windowNode.getPreSortedOrderPrefix());
}
Also used : WindowNode(io.prestosql.spi.plan.WindowNode) OrderingScheme(io.prestosql.spi.plan.OrderingScheme) Symbol(io.prestosql.spi.plan.Symbol) PlanNodeId(io.prestosql.spi.plan.PlanNodeId) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) FunctionHandle(io.prestosql.spi.function.FunctionHandle) CallExpression(io.prestosql.spi.relation.CallExpression) Test(org.testng.annotations.Test)

Example 9 with WindowNode

use of io.prestosql.spi.plan.WindowNode in project hetu-core by openlookeng.

the class TestWindowNode method getJsonCodec.

private JsonCodec<WindowNode> getJsonCodec() throws Exception {
    Module module = binder -> {
        SqlParser sqlParser = new SqlParser();
        TypeManager typeManager = new TestingTypeManager();
        binder.install(new JsonModule());
        binder.install(new HandleJsonModule());
        binder.bind(SqlParser.class).toInstance(sqlParser);
        binder.bind(TypeManager.class).toInstance(typeManager);
        configBinder(binder).bindConfig(FeaturesConfig.class);
        newSetBinder(binder, Type.class);
        jsonBinder(binder).addSerializerBinding(Slice.class).to(SliceSerializer.class);
        jsonBinder(binder).addDeserializerBinding(Slice.class).to(SliceDeserializer.class);
        jsonBinder(binder).addDeserializerBinding(Type.class).to(TestingTypeDeserializer.class);
        jsonBinder(binder).addSerializerBinding(Expression.class).to(Serialization.ExpressionSerializer.class);
        jsonBinder(binder).addDeserializerBinding(Expression.class).to(Serialization.ExpressionDeserializer.class);
        jsonBinder(binder).addDeserializerBinding(FunctionCall.class).to(Serialization.FunctionCallDeserializer.class);
        jsonBinder(binder).addKeySerializerBinding(VariableReferenceExpression.class).to(Serialization.VariableReferenceExpressionSerializer.class);
        jsonBinder(binder).addKeyDeserializerBinding(VariableReferenceExpression.class).to(Serialization.VariableReferenceExpressionDeserializer.class);
        jsonCodecBinder(binder).bindJsonCodec(WindowNode.class);
    };
    Bootstrap app = new Bootstrap(ImmutableList.of(module));
    Injector injector = app.strictConfig().doNotInitializeLogging().quiet().initialize();
    return injector.getInstance(new Key<JsonCodec<WindowNode>>() {
    });
}
Also used : Module(com.google.inject.Module) SliceDeserializer(io.prestosql.server.SliceDeserializer) Slice(io.airlift.slice.Slice) Key(com.google.inject.Key) Serialization(io.prestosql.sql.Serialization) Assert.assertEquals(org.testng.Assert.assertEquals) Test(org.testng.annotations.Test) SqlParser(io.prestosql.sql.parser.SqlParser) JsonBinder.jsonBinder(io.airlift.json.JsonBinder.jsonBinder) SortOrder(io.prestosql.spi.block.SortOrder) Types(io.prestosql.spi.sql.expression.Types) CallExpression(io.prestosql.spi.relation.CallExpression) ImmutableList(com.google.common.collect.ImmutableList) FunctionCall(io.prestosql.sql.tree.FunctionCall) Expressions.call(io.prestosql.sql.relational.Expressions.call) OrderingScheme(io.prestosql.spi.plan.OrderingScheme) Map(java.util.Map) Multibinder.newSetBinder(com.google.inject.multibindings.Multibinder.newSetBinder) SliceSerializer(io.prestosql.server.SliceSerializer) Type(io.prestosql.spi.type.Type) BIGINT(io.prestosql.spi.type.BigintType.BIGINT) Symbol(io.prestosql.spi.plan.Symbol) PlanNodeId(io.prestosql.spi.plan.PlanNodeId) JsonCodecBinder.jsonCodecBinder(io.airlift.json.JsonCodecBinder.jsonCodecBinder) ImmutableSet(com.google.common.collect.ImmutableSet) TypeSignatureProvider.fromTypes(io.prestosql.sql.analyzer.TypeSignatureProvider.fromTypes) TestingTypeManager(io.prestosql.spi.type.TestingTypeManager) ImmutableMap(com.google.common.collect.ImmutableMap) MetadataManager.createTestMetadataManager(io.prestosql.metadata.MetadataManager.createTestMetadataManager) BeforeClass(org.testng.annotations.BeforeClass) TypeManager(io.prestosql.spi.type.TypeManager) Set(java.util.Set) VariableReferenceExpression(io.prestosql.spi.relation.VariableReferenceExpression) UUID(java.util.UUID) TestingTypeDeserializer(io.prestosql.spi.type.TestingTypeDeserializer) Injector(com.google.inject.Injector) FunctionHandle(io.prestosql.spi.function.FunctionHandle) PlanSymbolAllocator(io.prestosql.sql.planner.PlanSymbolAllocator) ValuesNode(io.prestosql.spi.plan.ValuesNode) WindowNode(io.prestosql.spi.plan.WindowNode) Bootstrap(io.airlift.bootstrap.Bootstrap) FeaturesConfig(io.prestosql.sql.analyzer.FeaturesConfig) Optional(java.util.Optional) ConfigBinder.configBinder(io.airlift.configuration.ConfigBinder.configBinder) Expression(io.prestosql.sql.tree.Expression) JsonCodec(io.airlift.json.JsonCodec) JsonModule(io.airlift.json.JsonModule) HandleJsonModule(io.prestosql.metadata.HandleJsonModule) WindowNode(io.prestosql.spi.plan.WindowNode) FeaturesConfig(io.prestosql.sql.analyzer.FeaturesConfig) SqlParser(io.prestosql.sql.parser.SqlParser) SliceSerializer(io.prestosql.server.SliceSerializer) JsonModule(io.airlift.json.JsonModule) HandleJsonModule(io.prestosql.metadata.HandleJsonModule) Type(io.prestosql.spi.type.Type) SliceDeserializer(io.prestosql.server.SliceDeserializer) TestingTypeDeserializer(io.prestosql.spi.type.TestingTypeDeserializer) JsonCodec(io.airlift.json.JsonCodec) HandleJsonModule(io.prestosql.metadata.HandleJsonModule) Injector(com.google.inject.Injector) TestingTypeManager(io.prestosql.spi.type.TestingTypeManager) TypeManager(io.prestosql.spi.type.TypeManager) Bootstrap(io.airlift.bootstrap.Bootstrap) Module(com.google.inject.Module) JsonModule(io.airlift.json.JsonModule) HandleJsonModule(io.prestosql.metadata.HandleJsonModule) TestingTypeManager(io.prestosql.spi.type.TestingTypeManager)

Example 10 with WindowNode

use of io.prestosql.spi.plan.WindowNode in project hetu-core by openlookeng.

the class TestTypeValidator method testInvalidWindowFunctionCall.

@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "type of symbol 'sum(_[0-9]+)?' is expected to be double, but the actual type is bigint")
public void testInvalidWindowFunctionCall() {
    Symbol windowSymbol = planSymbolAllocator.newSymbol("sum", DOUBLE);
    FunctionHandle functionHandle = FUNCTION_MANAGER.lookupFunction("sum", fromTypes(DOUBLE));
    WindowNode.Frame frame = new WindowNode.Frame(WindowFrameType.RANGE, FrameBoundType.UNBOUNDED_PRECEDING, Optional.empty(), FrameBoundType.UNBOUNDED_FOLLOWING, Optional.empty(), Optional.empty(), Optional.empty());
    WindowNode.Function function = new WindowNode.Function(call("sum", functionHandle, BIGINT, ImmutableList.of(VariableReferenceSymbolConverter.toVariableReference(columnA, BIGINT))), ImmutableList.of(VariableReferenceSymbolConverter.toVariableReference(columnA, BIGINT)), frame);
    WindowNode.Specification specification = new WindowNode.Specification(ImmutableList.of(), Optional.empty());
    PlanNode node = new WindowNode(newId(), baseTableScan, specification, ImmutableMap.of(windowSymbol, function), Optional.empty(), ImmutableSet.of(), 0);
    assertTypesValid(node);
}
Also used : WindowNode(io.prestosql.spi.plan.WindowNode) PlanNode(io.prestosql.spi.plan.PlanNode) Symbol(io.prestosql.spi.plan.Symbol) FunctionHandle(io.prestosql.spi.function.FunctionHandle) Test(org.testng.annotations.Test)

Aggregations

WindowNode (io.prestosql.spi.plan.WindowNode)11 Symbol (io.prestosql.spi.plan.Symbol)9 FunctionHandle (io.prestosql.spi.function.FunctionHandle)7 PlanNode (io.prestosql.spi.plan.PlanNode)7 Test (org.testng.annotations.Test)6 OrderingScheme (io.prestosql.spi.plan.OrderingScheme)4 FunctionCall (io.prestosql.sql.tree.FunctionCall)4 SortOrder (io.prestosql.spi.block.SortOrder)3 CallExpression (io.prestosql.spi.relation.CallExpression)3 Expression (io.prestosql.sql.tree.Expression)3 Map (java.util.Map)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 PlanNodeId (io.prestosql.spi.plan.PlanNodeId)2 VariableReferenceExpression (io.prestosql.spi.relation.VariableReferenceExpression)2 Type (io.prestosql.spi.type.Type)2 ComparisonExpression (io.prestosql.sql.tree.ComparisonExpression)2 Optional (java.util.Optional)2 Set (java.util.Set)2 MoreObjects.toStringHelper (com.google.common.base.MoreObjects.toStringHelper)1