Search in sources :

Example 41 with QualifiedName

use of io.trino.sql.tree.QualifiedName in project trino by trinodb.

the class RelationPlanner method planJoin.

private RelationPlan planJoin(Expression criteria, Join.Type type, Scope scope, RelationPlan leftPlan, RelationPlan rightPlan, Analysis.SubqueryAnalysis subqueries) {
    // NOTE: symbols must be in the same order as the outputDescriptor
    List<Symbol> outputSymbols = ImmutableList.<Symbol>builder().addAll(leftPlan.getFieldMappings()).addAll(rightPlan.getFieldMappings()).build();
    PlanBuilder leftPlanBuilder = newPlanBuilder(leftPlan, analysis, lambdaDeclarationToSymbolMap).withScope(scope, outputSymbols);
    PlanBuilder rightPlanBuilder = newPlanBuilder(rightPlan, analysis, lambdaDeclarationToSymbolMap).withScope(scope, outputSymbols);
    ImmutableList.Builder<JoinNode.EquiJoinClause> equiClauses = ImmutableList.builder();
    List<Expression> complexJoinExpressions = new ArrayList<>();
    List<Expression> postInnerJoinConditions = new ArrayList<>();
    RelationType left = leftPlan.getDescriptor();
    RelationType right = rightPlan.getDescriptor();
    if (type != CROSS && type != IMPLICIT) {
        List<Expression> leftComparisonExpressions = new ArrayList<>();
        List<Expression> rightComparisonExpressions = new ArrayList<>();
        List<ComparisonExpression.Operator> joinConditionComparisonOperators = new ArrayList<>();
        for (Expression conjunct : ExpressionUtils.extractConjuncts(criteria)) {
            if (!isEqualComparisonExpression(conjunct) && type != INNER) {
                complexJoinExpressions.add(conjunct);
                continue;
            }
            Set<QualifiedName> dependencies = SymbolsExtractor.extractNames(conjunct, analysis.getColumnReferences());
            if (dependencies.stream().allMatch(left::canResolve) || dependencies.stream().allMatch(right::canResolve)) {
                // If the conjunct can be evaluated entirely with the inputs on either side of the join, add
                // it to the list complex expressions and let the optimizers figure out how to push it down later.
                complexJoinExpressions.add(conjunct);
            } else if (conjunct instanceof ComparisonExpression) {
                Expression firstExpression = ((ComparisonExpression) conjunct).getLeft();
                Expression secondExpression = ((ComparisonExpression) conjunct).getRight();
                ComparisonExpression.Operator comparisonOperator = ((ComparisonExpression) conjunct).getOperator();
                Set<QualifiedName> firstDependencies = SymbolsExtractor.extractNames(firstExpression, analysis.getColumnReferences());
                Set<QualifiedName> secondDependencies = SymbolsExtractor.extractNames(secondExpression, analysis.getColumnReferences());
                if (firstDependencies.stream().allMatch(left::canResolve) && secondDependencies.stream().allMatch(right::canResolve)) {
                    leftComparisonExpressions.add(firstExpression);
                    rightComparisonExpressions.add(secondExpression);
                    joinConditionComparisonOperators.add(comparisonOperator);
                } else if (firstDependencies.stream().allMatch(right::canResolve) && secondDependencies.stream().allMatch(left::canResolve)) {
                    leftComparisonExpressions.add(secondExpression);
                    rightComparisonExpressions.add(firstExpression);
                    joinConditionComparisonOperators.add(comparisonOperator.flip());
                } else {
                    // the case when we mix symbols from both left and right join side on either side of condition.
                    complexJoinExpressions.add(conjunct);
                }
            } else {
                complexJoinExpressions.add(conjunct);
            }
        }
        leftPlanBuilder = subqueryPlanner.handleSubqueries(leftPlanBuilder, leftComparisonExpressions, subqueries);
        rightPlanBuilder = subqueryPlanner.handleSubqueries(rightPlanBuilder, rightComparisonExpressions, subqueries);
        // Add projections for join criteria
        leftPlanBuilder = leftPlanBuilder.appendProjections(leftComparisonExpressions, symbolAllocator, idAllocator);
        rightPlanBuilder = rightPlanBuilder.appendProjections(rightComparisonExpressions, symbolAllocator, idAllocator);
        QueryPlanner.PlanAndMappings leftCoercions = coerce(leftPlanBuilder, leftComparisonExpressions, analysis, idAllocator, symbolAllocator, typeCoercion);
        leftPlanBuilder = leftCoercions.getSubPlan();
        QueryPlanner.PlanAndMappings rightCoercions = coerce(rightPlanBuilder, rightComparisonExpressions, analysis, idAllocator, symbolAllocator, typeCoercion);
        rightPlanBuilder = rightCoercions.getSubPlan();
        for (int i = 0; i < leftComparisonExpressions.size(); i++) {
            if (joinConditionComparisonOperators.get(i) == ComparisonExpression.Operator.EQUAL) {
                Symbol leftSymbol = leftCoercions.get(leftComparisonExpressions.get(i));
                Symbol rightSymbol = rightCoercions.get(rightComparisonExpressions.get(i));
                equiClauses.add(new JoinNode.EquiJoinClause(leftSymbol, rightSymbol));
            } else {
                postInnerJoinConditions.add(new ComparisonExpression(joinConditionComparisonOperators.get(i), leftCoercions.get(leftComparisonExpressions.get(i)).toSymbolReference(), rightCoercions.get(rightComparisonExpressions.get(i)).toSymbolReference()));
            }
        }
    }
    PlanNode root = new JoinNode(idAllocator.getNextId(), JoinNode.Type.typeConvert(type), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), leftPlanBuilder.getRoot().getOutputSymbols(), rightPlanBuilder.getRoot().getOutputSymbols(), false, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
    if (type != INNER) {
        for (Expression complexExpression : complexJoinExpressions) {
            Set<QualifiedName> dependencies = SymbolsExtractor.extractNamesNoSubqueries(complexExpression, analysis.getColumnReferences());
            // t JOIN u ON t.x + u.x = (...) get's planned on an arbitrary side
            if (dependencies.stream().allMatch(left::canResolve)) {
                leftPlanBuilder = subqueryPlanner.handleSubqueries(leftPlanBuilder, complexExpression, subqueries);
            } else {
                rightPlanBuilder = subqueryPlanner.handleSubqueries(rightPlanBuilder, complexExpression, subqueries);
            }
        }
    }
    TranslationMap translationMap = new TranslationMap(outerContext, scope, analysis, lambdaDeclarationToSymbolMap, outputSymbols).withAdditionalMappings(leftPlanBuilder.getTranslations().getMappings()).withAdditionalMappings(rightPlanBuilder.getTranslations().getMappings());
    if (type != INNER && !complexJoinExpressions.isEmpty()) {
        Expression joinedFilterCondition = ExpressionUtils.and(complexJoinExpressions);
        Expression rewrittenFilterCondition = translationMap.rewrite(joinedFilterCondition);
        root = new JoinNode(idAllocator.getNextId(), JoinNode.Type.typeConvert(type), leftPlanBuilder.getRoot(), rightPlanBuilder.getRoot(), equiClauses.build(), leftPlanBuilder.getRoot().getOutputSymbols(), rightPlanBuilder.getRoot().getOutputSymbols(), false, Optional.of(rewrittenFilterCondition), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
    }
    if (type == INNER) {
        // rewrite all the other conditions using output symbols from left + right plan node.
        PlanBuilder rootPlanBuilder = new PlanBuilder(translationMap, root);
        rootPlanBuilder = subqueryPlanner.handleSubqueries(rootPlanBuilder, complexJoinExpressions, subqueries);
        for (Expression expression : complexJoinExpressions) {
            postInnerJoinConditions.add(rootPlanBuilder.rewrite(expression));
        }
        root = rootPlanBuilder.getRoot();
        Expression postInnerJoinCriteria;
        if (!postInnerJoinConditions.isEmpty()) {
            postInnerJoinCriteria = ExpressionUtils.and(postInnerJoinConditions);
            root = new FilterNode(idAllocator.getNextId(), root, postInnerJoinCriteria);
        }
    }
    return new RelationPlan(root, scope, outputSymbols, outerContext);
}
Also used : Set(java.util.Set) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) AggregationNode.singleGroupingSet(io.trino.sql.planner.plan.AggregationNode.singleGroupingSet) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) FilterNode(io.trino.sql.planner.plan.FilterNode) ArrayList(java.util.ArrayList) PlanBuilder.newPlanBuilder(io.trino.sql.planner.PlanBuilder.newPlanBuilder) PlanNode(io.trino.sql.planner.plan.PlanNode) RelationType(io.trino.sql.analyzer.RelationType) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) JoinNode(io.trino.sql.planner.plan.JoinNode) QualifiedName(io.trino.sql.tree.QualifiedName) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) Expression(io.trino.sql.tree.Expression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression)

