Search in sources :

Example 1 with JoinCondition

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

the class PushJoinIntoTableScan method getPushableJoinCondition.

private Optional<JoinCondition> getPushableJoinCondition(Expression conjunct, Set<Symbol> leftSymbols, Set<Symbol> rightSymbols, Context context) {
    if (!(conjunct instanceof ComparisonExpression)) {
        return Optional.empty();
    }
    ComparisonExpression comparison = (ComparisonExpression) conjunct;
    if (!(comparison.getLeft() instanceof SymbolReference) || !(comparison.getRight() instanceof SymbolReference)) {
        return Optional.empty();
    }
    Symbol left = Symbol.from(comparison.getLeft());
    Symbol right = Symbol.from(comparison.getRight());
    ComparisonExpression.Operator operator = comparison.getOperator();
    if (!leftSymbols.contains(left)) {
        // lets try with flipped expression
        Symbol tmp = left;
        left = right;
        right = tmp;
        operator = operator.flip();
    }
    if (leftSymbols.contains(left) && rightSymbols.contains(right)) {
        return Optional.of(new JoinCondition(joinConditionOperator(operator), new Variable(left.getName(), context.getSymbolAllocator().getTypes().get(left)), new Variable(right.getName(), context.getSymbolAllocator().getTypes().get(right))));
    }
    return Optional.empty();
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Variable(io.trino.spi.expression.Variable) SymbolReference(io.trino.sql.tree.SymbolReference) Symbol(io.trino.sql.planner.Symbol) JoinCondition(io.trino.spi.connector.JoinCondition)

Example 2 with JoinCondition

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

the class DefaultJdbcMetadata method applyJoin.

@Override
public Optional<JoinApplicationResult<ConnectorTableHandle>> applyJoin(ConnectorSession session, JoinType joinType, ConnectorTableHandle left, ConnectorTableHandle right, List<JoinCondition> joinConditions, Map<String, ColumnHandle> leftAssignments, Map<String, ColumnHandle> rightAssignments, JoinStatistics statistics) {
    if (!isJoinPushdownEnabled(session)) {
        return Optional.empty();
    }
    JdbcTableHandle leftHandle = flushAttributesAsQuery(session, (JdbcTableHandle) left);
    JdbcTableHandle rightHandle = flushAttributesAsQuery(session, (JdbcTableHandle) right);
    int nextSyntheticColumnId = max(leftHandle.getNextSyntheticColumnId(), rightHandle.getNextSyntheticColumnId());
    ImmutableMap.Builder<JdbcColumnHandle, JdbcColumnHandle> newLeftColumnsBuilder = ImmutableMap.builder();
    for (JdbcColumnHandle column : jdbcClient.getColumns(session, leftHandle)) {
        newLeftColumnsBuilder.put(column, JdbcColumnHandle.builderFrom(column).setColumnName(column.getColumnName() + "_" + nextSyntheticColumnId).build());
        nextSyntheticColumnId++;
    }
    Map<JdbcColumnHandle, JdbcColumnHandle> newLeftColumns = newLeftColumnsBuilder.buildOrThrow();
    ImmutableMap.Builder<JdbcColumnHandle, JdbcColumnHandle> newRightColumnsBuilder = ImmutableMap.builder();
    for (JdbcColumnHandle column : jdbcClient.getColumns(session, rightHandle)) {
        newRightColumnsBuilder.put(column, JdbcColumnHandle.builderFrom(column).setColumnName(column.getColumnName() + "_" + nextSyntheticColumnId).build());
        nextSyntheticColumnId++;
    }
    Map<JdbcColumnHandle, JdbcColumnHandle> newRightColumns = newRightColumnsBuilder.buildOrThrow();
    ImmutableList.Builder<JdbcJoinCondition> jdbcJoinConditions = ImmutableList.builder();
    for (JoinCondition joinCondition : joinConditions) {
        Optional<JdbcColumnHandle> leftColumn = getVariableColumnHandle(leftAssignments, joinCondition.getLeftExpression());
        Optional<JdbcColumnHandle> rightColumn = getVariableColumnHandle(rightAssignments, joinCondition.getRightExpression());
        if (leftColumn.isEmpty() || rightColumn.isEmpty()) {
            return Optional.empty();
        }
        jdbcJoinConditions.add(new JdbcJoinCondition(leftColumn.get(), joinCondition.getOperator(), rightColumn.get()));
    }
    Optional<PreparedQuery> joinQuery = jdbcClient.implementJoin(session, joinType, asPreparedQuery(leftHandle), asPreparedQuery(rightHandle), jdbcJoinConditions.build(), newRightColumns.entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().getColumnName())), newLeftColumns.entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().getColumnName())), statistics);
    if (joinQuery.isEmpty()) {
        return Optional.empty();
    }
    return Optional.of(new JoinApplicationResult<>(new JdbcTableHandle(new JdbcQueryRelationHandle(joinQuery.get()), TupleDomain.all(), ImmutableList.of(), Optional.empty(), OptionalLong.empty(), Optional.of(ImmutableList.<JdbcColumnHandle>builder().addAll(newLeftColumns.values()).addAll(newRightColumns.values()).build()), ImmutableSet.<SchemaTableName>builder().addAll(leftHandle.getAllReferencedTables()).addAll(rightHandle.getAllReferencedTables()).build(), nextSyntheticColumnId), ImmutableMap.copyOf(newLeftColumns), ImmutableMap.copyOf(newRightColumns), false));
}
Also used : ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) SchemaTableName(io.trino.spi.connector.SchemaTableName) Constraint(io.trino.spi.connector.Constraint) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) JoinCondition(io.trino.spi.connector.JoinCondition)

