Search in sources :

Example 21 with Domain

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

the class CassandraClusteringPredicatesExtractor method getClusteringKeysSet.

private static ClusteringPushDownResult getClusteringKeysSet(List<CassandraColumnHandle> clusteringColumns, TupleDomain<ColumnHandle> predicates, VersionNumber cassandraVersion) {
    ImmutableSet.Builder<ColumnHandle> fullyPushedColumnPredicates = ImmutableSet.builder();
    ImmutableList.Builder<String> clusteringColumnSql = ImmutableList.builder();
    int allProcessedClusteringColumns = 0;
    for (CassandraColumnHandle columnHandle : clusteringColumns) {
        Domain domain = predicates.getDomains().get().get(columnHandle);
        if (domain == null) {
            break;
        }
        if (domain.isNullAllowed()) {
            break;
        }
        int currentlyProcessedClusteringColumn = allProcessedClusteringColumns;
        String predicateString = domain.getValues().getValuesProcessor().transform(ranges -> {
            if (ranges.getRangeCount() == 1) {
                fullyPushedColumnPredicates.add(columnHandle);
                return translateRangeIntoCql(columnHandle, getOnlyElement(ranges.getOrderedRanges()));
            }
            if (ranges.getOrderedRanges().stream().allMatch(Range::isSingleValue)) {
                if (isInExpressionNotAllowed(clusteringColumns, cassandraVersion, currentlyProcessedClusteringColumn)) {
                    return translateRangeIntoCql(columnHandle, ranges.getSpan());
                }
                String inValues = ranges.getOrderedRanges().stream().map(range -> toCqlLiteral(columnHandle, range.getSingleValue())).collect(joining(","));
                fullyPushedColumnPredicates.add(columnHandle);
                return CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + inValues + ")";
            }
            return translateRangeIntoCql(columnHandle, ranges.getSpan());
        }, discreteValues -> {
            if (discreteValues.isInclusive()) {
                if (discreteValues.getValuesCount() == 0) {
                    return null;
                }
                if (discreteValues.getValuesCount() == 1) {
                    fullyPushedColumnPredicates.add(columnHandle);
                    return format("%s = %s", CassandraCqlUtils.validColumnName(columnHandle.getName()), toCqlLiteral(columnHandle, getOnlyElement(discreteValues.getValues())));
                }
                if (isInExpressionNotAllowed(clusteringColumns, cassandraVersion, currentlyProcessedClusteringColumn)) {
                    return null;
                }
                String inValues = discreteValues.getValues().stream().map(columnHandle.getCassandraType()::toCqlLiteral).collect(joining(","));
                fullyPushedColumnPredicates.add(columnHandle);
                return CassandraCqlUtils.validColumnName(columnHandle.getName()) + " IN (" + inValues + " )";
            }
            return null;
        }, allOrNone -> null);
        if (predicateString == null) {
            break;
        }
        clusteringColumnSql.add(predicateString);
        // Check for last clustering column should only be restricted by range condition
        if (predicateString.contains(">") || predicateString.contains("<")) {
            break;
        }
        allProcessedClusteringColumns++;
    }
    List<String> clusteringColumnPredicates = clusteringColumnSql.build();
    return new ClusteringPushDownResult(fullyPushedColumnPredicates.build(), Joiner.on(" AND ").join(clusteringColumnPredicates));
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) Set(java.util.Set) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) TupleDomain(io.trino.spi.predicate.TupleDomain) String.format(java.lang.String.format) Collectors.joining(java.util.stream.Collectors.joining) CassandraCqlUtils(io.trino.plugin.cassandra.util.CassandraCqlUtils) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) VersionNumber(com.datastax.driver.core.VersionNumber) Joiner(com.google.common.base.Joiner) ColumnHandle(io.trino.spi.connector.ColumnHandle) ImmutableList(com.google.common.collect.ImmutableList) Range(io.trino.spi.predicate.Range) ImmutableSet(com.google.common.collect.ImmutableSet) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain)

Example 22 with Domain

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

the class CassandraPartitionManager method getPartitions.