Example 42 with QualifiedName

use of io.trino.sql.tree.QualifiedName in project trino by trinodb.

the class TestSqlParser method testCreateTableAsWith.

@Test
public void testCreateTableAsWith() {
    String queryParenthesizedWith = "CREATE TABLE foo " + "AS " + "( WITH t(x) AS (VALUES 1) " + "TABLE t ) " + "WITH NO DATA";
    String queryUnparenthesizedWith = "CREATE TABLE foo " + "AS " + "WITH t(x) AS (VALUES 1) " + "TABLE t " + "WITH NO DATA";
    String queryParenthesizedWithHasAlias = "CREATE TABLE foo(a) " + "AS " + "( WITH t(x) AS (VALUES 1) " + "TABLE t ) " + "WITH NO DATA";
    String queryUnparenthesizedWithHasAlias = "CREATE TABLE foo(a) " + "AS " + "WITH t(x) AS (VALUES 1) " + "TABLE t " + "WITH NO DATA";
    QualifiedName table = QualifiedName.of("foo");
    Query query = new Query(Optional.of(new With(false, ImmutableList.of(new WithQuery(identifier("t"), query(new Values(ImmutableList.of(new LongLiteral("1")))), Optional.of(ImmutableList.of(identifier("x"))))))), new Table(QualifiedName.of("t")), Optional.empty(), Optional.empty(), Optional.empty());
    assertStatement(queryParenthesizedWith, new CreateTableAsSelect(table, query, false, ImmutableList.of(), false, Optional.empty(), Optional.empty()));
    assertStatement(queryUnparenthesizedWith, new CreateTableAsSelect(table, query, false, ImmutableList.of(), false, Optional.empty(), Optional.empty()));
    assertStatement(queryParenthesizedWithHasAlias, new CreateTableAsSelect(table, query, false, ImmutableList.of(), false, Optional.of(ImmutableList.of(new Identifier("a"))), Optional.empty()));
    assertStatement(queryUnparenthesizedWithHasAlias, new CreateTableAsSelect(table, query, false, ImmutableList.of(), false, Optional.of(ImmutableList.of(new Identifier("a"))), Optional.empty()));
}
Also used : CreateTable(io.trino.sql.tree.CreateTable) DropTable(io.trino.sql.tree.DropTable) Table(io.trino.sql.tree.Table) TruncateTable(io.trino.sql.tree.TruncateTable) RenameTable(io.trino.sql.tree.RenameTable) QueryUtil.quotedIdentifier(io.trino.sql.QueryUtil.quotedIdentifier) Identifier(io.trino.sql.tree.Identifier) QueryUtil.simpleQuery(io.trino.sql.QueryUtil.simpleQuery) Query(io.trino.sql.tree.Query) WithQuery(io.trino.sql.tree.WithQuery) LongLiteral(io.trino.sql.tree.LongLiteral) WithQuery(io.trino.sql.tree.WithQuery) QualifiedName(io.trino.sql.tree.QualifiedName) CreateTableAsSelect(io.trino.sql.tree.CreateTableAsSelect) Values(io.trino.sql.tree.Values) With(io.trino.sql.tree.With) Test(org.junit.jupiter.api.Test)

