Search in sources :

Example 6 with Domain

use of io.trino.spi.predicate.Domain in project trino by trinodb.

the class PushPredicateIntoTableScan method computeEnforced.

public static TupleDomain<ColumnHandle> computeEnforced(TupleDomain<ColumnHandle> predicate, TupleDomain<ColumnHandle> unenforced) {
    // The engine requested the connector to apply a filter with a non-none TupleDomain.
    // A TupleDomain is effectively a list of column-Domain pairs.
    // The connector is expected enforce the respective domain entirely on none, some, or all of the columns.
    // 1. When the connector could enforce none of the domains, the unenforced would be equal to predicate;
    // 2. When the connector could enforce some of the domains, the unenforced would contain a subset of the column-Domain pairs;
    // 3. When the connector could enforce all of the domains, the unenforced would be TupleDomain.all().
    // In all 3 cases shown above, the unenforced is not TupleDomain.none().
    checkArgument(!unenforced.isNone());
    Map<ColumnHandle, Domain> predicateDomains = predicate.getDomains().get();
    Map<ColumnHandle, Domain> unenforcedDomains = unenforced.getDomains().get();
    ImmutableMap.Builder<ColumnHandle, Domain> enforcedDomainsBuilder = ImmutableMap.builder();
    for (Map.Entry<ColumnHandle, Domain> entry : predicateDomains.entrySet()) {
        ColumnHandle predicateColumnHandle = entry.getKey();
        if (unenforcedDomains.containsKey(predicateColumnHandle)) {
            checkArgument(entry.getValue().equals(unenforcedDomains.get(predicateColumnHandle)), "Enforced tuple domain cannot be determined. The connector is expected to enforce the respective domain entirely on none, some, or all of the column.");
        } else {
            enforcedDomainsBuilder.put(predicateColumnHandle, entry.getValue());
        }
    }
    Map<ColumnHandle, Domain> enforcedDomains = enforcedDomainsBuilder.buildOrThrow();
    checkArgument(enforcedDomains.size() + unenforcedDomains.size() == predicateDomains.size(), "Enforced tuple domain cannot be determined. Connector returned an unenforced TupleDomain that contains columns not in predicate.");
    return TupleDomain.withColumnDomains(enforcedDomains);
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap)

Example 7 with Domain

use of io.trino.spi.predicate.Domain in project trino by trinodb.

the class PushJoinIntoTableScan method apply.

@Override
public Result apply(JoinNode joinNode, Captures captures, Context context) {
    if (joinNode.isCrossJoin()) {
        return Result.empty();
    }
    TableScanNode left = captures.get(LEFT_TABLE_SCAN);
    TableScanNode right = captures.get(RIGHT_TABLE_SCAN);
    verify(!left.isUpdateTarget() && !right.isUpdateTarget(), "Unexpected Join over for-update table scan");
    Expression effectiveFilter = getEffectiveFilter(joinNode);
    FilterSplitResult filterSplitResult = splitFilter(effectiveFilter, left.getOutputSymbols(), right.getOutputSymbols(), context);
    if (!filterSplitResult.getRemainingFilter().equals(BooleanLiteral.TRUE_LITERAL)) {
        // TODO add extra filter node above join
        return Result.empty();
    }
    if (left.getEnforcedConstraint().isNone() || right.getEnforcedConstraint().isNone()) {
        // enforced constraint harder below.
        return Result.empty();
    }
    Map<String, ColumnHandle> leftAssignments = left.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue));
    Map<String, ColumnHandle> rightAssignments = right.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue));
    /*
         * We are (lazily) computing estimated statistics for join node and left and right table
         * and passing those to connector via applyJoin.
         *
         * There are a couple reasons for this approach:
         * - the engine knows how to estimate join and connector may not
         * - the engine may have cached stats for the table scans (within context.getStatsProvider()), so can be able to provide information more inexpensively
         * - in the future, the engine may be able to provide stats for table scan even in case when connector no longer can (see https://github.com/trinodb/trino/issues/6998)
         * - the pushdown feasibility assessment logic may be different (or configured differently) for different connectors/catalogs.
         */
    JoinStatistics joinStatistics = getJoinStatistics(joinNode, left, right, context);
    Optional<JoinApplicationResult<TableHandle>> joinApplicationResult = metadata.applyJoin(context.getSession(), getJoinType(joinNode), left.getTable(), right.getTable(), filterSplitResult.getPushableConditions(), // TODO we could pass only subset of assignments here, those which are needed to resolve filterSplitResult.getPushableConditions
    leftAssignments, rightAssignments, joinStatistics);
    if (joinApplicationResult.isEmpty()) {
        return Result.empty();
    }
    TableHandle handle = joinApplicationResult.get().getTableHandle();
    Map<ColumnHandle, ColumnHandle> leftColumnHandlesMapping = joinApplicationResult.get().getLeftColumnHandles();
    Map<ColumnHandle, ColumnHandle> rightColumnHandlesMapping = joinApplicationResult.get().getRightColumnHandles();
    ImmutableMap.Builder<Symbol, ColumnHandle> assignmentsBuilder = ImmutableMap.builder();
    assignmentsBuilder.putAll(left.getAssignments().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> leftColumnHandlesMapping.get(entry.getValue()))));
    assignmentsBuilder.putAll(right.getAssignments().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> rightColumnHandlesMapping.get(entry.getValue()))));
    Map<Symbol, ColumnHandle> assignments = assignmentsBuilder.buildOrThrow();
    // convert enforced constraint
    JoinNode.Type joinType = joinNode.getType();
    TupleDomain<ColumnHandle> leftConstraint = deriveConstraint(left.getEnforcedConstraint(), leftColumnHandlesMapping, joinType == RIGHT || joinType == FULL);
    TupleDomain<ColumnHandle> rightConstraint = deriveConstraint(right.getEnforcedConstraint(), rightColumnHandlesMapping, joinType == LEFT || joinType == FULL);
    TupleDomain<ColumnHandle> newEnforcedConstraint = TupleDomain.withColumnDomains(ImmutableMap.<ColumnHandle, Domain>builder().putAll(leftConstraint.getDomains().orElseThrow()).putAll(rightConstraint.getDomains().orElseThrow()).buildOrThrow());
    return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new TableScanNode(joinNode.getId(), handle, ImmutableList.copyOf(assignments.keySet()), assignments, newEnforcedConstraint, deriveTableStatisticsForPushdown(context.getStatsProvider(), context.getSession(), joinApplicationResult.get().isPrecalculateStatistics(), joinNode), false, Optional.empty()), Assignments.identity(joinNode.getOutputSymbols())));
}
Also used : PlanNode(io.trino.sql.planner.plan.PlanNode) LEFT(io.trino.sql.planner.plan.JoinNode.Type.LEFT) BooleanLiteral(io.trino.sql.tree.BooleanLiteral) Map(java.util.Map) JoinNode(io.trino.sql.planner.plan.JoinNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) Rules.deriveTableStatisticsForPushdown(io.trino.sql.planner.iterative.rule.Rules.deriveTableStatisticsForPushdown) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Domain(io.trino.spi.predicate.Domain) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Set(java.util.Set) BasicRelationStatistics(io.trino.spi.connector.BasicRelationStatistics) Patterns.tableScan(io.trino.sql.planner.plan.Patterns.tableScan) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Pattern(io.trino.matching.Pattern) SystemSessionProperties.isAllowPushdownIntoConnectors(io.trino.SystemSessionProperties.isAllowPushdownIntoConnectors) RIGHT(io.trino.sql.planner.plan.JoinNode.Type.RIGHT) SymbolReference(io.trino.sql.tree.SymbolReference) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) Session(io.trino.Session) JoinCondition(io.trino.spi.connector.JoinCondition) Patterns(io.trino.sql.planner.plan.Patterns) Variable(io.trino.spi.expression.Variable) Capture.newCapture(io.trino.matching.Capture.newCapture) JoinStatistics(io.trino.spi.connector.JoinStatistics) ImmutableList(com.google.common.collect.ImmutableList) JoinType(io.trino.spi.connector.JoinType) Verify.verify(com.google.common.base.Verify.verify) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Rule(io.trino.sql.planner.iterative.Rule) Join.left(io.trino.sql.planner.plan.Patterns.Join.left) ProjectNode(io.trino.sql.planner.plan.ProjectNode) ExpressionUtils(io.trino.sql.ExpressionUtils) Symbol(io.trino.sql.planner.Symbol) FULL(io.trino.sql.planner.plan.JoinNode.Type.FULL) TupleDomain(io.trino.spi.predicate.TupleDomain) Capture(io.trino.matching.Capture) JoinApplicationResult(io.trino.spi.connector.JoinApplicationResult) TableHandle(io.trino.metadata.TableHandle) Join.right(io.trino.sql.planner.plan.Patterns.Join.right) ExpressionUtils.and(io.trino.sql.ExpressionUtils.and) Double.isNaN(java.lang.Double.isNaN) Captures(io.trino.matching.Captures) Metadata(io.trino.metadata.Metadata) TypeProvider(io.trino.sql.planner.TypeProvider) Domain.onlyNull(io.trino.spi.predicate.Domain.onlyNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Symbol(io.trino.sql.planner.Symbol) JoinNode(io.trino.sql.planner.plan.JoinNode) JoinApplicationResult(io.trino.spi.connector.JoinApplicationResult) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) JoinStatistics(io.trino.spi.connector.JoinStatistics) TableScanNode(io.trino.sql.planner.plan.TableScanNode) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Expression(io.trino.sql.tree.Expression) TableHandle(io.trino.metadata.TableHandle) ProjectNode(io.trino.sql.planner.plan.ProjectNode) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap)

