Java tutorial
/* * Licensed to Crate under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. Crate licenses this file * to you under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial * agreement. */ package io.crate.execution.dsl.phases; import com.google.common.base.MoreObjects; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import io.crate.expression.symbol.Symbols; import io.crate.planner.PositionalOrderBy; import io.crate.planner.distribution.DistributionInfo; import io.crate.execution.dsl.projection.Projection; import io.crate.types.DataType; import io.crate.types.DataTypes; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import javax.annotation.Nullable; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.UUID; /** * A plan node which merges results from upstreams */ public class MergePhase extends AbstractProjectionsPhase implements UpstreamPhase { private final Collection<? extends DataType> inputTypes; private final int numUpstreams; /** The number of different inputs, e.g. Union has inputs from two Collect phases */ private final int numInputs; private final Collection<String> executionNodes; private DistributionInfo distributionInfo; /** * expects sorted input and produces sorted output */ @Nullable private PositionalOrderBy positionalOrderBy; /** * Creates a MergePhase to combine the results from multiple node operations. * @param jobId The JobID of the entire execution. * @param executionNodeId A unique execution id for this phase. * @param name The name of the MergePhase. * @param numUpstreams The number of nodes to expect data from. * @param numInputs The number of different inputs to read data from which is equal to * the number of upstream phases. * @param executionNodes The nodes where this MergePhase executes. * @param inputTypes The types of the input rows. * @param projections The projections to apply when merging. * @param distributionInfo The default strategy to use when distributing the results of the MergePhase. * @param positionalOrderBy The order by positions on which the input is pre-sorted on; setting this * will result in a sorted merge. */ public MergePhase(UUID jobId, int executionNodeId, String name, int numUpstreams, int numInputs, Collection<String> executionNodes, Collection<? extends DataType> inputTypes, List<Projection> projections, DistributionInfo distributionInfo, @Nullable PositionalOrderBy positionalOrderBy) { super(jobId, executionNodeId, name, projections); this.numInputs = numInputs; this.inputTypes = inputTypes; this.numUpstreams = numUpstreams; this.distributionInfo = distributionInfo; if (projections.isEmpty()) { outputTypes = Lists.newArrayList(inputTypes); } else { outputTypes = Symbols.typeView(Iterables.getLast(projections).outputs()); } this.positionalOrderBy = positionalOrderBy; this.executionNodes = executionNodes; } @Override public Type type() { return Type.MERGE; } @Override public Collection<String> nodeIds() { return executionNodes; } @Override public DistributionInfo distributionInfo() { return distributionInfo; } @Override public void distributionInfo(DistributionInfo distributionInfo) { this.distributionInfo = distributionInfo; } public int numUpstreams() { return numUpstreams; } /** * The number of inputs of the MergePhase. A typical MergePhase has only * one input. {@link io.crate.planner.operators.Union} has two. */ public int numInputs() { return numInputs; } public Collection<? extends DataType> inputTypes() { return inputTypes; } @Nullable public PositionalOrderBy orderByPositions() { return positionalOrderBy; } @Override public <C, R> R accept(ExecutionPhaseVisitor<C, R> visitor, C context) { return visitor.visitMergePhase(this, context); } public MergePhase(StreamInput in) throws IOException { super(in); distributionInfo = DistributionInfo.fromStream(in); numUpstreams = in.readVInt(); numInputs = in.readVInt(); int numCols = in.readVInt(); if (numCols > 0) { List<DataType> inputTypes = new ArrayList<>(numCols); for (int i = 0; i < numCols; i++) { inputTypes.add(DataTypes.fromStream(in)); } this.inputTypes = inputTypes; } else { inputTypes = Collections.emptyList(); } int numExecutionNodes = in.readVInt(); if (numExecutionNodes > 0) { executionNodes = new HashSet<>(numExecutionNodes); for (int i = 0; i < numExecutionNodes; i++) { executionNodes.add(in.readString()); } } else { executionNodes = Collections.emptySet(); } positionalOrderBy = PositionalOrderBy.fromStream(in); } @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); distributionInfo.writeTo(out); out.writeVInt(numUpstreams); out.writeVInt(numInputs); int numCols = inputTypes.size(); out.writeVInt(numCols); for (DataType inputType : inputTypes) { DataTypes.toStream(inputType, out); } out.writeVInt(executionNodes.size()); for (String node : executionNodes) { out.writeString(node); } PositionalOrderBy.toStream(positionalOrderBy, out); } @Override public String toString() { MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).add("executionPhaseId", phaseId()) .add("name", name()).add("projections", projections).add("outputTypes", outputTypes) .add("jobId", jobId()).add("numUpstreams", numUpstreams).add("numInputs", numInputs) .add("nodeOperations", executionNodes).add("inputTypes", inputTypes) .add("orderBy", positionalOrderBy); return helper.toString(); } }