Search in sources :

Example 1 with JoinUsing

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

the class RelationPlanner method planJoinUnnest.

private RelationPlan planJoinUnnest(RelationPlan leftPlan, Join joinNode, Unnest node) {
    Optional<Expression> filterExpression = Optional.empty();
    if (joinNode.getCriteria().isPresent()) {
        JoinCriteria criteria = joinNode.getCriteria().get();
        if (criteria instanceof NaturalJoin) {
            throw semanticException(NOT_SUPPORTED, joinNode, "Natural join involving UNNEST is not supported");
        }
        if (criteria instanceof JoinUsing) {
            throw semanticException(NOT_SUPPORTED, joinNode, "USING for join involving UNNEST is not supported");
        }
        Expression filter = (Expression) getOnlyElement(criteria.getNodes());
        if (filter.equals(TRUE_LITERAL)) {
            filterExpression = Optional.of(filter);
        } else {
            // TODO rewrite filter to support non-trivial join criteria
            throw semanticException(NOT_SUPPORTED, joinNode, "JOIN involving UNNEST on condition other than TRUE is not supported");
        }
    }
    return planUnnest(newPlanBuilder(leftPlan, analysis, lambdaDeclarationToSymbolMap), node, leftPlan.getFieldMappings(), filterExpression, joinNode.getType(), analysis.getScope(joinNode));
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) Expression(io.trino.sql.tree.Expression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression) JoinCriteria(io.trino.sql.tree.JoinCriteria) JoinUsing(io.trino.sql.tree.JoinUsing) NaturalJoin(io.trino.sql.tree.NaturalJoin)

Example 2 with JoinUsing

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

the class RelationPlanner method planCorrelatedJoin.

private RelationPlan planCorrelatedJoin(Join join, RelationPlan leftPlan, Lateral lateral) {
    PlanBuilder leftPlanBuilder = newPlanBuilder(leftPlan, analysis, lambdaDeclarationToSymbolMap);
    RelationPlan rightPlan = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, Optional.of(leftPlanBuilder.getTranslations()), session, recursiveSubqueries).process(lateral.getQuery(), null);
    PlanBuilder rightPlanBuilder = newPlanBuilder(rightPlan, analysis, lambdaDeclarationToSymbolMap);
    Expression filterExpression;
    if (join.getCriteria().isEmpty()) {
        filterExpression = TRUE_LITERAL;
    } else {
        JoinCriteria criteria = join.getCriteria().get();
        if (criteria instanceof JoinUsing || criteria instanceof NaturalJoin) {
            throw semanticException(NOT_SUPPORTED, join, "Correlated join with criteria other than ON is not supported");
        }
        filterExpression = (Expression) getOnlyElement(criteria.getNodes());
    }
    List<Symbol> outputSymbols = ImmutableList.<Symbol>builder().addAll(leftPlan.getFieldMappings()).addAll(rightPlan.getFieldMappings()).build();
    TranslationMap translationMap = new TranslationMap(outerContext, analysis.getScope(join), analysis, lambdaDeclarationToSymbolMap, outputSymbols).withAdditionalMappings(leftPlanBuilder.getTranslations().getMappings()).withAdditionalMappings(rightPlanBuilder.getTranslations().getMappings());
    Expression rewrittenFilterCondition = translationMap.rewrite(filterExpression);
    PlanBuilder planBuilder = subqueryPlanner.appendCorrelatedJoin(leftPlanBuilder, rightPlanBuilder.getRoot(), lateral.getQuery(), CorrelatedJoinNode.Type.typeConvert(join.getType()), rewrittenFilterCondition, ImmutableMap.of());
    return new RelationPlan(planBuilder.getRoot(), analysis.getScope(join), outputSymbols, outerContext);
}
Also used : ComparisonExpression(io.trino.sql.tree.ComparisonExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) Expression(io.trino.sql.tree.Expression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression) JoinCriteria(io.trino.sql.tree.JoinCriteria) JoinUsing(io.trino.sql.tree.JoinUsing) NaturalJoin(io.trino.sql.tree.NaturalJoin) PlanBuilder.newPlanBuilder(io.trino.sql.planner.PlanBuilder.newPlanBuilder)

Example 3 with JoinUsing

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

the class AstBuilder method visitJoinRelation.