Example 8 with Domain

use of io.trino.spi.predicate.Domain in project trino by trinodb.

the class PushPredicateThroughProjectIntoWindow method extractUpperBound.

private static OptionalInt extractUpperBound(TupleDomain<Symbol> tupleDomain, Symbol symbol) {
    if (tupleDomain.isNone()) {
        return OptionalInt.empty();
    }
    Domain rankingDomain = tupleDomain.getDomains().get().get(symbol);
    if (rankingDomain == null) {
        return OptionalInt.empty();
    }
    ValueSet values = rankingDomain.getValues();
    if (values.isAll() || values.isNone() || values.getRanges().getRangeCount() <= 0) {
        return OptionalInt.empty();
    }
    Range span = values.getRanges().getSpan();
    if (span.isHighUnbounded()) {
        return OptionalInt.empty();
    }
    long upperBound = (Long) span.getHighBoundedValue();
    if (!span.isHighInclusive()) {
        upperBound--;
    }
    if (upperBound >= Integer.MIN_VALUE && upperBound <= Integer.MAX_VALUE) {
        return OptionalInt.of(toIntExact(upperBound));
    }
    return OptionalInt.empty();
}
Also used : Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Range(io.trino.spi.predicate.Range) ValueSet(io.trino.spi.predicate.ValueSet)

Example 9 with Domain

use of io.trino.spi.predicate.Domain in project trino by trinodb.

the class HiveMetadata method buildColumnDomain.

private static Domain buildColumnDomain(ColumnHandle column, List<HivePartition> partitions) {
    checkArgument(!partitions.isEmpty(), "partitions cannot be empty");
    boolean hasNull = false;
    boolean hasNaN = false;
    List<Object> nonNullValues = new ArrayList<>();
    Type type = ((HiveColumnHandle) column).getType();
    for (HivePartition partition : partitions) {
        NullableValue value = partition.getKeys().get(column);
        if (value == null) {
            throw new TrinoException(HIVE_UNKNOWN_ERROR, format("Partition %s does not have a value for partition column %s", partition, column));
        }
        if (value.isNull()) {
            hasNull = true;
        } else {
            if (isFloatingPointNaN(type, value.getValue())) {
                hasNaN = true;
            }
            nonNullValues.add(value.getValue());
        }
    }
    Domain domain;
    if (nonNullValues.isEmpty()) {
        domain = Domain.none(type);
    } else if (hasNaN) {
        domain = Domain.notNull(type);
    } else {
        domain = Domain.multipleValues(type, nonNullValues);
    }
    if (hasNull) {
        domain = domain.union(Domain.onlyNull(type));
    }
    return domain;
}
Also used : ColumnStatisticType(io.trino.spi.statistics.ColumnStatisticType) TimestampType(io.trino.spi.type.TimestampType) MapType(io.trino.spi.type.MapType) TableStatisticType(io.trino.spi.statistics.TableStatisticType) HiveType.toHiveType(io.trino.plugin.hive.HiveType.toHiveType) TableType(org.apache.hadoop.hive.metastore.TableType) ErrorType(io.trino.spi.ErrorType) RowType(io.trino.spi.type.RowType) ArrayType(io.trino.spi.type.ArrayType) HiveWriteUtils.isWritableType(io.trino.plugin.hive.util.HiveWriteUtils.isWritableType) Type(io.trino.spi.type.Type) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) ArrayList(java.util.ArrayList) NullableValue(io.trino.spi.predicate.NullableValue) TrinoException(io.trino.spi.TrinoException) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain)

Example 10 with Domain

use of io.trino.spi.predicate.Domain in project trino by trinodb.

the class GlueExpressionUtil method buildGlueExpression.

public static String buildGlueExpression(List<String> columnNames, TupleDomain<String> partitionKeysFilter, boolean assumeCanonicalPartitionKeys, int expressionLengthLimit) {
    // this should have been handled by callers
    checkState(!partitionKeysFilter.isNone());
    if (partitionKeysFilter.isAll()) {
        // glue handles both null and "" as a tautology
        return "";
    }
    List<String> perColumnExpressions = new ArrayList<>();
    int expressionLength = 0;
    Map<String, Domain> domains = partitionKeysFilter.getDomains().get();
    for (String columnName : columnNames) {
        Domain domain = domains.get(columnName);
        if (domain != null) {
            Optional<String> columnExpression = buildGlueExpressionForSingleDomain(columnName, domain, assumeCanonicalPartitionKeys);
            if (columnExpression.isPresent()) {
                int newExpressionLength = expressionLength;
                if (expressionLength > 0) {
                    newExpressionLength += CONJUNCT_SEPARATOR.length();
                }
                newExpressionLength += columnExpression.get().length();
                if (newExpressionLength > expressionLengthLimit) {
                    continue;
                }
                perColumnExpressions.add(columnExpression.get());
                expressionLength = newExpressionLength;
            }
        }
    }
    return Joiner.on(CONJUNCT_SEPARATOR).join(perColumnExpressions);
}
Also used : ArrayList(java.util.ArrayList) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain)

Aggregations

Domain (io.trino.spi.predicate.Domain)120 TupleDomain (io.trino.spi.predicate.TupleDomain)107 ColumnHandle (io.trino.spi.connector.ColumnHandle)51 Test (org.testng.annotations.Test)45 Map (java.util.Map)38 ImmutableList (com.google.common.collect.ImmutableList)36 ImmutableMap (com.google.common.collect.ImmutableMap)33 List (java.util.List)27 Optional (java.util.Optional)25 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)23 Type (io.trino.spi.type.Type)23 ConnectorSession (io.trino.spi.connector.ConnectorSession)21 SchemaTableName (io.trino.spi.connector.SchemaTableName)21 Objects.requireNonNull (java.util.Objects.requireNonNull)21 Set (java.util.Set)20 Range (io.trino.spi.predicate.Range)19 ValueSet (io.trino.spi.predicate.ValueSet)18 Constraint (io.trino.spi.connector.Constraint)17 String.format (java.lang.String.format)17 ImmutableSet (com.google.common.collect.ImmutableSet)16