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));
}
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);
}
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));
}
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);
}
Aggregations