public CassandraPartitionResult getPartitions(CassandraTableHandle cassandraTableHandle, TupleDomain<ColumnHandle> tupleDomain) {
    // TODO support repeated applyFilter
    checkArgument(cassandraTableHandle.getPartitions().isEmpty(), "getPartitions() currently does not take into account table handle's partitions");
    CassandraTable table = cassandraSession.getTable(cassandraTableHandle.getSchemaTableName());
    // fetch the partitions
    List<CassandraPartition> allPartitions = getCassandraPartitions(table, tupleDomain);
    log.debug("%s.%s #partitions: %d", cassandraTableHandle.getSchemaName(), cassandraTableHandle.getTableName(), allPartitions.size());
    // do a final pass to filter based on fields that could not be used to build the prefix
    List<CassandraPartition> partitions = allPartitions.stream().filter(partition -> tupleDomain.overlaps(partition.getTupleDomain())).collect(toList());
    // All partition key domains will be fully evaluated, so we don't need to include those
    TupleDomain<ColumnHandle> remainingTupleDomain = TupleDomain.none();
    if (!tupleDomain.isNone()) {
        if (partitions.size() == 1 && partitions.get(0).isUnpartitioned()) {
            remainingTupleDomain = tupleDomain;
        } else {
            Set<ColumnHandle> usedPartitionColumns = partitions.stream().flatMap(partition -> Optional.ofNullable(partition.getTupleDomain()).flatMap(partitionTupleDomain -> partitionTupleDomain.getDomains().map(Map::keySet).map(Set::stream)).orElse(Stream.empty())).collect(toImmutableSet());
            remainingTupleDomain = tupleDomain.filter((column, domain) -> !usedPartitionColumns.contains(column));
        }
    }
    // push down indexed column fixed value predicates only for unpartitioned partition which uses token range query
    if ((partitions.size() == 1) && partitions.get(0).isUnpartitioned()) {
        Map<ColumnHandle, Domain> domains = tupleDomain.getDomains().get();
        List<ColumnHandle> indexedColumns = new ArrayList<>();
        // compose partitionId by using indexed column
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<ColumnHandle, Domain> entry : domains.entrySet()) {
            CassandraColumnHandle column = (CassandraColumnHandle) entry.getKey();
            Domain domain = entry.getValue();
            if (column.isIndexed() && domain.isSingleValue()) {
                sb.append(CassandraCqlUtils.validColumnName(column.getName())).append(" = ").append(column.getCassandraType().toCqlLiteral(entry.getValue().getSingleValue()));
                indexedColumns.add(column);
                // Only one indexed column predicate can be pushed down.
                break;
            }
        }
        if (sb.length() > 0) {
            CassandraPartition partition = partitions.get(0);
            TupleDomain<ColumnHandle> filterIndexedColumn = TupleDomain.withColumnDomains(Maps.filterKeys(remainingTupleDomain.getDomains().get(), not(in(indexedColumns))));
            partitions = new ArrayList<>();
            partitions.add(new CassandraPartition(partition.getKey(), sb.toString(), filterIndexedColumn, true));
            return new CassandraPartitionResult(partitions, filterIndexedColumn);
        }
    }
    return new CassandraPartitionResult(partitions, remainingTupleDomain);
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) Logger(io.airlift.log.Logger) Range(io.trino.spi.predicate.Range) Domain(io.trino.spi.predicate.Domain) Set(java.util.Set) TupleDomain(io.trino.spi.predicate.TupleDomain) Maps(com.google.common.collect.Maps) Sets(com.google.common.collect.Sets) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) CassandraCqlUtils(io.trino.plugin.cassandra.util.CassandraCqlUtils) List(java.util.List) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Predicates.in(com.google.common.base.Predicates.in) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) ImmutableList(com.google.common.collect.ImmutableList) Predicates.not(com.google.common.base.Predicates.not) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) Optional(java.util.Optional) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ColumnHandle(io.trino.spi.connector.ColumnHandle) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ArrayList(java.util.ArrayList) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Map(java.util.Map)

Example 23 with Domain

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

the class LocalDynamicFiltersCollector method createDynamicFilter.

