Search in sources :

Example 6 with ConnectorExpression

use of io.trino.spi.expression.ConnectorExpression in project trino by trinodb.

the class TestExpressionMatching method testExpressionCapture.

@Test
public void testExpressionCapture() {
    ConnectorExpression expression = new Call(createDecimalType(21, 2), new FunctionName("add"), List.of(new Variable("first", createDecimalType(10, 2)), new Variable("second", BIGINT)));
    ExpressionPattern pattern = expressionPattern("foo: decimal(p, s)");
    Match match = pattern.getPattern().match(expression).collect(onlyElement());
    MatchContext matchContext = new MatchContext();
    pattern.resolve(match.captures(), matchContext);
    assertThat(matchContext.keys()).containsExactlyInAnyOrder("p", "s", "foo");
    assertThat(matchContext.get("p")).isEqualTo(21L);
    assertThat(matchContext.get("s")).isEqualTo(2L);
    assertThat(matchContext.get("foo")).isSameAs(expression);
}
Also used : Call(io.trino.spi.expression.Call) FunctionName(io.trino.spi.expression.FunctionName) Variable(io.trino.spi.expression.Variable) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) Match(io.trino.matching.Match) Test(org.testng.annotations.Test)

Example 7 with ConnectorExpression

use of io.trino.spi.expression.ConnectorExpression in project trino by trinodb.

the class TestPruneTableScanColumns method mockApplyProjection.

private Optional<ProjectionApplicationResult<ConnectorTableHandle>> mockApplyProjection(ConnectorSession session, ConnectorTableHandle tableHandle, List<ConnectorExpression> projections, Map<String, ColumnHandle> assignments) {
    MockConnectorTableHandle handle = (MockConnectorTableHandle) tableHandle;
    List<Variable> variables = projections.stream().map(Variable.class::cast).collect(toImmutableList());
    List<ColumnHandle> newColumns = variables.stream().map(variable -> assignments.get(variable.getName())).collect(toImmutableList());
    if (handle.getColumns().isPresent() && newColumns.equals(handle.getColumns().get())) {
        return Optional.empty();
    }
    return Optional.of(new ProjectionApplicationResult<>(new MockConnectorTableHandle(handle.getTableName(), handle.getConstraint(), Optional.of(newColumns)), projections, variables.stream().map(variable -> new Assignment(variable.getName(), assignments.get(variable.getName()), ((MockConnectorColumnHandle) assignments.get(variable.getName())).getType())).collect(toImmutableList()), false));
}
Also used : ColumnMetadata(io.trino.spi.connector.ColumnMetadata) PlanMatchPattern(io.trino.sql.planner.assertions.PlanMatchPattern) Test(org.testng.annotations.Test) Variable(io.trino.spi.expression.Variable) CatalogName(io.trino.connector.CatalogName) ImmutableList(com.google.common.collect.ImmutableList) MockConnectorFactory(io.trino.connector.MockConnectorFactory) TpchTableHandle(io.trino.plugin.tpch.TpchTableHandle) ConnectorTableHandle(io.trino.spi.connector.ConnectorTableHandle) Map(java.util.Map) ColumnHandle(io.trino.spi.connector.ColumnHandle) ProjectionApplicationResult(io.trino.spi.connector.ProjectionApplicationResult) Symbol(io.trino.sql.planner.Symbol) TINY_SCHEMA_NAME(io.trino.plugin.tpch.TpchMetadata.TINY_SCHEMA_NAME) TpchColumnHandle(io.trino.plugin.tpch.TpchColumnHandle) RuleTester.defaultRuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester) ImmutableMap(com.google.common.collect.ImmutableMap) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) TINY_SCALE_FACTOR(io.trino.plugin.tpch.TpchMetadata.TINY_SCALE_FACTOR) MockConnectorColumnHandle(io.trino.connector.MockConnectorColumnHandle) Domain(io.trino.spi.predicate.Domain) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) ConnectorSession(io.trino.spi.connector.ConnectorSession) RuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester) TupleDomain(io.trino.spi.predicate.TupleDomain) SchemaTableName(io.trino.spi.connector.SchemaTableName) TpchTransactionHandle(io.trino.plugin.tpch.TpchTransactionHandle) DOUBLE(io.trino.spi.type.DoubleType.DOUBLE) MockConnectorTableHandle(io.trino.connector.MockConnectorTableHandle) MockConnectorTransactionHandle(io.trino.connector.MockConnectorTransactionHandle) List(java.util.List) TestingSession.testSessionBuilder(io.trino.testing.TestingSession.testSessionBuilder) TableHandle(io.trino.metadata.TableHandle) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) PlanMatchPattern.strictProject(io.trino.sql.planner.assertions.PlanMatchPattern.strictProject) Assignment(io.trino.spi.connector.Assignment) PlanMatchPattern.strictConstrainedTableScan(io.trino.sql.planner.assertions.PlanMatchPattern.strictConstrainedTableScan) Optional(java.util.Optional) TestingColumnHandle(io.trino.testing.TestingMetadata.TestingColumnHandle) PlanBuilder.expression(io.trino.sql.planner.iterative.rule.test.PlanBuilder.expression) DATE(io.trino.spi.type.DateType.DATE) PlanMatchPattern.tableScan(io.trino.sql.planner.assertions.PlanMatchPattern.tableScan) PlanMatchPattern.strictTableScan(io.trino.sql.planner.assertions.PlanMatchPattern.strictTableScan) Assignment(io.trino.spi.connector.Assignment) ColumnHandle(io.trino.spi.connector.ColumnHandle) TpchColumnHandle(io.trino.plugin.tpch.TpchColumnHandle) MockConnectorColumnHandle(io.trino.connector.MockConnectorColumnHandle) TestingColumnHandle(io.trino.testing.TestingMetadata.TestingColumnHandle) Variable(io.trino.spi.expression.Variable) MockConnectorTableHandle(io.trino.connector.MockConnectorTableHandle)

