All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.facebook.presto.jdbc.internal.spi.plan.TableScanNode Maven / Gradle / Ivy

The newest version!
/*
 * 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.jdbc.internal.spi.plan;

import com.facebook.presto.jdbc.internal.common.predicate.TupleDomain;
import com.facebook.presto.jdbc.internal.spi.ColumnHandle;
import com.facebook.presto.jdbc.internal.spi.SourceLocation;
import com.facebook.presto.jdbc.internal.spi.TableHandle;
import com.facebook.presto.jdbc.internal.spi.constraints.TableConstraint;
import com.facebook.presto.jdbc.internal.spi.relation.VariableReferenceExpression;
import com.facebook.presto.jdbc.internal.jackson.annotation.JsonCreator;
import com.facebook.presto.jdbc.internal.jackson.annotation.JsonProperty;

import com.facebook.presto.jdbc.internal.javax.annotation.Nullable;
import com.facebook.presto.jdbc.internal.javax.annotation.concurrent.Immutable;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;

@Immutable
public final class TableScanNode
        extends PlanNode
{
    private final TableHandle table;
    private final Map assignments;
    private final List outputVariables;

    // Used during predicate refinement over multiple passes of predicate pushdown
    // TODO: think about how to get rid of this in new planner
    // TODO: these two fields will not be effective if they are created by connectors until we have refactored PickTableLayout
    private final TupleDomain currentConstraint;
    private final TupleDomain enforcedConstraint;
    private final List> tableConstraints;

    /**
     * This constructor is for JSON deserialization only.  Do not use!
     */
    @JsonCreator
    public TableScanNode(
            Optional sourceLocation,
            @JsonProperty("id") PlanNodeId id,
            @JsonProperty("table") TableHandle table,
            @JsonProperty("outputVariables") List outputVariables,
            @JsonProperty("assignments") Map assignments)
    {
        super(sourceLocation, id, Optional.empty());
        this.table = requireNonNull(table, "table is null");
        this.outputVariables = unmodifiableList(requireNonNull(outputVariables, "outputVariables is null"));
        this.assignments = unmodifiableMap(new HashMap<>(requireNonNull(assignments, "assignments is null")));
        checkArgument(assignments.keySet().containsAll(outputVariables), "assignments does not cover all of outputs");
        this.currentConstraint = null;
        this.enforcedConstraint = null;
        this.tableConstraints = emptyList();
    }

    public TableScanNode(
            Optional sourceLocation,
            PlanNodeId id,
            TableHandle table,
            List outputVariables,
            Map assignments,
            TupleDomain currentConstraint,
            TupleDomain enforcedConstraint)
    {
        this (sourceLocation, id, table, outputVariables, assignments, emptyList(), currentConstraint, enforcedConstraint);
    }

    public TableScanNode(
            Optional sourceLocation,
            PlanNodeId id,
            TableHandle table,
            List outputVariables,
            Map assignments,
            List> tableConstraints,
            TupleDomain currentConstraint,
            TupleDomain enforcedConstraint)
    {
        this (sourceLocation, id, Optional.empty(), table, outputVariables, assignments, tableConstraints, currentConstraint, enforcedConstraint);
    }

    public TableScanNode(
            Optional sourceLocation,
            PlanNodeId id,
            Optional statsEquivalentPlanNode,
            TableHandle table,
            List outputVariables,
            Map assignments,
            List> tableConstraints,
            TupleDomain currentConstraint,
            TupleDomain enforcedConstraint)
    {
        super(sourceLocation, id, statsEquivalentPlanNode);
        this.table = requireNonNull(table, "table is null");
        this.outputVariables = unmodifiableList(requireNonNull(outputVariables, "outputVariables is null"));
        this.assignments = unmodifiableMap(new HashMap<>(requireNonNull(assignments, "assignments is null")));
        checkArgument(assignments.keySet().containsAll(outputVariables), "assignments does not cover all of outputs");
        this.currentConstraint = requireNonNull(currentConstraint, "currentConstraint is null");
        this.enforcedConstraint = requireNonNull(enforcedConstraint, "enforcedConstraint is null");
        if (!currentConstraint.isAll() || !enforcedConstraint.isAll()) {
            checkArgument(table.getLayout().isPresent(), "tableLayout must be present when currentConstraint or enforcedConstraint is non-trivial");
        }
        this.tableConstraints = requireNonNull(tableConstraints, "tableConstraints is null");
    }

    /**
     * Get the table handle provided by connector
     */
    @JsonProperty("table")
    public TableHandle getTable()
    {
        return table;
    }

    /**
     * Get table constraints defined by connector
     */
    public List> getTableConstraints()
    {
        return tableConstraints;
    }

    /**
     * Get the mapping from symbols to columns
     */
    @JsonProperty
    public Map getAssignments()
    {
        return assignments;
    }

    /**
     * A TupleDomain that represents a predicate that every row this TableScan node
     * produces is guaranteed to satisfy.
     * 

* This guarantee can have different origins. * For example, it may be successful predicate push down, or inherent guarantee provided by the underlying data. * * currentConstraint will only be used in planner. It is not transported to worker thus will be null on worker. */ @Nullable public TupleDomain getCurrentConstraint() { return currentConstraint; } /** * A TupleDomain that represents a predicate that has been successfully pushed into * this TableScan node. In other words, predicates that were removed from filters * above the TableScan node because the TableScan node can guarantee it. *

* This field is used to make sure that predicates which were previously pushed down * do not get lost in subsequent refinements of the table layout. */ public TupleDomain getEnforcedConstraint() { // enforcedConstraint can be pretty complex. As a result, it may incur a significant cost to serialize, store, and transport. checkState(enforcedConstraint != null, "enforcedConstraint should only be used in planner. It is not transported to workers."); return enforcedConstraint; } @Override public List getSources() { // table scan should be the leaf node return emptyList(); } @Override public LogicalProperties computeLogicalProperties(LogicalPropertiesProvider logicalPropertiesProvider) { requireNonNull(logicalPropertiesProvider, "logicalPropertiesProvider cannot be null."); return logicalPropertiesProvider.getTableScanProperties(this); } @Override @JsonProperty public List getOutputVariables() { return outputVariables; } @Override public R accept(PlanVisitor visitor, C context) { return visitor.visitTableScan(this, context); } @Override public PlanNode assignStatsEquivalentPlanNode(Optional statsEquivalentPlanNode) { return new TableScanNode(getSourceLocation(), getId(), statsEquivalentPlanNode, table, outputVariables, assignments, tableConstraints, currentConstraint, enforcedConstraint); } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(this.getClass().getSimpleName()); stringBuilder.append(" {"); stringBuilder.append("table='").append(table).append('\''); stringBuilder.append(", outputVariables='").append(outputVariables).append('\''); stringBuilder.append(", assignments='").append(assignments).append('\''); stringBuilder.append(", currentConstraint='").append(currentConstraint).append('\''); stringBuilder.append(", enforcedConstraint='").append(enforcedConstraint).append('\''); stringBuilder.append('}'); return stringBuilder.toString(); } @Override public PlanNode replaceChildren(List newChildren) { checkArgument(newChildren.isEmpty(), "newChildren is not empty"); return this; } private static void checkArgument(boolean test, String errorMessage) { if (!test) { throw new IllegalArgumentException(errorMessage); } } private static void checkState(boolean test, String errorMessage) { if (!test) { throw new IllegalStateException(errorMessage); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy