Package com.facebook.presto.sql.planner.plan

Source Code of com.facebook.presto.sql.planner.plan.TableScanNode$GeneratedPartitions

/*
* Licensed 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.
*/
package com.facebook.presto.sql.planner.plan;

import com.facebook.presto.spi.ColumnHandle;
import com.facebook.presto.spi.Partition;
import com.facebook.presto.spi.TableHandle;
import com.facebook.presto.spi.TupleDomain;
import com.facebook.presto.sql.planner.Symbol;
import com.facebook.presto.sql.tree.Expression;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import java.util.List;
import java.util.Map;

import static com.facebook.presto.sql.planner.DomainUtils.columnHandleToSymbol;
import static com.facebook.presto.sql.planner.DomainUtils.simplifyDomainFunction;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

@Immutable
public class TableScanNode
        extends PlanNode
{
    private final TableHandle table;
    private final List<Symbol> outputSymbols;
    private final Map<Symbol, ColumnHandle> assignments; // symbol -> column
    private final Optional<GeneratedPartitions> generatedPartitions;
    private final boolean partitionsDroppedBySerialization;
    private final TupleDomain partitionDomainSummary;

    // HACK!
    //
    // This field exists for the sole purpose of being able to print the original predicates (from the query) in
    // a human readable way. Predicates that get converted to and from TupleDomains might get more bulky and thus
    // more difficult to read when printed.
    // For example:
    // (ds > '2013-01-01') in the original query could easily become (ds IN ('2013-01-02', '2013-01-03', ...)) after the partitions are generated.
    // To make this work, the originalConstraint should be set exactly once after the first predicate push down and never adjusted after that.
    // In this way, we are always guaranteed to have a readable predicate that provides some kind of upper bound on the constraints.
    private final Expression originalConstraint;

    public TableScanNode(PlanNodeId id, TableHandle table, List<Symbol> outputSymbols, Map<Symbol, ColumnHandle> assignments, @Nullable Expression originalConstraint, Optional<GeneratedPartitions> generatedPartitions)
    {
        this(id, table, outputSymbols, assignments, originalConstraint, generatedPartitions, false);
    }

    @JsonCreator
    public TableScanNode(@JsonProperty("id") PlanNodeId id,
            @JsonProperty("table") TableHandle table,
            @JsonProperty("outputSymbols") List<Symbol> outputSymbols,
            @JsonProperty("assignments") Map<Symbol, ColumnHandle> assignments,
            @JsonProperty("originalConstraint") @Nullable Expression originalConstraint)
    {
        this(id, table, outputSymbols, assignments, originalConstraint, Optional.<GeneratedPartitions>absent(), true);
    }

    private TableScanNode(PlanNodeId id, TableHandle table, List<Symbol> outputSymbols, Map<Symbol, ColumnHandle> assignments, @Nullable Expression originalConstraint, Optional<GeneratedPartitions> generatedPartitions, boolean partitionsDroppedBySerialization)
    {
        super(id);

        checkNotNull(table, "table is null");
        checkNotNull(outputSymbols, "outputSymbols is null");
        checkNotNull(assignments, "assignments is null");
        checkArgument(assignments.keySet().containsAll(outputSymbols), "assignments does not cover all of outputSymbols");
        checkArgument(!assignments.isEmpty(), "assignments is empty");
        checkNotNull(generatedPartitions, "generatedPartitions is null");

        this.table = table;
        this.outputSymbols = ImmutableList.copyOf(outputSymbols);
        this.assignments = ImmutableMap.copyOf(assignments);
        this.originalConstraint = originalConstraint;
        this.generatedPartitions = generatedPartitions;
        this.partitionsDroppedBySerialization = partitionsDroppedBySerialization;
        this.partitionDomainSummary = computePartitionsDomainSummary(generatedPartitions);
        checkArgument(partitionDomainSummary.isNone() || assignments.values().containsAll(partitionDomainSummary.getDomains().keySet()), "Assignments do not include all of the ColumnHandles specified by the Partitions");
    }

    @JsonProperty("table")
    public TableHandle getTable()
    {
        return table;
    }

    @JsonProperty("outputSymbols")
    public List<Symbol> getOutputSymbols()
    {
        return outputSymbols;
    }

    @JsonProperty("assignments")
    public Map<Symbol, ColumnHandle> getAssignments()
    {
        return assignments;
    }

    @Nullable
    @JsonProperty("originalConstraint")
    public Expression getOriginalConstraint()
    {
        return originalConstraint;
    }

    public Optional<GeneratedPartitions> getGeneratedPartitions()
    {
        // If this exception throws, then we might want to consider making Partitions serializable by Jackson
        checkState(!partitionsDroppedBySerialization, "Can't access partitions after passing through serialization");
        return generatedPartitions;
    }

    public TupleDomain getPartitionsDomainSummary()
    {
        return partitionDomainSummary;
    }

    private static TupleDomain computePartitionsDomainSummary(Optional<GeneratedPartitions> generatedPartitions)
    {
        if (!generatedPartitions.isPresent()) {
            return TupleDomain.all();
        }

        TupleDomain tupleDomain = TupleDomain.none();
        for (Partition partition : generatedPartitions.get().getPartitions()) {
            tupleDomain = tupleDomain.columnWiseUnion(partition.getTupleDomain());
        }
        return tupleDomain;
    }

    @JsonProperty("partitionDomainSummary")
    public String getPrintablePartitionDomainSummary()
    {
        // Since partitions are not serializable, we can provide an additional jackson field purely for information purposes (i.e. for logging)
        // If partitions ever become serializable, we can get rid of this method
        StringBuilder builder = new StringBuilder()
                .append("TupleDomain:");
        if (partitionDomainSummary.isAll()) {
            builder.append("ALL");
        }
        else if (partitionDomainSummary.isNone()) {
            builder.append("NONE");
        }
        else {
            builder.append(Maps.transformValues(columnHandleToSymbol(partitionDomainSummary.getDomains(), assignments), simplifyDomainFunction()));
        }
        return builder.toString();
    }

    public List<PlanNode> getSources()
    {
        return ImmutableList.of();
    }

    public <C, R> R accept(PlanVisitor<C, R> visitor, C context)
    {
        return visitor.visitTableScan(this, context);
    }

    public static final class GeneratedPartitions
    {
        private final TupleDomain tupleDomainInput; // The TupleDomain used to generate the current list of Partitions
        private final List<Partition> partitions;

        public GeneratedPartitions(TupleDomain tupleDomainInput, List<Partition> partitions)
        {
            this.tupleDomainInput = checkNotNull(tupleDomainInput, "tupleDomainInput is null");
            this.partitions = ImmutableList.copyOf(checkNotNull(partitions, "partitions is null"));
        }

        public TupleDomain getTupleDomainInput()
        {
            return tupleDomainInput;
        }

        public List<Partition> getPartitions()
        {
            return partitions;
        }

        @Override
        public int hashCode()
        {
            return Objects.hashCode(tupleDomainInput, partitions);
        }

        @Override
        public boolean equals(Object obj)
        {
            if (this == obj) {
                return true;
            }
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            final GeneratedPartitions other = (GeneratedPartitions) obj;
            return Objects.equal(this.tupleDomainInput, other.tupleDomainInput) && Objects.equal(this.partitions, other.partitions);
        }
    }
}
TOP

Related Classes of com.facebook.presto.sql.planner.plan.TableScanNode$GeneratedPartitions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.