// *************** from clause *****************
@Override
public Node visitJoinRelation(SqlBaseParser.JoinRelationContext context) {
    Relation left = (Relation) visit(context.left);
    Relation right;
    if (context.CROSS() != null) {
        right = (Relation) visit(context.right);
        return new Join(getLocation(context), Join.Type.CROSS, left, right, Optional.empty());
    }
    JoinCriteria criteria;
    if (context.NATURAL() != null) {
        right = (Relation) visit(context.right);
        criteria = new NaturalJoin();
    } else {
        right = (Relation) visit(context.rightRelation);
        if (context.joinCriteria().ON() != null) {
            criteria = new JoinOn((Expression) visit(context.joinCriteria().booleanExpression()));
        } else if (context.joinCriteria().USING() != null) {
            criteria = new JoinUsing(visit(context.joinCriteria().identifier(), Identifier.class));
        } else {
            throw new IllegalArgumentException("Unsupported join criteria");
        }
    }
    Join.Type joinType;
    if (context.joinType().LEFT() != null) {
        joinType = Join.Type.LEFT;
    } else if (context.joinType().RIGHT() != null) {
        joinType = Join.Type.RIGHT;
    } else if (context.joinType().FULL() != null) {
        joinType = Join.Type.FULL;
    } else {
        joinType = Join.Type.INNER;
    }
    return new Join(getLocation(context), joinType, left, right, Optional.of(criteria));
}
Also used : AliasedRelation(io.trino.sql.tree.AliasedRelation) SampledRelation(io.trino.sql.tree.SampledRelation) Relation(io.trino.sql.tree.Relation) PatternRecognitionRelation(io.trino.sql.tree.PatternRecognitionRelation) Identifier(io.trino.sql.tree.Identifier) DereferenceExpression(io.trino.sql.tree.DereferenceExpression) LogicalExpression(io.trino.sql.tree.LogicalExpression) SearchedCaseExpression(io.trino.sql.tree.SearchedCaseExpression) BindExpression(io.trino.sql.tree.BindExpression) CoalesceExpression(io.trino.sql.tree.CoalesceExpression) QuantifiedComparisonExpression(io.trino.sql.tree.QuantifiedComparisonExpression) SimpleCaseExpression(io.trino.sql.tree.SimpleCaseExpression) SubqueryExpression(io.trino.sql.tree.SubqueryExpression) LambdaExpression(io.trino.sql.tree.LambdaExpression) SubscriptExpression(io.trino.sql.tree.SubscriptExpression) NullIfExpression(io.trino.sql.tree.NullIfExpression) ArithmeticUnaryExpression(io.trino.sql.tree.ArithmeticUnaryExpression) InListExpression(io.trino.sql.tree.InListExpression) NotExpression(io.trino.sql.tree.NotExpression) ArithmeticBinaryExpression(io.trino.sql.tree.ArithmeticBinaryExpression) TryExpression(io.trino.sql.tree.TryExpression) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) IfExpression(io.trino.sql.tree.IfExpression) Expression(io.trino.sql.tree.Expression) JoinCriteria(io.trino.sql.tree.JoinCriteria) NaturalJoin(io.trino.sql.tree.NaturalJoin) Join(io.trino.sql.tree.Join) JoinUsing(io.trino.sql.tree.JoinUsing) NaturalJoin(io.trino.sql.tree.NaturalJoin) JoinOn(io.trino.sql.tree.JoinOn)

Example 4 with JoinUsing

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

the class RelationPlanner method planJoinUsing.