Aggregations

QualifiedName (io.trino.sql.tree.QualifiedName)42 Test (org.testng.annotations.Test)29 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)7 FunctionCall (io.trino.sql.tree.FunctionCall)7 Identifier (io.trino.sql.tree.Identifier)7 ImmutableList (com.google.common.collect.ImmutableList)4 AllColumns (io.trino.sql.tree.AllColumns)4 Test (org.junit.jupiter.api.Test)4 ImmutableMap (com.google.common.collect.ImmutableMap)3 ImmutableSet (com.google.common.collect.ImmutableSet)3 MetadataManager.createTestMetadataManager (io.trino.metadata.MetadataManager.createTestMetadataManager)3 ResolvedFunction (io.trino.metadata.ResolvedFunction)3 ASC_NULLS_LAST (io.trino.spi.connector.SortOrder.ASC_NULLS_LAST)3 BIGINT (io.trino.spi.type.BigintType.BIGINT)3 QueryUtil.quotedIdentifier (io.trino.sql.QueryUtil.quotedIdentifier)3 TypeSignatureProvider.fromTypes (io.trino.sql.analyzer.TypeSignatureProvider.fromTypes)3 OrderingScheme (io.trino.sql.planner.OrderingScheme)3 PlanMatchPattern.functionCall (io.trino.sql.planner.assertions.PlanMatchPattern.functionCall)3 PlanMatchPattern.patternRecognition (io.trino.sql.planner.assertions.PlanMatchPattern.patternRecognition)3 PlanMatchPattern.specification (io.trino.sql.planner.assertions.PlanMatchPattern.specification)3