diff --git a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaMetadata.java b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaMetadata.java index 61d50f444f4a..399433835d2e 100644 --- a/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaMetadata.java +++ b/core/trino-main/src/main/java/io/trino/connector/informationschema/InformationSchemaMetadata.java @@ -184,7 +184,7 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { InformationSchemaTableHandle table = (InformationSchemaTableHandle) handle; diff --git a/core/trino-main/src/main/java/io/trino/connector/system/SystemTablesMetadata.java b/core/trino-main/src/main/java/io/trino/connector/system/SystemTablesMetadata.java index 98228ac46f32..27be854e1f98 100644 --- a/core/trino-main/src/main/java/io/trino/connector/system/SystemTablesMetadata.java +++ b/core/trino-main/src/main/java/io/trino/connector/system/SystemTablesMetadata.java @@ -139,7 +139,7 @@ public Map> listTableColumns(ConnectorSess } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { SystemTableHandle table = (SystemTableHandle) handle; @@ -166,7 +166,7 @@ public Optional> applyFilter(C return Optional.of(new ConstraintApplicationResult<>(table, constraint.getSummary(), false)); } - private Constraint effectiveConstraint(TupleDomain oldDomain, Constraint newConstraint, TupleDomain effectiveDomain) + private Constraint effectiveConstraint(TupleDomain oldDomain, Constraint newConstraint, TupleDomain effectiveDomain) { if (effectiveDomain.isNone() || newConstraint.predicate().isEmpty()) { return new Constraint(effectiveDomain); diff --git a/core/trino-main/src/main/java/io/trino/connector/system/jdbc/ColumnJdbcTable.java b/core/trino-main/src/main/java/io/trino/connector/system/jdbc/ColumnJdbcTable.java index d4bc2c8e77be..780442a24e95 100644 --- a/core/trino-main/src/main/java/io/trino/connector/system/jdbc/ColumnJdbcTable.java +++ b/core/trino-main/src/main/java/io/trino/connector/system/jdbc/ColumnJdbcTable.java @@ -146,7 +146,7 @@ public ConnectorTableMetadata getTableMetadata() } @Override - public TupleDomain applyFilter(ConnectorSession connectorSession, Constraint constraint) + public TupleDomain applyFilter(ConnectorSession connectorSession, Constraint constraint) { TupleDomain tupleDomain = constraint.getSummary(); if (tupleDomain.isNone() || constraint.predicate().isEmpty()) { diff --git a/core/trino-main/src/main/java/io/trino/connector/system/jdbc/JdbcTable.java b/core/trino-main/src/main/java/io/trino/connector/system/jdbc/JdbcTable.java index 6e414e79e640..56ae0bc54d50 100644 --- a/core/trino-main/src/main/java/io/trino/connector/system/jdbc/JdbcTable.java +++ b/core/trino-main/src/main/java/io/trino/connector/system/jdbc/JdbcTable.java @@ -38,7 +38,7 @@ public final Distribution getDistribution() * and without column handles it's currently not possible to express Constraint or ConstraintApplicationResult. * TODO provide equivalent API in the SystemTable interface */ - public TupleDomain applyFilter(ConnectorSession session, Constraint constraint) + public TupleDomain applyFilter(ConnectorSession session, Constraint constraint) { return constraint.getSummary(); } diff --git a/core/trino-main/src/main/java/io/trino/metadata/Metadata.java b/core/trino-main/src/main/java/io/trino/metadata/Metadata.java index cd6d0ba80d41..1cf35a16e355 100644 --- a/core/trino-main/src/main/java/io/trino/metadata/Metadata.java +++ b/core/trino-main/src/main/java/io/trino/metadata/Metadata.java @@ -49,6 +49,7 @@ import io.trino.spi.function.AggregationFunctionMetadata; import io.trino.spi.function.FunctionMetadata; import io.trino.spi.function.OperatorType; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; import io.trino.spi.predicate.TupleDomain; import io.trino.spi.security.GrantInfo; import io.trino.spi.security.Identity; @@ -483,7 +484,9 @@ default boolean isView(Session session, QualifiedObjectName viewName) Optional> applyLimit(Session session, TableHandle table, long limit); - Optional> applyFilter(Session session, TableHandle table, Constraint constraint); + Optional> applyFilter(Session session, TableHandle table, Constraint constraint); + + Optional> applyFilter(Session session, TableFunctionHandle handle, Constraint constraint); Optional> applyProjection(Session session, TableHandle table, List projections, Map assignments); diff --git a/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java b/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java index 08cac3b0e583..66cf7ded2127 100644 --- a/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java +++ b/core/trino-main/src/main/java/io/trino/metadata/MetadataManager.java @@ -91,6 +91,7 @@ import io.trino.spi.function.OperatorType; import io.trino.spi.function.QualifiedFunctionName; import io.trino.spi.function.Signature; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; import io.trino.spi.predicate.TupleDomain; import io.trino.spi.security.GrantInfo; import io.trino.spi.security.Identity; @@ -1816,16 +1817,28 @@ public void validateScan(Session session, TableHandle table) } @Override - public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) + public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) { CatalogHandle catalogHandle = table.getCatalogHandle(); ConnectorMetadata metadata = getMetadata(session, catalogHandle); ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); - return metadata.applyFilter(connectorSession, table.getConnectorHandle(), constraint) + Optional> connectorTableHandleObjectConstraintApplicationResult = + metadata.applyFilter(connectorSession, table.getConnectorHandle(), constraint); + return connectorTableHandleObjectConstraintApplicationResult .map(result -> result.transform(handle -> new TableHandle(catalogHandle, handle, table.getTransaction()))); } + @Override + public Optional> applyFilter(Session session, TableFunctionHandle handle, Constraint constraint) + { + CatalogHandle catalogHandle = handle.getCatalogHandle(); + ConnectorMetadata metadata = getMetadata(session, catalogHandle); + + ConnectorSession connectorSession = session.toConnectorSession(catalogHandle); + return metadata.applyFilter(connectorSession, handle.getFunctionHandle(), constraint); + } + @Override public Optional> applyProjection(Session session, TableHandle table, List projections, Map assignments) { diff --git a/core/trino-main/src/main/java/io/trino/split/SplitManager.java b/core/trino-main/src/main/java/io/trino/split/SplitManager.java index b6bc7a9c1544..227e130b84fc 100644 --- a/core/trino-main/src/main/java/io/trino/split/SplitManager.java +++ b/core/trino-main/src/main/java/io/trino/split/SplitManager.java @@ -23,6 +23,7 @@ import io.trino.metadata.TableFunctionHandle; import io.trino.metadata.TableHandle; import io.trino.spi.connector.CatalogHandle; +import io.trino.spi.connector.ColumnHandle; import io.trino.spi.connector.ConnectorSession; import io.trino.spi.connector.ConnectorSplitManager; import io.trino.spi.connector.ConnectorSplitSource; @@ -54,7 +55,7 @@ public SplitSource getSplits( Span parentSpan, TableHandle table, DynamicFilter dynamicFilter, - Constraint constraint) + Constraint constraint) { CatalogHandle catalogHandle = table.getCatalogHandle(); ConnectorSplitManager splitManager = splitManagerProvider.getService(catalogHandle); diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizers.java b/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizers.java index 7b029fde0848..cf73191a37bc 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizers.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizers.java @@ -149,6 +149,7 @@ import io.trino.sql.planner.iterative.rule.PushDownDereferencesThroughTopNRanking; import io.trino.sql.planner.iterative.rule.PushDownDereferencesThroughWindow; import io.trino.sql.planner.iterative.rule.PushDownProjectionsFromPatternRecognition; +import io.trino.sql.planner.iterative.rule.PushFilterIntoTableFunction; import io.trino.sql.planner.iterative.rule.PushFilterThroughCountAggregation; import io.trino.sql.planner.iterative.rule.PushInequalityFilterExpressionBelowJoinRuleSet; import io.trino.sql.planner.iterative.rule.PushJoinIntoTableScan; @@ -454,6 +455,7 @@ public PlanOptimizers( new PruneOrderByInAggregation(metadata), new RewriteSpatialPartitioningAggregation(plannerContext), new SimplifyCountOverConstant(plannerContext), + new PushFilterIntoTableFunction(plannerContext, typeAnalyzer), new PreAggregateCaseAggregations(plannerContext, typeAnalyzer))) .build()), new IterativeOptimizer( @@ -594,7 +596,8 @@ public PlanOptimizers( ImmutableSet.of( new ApplyTableScanRedirection(plannerContext), new PruneTableScanColumns(metadata), - new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)))); + new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false), + new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)))); Set> pushIntoTableScanRulesExceptJoins = ImmutableSet.>builder() .addAll(columnPruningRules) @@ -603,6 +606,7 @@ public PlanOptimizers( .add(new RemoveRedundantIdentityProjections()) .add(new PushLimitIntoTableScan(metadata)) .add(new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)) + .add(new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)) .add(new PushSampleIntoTableScan(metadata)) .add(new PushAggregationIntoTableScan(plannerContext, typeAnalyzer)) .add(new PushDistinctLimitIntoTableScan(plannerContext, typeAnalyzer)) @@ -667,6 +671,7 @@ public PlanOptimizers( ImmutableSet.>builder() .addAll(simplifyOptimizerRules) // Should be always run after PredicatePushDown .add(new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)) + .add(new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)) .build()), new UnaliasSymbolReferences(metadata), // Run again because predicate pushdown and projection pushdown might add more projections columnPruningOptimizer, // Make sure to run this before index join. Filtered projections may not have all the columns. @@ -732,6 +737,7 @@ public PlanOptimizers( ImmutableSet.>builder() .addAll(simplifyOptimizerRules) // Should be always run after PredicatePushDown .add(new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)) + .add(new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)) .build()), pushProjectionIntoTableScanOptimizer, // Projection pushdown rules may push reducing projections (e.g. dereferences) below filters for potential @@ -746,6 +752,7 @@ public PlanOptimizers( ImmutableSet.>builder() .addAll(simplifyOptimizerRules) // Should be always run after PredicatePushDown .add(new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)) + .add(new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)) .build()), columnPruningOptimizer, new IterativeOptimizer( @@ -811,6 +818,7 @@ public PlanOptimizers( costCalculator, ImmutableSet.of( new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, true), + new PushFilterIntoTableFunction(plannerContext, typeAnalyzer), new RemoveEmptyUnionBranches(), new EvaluateEmptyIntersect(), new RemoveEmptyExceptBranches(), @@ -906,6 +914,7 @@ public PlanOptimizers( .addAll(simplifyOptimizerRules) // Should be always run after PredicatePushDown .add(new PushPredicateIntoTableScan(plannerContext, typeAnalyzer, false)) .add(new RemoveRedundantPredicateAboveTableScan(plannerContext, typeAnalyzer)) + .add(new PushFilterIntoTableFunction(plannerContext, typeAnalyzer)) .build())); // Remove unsupported dynamic filters introduced by PredicatePushdown. Also, cleanup dynamic filters removed by // PushPredicateIntoTableScan and RemoveRedundantPredicateAboveTableScan due to those rules replacing table scans with empty ValuesNode diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/SplitSourceFactory.java b/core/trino-main/src/main/java/io/trino/sql/planner/SplitSourceFactory.java index d4d7f1caa17f..74943903deec 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/SplitSourceFactory.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/SplitSourceFactory.java @@ -176,10 +176,10 @@ private SplitSource createSplitSource(TableHandle table, Map constraint = filterPredicate .map(predicate -> filterConjuncts(plannerContext.getMetadata(), predicate, expression -> !DynamicFilters.isDynamicFilter(expression))) .map(predicate -> new LayoutConstraintEvaluator(plannerContext, typeAnalyzer, session, typeProvider, assignments, predicate)) - .map(evaluator -> new Constraint(TupleDomain.all(), evaluator::isCandidate, evaluator.getArguments())) // we are interested only in functional predicate here, so we set the summary to ALL. + .map(evaluator -> new Constraint<>(TupleDomain.all(), evaluator::isCandidate, evaluator.getArguments())) // we are interested only in functional predicate here, so we set the summary to ALL. .orElse(alwaysTrue()); // get dataSource for table diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/ImplementTableFunctionSource.java b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/ImplementTableFunctionSource.java index 4d18d1f03dfd..c8504a9121f0 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/ImplementTableFunctionSource.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/ImplementTableFunctionSource.java @@ -21,6 +21,7 @@ import io.trino.matching.Pattern; import io.trino.metadata.Metadata; import io.trino.metadata.ResolvedFunction; +import io.trino.spi.predicate.TupleDomain; import io.trino.spi.type.Type; import io.trino.sql.planner.OrderingScheme; import io.trino.sql.planner.Symbol; @@ -171,7 +172,8 @@ public Result apply(TableFunctionNode node, Captures captures, Context context) ImmutableSet.of(), 0, Optional.empty(), - node.getHandle())); + node.getHandle(), + TupleDomain.all())); } if (node.getSources().size() == 1) { @@ -193,7 +195,8 @@ public Result apply(TableFunctionNode node, Captures captures, Context context) ImmutableSet.of(), 0, Optional.empty(), - node.getHandle())); + node.getHandle(), + TupleDomain.all())); } Map sources = mapSourcesByName(node.getSources(), node.getTableArgumentProperties()); ImmutableList.Builder intermediateResultsBuilder = ImmutableList.builder(); @@ -288,7 +291,8 @@ public Result apply(TableFunctionNode node, Captures captures, Context context) ImmutableSet.of(), 0, Optional.empty(), - node.getHandle())); + node.getHandle(), + TupleDomain.all())); } private static Map mapSourcesByName(List sources, List properties) diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorColumns.java b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorColumns.java index 84d9cdf8406e..639dae65d2bb 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorColumns.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorColumns.java @@ -82,6 +82,7 @@ protected Optional pushDownProjectOff(Context context, TableFunctionPr node.getPrePartitioned(), node.getPreSorted(), node.getHashSymbol(), - node.getHandle())); + node.getHandle(), + node.getEnforcedConstraint())); } } diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorSourceColumns.java b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorSourceColumns.java index 72f1a5ec03de..af932ce1c89c 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorSourceColumns.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PruneTableFunctionProcessorSourceColumns.java @@ -98,7 +98,8 @@ public Result apply(TableFunctionProcessorNode node, Captures captures, Context node.getPrePartitioned(), node.getPreSorted(), node.getHashSymbol(), - node.getHandle()))) + node.getHandle(), + node.getEnforcedConstraint()))) .orElse(Result.empty()); } } diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushFilterIntoTableFunction.java b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushFilterIntoTableFunction.java new file mode 100644 index 000000000000..f13d0f14af38 --- /dev/null +++ b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushFilterIntoTableFunction.java @@ -0,0 +1,221 @@ +/* + * 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 io.trino.sql.planner.iterative.rule; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableMap; +import io.trino.Session; +import io.trino.matching.Capture; +import io.trino.matching.Captures; +import io.trino.matching.Pattern; +import io.trino.metadata.TableFunctionHandle; +import io.trino.spi.connector.Constraint; +import io.trino.spi.connector.ConstraintApplicationResult; +import io.trino.spi.expression.ConnectorExpression; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; +import io.trino.spi.predicate.TupleDomain; +import io.trino.spi.type.Type; +import io.trino.sql.PlannerContext; +import io.trino.sql.planner.ConnectorExpressionTranslator; +import io.trino.sql.planner.DomainTranslator; +import io.trino.sql.planner.ExpressionInterpreter; +import io.trino.sql.planner.LiteralEncoder; +import io.trino.sql.planner.NoOpSymbolResolver; +import io.trino.sql.planner.Symbol; +import io.trino.sql.planner.SymbolAllocator; +import io.trino.sql.planner.TypeAnalyzer; +import io.trino.sql.planner.iterative.Rule; +import io.trino.sql.planner.plan.FilterNode; +import io.trino.sql.planner.plan.PlanNode; +import io.trino.sql.planner.plan.TableFunctionProcessorNode; +import io.trino.sql.tree.Expression; +import io.trino.sql.tree.NodeRef; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.IntStream; + +import static com.google.common.collect.ImmutableMap.toImmutableMap; +import static io.trino.SystemSessionProperties.isAllowPushdownIntoConnectors; +import static io.trino.matching.Capture.newCapture; +import static io.trino.sql.ExpressionUtils.combineConjuncts; +import static io.trino.sql.planner.iterative.rule.PushPredicateIntoTableScan.computeEnforced; +import static io.trino.sql.planner.iterative.rule.PushPredicateIntoTableScan.createResultingPredicate; +import static io.trino.sql.planner.iterative.rule.PushPredicateIntoTableScan.splitExpression; +import static io.trino.sql.planner.plan.Patterns.filter; +import static io.trino.sql.planner.plan.Patterns.source; +import static io.trino.sql.planner.plan.Patterns.tableFunctionProcessor; +import static io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; + +public class PushFilterIntoTableFunction + implements Rule +{ + private static final Capture TABLE_FUNCTION_PROCESSOR_NODE = newCapture(); + private static final Pattern PATTERN = filter().with(source().matching( + tableFunctionProcessor().capturedAs(TABLE_FUNCTION_PROCESSOR_NODE))); + + private final PlannerContext plannerContext; + private final TypeAnalyzer typeAnalyzer; + + public PushFilterIntoTableFunction(PlannerContext plannerContext, TypeAnalyzer typeAnalyzer) + { + this.plannerContext = plannerContext; + this.typeAnalyzer = typeAnalyzer; + } + + @Override + public Pattern getPattern() + { + return PATTERN; + } + + @Override + public Result apply(FilterNode filterNode, Captures captures, Context context) + { + TableFunctionProcessorNode tableFunctionProcessorNode = captures.get(TABLE_FUNCTION_PROCESSOR_NODE); + + Optional rewritten = pushFilterIntoTableFunctionProcessorNode( + filterNode, + tableFunctionProcessorNode, + context.getSession(), + context.getSymbolAllocator(), + plannerContext, + new DomainTranslator(plannerContext), + typeAnalyzer); + + if (rewritten.isEmpty() || arePlansSame(filterNode, tableFunctionProcessorNode, rewritten.get())) { + return Result.empty(); + } + + return Result.ofPlanNode(rewritten.get()); + } + + public static Optional pushFilterIntoTableFunctionProcessorNode( + FilterNode filterNode, + TableFunctionProcessorNode node, + Session session, + SymbolAllocator symbolAllocator, + PlannerContext plannerContext, + DomainTranslator domainTranslator, + TypeAnalyzer typeAnalyzer) + { + if (!isAllowPushdownIntoConnectors(session)) { + return Optional.empty(); + } + + PushPredicateIntoTableScan.SplitExpression splitExpression = splitExpression(plannerContext, filterNode.getPredicate()); + DomainTranslator.ExtractionResult decomposedPredicate = DomainTranslator.getExtractionResult( + plannerContext, + session, + splitExpression.getDeterministicPredicate(), + symbolAllocator.getTypes()); + + List outputSymbols = node.getOutputSymbols(); + + BiMap assignments = HashBiMap.create(IntStream.range(0, outputSymbols.size()).boxed() + .collect(toImmutableMap(identity(), outputSymbols::get))); + + TupleDomain newDomain = decomposedPredicate.getTupleDomain() + .transformKeys(assignments.inverse()::get) + .intersect(node.getEnforcedConstraint()); + + ConnectorExpressionTranslator.ConnectorExpressionTranslation expressionTranslation = ConnectorExpressionTranslator.translateConjuncts( + session, + decomposedPredicate.getRemainingExpression(), + symbolAllocator.getTypes(), + plannerContext, + typeAnalyzer); + ImmutableMap nameToPosition = assignments.inverse().entrySet().stream() + .collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue)); + Constraint constraint = new Constraint<>(newDomain, expressionTranslation.connectorExpression(), nameToPosition); + + Optional> result = plannerContext.getMetadata().applyFilter(session, node.getHandle(), constraint); + if (result.isEmpty()) { + return Optional.empty(); + } + + TupleDomain remainingFilter = result.get().getRemainingFilter(); + Optional remainingConnectorExpression = result.get().getRemainingExpression(); + + TableFunctionProcessorNode tableFunctionProcessorNode = new TableFunctionProcessorNode( + node.getId(), + node.getName(), + node.getProperOutputs(), + node.getSource(), + node.isPruneWhenEmpty(), + node.getPassThroughSpecifications(), + node.getRequiredSymbols(), + node.getMarkerSymbols(), + node.getSpecification(), + node.getPrePartitioned(), + node.getPreSorted(), + node.getHashSymbol(), + new TableFunctionHandle(node.getHandle().getCatalogHandle(), result.get().getHandle(), node.getHandle().getTransactionHandle()), + computeEnforced(newDomain, remainingFilter)); + + Expression remainingDecomposedPredicate; + if (remainingConnectorExpression.isEmpty() || remainingConnectorExpression.get().equals(expressionTranslation.connectorExpression())) { + remainingDecomposedPredicate = decomposedPredicate.getRemainingExpression(); + } + else { + Map variableMappings = node.getOutputSymbols().stream().collect(toMap(Symbol::getName, identity())); + LiteralEncoder literalEncoder = new LiteralEncoder(plannerContext); + Expression translatedExpression = ConnectorExpressionTranslator.translate(session, remainingConnectorExpression.get(), plannerContext, variableMappings, literalEncoder); + Map, Type> translatedExpressionTypes = typeAnalyzer.getTypes(session, symbolAllocator.getTypes(), translatedExpression); + translatedExpression = literalEncoder.toExpression( + session, + new ExpressionInterpreter(translatedExpression, plannerContext, session, translatedExpressionTypes) + .optimize(NoOpSymbolResolver.INSTANCE), + translatedExpressionTypes.get(NodeRef.of(translatedExpression))); + remainingDecomposedPredicate = combineConjuncts(plannerContext.getMetadata(), translatedExpression, expressionTranslation.remainingExpression()); + } + Expression resultingPredicate = createResultingPredicate( + plannerContext, + session, + symbolAllocator, + typeAnalyzer, + splitExpression.getDynamicFilter(), + domainTranslator.toPredicate(session, remainingFilter.transformKeys(assignments::get)), + splitExpression.getNonDeterministicPredicate(), + remainingDecomposedPredicate); + + if (!TRUE_LITERAL.equals(resultingPredicate)) { + return Optional.of(new FilterNode(filterNode.getId(), tableFunctionProcessorNode, resultingPredicate)); + } + return Optional.of(tableFunctionProcessorNode); + } + + private boolean arePlansSame(FilterNode filter, TableFunctionProcessorNode tableFunctionProcessorNode, PlanNode rewritten) + { + if (!(rewritten instanceof FilterNode rewrittenFilter)) { + return false; + } + + if (!Objects.equals(filter.getPredicate(), rewrittenFilter.getPredicate())) { + return false; + } + + if (!(rewrittenFilter.getSource() instanceof TableFunctionProcessorNode rewrittenTableFunctionProcessorNode)) { + return false; + } + + return Objects.equals(tableFunctionProcessorNode.getEnforcedConstraint(), rewrittenTableFunctionProcessorNode.getEnforcedConstraint()) && + Objects.equals(tableFunctionProcessorNode.getHandle(), rewrittenTableFunctionProcessorNode.getHandle()); + } +} diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushPredicateIntoTableScan.java b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushPredicateIntoTableScan.java index cb2cbe6c41dc..740c305ff97b 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushPredicateIntoTableScan.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/iterative/rule/PushPredicateIntoTableScan.java @@ -192,7 +192,7 @@ public static Optional pushFilterIntoTableScan( Map assignments = ImmutableBiMap.copyOf(node.getAssignments()).inverse(); - Constraint constraint; + Constraint constraint; // use evaluator only when there is some predicate which could not be translated into tuple domain if (pruneWithPredicateExpression && !TRUE_LITERAL.equals(decomposedPredicate.getRemainingExpression())) { LayoutConstraintEvaluator evaluator = new LayoutConstraintEvaluator( @@ -207,12 +207,12 @@ public static Optional pushFilterIntoTableScan( // Simplify the tuple domain to avoid creating an expression with too many nodes, // which would be expensive to evaluate in the call to isCandidate below. domainTranslator.toPredicate(session, newDomain.simplify().transformKeys(assignments::get)))); - constraint = new Constraint(newDomain, expressionTranslation.connectorExpression(), connectorExpressionAssignments, evaluator::isCandidate, evaluator.getArguments()); + constraint = new Constraint<>(newDomain, expressionTranslation.connectorExpression(), connectorExpressionAssignments, evaluator::isCandidate, evaluator.getArguments()); } else { // Currently, invoking the expression interpreter is very expensive. // TODO invoke the interpreter unconditionally when the interpreter becomes cheap enough. - constraint = new Constraint(newDomain, expressionTranslation.connectorExpression(), connectorExpressionAssignments); + constraint = new Constraint<>(newDomain, expressionTranslation.connectorExpression(), connectorExpressionAssignments); } // check if new domain is wider than domain already provided by table scan @@ -244,7 +244,7 @@ public static Optional pushFilterIntoTableScan( return Optional.of(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of())); } - Optional> result = plannerContext.getMetadata().applyFilter(session, node.getTable(), constraint); + Optional> result = plannerContext.getMetadata().applyFilter(session, node.getTable(), constraint); if (result.isEmpty()) { return Optional.empty(); @@ -330,7 +330,7 @@ private static void verifyTablePartitioning( verify(newTablePartitioning.equals(oldTablePartitioning), "Partitioning must not change after predicate is pushed down"); } - private static SplitExpression splitExpression(PlannerContext plannerContext, Expression predicate) + public static SplitExpression splitExpression(PlannerContext plannerContext, Expression predicate) { Metadata metadata = plannerContext.getMetadata(); @@ -386,7 +386,7 @@ static Expression createResultingPredicate( return expression; } - public static TupleDomain computeEnforced(TupleDomain predicate, TupleDomain unenforced) + public static TupleDomain computeEnforced(TupleDomain predicate, TupleDomain 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. @@ -398,23 +398,23 @@ public static TupleDomain computeEnforced(TupleDomain predicateDomains = predicate.getDomains().get(); - Map unenforcedDomains = unenforced.getDomains().get(); - ImmutableMap.Builder enforcedDomainsBuilder = ImmutableMap.builder(); - for (Map.Entry entry : predicateDomains.entrySet()) { - ColumnHandle predicateColumnHandle = entry.getKey(); + Map predicateDomains = predicate.getDomains().get(); + Map unenforcedDomains = unenforced.getDomains().get(); + ImmutableMap.Builder enforcedDomainsBuilder = ImmutableMap.builder(); + for (Map.Entry entry : predicateDomains.entrySet()) { + T column = entry.getKey(); Domain predicateDomain = entry.getValue(); - if (unenforcedDomains.containsKey(predicateColumnHandle)) { - Domain unenforcedDomain = unenforcedDomains.get(predicateColumnHandle); + if (unenforcedDomains.containsKey(column)) { + Domain unenforcedDomain = unenforcedDomains.get(column); checkArgument( predicateDomain.contains(unenforcedDomain), "Unexpected unenforced domain %s on column %s. Expected all, none, or a domain equal to or narrower than %s", unenforcedDomain, - predicateColumnHandle, + column, predicateDomain); } else { - enforcedDomainsBuilder.put(predicateColumnHandle, predicateDomain); + enforcedDomainsBuilder.put(column, predicateDomain); } } return TupleDomain.withColumnDomains(enforcedDomainsBuilder.buildOrThrow()); @@ -426,7 +426,7 @@ public boolean getPruneWithPredicateExpression() return pruneWithPredicateExpression; } - private static class SplitExpression + public static class SplitExpression { private final Expression dynamicFilter; private final Expression deterministicPredicate; diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/AddLocalExchanges.java b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/AddLocalExchanges.java index 952f7ecc590d..656c2446b72c 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/AddLocalExchanges.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/AddLocalExchanges.java @@ -567,7 +567,8 @@ public PlanWithProperties visitTableFunctionProcessor(TableFunctionProcessorNode prePartitionedInputs, preSortedOrderPrefix, node.getHashSymbol(), - node.getHandle()); + node.getHandle(), + node.getEnforcedConstraint()); return deriveProperties(result, child.getProperties()); } diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/SymbolMapper.java b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/SymbolMapper.java index 4d6bcd959fd4..9b69753b6626 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/SymbolMapper.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/SymbolMapper.java @@ -416,7 +416,8 @@ public TableFunctionProcessorNode map(TableFunctionProcessorNode node, PlanNode .collect(toImmutableSet()), newSpecification.map(SpecificationWithPreSortedPrefix::preSorted).orElse(node.getPreSorted()), node.getHashSymbol().map(this::map), - node.getHandle()); + node.getHandle(), + node.getEnforcedConstraint()); } public LimitNode map(LimitNode node, PlanNode source) diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/UnaliasSymbolReferences.java b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/UnaliasSymbolReferences.java index 4baa276e82db..442c9cb9f212 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/UnaliasSymbolReferences.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/optimizations/UnaliasSymbolReferences.java @@ -398,7 +398,8 @@ public PlanAndMappings visitTableFunctionProcessor(TableFunctionProcessorNode no ImmutableSet.of(), 0, node.getHashSymbol().map(mapper::map), - node.getHandle()), + node.getHandle(), + node.getEnforcedConstraint()), mapping); } diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/plan/TableFunctionProcessorNode.java b/core/trino-main/src/main/java/io/trino/sql/planner/plan/TableFunctionProcessorNode.java index 72bc80910ada..0a5c27828a4f 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/plan/TableFunctionProcessorNode.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/plan/TableFunctionProcessorNode.java @@ -14,14 +14,17 @@ package io.trino.sql.planner.plan; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import io.trino.metadata.TableFunctionHandle; +import io.trino.spi.predicate.TupleDomain; import io.trino.sql.planner.OrderingScheme; import io.trino.sql.planner.Symbol; import io.trino.sql.planner.plan.TableFunctionNode.PassThroughSpecification; +import jakarta.annotation.Nullable; import java.util.Collection; import java.util.List; @@ -30,6 +33,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.Iterables.getOnlyElement; import static java.util.Objects.requireNonNull; @@ -70,6 +74,9 @@ public class TableFunctionProcessorNode private final TableFunctionHandle handle; + @Nullable // null on workers + private final TupleDomain enforcedConstraint; + @JsonCreator public TableFunctionProcessorNode( @JsonProperty("id") PlanNodeId id, @@ -85,6 +92,39 @@ public TableFunctionProcessorNode( @JsonProperty("preSorted") int preSorted, @JsonProperty("hashSymbol") Optional hashSymbol, @JsonProperty("handle") TableFunctionHandle handle) + { + this( + id, + name, + properOutputs, + source, + pruneWhenEmpty, + passThroughSpecifications, + requiredSymbols, + markerSymbols, + specification, + prePartitioned, + preSorted, + hashSymbol, + handle, + null); + } + + public TableFunctionProcessorNode( + PlanNodeId id, + String name, + List properOutputs, + Optional source, + boolean pruneWhenEmpty, + List passThroughSpecifications, + List> requiredSymbols, + Optional> markerSymbols, + Optional specification, + Set prePartitioned, + int preSorted, + Optional hashSymbol, + TableFunctionHandle handle, + TupleDomain enforcedConstraint) { super(id); this.name = requireNonNull(name, "name is null"); @@ -114,6 +154,7 @@ public TableFunctionProcessorNode( checkArgument(preSorted == 0 || partitionBy.equals(prePartitioned), "to specify pre-sorted symbols, it is required that all partitioning symbols are pre-partitioned"); this.hashSymbol = requireNonNull(hashSymbol, "hashSymbol is null"); this.handle = requireNonNull(handle, "handle is null"); + this.enforcedConstraint = enforcedConstraint; } @JsonProperty @@ -211,6 +252,14 @@ public List getOutputSymbols() return symbols.build(); } + @Nullable + @JsonIgnore + public TupleDomain getEnforcedConstraint() + { + checkState(enforcedConstraint != null, "enforcedConstraint should only be used in planner. It is not transported to workers."); + return enforcedConstraint; + } + @Override public R accept(PlanVisitor visitor, C context) { @@ -234,6 +283,7 @@ public PlanNode replaceChildren(List newSources) prePartitioned, preSorted, hashSymbol, - handle); + handle, + enforcedConstraint); } } diff --git a/core/trino-main/src/main/java/io/trino/tracing/TracingConnectorMetadata.java b/core/trino-main/src/main/java/io/trino/tracing/TracingConnectorMetadata.java index 2826bf33c6f9..d19f9da60028 100644 --- a/core/trino-main/src/main/java/io/trino/tracing/TracingConnectorMetadata.java +++ b/core/trino-main/src/main/java/io/trino/tracing/TracingConnectorMetadata.java @@ -1044,7 +1044,16 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + { + Span span = startSpan("applyFilter", handle); + try (var ignored = scopedSpan(span)) { + return delegate.applyFilter(session, handle, constraint); + } + } + + @Override + public Optional> applyFilter(ConnectorSession session, ConnectorTableFunctionHandle handle, Constraint constraint) { Span span = startSpan("applyFilter", handle); try (var ignored = scopedSpan(span)) { @@ -1301,4 +1310,13 @@ private Span startSpan(String methodName, FunctionId functionId) } return span; } + + private Span startSpan(String methodName, ConnectorTableFunctionHandle handle) + { + Span span = startSpan(methodName); + if (span.isRecording()) { + span.setAttribute(TrinoAttributes.HANDLE, handle.toString()); + } + return span; + } } diff --git a/core/trino-main/src/main/java/io/trino/tracing/TracingMetadata.java b/core/trino-main/src/main/java/io/trino/tracing/TracingMetadata.java index 54264a4aab9c..933c97521888 100644 --- a/core/trino-main/src/main/java/io/trino/tracing/TracingMetadata.java +++ b/core/trino-main/src/main/java/io/trino/tracing/TracingMetadata.java @@ -76,6 +76,7 @@ import io.trino.spi.function.AggregationFunctionMetadata; import io.trino.spi.function.FunctionMetadata; import io.trino.spi.function.OperatorType; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; import io.trino.spi.predicate.TupleDomain; import io.trino.spi.security.GrantInfo; import io.trino.spi.security.Identity; @@ -885,7 +886,7 @@ public Optional> applyLimit(Session session, } @Override - public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) + public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) { Span span = startSpan("applyFilter", table); try (var ignored = scopedSpan(span)) { @@ -893,6 +894,19 @@ public Optional> applyFilter(Session se } } + @Override + public Optional> applyFilter(Session session, TableFunctionHandle handle, Constraint constraint) + { + Span span = startSpan("applyFilter"); + if (span.isRecording()) { + span.setAttribute(TrinoAttributes.CATALOG, handle.getCatalogHandle().getCatalogName()); + span.setAttribute(TrinoAttributes.HANDLE, handle.toString()); + } + try (var ignored = scopedSpan(span)) { + return delegate.applyFilter(session, handle, constraint); + } + } + @Override public Optional> applyProjection(Session session, TableHandle table, List projections, Map assignments) { diff --git a/core/trino-main/src/test/java/io/trino/connector/MockConnector.java b/core/trino-main/src/test/java/io/trino/connector/MockConnector.java index cd84f44afce2..60296eeb212e 100644 --- a/core/trino-main/src/test/java/io/trino/connector/MockConnector.java +++ b/core/trino-main/src/test/java/io/trino/connector/MockConnector.java @@ -20,6 +20,7 @@ import io.airlift.slice.Slice; import io.trino.connector.MockConnectorFactory.ApplyAggregation; import io.trino.connector.MockConnectorFactory.ApplyFilter; +import io.trino.connector.MockConnectorFactory.ApplyFilterForPtf; import io.trino.connector.MockConnectorFactory.ApplyJoin; import io.trino.connector.MockConnectorFactory.ApplyProjection; import io.trino.connector.MockConnectorFactory.ApplyTableFunction; @@ -148,6 +149,7 @@ public class MockConnector private final MockConnectorFactory.ApplyJoin applyJoin; private final MockConnectorFactory.ApplyTopN applyTopN; private final MockConnectorFactory.ApplyFilter applyFilter; + private final MockConnectorFactory.ApplyFilterForPtf applyFilterForPtf; private final MockConnectorFactory.ApplyTableFunction applyTableFunction; private final MockConnectorFactory.ApplyTableScanRedirect applyTableScanRedirect; private final BiFunction> redirectTable; @@ -194,6 +196,7 @@ public class MockConnector ApplyJoin applyJoin, ApplyTopN applyTopN, ApplyFilter applyFilter, + ApplyFilterForPtf applyFilterForPtf, ApplyTableFunction applyTableFunction, ApplyTableScanRedirect applyTableScanRedirect, BiFunction> redirectTable, @@ -238,6 +241,7 @@ public class MockConnector this.applyJoin = requireNonNull(applyJoin, "applyJoin is null"); this.applyTopN = requireNonNull(applyTopN, "applyTopN is null"); this.applyFilter = requireNonNull(applyFilter, "applyFilter is null"); + this.applyFilterForPtf = requireNonNull(applyFilterForPtf, "applyFilter is null"); this.applyTableFunction = requireNonNull(applyTableFunction, "applyTableFunction is null"); this.applyTableScanRedirect = requireNonNull(applyTableScanRedirect, "applyTableScanRedirection is null"); this.redirectTable = requireNonNull(redirectTable, "redirectTable is null"); @@ -448,11 +452,17 @@ public Optional> applyTopN( } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { return applyFilter.apply(session, handle, constraint); } + @Override + public Optional> applyFilter(ConnectorSession session, ConnectorTableFunctionHandle handle, Constraint constraint) + { + return applyFilterForPtf.apply(session, handle, constraint); + } + @Override public Optional> applyTableFunction(ConnectorSession session, ConnectorTableFunctionHandle handle) { diff --git a/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java b/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java index 84724f1d9be5..71c2d5406b4c 100644 --- a/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java +++ b/core/trino-main/src/test/java/io/trino/connector/MockConnectorFactory.java @@ -104,6 +104,7 @@ public class MockConnectorFactory private final ApplyJoin applyJoin; private final ApplyTopN applyTopN; private final ApplyFilter applyFilter; + private final ApplyFilterForPtf applyFilterForPtf; private final ApplyTableFunction applyTableFunction; private final ApplyTableScanRedirect applyTableScanRedirect; private final BiFunction> redirectTable; @@ -152,6 +153,7 @@ private MockConnectorFactory( ApplyJoin applyJoin, ApplyTopN applyTopN, ApplyFilter applyFilter, + ApplyFilterForPtf applyFilterForPtf, ApplyTableFunction applyTableFunction, ApplyTableScanRedirect applyTableScanRedirect, BiFunction> redirectTable, @@ -197,6 +199,7 @@ private MockConnectorFactory( this.applyJoin = requireNonNull(applyJoin, "applyJoin is null"); this.applyTopN = requireNonNull(applyTopN, "applyTopN is null"); this.applyFilter = requireNonNull(applyFilter, "applyFilter is null"); + this.applyFilterForPtf = requireNonNull(applyFilterForPtf, "applyFilterForPtf is null"); this.applyTableFunction = requireNonNull(applyTableFunction, "applyTableFunction is null"); this.applyTableScanRedirect = requireNonNull(applyTableScanRedirect, "applyTableScanRedirection is null"); this.redirectTable = requireNonNull(redirectTable, "redirectTable is null"); @@ -252,6 +255,7 @@ public Connector create(String catalogName, Map config, Connecto applyJoin, applyTopN, applyFilter, + applyFilterForPtf, applyTableFunction, applyTableScanRedirect, redirectTable, @@ -342,7 +346,13 @@ Optional> apply( @FunctionalInterface public interface ApplyFilter { - Optional> apply(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint); + Optional> apply(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint); + } + + @FunctionalInterface + public interface ApplyFilterForPtf + { + Optional> apply(ConnectorSession session, ConnectorTableFunctionHandle handle, Constraint constraint); } @FunctionalInterface @@ -389,6 +399,7 @@ public static final class Builder private Supplier> eventListeners = ImmutableList::of; private ApplyTopN applyTopN = (session, handle, topNCount, sortItems, assignments) -> Optional.empty(); private ApplyFilter applyFilter = (session, handle, constraint) -> Optional.empty(); + private ApplyFilterForPtf applyFilterForPtf = ((session, handle, constraint) -> Optional.empty()); private ApplyTableFunction applyTableFunction = (session, handle) -> Optional.empty(); private ApplyTableScanRedirect applyTableScanRedirect = (session, handle) -> Optional.empty(); private BiFunction> redirectTable = (session, tableName) -> Optional.empty(); @@ -540,6 +551,12 @@ public Builder withApplyFilter(ApplyFilter applyFilter) return this; } + public Builder withApplyFilterForPtf(ApplyFilterForPtf applyFilterForPtf) + { + this.applyFilterForPtf = applyFilterForPtf; + return this; + } + public Builder withApplyTableFunction(ApplyTableFunction applyTableFunction) { this.applyTableFunction = applyTableFunction; @@ -750,6 +767,7 @@ public MockConnectorFactory build() applyJoin, applyTopN, applyFilter, + applyFilterForPtf, applyTableFunction, applyTableScanRedirect, redirectTable, diff --git a/core/trino-main/src/test/java/io/trino/metadata/AbstractMockMetadata.java b/core/trino-main/src/test/java/io/trino/metadata/AbstractMockMetadata.java index b6181e111c37..d362600c1112 100644 --- a/core/trino-main/src/test/java/io/trino/metadata/AbstractMockMetadata.java +++ b/core/trino-main/src/test/java/io/trino/metadata/AbstractMockMetadata.java @@ -57,6 +57,7 @@ import io.trino.spi.function.FunctionMetadata; import io.trino.spi.function.FunctionNullability; import io.trino.spi.function.OperatorType; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; import io.trino.spi.predicate.TupleDomain; import io.trino.spi.security.GrantInfo; import io.trino.spi.security.Identity; @@ -595,7 +596,13 @@ public Optional> applyLimit(Session session, } @Override - public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) + public Optional> applyFilter(Session session, TableHandle table, Constraint constraint) + { + return Optional.empty(); + } + + @Override + public Optional> applyFilter(Session session, TableFunctionHandle handle, Constraint constraint) { return Optional.empty(); } diff --git a/core/trino-main/src/test/java/io/trino/metadata/TestInformationSchemaMetadata.java b/core/trino-main/src/test/java/io/trino/metadata/TestInformationSchemaMetadata.java index 587cd54e03b4..0ddcd537e140 100644 --- a/core/trino-main/src/test/java/io/trino/metadata/TestInformationSchemaMetadata.java +++ b/core/trino-main/src/test/java/io/trino/metadata/TestInformationSchemaMetadata.java @@ -115,7 +115,7 @@ public void testInformationSchemaPredicatePushdown() ImmutableMap.Builder 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())); + Constraint constraint = new Constraint<>(TupleDomain.withColumnDomains(domains.buildOrThrow())); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); @@ -132,7 +132,7 @@ public void testInformationSchemaPredicatePushdown() public void testInformationSchemaPredicatePushdownWithConstraintPredicate() { TransactionId transactionId = transactionManager.beginTransaction(false); - Constraint constraint = new Constraint(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint, testConstraintColumns()); + Constraint constraint = new Constraint<>(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint, testConstraintColumns()); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); @@ -154,7 +154,7 @@ public void testInformationSchemaPredicatePushdownWithoutSchemaPredicate() // predicate without schema predicates should cause schemas to be enumerated when table predicates are present ImmutableMap.Builder domains = ImmutableMap.builder(); domains.put(new InformationSchemaColumnHandle("table_name"), Domain.singleValue(VARCHAR, Slices.utf8Slice("test_view"))); - Constraint constraint = new Constraint(TupleDomain.withColumnDomains(domains.buildOrThrow())); + Constraint constraint = new Constraint<>(TupleDomain.withColumnDomains(domains.buildOrThrow())); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); @@ -178,7 +178,7 @@ public void testInformationSchemaPredicatePushdownWithoutTablePredicate() // predicate without table name predicates should not cause table level prefixes to be evaluated ImmutableMap.Builder domains = ImmutableMap.builder(); domains.put(new InformationSchemaColumnHandle("table_schema"), Domain.singleValue(VARCHAR, Slices.utf8Slice("test_schema"))); - Constraint constraint = new Constraint(TupleDomain.withColumnDomains(domains.buildOrThrow())); + Constraint constraint = new Constraint<>(TupleDomain.withColumnDomains(domains.buildOrThrow())); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); @@ -197,7 +197,7 @@ public void testInformationSchemaPredicatePushdownWithConstraintPredicateOnViews TransactionId transactionId = transactionManager.beginTransaction(false); // predicate on non columns enumerating table should not cause tables to be enumerated - Constraint constraint = new Constraint(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint, testConstraintColumns()); + Constraint constraint = new Constraint<>(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint, testConstraintColumns()); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle) @@ -217,12 +217,12 @@ public void testInformationSchemaPredicatePushdownOnCatalogWiseTables() // Predicate pushdown shouldn't work for catalog-wise tables because the table prefixes for them are always // ImmutableSet.of(new QualifiedTablePrefix(catalogName)); - Constraint constraint = new Constraint(TupleDomain.all()); + Constraint constraint = new Constraint<>(TupleDomain.all()); ConnectorSession session = createNewSession(transactionId); ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata, MAX_PREFIXES_COUNT); InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle) metadata.getTableHandle(session, new SchemaTableName("information_schema", "schemata")); - Optional> result = metadata.applyFilter(session, tableHandle, constraint); + Optional> result = metadata.applyFilter(session, tableHandle, constraint); assertFalse(result.isPresent()); } @@ -237,7 +237,7 @@ public void testInformationSchemaPredicatePushdownForEmptyNames() ConnectorTableHandle tableHandle = metadata.getTableHandle(session, new SchemaTableName("information_schema", "tables")); // Empty schema name - InformationSchemaTableHandle filtered = metadata.applyFilter(session, tableHandle, new Constraint(TupleDomain.withColumnDomains( + InformationSchemaTableHandle filtered = metadata.applyFilter(session, tableHandle, new Constraint<>(TupleDomain.withColumnDomains( ImmutableMap.of(tableSchemaColumn, Domain.singleValue(VARCHAR, Slices.utf8Slice("")))))) .map(ConstraintApplicationResult::getHandle) .map(InformationSchemaTableHandle.class::cast) @@ -247,7 +247,7 @@ public void testInformationSchemaPredicatePushdownForEmptyNames() assertEquals(filtered.getPrefixes(), ImmutableSet.of(new QualifiedTablePrefix("test_catalog", ""))); // Empty table name - filtered = metadata.applyFilter(session, tableHandle, new Constraint(TupleDomain.withColumnDomains( + filtered = metadata.applyFilter(session, tableHandle, new Constraint<>(TupleDomain.withColumnDomains( ImmutableMap.of(tableNameColumn, Domain.singleValue(VARCHAR, Slices.utf8Slice("")))))) .map(ConstraintApplicationResult::getHandle) .map(InformationSchemaTableHandle.class::cast) diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/TestPushFilterIntoTableFunction.java b/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/TestPushFilterIntoTableFunction.java new file mode 100644 index 000000000000..64850c3426b2 --- /dev/null +++ b/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/TestPushFilterIntoTableFunction.java @@ -0,0 +1,148 @@ +/* + * 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 io.trino.sql.planner.iterative.rule; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import io.trino.Session; +import io.trino.connector.MockConnectorFactory; +import io.trino.spi.connector.CatalogHandle; +import io.trino.spi.connector.ConstraintApplicationResult; +import io.trino.spi.function.table.ConnectorTableFunctionHandle; +import io.trino.spi.predicate.NullableValue; +import io.trino.spi.predicate.TupleDomain; +import io.trino.sql.planner.iterative.rule.test.BaseRuleTest; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.ResourceLock; + +import java.util.Optional; + +import static io.trino.spi.type.BigintType.BIGINT; +import static io.trino.sql.planner.TypeAnalyzer.createTestingTypeAnalyzer; +import static io.trino.sql.planner.assertions.PlanMatchPattern.filter; +import static io.trino.sql.planner.assertions.PlanMatchPattern.tableFunctionProcessor; +import static io.trino.sql.planner.assertions.PlanMatchPattern.values; +import static io.trino.sql.planner.iterative.rule.test.PlanBuilder.expression; + +@ResourceLock("TestPushFilterIntoTableFunction") +public class TestPushFilterIntoTableFunction + extends BaseRuleTest +{ + private static final String MOCK_CATALOG = "mock_catalog"; + private static final ConnectorTableFunctionHandle TABLE_FUNCTION_CONSUMES_ENTIRE_PREDICATE = new ConnectorTableFunctionHandle() {}; + + public static final int PUSHDOWN_COLUMN = 1; + private static final ConnectorTableFunctionHandle TABLE_FUNCTION_CONSUMES_PREDICATE_PARTIALLY = new ConnectorTableFunctionHandle() {}; + + private static final ConnectorTableFunctionHandle RESULT_TABLE_FUNCTION_HANDLE = new ConnectorTableFunctionHandle() {}; + private PushFilterIntoTableFunction pushFilterIntoTableFunction; + private CatalogHandle catalogHandle; + private CatalogHandle mockCatalogHandle; + + @BeforeAll + public void init() + { + pushFilterIntoTableFunction = new PushFilterIntoTableFunction(tester().getPlannerContext(), createTestingTypeAnalyzer(tester().getPlannerContext())); + + catalogHandle = tester().getCurrentCatalogHandle(); + MockConnectorFactory mockConnectorFactory = MockConnectorFactory.builder() + .withApplyFilterForPtf((session, tableFunctionHandle, constraint) -> { + if (tableFunctionHandle.equals(TABLE_FUNCTION_CONSUMES_ENTIRE_PREDICATE)) { + return Optional.of(new ConstraintApplicationResult<>(RESULT_TABLE_FUNCTION_HANDLE, TupleDomain.all(), false)); + } + if (tableFunctionHandle.equals(TABLE_FUNCTION_CONSUMES_PREDICATE_PARTIALLY)) { + return Optional.of(new ConstraintApplicationResult<>( + RESULT_TABLE_FUNCTION_HANDLE, + TupleDomain.fromFixedValues(ImmutableMap.of(PUSHDOWN_COLUMN, NullableValue.of(BIGINT, (long) 1))), + false)); + } + return Optional.empty(); + }) + .build(); + tester().getQueryRunner().createCatalog(MOCK_CATALOG, mockConnectorFactory, ImmutableMap.of()); + mockCatalogHandle = tester().getQueryRunner().getCatalogHandle(MOCK_CATALOG); + } + + @Test + public void testDoesNotFireIfNoTableFunctionProcessor() + { + tester().assertThat(pushFilterIntoTableFunction) + .on(p -> p.values(p.symbol("a", BIGINT))) + .doesNotFire(); + } + + @Test + public void testDoesNotFireWhenApplyFilterReturnsEmptyResult() + { + tester().assertThat(pushFilterIntoTableFunction) + .on(p -> p.filter( + expression("p = BIGINT '44' "), + p.tableFunctionProcessor( + builder -> builder + .name("test_function") + .properOutputs(p.symbol("p")) + .source(p.values(p.symbol("x"))) + .catalogHandle(catalogHandle)))) + .doesNotFire(); + } + + @Test + public void testRemovesPredicateWhenFunctionConsumesIt() + { + Session session = Session.builder(tester().getSession()) + .setCatalog(MOCK_CATALOG) + .build(); + tester().assertThat(pushFilterIntoTableFunction) + .withSession(session) + .on(p -> p.filter( + expression("p = BIGINT '44' "), + p.tableFunctionProcessor( + builder -> builder + .name("test_function") + .properOutputs(p.symbol("p")) + .source(p.values(p.symbol("x"))) + .catalogHandle(mockCatalogHandle) + .connectorTableFunctionHandle(TABLE_FUNCTION_CONSUMES_ENTIRE_PREDICATE)))) + .matches(tableFunctionProcessor( + builder -> builder + .name("test_function") + .properOutputs(ImmutableList.of("p")), + values("x"))); + } + + @Test + public void testNarrowsPredicateWhenFunctionPartiallyConsumesIt() + { + Session session = Session.builder(tester().getSession()) + .setCatalog(MOCK_CATALOG) + .build(); + tester().assertThat(pushFilterIntoTableFunction) + .withSession(session) + .on(p -> p.filter( + expression("p = BIGINT '44' AND z = BIGINT '1'"), + p.tableFunctionProcessor( + builder -> builder + .name("test_function") + .properOutputs(p.symbol("p"), p.symbol("z")) + .source(p.values(p.symbol("x"))) + .catalogHandle(mockCatalogHandle) + .connectorTableFunctionHandle(TABLE_FUNCTION_CONSUMES_PREDICATE_PARTIALLY)))) + .matches(filter("z = BIGINT '1'", tableFunctionProcessor( + builder -> builder + .name("test_function") + .properOutputs(ImmutableList.of("p", "z")), + values("x")))); + } +} diff --git a/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/test/TableFunctionProcessorBuilder.java b/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/test/TableFunctionProcessorBuilder.java index e3a6c901eebe..3395615d5e83 100644 --- a/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/test/TableFunctionProcessorBuilder.java +++ b/core/trino-main/src/test/java/io/trino/sql/planner/iterative/rule/test/TableFunctionProcessorBuilder.java @@ -16,7 +16,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import io.trino.metadata.TableFunctionHandle; +import io.trino.spi.connector.CatalogHandle; import io.trino.spi.function.table.ConnectorTableFunctionHandle; +import io.trino.spi.predicate.TupleDomain; import io.trino.sql.planner.PlanNodeIdAllocator; import io.trino.sql.planner.Symbol; import io.trino.sql.planner.plan.DataOrganizationSpecification; @@ -45,6 +47,8 @@ public class TableFunctionProcessorBuilder private Set prePartitioned = ImmutableSet.of(); private int preSorted; private Optional hashSymbol = Optional.empty(); + private CatalogHandle catalogHandle = TEST_CATALOG_HANDLE; + private ConnectorTableFunctionHandle connectorTableFunctionHandle; public TableFunctionProcessorBuilder() {} @@ -114,6 +118,18 @@ public TableFunctionProcessorBuilder hashSymbol(Symbol hashSymbol) return this; } + public TableFunctionProcessorBuilder catalogHandle(CatalogHandle catalogHandle) + { + this.catalogHandle = catalogHandle; + return this; + } + + public TableFunctionProcessorBuilder connectorTableFunctionHandle(ConnectorTableFunctionHandle connectorTableFunctionHandle) + { + this.connectorTableFunctionHandle = connectorTableFunctionHandle; + return this; + } + public TableFunctionProcessorNode build(PlanNodeIdAllocator idAllocator) { return new TableFunctionProcessorNode( @@ -129,6 +145,11 @@ public TableFunctionProcessorNode build(PlanNodeIdAllocator idAllocator) prePartitioned, preSorted, hashSymbol, - new TableFunctionHandle(TEST_CATALOG_HANDLE, new ConnectorTableFunctionHandle() {}, TestingTransactionHandle.create())); + new TableFunctionHandle( + catalogHandle, + connectorTableFunctionHandle == null ? + new ConnectorTableFunctionHandle() {} : connectorTableFunctionHandle, + TestingTransactionHandle.create()), + TupleDomain.all()); } } diff --git a/core/trino-spi/pom.xml b/core/trino-spi/pom.xml index 9e0e9f572ce4..53f47ec754c7 100644 --- a/core/trino-spi/pom.xml +++ b/core/trino-spi/pom.xml @@ -229,6 +229,206 @@ + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.ConstraintApplicationResult<T>::<init>(T, ===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===, boolean) + parameter void io.trino.spi.connector.ConstraintApplicationResult<T, G>::<init>(T, ===io.trino.spi.predicate.TupleDomain<G>===, boolean) + 1 + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.ConstraintApplicationResult<T>::<init>(T, ===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===, io.trino.spi.expression.ConnectorExpression, boolean) + parameter void io.trino.spi.connector.ConstraintApplicationResult<T, G>::<init>(T, ===io.trino.spi.predicate.TupleDomain<G>===, io.trino.spi.expression.ConnectorExpression, boolean) + 1 + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.method.returnTypeTypeParametersChanged + method io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle> io.trino.spi.connector.ConstraintApplicationResult<T>::getRemainingFilter() + method io.trino.spi.predicate.TupleDomain<G> io.trino.spi.connector.ConstraintApplicationResult<T, G>::getRemainingFilter() + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.method.returnTypeTypeParametersChanged + method <U> io.trino.spi.connector.ConstraintApplicationResult<U> io.trino.spi.connector.ConstraintApplicationResult<T>::transform(java.util.function.Function<T, U>) + method <U> io.trino.spi.connector.ConstraintApplicationResult<U, G> io.trino.spi.connector.ConstraintApplicationResult<T, G>::transform(java.util.function.Function<T, U>) + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.method.returnTypeTypeParametersChanged + method java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + method <T> java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle, T>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.generics.elementNowParameterized + method java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + method <T> java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle, T>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.generics.formalTypeParameterAdded + method java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + method <T> java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle, T>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + T + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + true + java.generics.formalTypeParameterAdded + class io.trino.spi.connector.ConstraintApplicationResult<T> + class io.trino.spi.connector.ConstraintApplicationResult<T, G> + G + This is needed to make ConstraintApplicationResult not depend on ColumnHandle + + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===) + parameter void io.trino.spi.connector.Constraint<T>::<init>(===io.trino.spi.predicate.TupleDomain<T>===) + 0 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(===io.trino.spi.predicate.TupleDomain<T>===, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, T>) + 0 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, io.trino.spi.expression.ConnectorExpression, ===java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>===) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, io.trino.spi.expression.ConnectorExpression, ===java.util.Map<java.lang.String, T>===) + 2 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===, java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>, java.util.Set<io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(===io.trino.spi.predicate.TupleDomain<T>===, java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>, java.util.Set<T>) + 0 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, ===java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>===, java.util.Set<io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, ===java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>===, java.util.Set<T>) + 1 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>, ===java.util.Set<io.trino.spi.connector.ColumnHandle>===) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>, ===java.util.Set<T>===) + 2 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(===io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>===, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>, java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>, java.util.Set<io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(===io.trino.spi.predicate.TupleDomain<T>===, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, T>, java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>, java.util.Set<T>) + 0 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, io.trino.spi.expression.ConnectorExpression, ===java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>===, java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>, java.util.Set<io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, io.trino.spi.expression.ConnectorExpression, ===java.util.Map<java.lang.String, T>===, java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>, java.util.Set<T>) + 2 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>, ===java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>===, java.util.Set<io.trino.spi.connector.ColumnHandle>) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, T>, ===java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>===, java.util.Set<T>) + 3 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.parameterTypeParameterChanged + parameter void io.trino.spi.connector.Constraint::<init>(io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle>, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle>, java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>, ===java.util.Set<io.trino.spi.connector.ColumnHandle>===) + parameter void io.trino.spi.connector.Constraint<T>::<init>(io.trino.spi.predicate.TupleDomain<T>, io.trino.spi.expression.ConnectorExpression, java.util.Map<java.lang.String, T>, java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>, ===java.util.Set<T>===) + 4 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.returnTypeTypeParametersChanged + method java.util.Map<java.lang.String, io.trino.spi.connector.ColumnHandle> io.trino.spi.connector.Constraint::getAssignments() + method java.util.Map<java.lang.String, T> io.trino.spi.connector.Constraint<T>::getAssignments() + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.returnTypeTypeParametersChanged + method java.util.Optional<java.util.Set<io.trino.spi.connector.ColumnHandle>> io.trino.spi.connector.Constraint::getPredicateColumns() + method java.util.Optional<java.util.Set<T>> io.trino.spi.connector.Constraint<T>::getPredicateColumns() + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.returnTypeTypeParametersChanged + method io.trino.spi.predicate.TupleDomain<io.trino.spi.connector.ColumnHandle> io.trino.spi.connector.Constraint::getSummary() + method io.trino.spi.predicate.TupleDomain<T> io.trino.spi.connector.Constraint<T>::getSummary() + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.returnTypeTypeParametersChanged + method java.util.Optional<java.util.function.Predicate<java.util.Map<io.trino.spi.connector.ColumnHandle, io.trino.spi.predicate.NullableValue>>> io.trino.spi.connector.Constraint::predicate() + method java.util.Optional<java.util.function.Predicate<java.util.Map<T, io.trino.spi.predicate.NullableValue>>> io.trino.spi.connector.Constraint<T>::predicate() + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.generics.elementNowParameterized + class io.trino.spi.connector.Constraint + class io.trino.spi.connector.Constraint<T> + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.generics.formalTypeParameterAdded + class io.trino.spi.connector.Constraint + class io.trino.spi.connector.Constraint<T> + T + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + + true + java.method.parameterTypeParameterChanged + parameter java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, ===io.trino.spi.connector.Constraint===) + parameter java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.ColumnHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, ===io.trino.spi.connector.Constraint<io.trino.spi.connector.ColumnHandle>===) + 2 + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + + + true + java.method.returnTypeTypeParametersChanged + method java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint) + method java.util.Optional<io.trino.spi.connector.ConstraintApplicationResult<io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.ColumnHandle>> io.trino.spi.connector.ConnectorMetadata::applyFilter(io.trino.spi.connector.ConnectorSession, io.trino.spi.connector.ConnectorTableHandle, io.trino.spi.connector.Constraint<io.trino.spi.connector.ColumnHandle>) + ADD YOUR EXPLANATION FOR THE NECESSITY OF THIS CHANGE + diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java index de812af2b801..7023bdfafb92 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorMetadata.java @@ -1088,7 +1088,21 @@ default Optional> applyLimit(Connec * * @param constraint constraint to be applied to the table. {@link Constraint#getSummary()} is guaranteed not to be {@link TupleDomain#isNone() none}. */ - default Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + default Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + { + // applyFilter is expected not to be invoked with a "false" constraint + if (constraint.getSummary().isNone()) { + throw new IllegalArgumentException("constraint summary is NONE"); + } + if (FALSE.equals(constraint.getExpression())) { + // DomainTranslator translates FALSE expressions into TupleDomain.none() (via Visitor#visitBooleanLiteral) + // so the remaining expression shouldn't be FALSE and therefore the translated connectorExpression shouldn't be FALSE either. + throw new IllegalArgumentException("constraint expression is FALSE"); + } + return Optional.empty(); + } + + default Optional> applyFilter(ConnectorSession session, ConnectorTableFunctionHandle handle, Constraint constraint) { // applyFilter is expected not to be invoked with a "false" constraint if (constraint.getSummary().isNone()) { diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/Constraint.java b/core/trino-spi/src/main/java/io/trino/spi/connector/Constraint.java index af40b8a46a08..1e617efe04e6 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/Constraint.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/Constraint.java @@ -26,16 +26,16 @@ import static io.trino.spi.expression.Constant.TRUE; import static java.util.Objects.requireNonNull; -public class Constraint +public class Constraint { private static final Constraint ALWAYS_TRUE = new Constraint(TupleDomain.all()); private static final Constraint ALWAYS_FALSE = new Constraint(TupleDomain.none(), bindings -> false, Set.of()); - private final TupleDomain summary; + private final TupleDomain summary; private final ConnectorExpression expression; - private final Map assignments; - private final Optional>> predicate; - private final Optional> predicateColumns; + private final Map assignments; + private final Optional>> predicate; + private final Optional> predicateColumns; public static Constraint alwaysTrue() { @@ -47,37 +47,37 @@ public static Constraint alwaysFalse() return ALWAYS_FALSE; } - public Constraint(TupleDomain summary) + public Constraint(TupleDomain summary) { this(summary, TRUE, Map.of(), Optional.empty(), Optional.empty()); } - public Constraint(TupleDomain summary, Predicate> predicate, Set predicateColumns) + public Constraint(TupleDomain summary, Predicate> predicate, Set predicateColumns) { this(summary, TRUE, Map.of(), Optional.of(predicate), Optional.of(predicateColumns)); } - public Constraint(TupleDomain summary, ConnectorExpression expression, Map assignments) + public Constraint(TupleDomain summary, ConnectorExpression expression, Map assignments) { this(summary, expression, assignments, Optional.empty(), Optional.empty()); } public Constraint( - TupleDomain summary, + TupleDomain summary, ConnectorExpression expression, - Map assignments, - Predicate> predicate, - Set predicateColumns) + Map assignments, + Predicate> predicate, + Set predicateColumns) { this(summary, expression, assignments, Optional.of(predicate), Optional.of(predicateColumns)); } private Constraint( - TupleDomain summary, + TupleDomain summary, ConnectorExpression expression, - Map assignments, - Optional>> predicate, - Optional> predicateColumns) + Map assignments, + Optional>> predicate, + Optional> predicateColumns) { this.summary = requireNonNull(summary, "summary is null"); this.expression = requireNonNull(expression, "expression is null"); @@ -96,7 +96,7 @@ private Constraint( /** * @return a predicate which is equivalent to, or looser than {@link #predicate} (if present), and should be AND-ed with, {@link #getExpression}. */ - public TupleDomain getSummary() + public TupleDomain getSummary() { return summary; } @@ -113,7 +113,7 @@ public ConnectorExpression getExpression() * @return mappings from variable names to table column handles * It is guaranteed that all the required mappings for {@link #getExpression} will be provided but not necessarily *all* the column handles of the table */ - public Map getAssignments() + public Map getAssignments() { return assignments; } @@ -126,7 +126,7 @@ public Map getAssignments() * * @see #getPredicateColumns() */ - public Optional>> predicate() + public Optional>> predicate() { return predicate; } @@ -134,7 +134,7 @@ public Optional>> predicate() /** * Set of columns the {@link #predicate()} result depends on. It's present if and only if {@link #predicate()} is present. */ - public Optional> getPredicateColumns() + public Optional> getPredicateColumns() { return predicateColumns; } diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConstraintApplicationResult.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConstraintApplicationResult.java index 04dd3122d5c1..20414f9cb53f 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConstraintApplicationResult.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConstraintApplicationResult.java @@ -21,10 +21,10 @@ import static java.util.Objects.requireNonNull; -public class ConstraintApplicationResult +public class ConstraintApplicationResult { private final T handle; - private final TupleDomain remainingFilter; + private final TupleDomain remainingFilter; private final Optional remainingExpression; private final boolean precalculateStatistics; @@ -32,7 +32,7 @@ public class ConstraintApplicationResult * @param precalculateStatistics Indicates whether engine should consider calculating statistics based on the plan before pushdown, * as the connector may be unable to provide good table statistics for {@code handle}. */ - public ConstraintApplicationResult(T handle, TupleDomain remainingFilter, boolean precalculateStatistics) + public ConstraintApplicationResult(T handle, TupleDomain remainingFilter, boolean precalculateStatistics) { this(handle, remainingFilter, Optional.empty(), precalculateStatistics); } @@ -42,7 +42,7 @@ public ConstraintApplicationResult(T handle, TupleDomain remaining * @param precalculateStatistics Indicates whether engine should consider calculating statistics based on the plan before pushdown, * as the connector may be unable to provide good table statistics for {@code handle}. */ - public ConstraintApplicationResult(T handle, TupleDomain remainingFilter, ConnectorExpression remainingExpression, boolean precalculateStatistics) + public ConstraintApplicationResult(T handle, TupleDomain remainingFilter, ConnectorExpression remainingExpression, boolean precalculateStatistics) { this(handle, remainingFilter, Optional.of(remainingExpression), precalculateStatistics); } @@ -53,7 +53,7 @@ public ConstraintApplicationResult(T handle, TupleDomain remaining * @param precalculateStatistics Indicates whether engine should consider calculating statistics based on the plan before pushdown, * as the connector may be unable to provide good table statistics for {@code handle}. */ - private ConstraintApplicationResult(T handle, TupleDomain remainingFilter, Optional remainingExpression, boolean precalculateStatistics) + private ConstraintApplicationResult(T handle, TupleDomain remainingFilter, Optional remainingExpression, boolean precalculateStatistics) { this.handle = requireNonNull(handle, "handle is null"); this.remainingFilter = requireNonNull(remainingFilter, "remainingFilter is null"); @@ -66,7 +66,7 @@ public T getHandle() return handle; } - public TupleDomain getRemainingFilter() + public TupleDomain getRemainingFilter() { return remainingFilter; } @@ -81,7 +81,7 @@ public boolean isPrecalculateStatistics() return precalculateStatistics; } - public ConstraintApplicationResult transform(Function transformHandle) + public ConstraintApplicationResult transform(Function transformHandle) { return new ConstraintApplicationResult<>(transformHandle.apply(handle), remainingFilter, remainingExpression, precalculateStatistics); } diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorMetadata.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorMetadata.java index 5a5a2bf2b64b..308adf78af32 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorMetadata.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/classloader/ClassLoaderSafeConnectorMetadata.java @@ -884,13 +884,21 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(classLoader)) { return delegate.applyFilter(session, table, constraint); } } + @Override + public Optional> applyFilter(ConnectorSession session, ConnectorTableFunctionHandle handle, Constraint constraint) + { + try (ThreadContextClassLoader ignored = new ThreadContextClassLoader(classLoader)) { + return delegate.applyFilter(session, handle, constraint); + } + } + @Override public Optional> applyProjection(ConnectorSession session, ConnectorTableHandle table, List projections, Map assignments) { diff --git a/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java b/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java index e2e871c34ebd..2bb0b11efabc 100644 --- a/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java +++ b/plugin/trino-accumulo/src/main/java/io/trino/plugin/accumulo/AccumuloMetadata.java @@ -365,7 +365,7 @@ public Map> listTableColumns(ConnectorSess } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { AccumuloTableHandle handle = (AccumuloTableHandle) table; diff --git a/plugin/trino-atop/src/main/java/io/trino/plugin/atop/AtopMetadata.java b/plugin/trino-atop/src/main/java/io/trino/plugin/atop/AtopMetadata.java index b5065f82ce7a..ade0e518270e 100644 --- a/plugin/trino-atop/src/main/java/io/trino/plugin/atop/AtopMetadata.java +++ b/plugin/trino-atop/src/main/java/io/trino/plugin/atop/AtopMetadata.java @@ -148,7 +148,7 @@ public ColumnMetadata getColumnMetadata(ConnectorSession session, ConnectorTable } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { AtopTableHandle handle = (AtopTableHandle) table; diff --git a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java index 8d49c4f79861..e97eeb6c1f9c 100644 --- a/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java +++ b/plugin/trino-base-jdbc/src/main/java/io/trino/plugin/jdbc/DefaultJdbcMetadata.java @@ -158,7 +158,7 @@ public Optional getSystemTable(ConnectorSession session, SchemaTabl } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { if (isTableHandleForProcedure(table)) { return Optional.empty(); diff --git a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java index 9a55e499eb91..bbcadc28dd8f 100644 --- a/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java +++ b/plugin/trino-base-jdbc/src/test/java/io/trino/plugin/jdbc/TestDefaultJdbcMetadata.java @@ -400,7 +400,7 @@ private JdbcTableHandle applyCountAggregation(ConnectorSession session, Connecto private JdbcTableHandle applyFilter(ConnectorSession session, ConnectorTableHandle tableHandle, Constraint constraint) { - Optional> filterResult = metadata.applyFilter( + Optional> filterResult = metadata.applyFilter( session, tableHandle, constraint); diff --git a/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java b/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java index 14a0657e9d74..b42473d20791 100644 --- a/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java +++ b/plugin/trino-bigquery/src/main/java/io/trino/plugin/bigquery/BigQueryMetadata.java @@ -771,10 +771,10 @@ public Optional> applyProjecti } @Override - public Optional> applyFilter( + public Optional> applyFilter( ConnectorSession session, ConnectorTableHandle handle, - Constraint constraint) + Constraint constraint) { log.debug("applyFilter(session=%s, handle=%s, summary=%s, predicate=%s, columns=%s)", session, handle, constraint.getSummary(), constraint.predicate(), constraint.getPredicateColumns()); diff --git a/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java b/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java index de4b76875ae7..9e9d955eb224 100644 --- a/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java +++ b/plugin/trino-cassandra/src/main/java/io/trino/plugin/cassandra/CassandraMetadata.java @@ -227,7 +227,7 @@ public ColumnMetadata getColumnMetadata(ConnectorSession session, ConnectorTable } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle connectorTableHandle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle connectorTableHandle, Constraint constraint) { CassandraTableHandle tableHandle = (CassandraTableHandle) connectorTableHandle; if (tableHandle.isSynthetic()) { diff --git a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnector.java b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnector.java index 821c1818acea..c023cce04f77 100644 --- a/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnector.java +++ b/plugin/trino-cassandra/src/test/java/io/trino/plugin/cassandra/TestCassandraConnector.java @@ -188,7 +188,8 @@ public void testGetRecords() ConnectorTransactionHandle transaction = CassandraTransactionHandle.INSTANCE; - tableHandle = metadata.applyFilter(SESSION, tableHandle, Constraint.alwaysTrue()).get().getHandle(); + Constraint constraint = Constraint.alwaysTrue(); + tableHandle = metadata.applyFilter(SESSION, tableHandle, constraint).get().getHandle(); List splits = getAllSplits(splitManager.getSplits(transaction, SESSION, tableHandle, DynamicFilter.EMPTY, Constraint.alwaysTrue())); @@ -312,7 +313,8 @@ public void testGetUserDefinedType() ConnectorTransactionHandle transaction = CassandraTransactionHandle.INSTANCE; - tableHandle = metadata.applyFilter(SESSION, tableHandle, Constraint.alwaysTrue()).get().getHandle(); + Constraint constraint = Constraint.alwaysTrue(); + tableHandle = metadata.applyFilter(SESSION, tableHandle, constraint).get().getHandle(); List splits = getAllSplits(splitManager.getSplits(transaction, SESSION, tableHandle, DynamicFilter.EMPTY, Constraint.alwaysTrue())); diff --git a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java index c3f3f76c559b..2ac52fbcd347 100644 --- a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java +++ b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeMetadata.java @@ -2508,7 +2508,7 @@ public void rollback() } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { DeltaLakeTableHandle tableHandle = (DeltaLakeTableHandle) handle; SchemaTableName tableName = tableHandle.getSchemaTableName(); diff --git a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeSplitManager.java b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeSplitManager.java index b0cff466065e..98469f0b0a00 100644 --- a/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeSplitManager.java +++ b/plugin/trino-delta-lake/src/main/java/io/trino/plugin/deltalake/DeltaLakeSplitManager.java @@ -144,7 +144,7 @@ private Stream getSplits( ConnectorSession session, Optional maxScannedFileSize, Set columnsCoveredByDynamicFilter, - Constraint constraint) + Constraint constraint) { TableSnapshot tableSnapshot; try { diff --git a/plugin/trino-elasticsearch/src/main/java/io/trino/plugin/elasticsearch/ElasticsearchMetadata.java b/plugin/trino-elasticsearch/src/main/java/io/trino/plugin/elasticsearch/ElasticsearchMetadata.java index cc3aa9f72c44..b5e23913059f 100644 --- a/plugin/trino-elasticsearch/src/main/java/io/trino/plugin/elasticsearch/ElasticsearchMetadata.java +++ b/plugin/trino-elasticsearch/src/main/java/io/trino/plugin/elasticsearch/ElasticsearchMetadata.java @@ -487,7 +487,7 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { ElasticsearchTableHandle handle = (ElasticsearchTableHandle) table; diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java index c16b7d0cdfab..ea573253fe7a 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java @@ -2931,7 +2931,7 @@ public ConnectorTableProperties getTableProperties(ConnectorSession session, Con } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle tableHandle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle tableHandle, Constraint constraint) { HiveTableHandle handle = (HiveTableHandle) tableHandle; checkArgument(handle.getAnalyzePartitionValues().isEmpty() || constraint.getSummary().isAll(), "Analyze should not have a constraint"); diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HivePartitionManager.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HivePartitionManager.java index b105971a8aac..91cff3ce73dc 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HivePartitionManager.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HivePartitionManager.java @@ -67,7 +67,7 @@ public HivePartitionManager( this.domainCompactionThreshold = domainCompactionThreshold; } - public HivePartitionResult getPartitions(SemiTransactionalHiveMetastore metastore, ConnectorTableHandle tableHandle, Constraint constraint) + public HivePartitionResult getPartitions(SemiTransactionalHiveMetastore metastore, ConnectorTableHandle tableHandle, Constraint constraint) { HiveTableHandle hiveTableHandle = (HiveTableHandle) tableHandle; TupleDomain effectivePredicate = constraint.getSummary() @@ -140,7 +140,7 @@ public HivePartitionResult getPartitions(ConnectorTableHandle tableHandle, List< return new HivePartitionResult(partitionColumns, Optional.empty(), partitionList, TupleDomain.all(), TupleDomain.all(), bucketHandle, Optional.empty()); } - public HiveTableHandle applyPartitionResult(HiveTableHandle handle, HivePartitionResult partitions, Constraint constraint) + public HiveTableHandle applyPartitionResult(HiveTableHandle handle, HivePartitionResult partitions, Constraint constraint) { Optional> partitionNames = partitions.getPartitionNames(); TupleDomain enforcedConstraint = handle.getEnforcedConstraint(); diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java index f06ff628946d..22b458ea548f 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/AbstractTestHive.java @@ -5283,7 +5283,7 @@ protected ConnectorTableHandle getTableHandle(ConnectorMetadata metadata, Schema return handle; } - private HiveTableHandle applyFilter(ConnectorMetadata metadata, ConnectorTableHandle tableHandle, Constraint constraint) + private HiveTableHandle applyFilter(ConnectorMetadata metadata, ConnectorTableHandle tableHandle, Constraint constraint) { return metadata.applyFilter(newSession(), tableHandle, constraint) .map(ConstraintApplicationResult::getHandle) diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java index 05bbfcd5e642..1ac6ef92222e 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java @@ -3783,7 +3783,8 @@ private Object getHiveTableProperty(String tableName, Function new AssertionError("table not found: " + name)); - table = metadata.applyFilter(transactionSession, table, Constraint.alwaysTrue()) + Constraint constraint = Constraint.alwaysTrue(); + table = metadata.applyFilter(transactionSession, table, constraint) .orElseThrow(() -> new AssertionError("applyFilter did not return a result")) .getHandle(); return propertyGetter.apply((HiveTableHandle) table.getConnectorHandle()); diff --git a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java index 709e7439862c..eea2e3b295c7 100644 --- a/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java +++ b/plugin/trino-hudi/src/main/java/io/trino/plugin/hudi/HudiMetadata.java @@ -158,7 +158,7 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle tableHandle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle tableHandle, Constraint constraint) { HudiTableHandle handle = (HudiTableHandle) tableHandle; HudiPredicates predicates = HudiPredicates.from(constraint.getSummary()); diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergMetadata.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergMetadata.java index 3d44d61da42e..59dbeada5a08 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergMetadata.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergMetadata.java @@ -2418,7 +2418,7 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { IcebergTableHandle table = (IcebergTableHandle) handle; ConstraintExtractor.ExtractionResult extractionResult = extractTupleDomain(constraint); diff --git a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergSplitSource.java b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergSplitSource.java index 0efebcf1a471..ee5237e98f98 100644 --- a/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergSplitSource.java +++ b/plugin/trino-iceberg/src/main/java/io/trino/plugin/iceberg/IcebergSplitSource.java @@ -422,7 +422,7 @@ else if (upperBound != null) { static boolean partitionMatchesConstraint( Set identityPartitionColumns, Supplier> partitionValues, - Constraint constraint) + Constraint constraint) { // We use Constraint just to pass functional predicate here from DistributedExecutionPlanner verify(constraint.getSummary().isAll()); diff --git a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/BaseIcebergConnectorTest.java b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/BaseIcebergConnectorTest.java index 3a4c87bac214..b1b8f7d4ce07 100644 --- a/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/BaseIcebergConnectorTest.java +++ b/plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/BaseIcebergConnectorTest.java @@ -3923,7 +3923,7 @@ private void assertFilterPushdown( filter.entrySet().stream() .collect(toImmutableMap(entry -> columns.get(entry.getKey()), Map.Entry::getValue))); - Optional> result = metadata.applyFilter(session, table, new Constraint(domains)); + Optional> result = metadata.applyFilter(session, table, new Constraint(domains)); assertEquals((expectedUnenforcedPredicate == null && expectedEnforcedPredicate == null), result.isEmpty()); diff --git a/plugin/trino-jmx/src/main/java/io/trino/plugin/jmx/JmxMetadata.java b/plugin/trino-jmx/src/main/java/io/trino/plugin/jmx/JmxMetadata.java index 43efd522e81d..df5d433b899a 100644 --- a/plugin/trino-jmx/src/main/java/io/trino/plugin/jmx/JmxMetadata.java +++ b/plugin/trino-jmx/src/main/java/io/trino/plugin/jmx/JmxMetadata.java @@ -260,7 +260,7 @@ public Iterator streamTableColumns(ConnectorSession sessio } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { Map domains = constraint.getSummary().getDomains().orElseThrow(() -> new IllegalArgumentException("constraint summary is NONE")); diff --git a/plugin/trino-jmx/src/test/java/io/trino/plugin/jmx/TestJmxMetadata.java b/plugin/trino-jmx/src/test/java/io/trino/plugin/jmx/TestJmxMetadata.java index bc1954fc40ae..5a7d20d31dc3 100644 --- a/plugin/trino-jmx/src/test/java/io/trino/plugin/jmx/TestJmxMetadata.java +++ b/plugin/trino-jmx/src/test/java/io/trino/plugin/jmx/TestJmxMetadata.java @@ -137,7 +137,7 @@ public void testGetCumulativeTableHandleForHistorySchema() public void testApplyFilterWithoutConstraint() { JmxTableHandle handle = metadata.getTableHandle(SESSION, new SchemaTableName(JMX_SCHEMA_NAME, "java.lang:*")); - Optional> result = metadata.applyFilter(SESSION, handle, new Constraint(TupleDomain.all())); + Optional> result = metadata.applyFilter(SESSION, handle, new Constraint(TupleDomain.all())); assertFalse(result.isPresent()); } @@ -155,7 +155,7 @@ public void testApplyFilterWithConstraint() TupleDomain tupleDomain = TupleDomain.fromFixedValues(ImmutableMap.of(nodeColumnHandle, nodeColumnValue, objectNameColumnHandle, objectNameColumnValue)); - Optional> result = metadata.applyFilter(SESSION, handle, new Constraint(tupleDomain)); + Optional> result = metadata.applyFilter(SESSION, handle, new Constraint(tupleDomain)); assertTrue(result.isPresent()); assertEquals(result.get().getRemainingFilter(), TupleDomain.fromFixedValues(ImmutableMap.of(objectNameColumnHandle, objectNameColumnValue))); @@ -172,7 +172,7 @@ public void testApplyFilterWithSameConstraint() JmxTableHandle newTableHandle = new JmxTableHandle(handle.getTableName(), handle.getObjectNames(), handle.getColumnHandles(), handle.isLiveData(), nodeTupleDomain); - Optional> result = metadata.applyFilter(SESSION, newTableHandle, new Constraint(nodeTupleDomain)); + Optional> result = metadata.applyFilter(SESSION, newTableHandle, new Constraint(nodeTupleDomain)); assertFalse(result.isPresent()); } diff --git a/plugin/trino-kafka/src/main/java/io/trino/plugin/kafka/KafkaMetadata.java b/plugin/trino-kafka/src/main/java/io/trino/plugin/kafka/KafkaMetadata.java index aa7af3535170..aaba8df65d4b 100644 --- a/plugin/trino-kafka/src/main/java/io/trino/plugin/kafka/KafkaMetadata.java +++ b/plugin/trino-kafka/src/main/java/io/trino/plugin/kafka/KafkaMetadata.java @@ -230,7 +230,7 @@ private ConnectorTableMetadata getTableMetadata(ConnectorSession session, Schema } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { KafkaTableHandle handle = (KafkaTableHandle) table; TupleDomain oldDomain = handle.getConstraint(); diff --git a/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java b/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java index 7348bdd6b54c..0a02f90dc73c 100755 --- a/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java +++ b/plugin/trino-kudu/src/main/java/io/trino/plugin/kudu/KuduMetadata.java @@ -443,7 +443,7 @@ public ConnectorTableProperties getTableProperties(ConnectorSession session, Con } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { KuduTableHandle handle = (KuduTableHandle) table; diff --git a/plugin/trino-local-file/src/main/java/io/trino/plugin/localfile/LocalFileMetadata.java b/plugin/trino-local-file/src/main/java/io/trino/plugin/localfile/LocalFileMetadata.java index 44eac2de4e5b..ffe25e42cf5b 100644 --- a/plugin/trino-local-file/src/main/java/io/trino/plugin/localfile/LocalFileMetadata.java +++ b/plugin/trino-local-file/src/main/java/io/trino/plugin/localfile/LocalFileMetadata.java @@ -132,7 +132,7 @@ private List listTables(ConnectorSession session, SchemaTablePr } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { LocalFileTableHandle handle = (LocalFileTableHandle) table; diff --git a/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoMetadata.java b/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoMetadata.java index d8c5d8b031ae..d9267671d890 100644 --- a/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoMetadata.java +++ b/plugin/trino-mongodb/src/main/java/io/trino/plugin/mongodb/MongoMetadata.java @@ -587,7 +587,7 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { MongoTableHandle handle = (MongoTableHandle) table; diff --git a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotMetadata.java b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotMetadata.java index 1a26b95c8fff..57af83709124 100755 --- a/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotMetadata.java +++ b/plugin/trino-pinot/src/main/java/io/trino/plugin/pinot/PinotMetadata.java @@ -270,7 +270,7 @@ public Optional> applyLimit(Connect } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { PinotTableHandle handle = (PinotTableHandle) table; TupleDomain oldDomain = handle.getConstraint(); diff --git a/plugin/trino-prometheus/src/main/java/io/trino/plugin/prometheus/PrometheusMetadata.java b/plugin/trino-prometheus/src/main/java/io/trino/plugin/prometheus/PrometheusMetadata.java index b1b5e828f218..99f99fcdb841 100644 --- a/plugin/trino-prometheus/src/main/java/io/trino/plugin/prometheus/PrometheusMetadata.java +++ b/plugin/trino-prometheus/src/main/java/io/trino/plugin/prometheus/PrometheusMetadata.java @@ -154,7 +154,7 @@ public ColumnMetadata getColumnMetadata(ConnectorSession session, ConnectorTable } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { PrometheusTableHandle tableHandle = ((PrometheusTableHandle) handle) .withPredicate(constraint.getSummary()); diff --git a/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java b/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java index 4b9268970c17..3b25517d4958 100644 --- a/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java +++ b/plugin/trino-raptor-legacy/src/main/java/io/trino/plugin/raptor/legacy/RaptorMetadata.java @@ -307,7 +307,7 @@ public Map> listTableColumns(ConnectorSess } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle handle, Constraint constraint) { RaptorTableHandle table = (RaptorTableHandle) handle; TupleDomain newDomain = constraint.getSummary().transformKeys(RaptorColumnHandle.class::cast); diff --git a/plugin/trino-redis/src/main/java/io/trino/plugin/redis/RedisMetadata.java b/plugin/trino-redis/src/main/java/io/trino/plugin/redis/RedisMetadata.java index ead3c6e30fa1..55f61bc6210b 100644 --- a/plugin/trino-redis/src/main/java/io/trino/plugin/redis/RedisMetadata.java +++ b/plugin/trino-redis/src/main/java/io/trino/plugin/redis/RedisMetadata.java @@ -188,7 +188,7 @@ public Map getColumnHandles(ConnectorSession session, Conn } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { RedisTableHandle handle = (RedisTableHandle) table; TupleDomain oldDomain = handle.getConstraint(); diff --git a/plugin/trino-thrift/src/main/java/io/trino/plugin/thrift/ThriftMetadata.java b/plugin/trino-thrift/src/main/java/io/trino/plugin/thrift/ThriftMetadata.java index edaf3290ff33..d90b56305051 100644 --- a/plugin/trino-thrift/src/main/java/io/trino/plugin/thrift/ThriftMetadata.java +++ b/plugin/trino-thrift/src/main/java/io/trino/plugin/thrift/ThriftMetadata.java @@ -163,7 +163,7 @@ public Optional resolveIndex(ConnectorSession session, C } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { ThriftTableHandle handle = (ThriftTableHandle) table; diff --git a/plugin/trino-tpch/src/main/java/io/trino/plugin/tpch/TpchMetadata.java b/plugin/trino-tpch/src/main/java/io/trino/plugin/tpch/TpchMetadata.java index f529842f0c0e..2e6c5ae31435 100644 --- a/plugin/trino-tpch/src/main/java/io/trino/plugin/tpch/TpchMetadata.java +++ b/plugin/trino-tpch/src/main/java/io/trino/plugin/tpch/TpchMetadata.java @@ -202,7 +202,7 @@ public TpchTableHandle getTableHandle(ConnectorSession session, SchemaTableName return new TpchTableHandle(tableName.getSchemaName(), tableName.getTableName(), scaleFactor); } - private Set filterValues(Set nullableValues, TpchColumn column, Constraint constraint) + private Set filterValues(Set nullableValues, TpchColumn column, Constraint constraint) { return nullableValues.stream() .filter(convertToPredicate(constraint.getSummary(), toColumnHandle(column))) @@ -470,7 +470,7 @@ else if (tableHandle.getTableName().equals(TpchTable.PART.getTableName())) { } @Override - public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) + public Optional> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) { TpchTableHandle handle = (TpchTableHandle) table; diff --git a/plugin/trino-tpch/src/test/java/io/trino/plugin/tpch/TestTpchMetadata.java b/plugin/trino-tpch/src/test/java/io/trino/plugin/tpch/TestTpchMetadata.java index b637c8cc69e9..816903af0e60 100644 --- a/plugin/trino-tpch/src/test/java/io/trino/plugin/tpch/TestTpchMetadata.java +++ b/plugin/trino-tpch/src/test/java/io/trino/plugin/tpch/TestTpchMetadata.java @@ -173,7 +173,7 @@ private void testTableStats(String schema, TpchTable table, double expectedRo private void testTableStats(String schema, TpchTable table, Constraint constraint, double expectedRowCount) { TpchTableHandle tableHandle = tpchMetadata.getTableHandle(session, new SchemaTableName(schema, table.getTableName())); - Optional> result = tpchMetadata.applyFilter(session, tableHandle, constraint); + Optional> result = tpchMetadata.applyFilter(session, tableHandle, constraint); if (result.isPresent()) { tableHandle = (TpchTableHandle) result.get().getHandle(); } @@ -278,7 +278,7 @@ private void testColumnStats(String schema, TpchTable table, TpchColumn co private void testColumnStats(String schema, TpchTable table, TpchColumn column, Constraint constraint, ColumnStatistics expected) { TpchTableHandle tableHandle = tpchMetadata.getTableHandle(session, new SchemaTableName(schema, table.getTableName())); - Optional> result = tpchMetadata.applyFilter(session, tableHandle, constraint); + Optional> result = tpchMetadata.applyFilter(session, tableHandle, constraint); if (result.isPresent()) { tableHandle = (TpchTableHandle) result.get().getHandle(); } @@ -301,7 +301,7 @@ public void testOrdersOrderStatusPredicatePushdown() TpchTableHandle tableHandle = tpchMetadata.getTableHandle(session, new SchemaTableName("sf1", ORDERS.getTableName())); TupleDomain domain; - ConstraintApplicationResult result; + ConstraintApplicationResult result; domain = fixedValueTupleDomain(tpchMetadata, ORDER_STATUS, utf8Slice("P")); result = tpchMetadata.applyFilter(session, tableHandle, new Constraint(domain, convertToPredicate(domain, ORDER_STATUS), Set.of(tpchMetadata.toColumnHandle(ORDER_STATUS)))).get(); @@ -328,7 +328,7 @@ public void testPartTypeAndPartContainerPredicatePushdown() TpchTableHandle tableHandle = tpchMetadata.getTableHandle(session, new SchemaTableName("sf1", PART.getTableName())); TupleDomain domain; - ConstraintApplicationResult result; + ConstraintApplicationResult result; domain = fixedValueTupleDomain(tpchMetadata, PartColumn.TYPE, utf8Slice("SMALL BRUSHED COPPER")); result = tpchMetadata.applyFilter(session, tableHandle, new Constraint(