Example 8 with ConnectorExpression

use of io.trino.spi.expression.ConnectorExpression in project trino by trinodb.

the class DefaultJdbcMetadata method applyFilter.

@Override
public Optional<ConstraintApplicationResult<ConnectorTableHandle>> applyFilter(ConnectorSession session, ConnectorTableHandle table, Constraint constraint) {
    JdbcTableHandle handle = (JdbcTableHandle) table;
    if (handle.getSortOrder().isPresent() && handle.getLimit().isPresent()) {
        handle = flushAttributesAsQuery(session, handle);
    }
    TupleDomain<ColumnHandle> oldDomain = handle.getConstraint();
    TupleDomain<ColumnHandle> newDomain = oldDomain.intersect(constraint.getSummary());
    List<String> newConstraintExpressions;
    TupleDomain<ColumnHandle> remainingFilter;
    Optional<ConnectorExpression> remainingExpression;
    if (newDomain.isNone()) {
        newConstraintExpressions = ImmutableList.of();
        remainingFilter = TupleDomain.all();
        remainingExpression = Optional.of(Constant.TRUE);
    } else {
        Map<ColumnHandle, Domain> domains = newDomain.getDomains().orElseThrow();
        List<JdbcColumnHandle> columnHandles = domains.keySet().stream().map(JdbcColumnHandle.class::cast).collect(toImmutableList());
        List<ColumnMapping> columnMappings = jdbcClient.toColumnMappings(session, columnHandles.stream().map(JdbcColumnHandle::getJdbcTypeHandle).collect(toImmutableList()));
        Map<ColumnHandle, Domain> supported = new HashMap<>();
        Map<ColumnHandle, Domain> unsupported = new HashMap<>();
        for (int i = 0; i < columnHandles.size(); i++) {
            JdbcColumnHandle column = columnHandles.get(i);
            ColumnMapping mapping = columnMappings.get(i);
            DomainPushdownResult pushdownResult = mapping.getPredicatePushdownController().apply(session, domains.get(column));
            supported.put(column, pushdownResult.getPushedDown());
            unsupported.put(column, pushdownResult.getRemainingFilter());
        }
        newDomain = TupleDomain.withColumnDomains(supported);
        remainingFilter = TupleDomain.withColumnDomains(unsupported);
        if (isComplexExpressionPushdown(session)) {
            List<String> newExpressions = new ArrayList<>();
            List<ConnectorExpression> remainingExpressions = new ArrayList<>();
            for (ConnectorExpression expression : extractConjuncts(constraint.getExpression())) {
                Optional<String> converted = jdbcClient.convertPredicate(session, expression, constraint.getAssignments());
                if (converted.isPresent()) {
                    newExpressions.add(converted.get());
                } else {
                    remainingExpressions.add(expression);
                }
            }
            newConstraintExpressions = ImmutableSet.<String>builder().addAll(handle.getConstraintExpressions()).addAll(newExpressions).build().asList();
            remainingExpression = Optional.of(and(remainingExpressions));
        } else {
            newConstraintExpressions = ImmutableList.of();
            remainingExpression = Optional.empty();
        }
    }
    if (oldDomain.equals(newDomain) && handle.getConstraintExpressions().equals(newConstraintExpressions)) {
        return Optional.empty();
    }
    handle = new JdbcTableHandle(handle.getRelationHandle(), newDomain, newConstraintExpressions, handle.getSortOrder(), handle.getLimit(), handle.getColumns(), handle.getOtherReferencedTables(), handle.getNextSyntheticColumnId());
    return Optional.of(remainingExpression.isPresent() ? new ConstraintApplicationResult<>(handle, remainingFilter, remainingExpression.get(), false) : new ConstraintApplicationResult<>(handle, remainingFilter, false));
}
Also used : ColumnHandle(io.trino.spi.connector.ColumnHandle) HashMap(java.util.HashMap) ConnectorExpression(io.trino.spi.expression.ConnectorExpression) ArrayList(java.util.ArrayList) Constraint(io.trino.spi.connector.Constraint) ConstraintApplicationResult(io.trino.spi.connector.ConstraintApplicationResult) Domain(io.trino.spi.predicate.Domain) TupleDomain(io.trino.spi.predicate.TupleDomain) DomainPushdownResult(io.trino.plugin.jdbc.PredicatePushdownController.DomainPushdownResult)