// Called during TableScan planning (no need to be synchronized as local planning is single threaded)
public DynamicFilter createDynamicFilter(List<Descriptor> descriptors, Map<Symbol, ColumnHandle> columnsMap, TypeProvider typeProvider, PlannerContext plannerContext) {
    Multimap<DynamicFilterId, Descriptor> descriptorMap = extractSourceSymbols(descriptors);
    // Iterate over dynamic filters that are collected (correspond to one of the futures), and required for filtering (correspond to one of the descriptors).
    // It is possible that some dynamic filters are collected in a different stage - and will not available here.
    // It is also possible that not all local dynamic filters are needed for this specific table scan.
    List<ListenableFuture<TupleDomain<ColumnHandle>>> predicateFutures = descriptorMap.keySet().stream().filter(futures.keySet()::contains).map(filterId -> {
        // Probe-side columns that can be filtered with this dynamic filter resulting domain.
        return Futures.transform(requireNonNull(futures.get(filterId), () -> format("Missing dynamic filter %s", filterId)), // Construct a probe-side predicate by duplicating the resulting domain over the corresponding columns.
        domain -> TupleDomain.withColumnDomains(descriptorMap.get(filterId).stream().collect(toImmutableMap(descriptor -> {
            Symbol probeSymbol = Symbol.from(descriptor.getInput());
            return requireNonNull(columnsMap.get(probeSymbol), () -> format("Missing probe column for %s", probeSymbol));
        }, descriptor -> {
            Type targetType = typeProvider.get(Symbol.from(descriptor.getInput()));
            Domain updatedDomain = descriptor.applyComparison(domain);
            if (!updatedDomain.getType().equals(targetType)) {
                return applySaturatedCasts(plannerContext.getMetadata(), plannerContext.getFunctionManager(), plannerContext.getTypeOperators(), session, updatedDomain, targetType);
            }
            return updatedDomain;
        }))), directExecutor());
    }).collect(toImmutableList());
    Set<ColumnHandle> columnsCovered = descriptorMap.values().stream().map(Descriptor::getInput).map(Symbol::from).map(probeSymbol -> requireNonNull(columnsMap.get(probeSymbol), () -> "Missing probe column for " + probeSymbol)).collect(toImmutableSet());
    return new TableSpecificDynamicFilter(columnsCovered, predicateFutures);
}
Also used : ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Type(io.trino.spi.type.Type) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Multimap(com.google.common.collect.Multimap) SettableFuture(com.google.common.util.concurrent.SettableFuture) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) DynamicFilters.extractSourceSymbols(io.trino.sql.DynamicFilters.extractSourceSymbols) Verify.verify(com.google.common.base.Verify.verify) Descriptor(io.trino.sql.DynamicFilters.Descriptor) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) ColumnHandle(io.trino.spi.connector.ColumnHandle) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) ImmutableSet(com.google.common.collect.ImmutableSet) Domain(io.trino.spi.predicate.Domain) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Set(java.util.Set) ThreadSafe(javax.annotation.concurrent.ThreadSafe) TupleDomain(io.trino.spi.predicate.TupleDomain) GuardedBy(javax.annotation.concurrent.GuardedBy) String.format(java.lang.String.format) MoreExecutors.directExecutor(com.google.common.util.concurrent.MoreExecutors.directExecutor) Futures(com.google.common.util.concurrent.Futures) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) DynamicFilter(io.trino.spi.connector.DynamicFilter) DomainCoercer.applySaturatedCasts(io.trino.sql.planner.DomainCoercer.applySaturatedCasts) MoreFutures.addSuccessCallback(io.airlift.concurrent.MoreFutures.addSuccessCallback) MoreFutures.unmodifiableFuture(io.airlift.concurrent.MoreFutures.unmodifiableFuture) Session(io.trino.Session) PlannerContext(io.trino.sql.PlannerContext) ColumnHandle(io.trino.spi.connector.ColumnHandle) Type(io.trino.spi.type.Type) Descriptor(io.trino.sql.DynamicFilters.Descriptor) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId)

Example 24 with Domain

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

the class TestInformationSchemaMetadata method testInformationSchemaPredicatePushdown.

/**
 * Tests information schema predicate pushdown when both schema and table name are specified.
 */