private RelationPlan planJoinUsing(Join node, RelationPlan left, RelationPlan right) {
    /* Given: l JOIN r USING (k1, ..., kn)

           produces:

            - project
                    coalesce(l.k1, r.k1)
                    ...,
                    coalesce(l.kn, r.kn)
                    l.v1,
                    ...,
                    l.vn,
                    r.v1,
                    ...,
                    r.vn
              - join (l.k1 = r.k1 and ... l.kn = r.kn)
                    - project
                        cast(l.k1 as commonType(l.k1, r.k1))
                        ...
                    - project
                        cast(rl.k1 as commonType(l.k1, r.k1))

            If casts are redundant (due to column type and common type being equal),
            they will be removed by optimization passes.
        */
    List<Identifier> joinColumns = ((JoinUsing) node.getCriteria().orElseThrow()).getColumns();
    Analysis.JoinUsingAnalysis joinAnalysis = analysis.getJoinUsing(node);
    ImmutableList.Builder<JoinNode.EquiJoinClause> clauses = ImmutableList.builder();
    Map<Identifier, Symbol> leftJoinColumns = new HashMap<>();
    Map<Identifier, Symbol> rightJoinColumns = new HashMap<>();
    Assignments.Builder leftCoercions = Assignments.builder();
    Assignments.Builder rightCoercions = Assignments.builder();
    leftCoercions.putIdentities(left.getRoot().getOutputSymbols());
    rightCoercions.putIdentities(right.getRoot().getOutputSymbols());
    for (int i = 0; i < joinColumns.size(); i++) {
        Identifier identifier = joinColumns.get(i);
        Type type = analysis.getType(identifier);
        // compute the coercion for the field on the left to the common supertype of left & right
        Symbol leftOutput = symbolAllocator.newSymbol(identifier, type);
        int leftField = joinAnalysis.getLeftJoinFields().get(i);
        leftCoercions.put(leftOutput, new Cast(left.getSymbol(leftField).toSymbolReference(), toSqlType(type), false, typeCoercion.isTypeOnlyCoercion(left.getDescriptor().getFieldByIndex(leftField).getType(), type)));
        leftJoinColumns.put(identifier, leftOutput);
        // compute the coercion for the field on the right to the common supertype of left & right
        Symbol rightOutput = symbolAllocator.newSymbol(identifier, type);
        int rightField = joinAnalysis.getRightJoinFields().get(i);
        rightCoercions.put(rightOutput, new Cast(right.getSymbol(rightField).toSymbolReference(), toSqlType(type), false, typeCoercion.isTypeOnlyCoercion(right.getDescriptor().getFieldByIndex(rightField).getType(), type)));
        rightJoinColumns.put(identifier, rightOutput);
        clauses.add(new JoinNode.EquiJoinClause(leftOutput, rightOutput));
    }
    ProjectNode leftCoercion = new ProjectNode(idAllocator.getNextId(), left.getRoot(), leftCoercions.build());
    ProjectNode rightCoercion = new ProjectNode(idAllocator.getNextId(), right.getRoot(), rightCoercions.build());
    JoinNode join = new JoinNode(idAllocator.getNextId(), JoinNode.Type.typeConvert(node.getType()), leftCoercion, rightCoercion, clauses.build(), leftCoercion.getOutputSymbols(), rightCoercion.getOutputSymbols(), false, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(), Optional.empty());
    // Add a projection to produce the outputs of the columns in the USING clause,
    // which are defined as coalesce(l.k, r.k)
    Assignments.Builder assignments = Assignments.builder();
    ImmutableList.Builder<Symbol> outputs = ImmutableList.builder();
    for (Identifier column : joinColumns) {
        Symbol output = symbolAllocator.newSymbol(column, analysis.getType(column));
        outputs.add(output);
        assignments.put(output, new CoalesceExpression(leftJoinColumns.get(column).toSymbolReference(), rightJoinColumns.get(column).toSymbolReference()));
    }
    for (int field : joinAnalysis.getOtherLeftFields()) {
        Symbol symbol = left.getFieldMappings().get(field);
        outputs.add(symbol);
        assignments.put(symbol, symbol.toSymbolReference());
    }
    for (int field : joinAnalysis.getOtherRightFields()) {
        Symbol symbol = right.getFieldMappings().get(field);
        outputs.add(symbol);
        assignments.put(symbol, symbol.toSymbolReference());
    }
    return new RelationPlan(new ProjectNode(idAllocator.getNextId(), join, assignments.build()), analysis.getScope(node), outputs.build(), outerContext);
}
Also used : Cast(io.trino.sql.tree.Cast) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) CorrelatedJoinNode(io.trino.sql.planner.plan.CorrelatedJoinNode) JoinNode(io.trino.sql.planner.plan.JoinNode) Assignments(io.trino.sql.planner.plan.Assignments) JoinUsing(io.trino.sql.tree.JoinUsing) RelationType(io.trino.sql.analyzer.RelationType) RowType(io.trino.spi.type.RowType) TypeSignatureTranslator.toSqlType(io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType) Type(io.trino.spi.type.Type) Identifier(io.trino.sql.tree.Identifier) UnnestAnalysis(io.trino.sql.analyzer.Analysis.UnnestAnalysis) Analysis(io.trino.sql.analyzer.Analysis) ProjectNode(io.trino.sql.planner.plan.ProjectNode) CoalesceExpression(io.trino.sql.tree.CoalesceExpression)

Aggregations

CoalesceExpression (io.trino.sql.tree.CoalesceExpression)4 JoinUsing (io.trino.sql.tree.JoinUsing)4 ComparisonExpression (io.trino.sql.tree.ComparisonExpression)3 Expression (io.trino.sql.tree.Expression)3 JoinCriteria (io.trino.sql.tree.JoinCriteria)3 NaturalJoin (io.trino.sql.tree.NaturalJoin)3 SubqueryExpression (io.trino.sql.tree.SubqueryExpression)3 Identifier (io.trino.sql.tree.Identifier)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)1 RowType (io.trino.spi.type.RowType)1 Type (io.trino.spi.type.Type)1 Analysis (io.trino.sql.analyzer.Analysis)1 UnnestAnalysis (io.trino.sql.analyzer.Analysis.UnnestAnalysis)1 RelationType (io.trino.sql.analyzer.RelationType)1 TypeSignatureTranslator.toSqlType (io.trino.sql.analyzer.TypeSignatureTranslator.toSqlType)1 PlanBuilder.newPlanBuilder (io.trino.sql.planner.PlanBuilder.newPlanBuilder)1 Assignments (io.trino.sql.planner.plan.Assignments)1 CorrelatedJoinNode (io.trino.sql.planner.plan.CorrelatedJoinNode)1 JoinNode (io.trino.sql.planner.plan.JoinNode)1