Search in sources :

Example 1 with DynamicFilter

use of io.trino.spi.connector.DynamicFilter in project trino by trinodb.

the class TestBackgroundHiveSplitLoader method testIncompleteDynamicFilterTimeout.

@Test(timeOut = 30_000)
public void testIncompleteDynamicFilterTimeout() throws Exception {
    BackgroundHiveSplitLoader backgroundHiveSplitLoader = backgroundHiveSplitLoader(new DynamicFilter() {

        @Override
        public Set<ColumnHandle> getColumnsCovered() {
            return ImmutableSet.of();
        }

        @Override
        public CompletableFuture<?> isBlocked() {
            return unmodifiableFuture(CompletableFuture.runAsync(() -> {
                try {
                    TimeUnit.HOURS.sleep(1);
                } catch (InterruptedException e) {
                    throw new IllegalStateException(e);
                }
            }));
        }

        @Override
        public boolean isComplete() {
            return false;
        }

        @Override
        public boolean isAwaitable() {
            return true;
        }

        @Override
        public TupleDomain<ColumnHandle> getCurrentPredicate() {
            return TupleDomain.all();
        }
    }, new Duration(1, SECONDS));
    HiveSplitSource hiveSplitSource = hiveSplitSource(backgroundHiveSplitLoader);
    backgroundHiveSplitLoader.start(hiveSplitSource);
    assertEquals(drain(hiveSplitSource).size(), 2);
    assertTrue(hiveSplitSource.isFinished());
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Set(java.util.Set) ImmutableSet(com.google.common.collect.ImmutableSet) TupleDomain(io.trino.spi.predicate.TupleDomain) DynamicFilter(io.trino.spi.connector.DynamicFilter) Duration(io.airlift.units.Duration) Test(org.testng.annotations.Test)

Example 2 with DynamicFilter

use of io.trino.spi.connector.DynamicFilter in project trino by trinodb.

the class TestLocalDynamicFiltersCollector method testDynamicFilterCoercion.

@Test
public void testDynamicFilterCoercion() {
    LocalDynamicFiltersCollector collector = new LocalDynamicFiltersCollector(TEST_SESSION);
    DynamicFilterId filterId = new DynamicFilterId("filter");
    collector.register(ImmutableSet.of(filterId));
    SymbolAllocator symbolAllocator = new SymbolAllocator();
    Symbol symbol = symbolAllocator.newSymbol("symbol", INTEGER);
    ColumnHandle column = new TestingColumnHandle("column");
    DynamicFilter filter = createDynamicFilter(collector, ImmutableList.of(new DynamicFilters.Descriptor(filterId, new Cast(symbol.toSymbolReference(), toSqlType(BIGINT)))), ImmutableMap.of(symbol, column), symbolAllocator.getTypes());
    assertEquals(filter.getColumnsCovered(), Set.of(column), "columns covered");
    // Filter is blocked and not completed.
    CompletableFuture<?> isBlocked = filter.isBlocked();
    assertFalse(filter.isComplete());
    assertTrue(filter.isAwaitable());
    assertFalse(isBlocked.isDone());
    assertEquals(filter.getCurrentPredicate(), TupleDomain.all());
    Domain domain = Domain.singleValue(BIGINT, 7L);
    collector.collectDynamicFilterDomains(ImmutableMap.of(filterId, domain));
    // Unblocked and completed.
    assertTrue(filter.isComplete());
    assertFalse(filter.isAwaitable());
    assertTrue(isBlocked.isDone());
    assertEquals(filter.getCurrentPredicate(), TupleDomain.withColumnDomains(ImmutableMap.of(column, Domain.singleValue(INTEGER, 7L))));
}
Also used : Cast(io.trino.sql.tree.Cast) TestingColumnHandle(io.trino.spi.connector.TestingColumnHandle) ColumnHandle(io.trino.spi.connector.ColumnHandle) TestingColumnHandle(io.trino.spi.connector.TestingColumnHandle) DynamicFilter(io.trino.spi.connector.DynamicFilter) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) Test(org.testng.annotations.Test)

Example 3 with DynamicFilter

use of io.trino.spi.connector.DynamicFilter in project trino by trinodb.

the class TestLocalDynamicFiltersCollector method testMultipleBuildColumnsSingleProbeColumn.