Example 3 with JoinCondition

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

the class PushJoinIntoTableScan method splitFilter.

private FilterSplitResult splitFilter(Expression filter, List<Symbol> leftSymbolsList, List<Symbol> rightSymbolsList, Context context) {
    Set<Symbol> leftSymbols = ImmutableSet.copyOf(leftSymbolsList);
    Set<Symbol> rightSymbols = ImmutableSet.copyOf(rightSymbolsList);
    ImmutableList.Builder<JoinCondition> comparisonConditions = ImmutableList.builder();
    ImmutableList.Builder<Expression> remainingConjuncts = ImmutableList.builder();
    for (Expression conjunct : extractConjuncts(filter)) {
        getPushableJoinCondition(conjunct, leftSymbols, rightSymbols, context).ifPresentOrElse(comparisonConditions::add, () -> remainingConjuncts.add(conjunct));
    }
    return new FilterSplitResult(comparisonConditions.build(), ExpressionUtils.and(remainingConjuncts.build()));
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) Expression(io.trino.sql.tree.Expression) Symbol(io.trino.sql.planner.Symbol) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) JoinCondition(io.trino.spi.connector.JoinCondition)

Example 4 with JoinCondition

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

the class TestPushJoinIntoTableScan method testPushJoinIntoTableScan.

@Test(dataProvider = "testPushJoinIntoTableScanParams")
public void testPushJoinIntoTableScan(JoinNode.Type joinType, Optional<ComparisonExpression.Operator> filterComparisonOperator) {
    try (RuleTester ruleTester = defaultRuleTester()) {
        MockConnectorFactory connectorFactory = createMockConnectorFactory((session, applyJoinType, left, right, joinConditions, leftAssignments, rightAssignments) -> {
            assertThat(((MockConnectorTableHandle) left).getTableName()).isEqualTo(TABLE_A_SCHEMA_TABLE_NAME);
            assertThat(((MockConnectorTableHandle) right).getTableName()).isEqualTo(TABLE_B_SCHEMA_TABLE_NAME);
            Assertions.assertThat(applyJoinType).isEqualTo(toSpiJoinType(joinType));
            JoinCondition.Operator expectedOperator = filterComparisonOperator.map(this::getConditionOperator).orElse(JoinCondition.Operator.EQUAL);
            Assertions.assertThat(joinConditions).containsExactly(new JoinCondition(expectedOperator, COLUMN_A1_VARIABLE, COLUMN_B1_VARIABLE));
            return Optional.of(new JoinApplicationResult<>(JOIN_CONNECTOR_TABLE_HANDLE, JOIN_TABLE_A_COLUMN_MAPPING, JOIN_TABLE_B_COLUMN_MAPPING, false));
        });
        ruleTester.getQueryRunner().createCatalog(MOCK_CATALOG, connectorFactory, ImmutableMap.of());
        ruleTester.assertThat(new PushJoinIntoTableScan(ruleTester.getMetadata())).on(p -> {
            Symbol columnA1Symbol = p.symbol(COLUMN_A1);
            Symbol columnA2Symbol = p.symbol(COLUMN_A2);
            Symbol columnB1Symbol = p.symbol(COLUMN_B1);
            TableScanNode left = p.tableScan(TABLE_A_HANDLE, ImmutableList.of(columnA1Symbol, columnA2Symbol), ImmutableMap.of(columnA1Symbol, COLUMN_A1_HANDLE, columnA2Symbol, COLUMN_A2_HANDLE));
            TableScanNode right = p.tableScan(TABLE_B_HANDLE, ImmutableList.of(columnB1Symbol), ImmutableMap.of(columnB1Symbol, COLUMN_B1_HANDLE));
            if (filterComparisonOperator.isEmpty()) {
                return p.join(joinType, left, right, new JoinNode.EquiJoinClause(columnA1Symbol, columnB1Symbol));
            }
            return p.join(joinType, left, right, new ComparisonExpression(filterComparisonOperator.get(), columnA1Symbol.toSymbolReference(), columnB1Symbol.toSymbolReference()));
        }).withSession(MOCK_SESSION).matches(project(tableScan(JOIN_PUSHDOWN_SCHEMA_TABLE_NAME.getTableName())));
    }
}
Also used : MockConnectorFactory(io.trino.connector.MockConnectorFactory) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) TableScanNode(io.trino.sql.planner.plan.TableScanNode) RuleTester.defaultRuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester) RuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester) MockConnectorTableHandle(io.trino.connector.MockConnectorTableHandle) Symbol(io.trino.sql.planner.Symbol) JoinNode(io.trino.sql.planner.plan.JoinNode) JoinCondition(io.trino.spi.connector.JoinCondition) Test(org.testng.annotations.Test)

Aggregations

JoinCondition (io.trino.spi.connector.JoinCondition)4 Symbol (io.trino.sql.planner.Symbol)3 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)1 MockConnectorFactory (io.trino.connector.MockConnectorFactory)1 MockConnectorTableHandle (io.trino.connector.MockConnectorTableHandle)1 Constraint (io.trino.spi.connector.Constraint)1 SchemaTableName (io.trino.spi.connector.SchemaTableName)1 Variable (io.trino.spi.expression.Variable)1 RuleTester (io.trino.sql.planner.iterative.rule.test.RuleTester)1 RuleTester.defaultRuleTester (io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester)1 JoinNode (io.trino.sql.planner.plan.JoinNode)1 TableScanNode (io.trino.sql.planner.plan.TableScanNode)1 Expression (io.trino.sql.tree.Expression)1 SymbolReference (io.trino.sql.tree.SymbolReference)1 Test (org.testng.annotations.Test)1