@Test
public void testInformationSchemaPredicatePushdown() {
    TransactionId transactionId = transactionManager.beginTransaction(false);
    ImmutableMap.Builder<ColumnHandle, Domain> domains = ImmutableMap.builder();
    domains.put(new InformationSchemaColumnHandle("table_schema"), Domain.singleValue(VARCHAR, Slices.utf8Slice("test_schema")));
    domains.put(new InformationSchemaColumnHandle("table_name"), Domain.singleValue(VARCHAR, Slices.utf8Slice("test_view")));
    Constraint constraint = new Constraint(TupleDomain.withColumnDomains(domains.buildOrThrow()));
    ConnectorSession session = createNewSession(transactionId);
    ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata);
    InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle) metadata.getTableHandle(session, new SchemaTableName("information_schema", "views"));
    tableHandle = metadata.applyFilter(session, tableHandle, constraint).map(ConstraintApplicationResult::getHandle).map(InformationSchemaTableHandle.class::cast).orElseThrow(AssertionError::new);
    assertEquals(tableHandle.getPrefixes(), ImmutableSet.of(new QualifiedTablePrefix("test_catalog", "test_schema", "test_view")));
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) InformationSchemaColumnHandle(io.trino.connector.informationschema.InformationSchemaColumnHandle) Constraint(io.trino.spi.connector.Constraint) SchemaTableName(io.trino.spi.connector.SchemaTableName) ImmutableMap(com.google.common.collect.ImmutableMap) TransactionId(io.trino.transaction.TransactionId) InformationSchemaTableHandle(io.trino.connector.informationschema.InformationSchemaTableHandle) InformationSchemaColumnHandle(io.trino.connector.informationschema.InformationSchemaColumnHandle) ConnectorSession(io.trino.spi.connector.ConnectorSession) ConnectorMetadata(io.trino.spi.connector.ConnectorMetadata) InformationSchemaMetadata(io.trino.connector.informationschema.InformationSchemaMetadata) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Test(org.testng.annotations.Test)

Example 25 with Domain

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

the class TestInformationSchemaMetadata method testInformationSchemaPredicatePushdownWithoutTablePredicate.

@Test
public void testInformationSchemaPredicatePushdownWithoutTablePredicate() {
    TransactionId transactionId = transactionManager.beginTransaction(false);
    // predicate without table name predicates should not cause table level prefixes to be evaluated
    ImmutableMap.Builder<ColumnHandle, Domain> domains = ImmutableMap.builder();
    domains.put(new InformationSchemaColumnHandle("table_schema"), Domain.singleValue(VARCHAR, Slices.utf8Slice("test_schema")));
    Constraint constraint = new Constraint(TupleDomain.withColumnDomains(domains.buildOrThrow()));
    ConnectorSession session = createNewSession(transactionId);
    ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata);
    InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle) metadata.getTableHandle(session, new SchemaTableName("information_schema", "views"));
    tableHandle = metadata.applyFilter(session, tableHandle, constraint).map(ConstraintApplicationResult::getHandle).map(InformationSchemaTableHandle.class::cast).orElseThrow(AssertionError::new);
    assertEquals(tableHandle.getPrefixes(), ImmutableSet.of(new QualifiedTablePrefix("test_catalog", "test_schema")));
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) InformationSchemaColumnHandle(io.trino.connector.informationschema.InformationSchemaColumnHandle) Constraint(io.trino.spi.connector.Constraint) SchemaTableName(io.trino.spi.connector.SchemaTableName) ImmutableMap(com.google.common.collect.ImmutableMap) TransactionId(io.trino.transaction.TransactionId) InformationSchemaTableHandle(io.trino.connector.informationschema.InformationSchemaTableHandle) InformationSchemaColumnHandle(io.trino.connector.informationschema.InformationSchemaColumnHandle) ConnectorSession(io.trino.spi.connector.ConnectorSession) ConnectorMetadata(io.trino.spi.connector.ConnectorMetadata) InformationSchemaMetadata(io.trino.connector.informationschema.InformationSchemaMetadata) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) Test(org.testng.annotations.Test)

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