/* * Licensed to CRATE Technology GmbH ("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.planner.node.dql; import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import io.crate.analyze.symbol.Symbol; import io.crate.analyze.symbol.Symbols; import io.crate.planner.node.ExecutionPhase; import io.crate.planner.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 org.elasticsearch.common.io.stream.Streamable; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.Function; public abstract class AbstractProjectionsPhase implements Streamable, ExecutionPhase { private UUID jobId; private int executionPhaseId; private String name; protected List<Projection> projections = ImmutableList.of(); protected List<DataType> outputTypes = ImmutableList.of(); public AbstractProjectionsPhase() { } protected AbstractProjectionsPhase(UUID jobId, int executionPhaseId, String name, List<Projection> projections) { this.jobId = jobId; this.executionPhaseId = executionPhaseId; this.name = name; this.projections = projections; } protected static List<DataType> extractOutputTypes(List<Symbol> outputs, List<Projection> projections) { Projection lastProjection = Iterables.getLast(projections, null); if (lastProjection == null) { return Symbols.extractTypes(outputs); } else { return Symbols.extractTypes(lastProjection.outputs()); } } public String name() { return name; } public UUID jobId() { return jobId; } @Override public int phaseId() { return executionPhaseId; } public boolean hasProjections() { return projections != null && projections.size() > 0; } public List<Projection> projections() { return projections; } public void addProjection(Projection projection) { List<Projection> projections = new ArrayList<>(this.projections); projections.add(projection); this.projections = ImmutableList.copyOf(projections); outputTypes = Symbols.extractTypes(projection.outputs()); } public Optional<Projection> finalProjection() { if (projections.size() == 0) { return Optional.absent(); } else { return Optional.of(projections.get(projections.size() - 1)); } } public void replaceSymbols(Function<Symbol, Symbol> replaceFunction) { for (Projection projection : projections) { projection.replaceSymbols(replaceFunction); } } public List<DataType> outputTypes() { return outputTypes; } @Override public void readFrom(StreamInput in) throws IOException { name = in.readString(); jobId = new UUID(in.readLong(), in.readLong()); executionPhaseId = in.readVInt(); int numCols = in.readVInt(); if (numCols > 0) { outputTypes = new ArrayList<>(numCols); for (int i = 0; i < numCols; i++) { outputTypes.add(DataTypes.fromStream(in)); } } int numProjections = in.readVInt(); if (numProjections > 0) { projections = new ArrayList<>(numProjections); for (int i = 0; i < numProjections; i++) { projections.add(Projection.fromStream(in)); } } } @Override public void writeTo(StreamOutput out) throws IOException { out.writeString(name); assert jobId != null : "jobId must not be null"; out.writeLong(jobId.getMostSignificantBits()); out.writeLong(jobId.getLeastSignificantBits()); out.writeVInt(executionPhaseId); int numCols = outputTypes.size(); out.writeVInt(numCols); for (int i = 0; i < numCols; i++) { DataTypes.toStream(outputTypes.get(i), out); } if (hasProjections()) { out.writeVInt(projections.size()); for (Projection p : projections) { Projection.toStream(p, out); } } else { out.writeVInt(0); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AbstractProjectionsPhase node = (AbstractProjectionsPhase) o; return !(name != null ? !name.equals(node.name) : node.name != null); } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("name", name) .add("projections", projections) .add("outputTypes", outputTypes) .toString(); } }