Example 9 with ConnectorExpression

use of io.trino.spi.expression.ConnectorExpression in project trino by trinodb.

the class GenericRewrite method rewrite.

@Override
public Optional<String> rewrite(ConnectorExpression expression, Captures captures, RewriteContext<String> context) {
    MatchContext matchContext = new MatchContext();
    expressionPattern.resolve(captures, matchContext);
    StringBuilder rewritten = new StringBuilder();
    Matcher matcher = REWRITE_TOKENS.matcher(rewritePattern);
    while (matcher.find()) {
        String identifier = matcher.group(0);
        Optional<Object> capture = matchContext.getIfPresent(identifier);
        String replacement;
        if (capture.isPresent()) {
            Object value = capture.get();
            if (value instanceof Long) {
                replacement = Long.toString((Long) value);
            } else if (value instanceof ConnectorExpression) {
                Optional<String> rewrittenExpression = context.defaultRewrite((ConnectorExpression) value);
                if (rewrittenExpression.isEmpty()) {
                    return Optional.empty();
                }
                replacement = format("(%s)", rewrittenExpression.get());
            } else {
                throw new UnsupportedOperationException(format("Unsupported value: %s (%s)", value, value.getClass()));
            }
        } else {
            replacement = identifier;
        }
        matcher.appendReplacement(rewritten, quoteReplacement(replacement));
    }
    matcher.appendTail(rewritten);
    return Optional.of(rewritten.toString());
}
Also used : Optional(java.util.Optional) Matcher(java.util.regex.Matcher) ConnectorExpression(io.trino.spi.expression.ConnectorExpression)

Example 10 with ConnectorExpression

use of io.trino.spi.expression.ConnectorExpression in project trino by trinodb.

the class RewriteOr method rewrite.

@Override
public Optional<String> rewrite(Call call, Captures captures, RewriteContext<String> context) {
    List<ConnectorExpression> arguments = call.getArguments();
    verify(!arguments.isEmpty(), "no arguments");
    List<String> terms = new ArrayList<>(arguments.size());
    for (ConnectorExpression argument : arguments) {
        verify(argument.getType() == BOOLEAN, "Unexpected type of OR argument: %s", argument.getType());
        Optional<String> rewritten = context.defaultRewrite(argument);
        if (rewritten.isEmpty()) {
            return Optional.empty();
        }
        terms.add(rewritten.get());
    }
    return Optional.of(terms.stream().collect(Collectors.joining(") OR (", "(", ")")));
}
Also used : ConnectorExpression(io.trino.spi.expression.ConnectorExpression) ArrayList(java.util.ArrayList)

Aggregations

ConnectorExpression (io.trino.spi.expression.ConnectorExpression)29 Variable (io.trino.spi.expression.Variable)21 ColumnHandle (io.trino.spi.connector.ColumnHandle)13 ImmutableList (com.google.common.collect.ImmutableList)11 Test (org.testng.annotations.Test)11 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)10 Assignment (io.trino.spi.connector.Assignment)10 TupleDomain (io.trino.spi.predicate.TupleDomain)10 Map (java.util.Map)10 Optional (java.util.Optional)10 ImmutableMap (com.google.common.collect.ImmutableMap)9 List (java.util.List)9 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)8 Domain (io.trino.spi.predicate.Domain)8 HashMap (java.util.HashMap)8 AggregateFunction (io.trino.spi.connector.AggregateFunction)7 ProjectionApplicationResult (io.trino.spi.connector.ProjectionApplicationResult)7 ArrayList (java.util.ArrayList)7 Objects.requireNonNull (java.util.Objects.requireNonNull)7 Verify.verify (com.google.common.base.Verify.verify)6