@Test
public void testMultipleBuildColumnsSingleProbeColumn() {
    LocalDynamicFiltersCollector collector = new LocalDynamicFiltersCollector(TEST_SESSION);
    DynamicFilterId filter1 = new DynamicFilterId("filter1");
    DynamicFilterId filter2 = new DynamicFilterId("filter2");
    collector.register(ImmutableSet.of(filter1));
    collector.register(ImmutableSet.of(filter2));
    // Multiple build-side columns matching the same probe-side column.
    SymbolAllocator symbolAllocator = new SymbolAllocator();
    Symbol symbol = symbolAllocator.newSymbol("symbol", BIGINT);
    ColumnHandle column = new TestingColumnHandle("column");
    DynamicFilter filter = createDynamicFilter(collector, ImmutableList.of(new DynamicFilters.Descriptor(filter1, symbol.toSymbolReference()), new DynamicFilters.Descriptor(filter2, symbol.toSymbolReference())), ImmutableMap.of(symbol, column), symbolAllocator.getTypes());
    assertEquals(filter.getColumnsCovered(), Set.of(column), "columns covered");
    // Filter is blocking and not completed.
    CompletableFuture<?> isBlocked = filter.isBlocked();
    assertFalse(filter.isComplete());
    assertTrue(filter.isAwaitable());
    assertFalse(isBlocked.isDone());
    assertEquals(filter.getCurrentPredicate(), TupleDomain.all());
    collector.collectDynamicFilterDomains(ImmutableMap.of(filter1, Domain.multipleValues(BIGINT, ImmutableList.of(1L, 2L, 3L))));
    // Unblocked, but not completed.
    assertFalse(filter.isComplete());
    assertTrue(filter.isAwaitable());
    assertTrue(isBlocked.isDone());
    assertEquals(filter.getCurrentPredicate(), TupleDomain.withColumnDomains(ImmutableMap.of(column, Domain.multipleValues(BIGINT, ImmutableList.of(1L, 2L, 3L)))));
    // Create a new blocking future, waiting for next completion.
    isBlocked = filter.isBlocked();
    assertFalse(isBlocked.isDone());
    assertFalse(filter.isComplete());
    assertTrue(filter.isAwaitable());
    collector.collectDynamicFilterDomains(ImmutableMap.of(filter2, Domain.multipleValues(BIGINT, ImmutableList.of(2L, 3L, 4L))));
    // Unblocked and completed.
    assertTrue(filter.isComplete());
    assertFalse(filter.isAwaitable());
    assertTrue(isBlocked.isDone());
    assertEquals(filter.getCurrentPredicate(), TupleDomain.withColumnDomains(ImmutableMap.of(column, Domain.multipleValues(BIGINT, ImmutableList.of(2L, 3L)))));
}
Also used : TestingColumnHandle(io.trino.spi.connector.TestingColumnHandle) ColumnHandle(io.trino.spi.connector.ColumnHandle) TestingColumnHandle(io.trino.spi.connector.TestingColumnHandle) DynamicFilter(io.trino.spi.connector.DynamicFilter) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) Test(org.testng.annotations.Test)

Example 4 with DynamicFilter

use of io.trino.spi.connector.DynamicFilter 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 5 with DynamicFilter

use of io.trino.spi.connector.DynamicFilter in project trino by trinodb.

the class TestDynamicFilterService method testMultipleColumnMapping.

@Test
public void testMultipleColumnMapping() {
    DynamicFilterService dynamicFilterService = createDynamicFilterService();
    DynamicFilterId filterId1 = new DynamicFilterId("df1");
    SymbolAllocator symbolAllocator = new SymbolAllocator();
    Symbol symbol1 = symbolAllocator.newSymbol("DF_SYMBOL1", INTEGER);
    Symbol symbol2 = symbolAllocator.newSymbol("DF_SYMBOL2", INTEGER);
    Expression df1 = symbol1.toSymbolReference();
    Expression df2 = symbol2.toSymbolReference();
    QueryId queryId = new QueryId("query");
    StageId stageId1 = new StageId(queryId, 1);
    dynamicFilterService.registerQuery(queryId, session, ImmutableSet.of(filterId1), ImmutableSet.of(filterId1), ImmutableSet.of());
    dynamicFilterService.stageCannotScheduleMoreTasks(stageId1, 0, 1);
    TestingColumnHandle column1 = new TestingColumnHandle("probeColumnA");
    TestingColumnHandle column2 = new TestingColumnHandle("probeColumnB");
    DynamicFilter dynamicFilter = dynamicFilterService.createDynamicFilter(queryId, ImmutableList.of(new DynamicFilters.Descriptor(filterId1, df1), new DynamicFilters.Descriptor(filterId1, df2)), ImmutableMap.of(symbol1, column1, symbol2, column2), symbolAllocator.getTypes());
    assertEquals(dynamicFilter.getColumnsCovered(), Set.of(column1, column2), "columns covered");
    Domain domain = singleValue(INTEGER, 1L);
    dynamicFilterService.addTaskDynamicFilters(new TaskId(stageId1, 0, 0), ImmutableMap.of(filterId1, domain));
    assertEquals(dynamicFilter.getCurrentPredicate(), TupleDomain.withColumnDomains(ImmutableMap.of(column1, domain, column2, domain)));
}
Also used : SymbolAllocator(io.trino.sql.planner.SymbolAllocator) TestingColumnHandle(io.trino.spi.connector.TestingColumnHandle) TaskId(io.trino.execution.TaskId) DynamicFilters.createDynamicFilterExpression(io.trino.sql.DynamicFilters.createDynamicFilterExpression) Expression(io.trino.sql.tree.Expression) DynamicFilter(io.trino.spi.connector.DynamicFilter) Symbol(io.trino.sql.planner.Symbol) QueryId(io.trino.spi.QueryId) StageId(io.trino.execution.StageId) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) Test(org.testng.annotations.Test)

Aggregations

DynamicFilter (io.trino.spi.connector.DynamicFilter)32 Test (org.testng.annotations.Test)23 DynamicFilterId (io.trino.sql.planner.plan.DynamicFilterId)20 TestingColumnHandle (io.trino.spi.connector.TestingColumnHandle)19 ColumnHandle (io.trino.spi.connector.ColumnHandle)18 TupleDomain (io.trino.spi.predicate.TupleDomain)13 Symbol (io.trino.sql.planner.Symbol)11 SymbolAllocator (io.trino.sql.planner.SymbolAllocator)11 QueryId (io.trino.spi.QueryId)10 List (java.util.List)10 ImmutableList (com.google.common.collect.ImmutableList)9 StageId (io.trino.execution.StageId)9 Domain (io.trino.spi.predicate.Domain)9 Objects.requireNonNull (java.util.Objects.requireNonNull)9 TaskId (io.trino.execution.TaskId)8 ConnectorSession (io.trino.spi.connector.ConnectorSession)8 ConnectorTableHandle (io.trino.spi.connector.ConnectorTableHandle)8 ConnectorTransactionHandle (io.trino.spi.connector.ConnectorTransactionHandle)8 Optional (java.util.Optional)8 Inject (javax.inject.Inject)8