use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.
the class TransformUncorrelatedSubqueryToJoin method apply.
@Override
public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context) {
// handle INNER and LEFT correlated join
if (correlatedJoinNode.getType() == INNER || correlatedJoinNode.getType() == LEFT) {
return Result.ofPlanNode(rewriteToJoin(correlatedJoinNode, correlatedJoinNode.getType().toJoinNodeType(), correlatedJoinNode.getFilter()));
}
checkState(correlatedJoinNode.getType() == RIGHT || correlatedJoinNode.getType() == FULL, "unexpected CorrelatedJoin type: " + correlatedJoinNode.getType());
// handle RIGHT and FULL correlated join ON TRUE
JoinNode.Type type;
if (correlatedJoinNode.getType() == RIGHT) {
type = JoinNode.Type.INNER;
} else {
type = JoinNode.Type.LEFT;
}
JoinNode joinNode = rewriteToJoin(correlatedJoinNode, type, TRUE_LITERAL);
if (correlatedJoinNode.getFilter().equals(TRUE_LITERAL)) {
return Result.ofPlanNode(joinNode);
}
// handle RIGHT correlated join on condition other than TRUE
if (correlatedJoinNode.getType() == RIGHT) {
Assignments.Builder assignments = Assignments.builder();
assignments.putIdentities(Sets.intersection(ImmutableSet.copyOf(correlatedJoinNode.getSubquery().getOutputSymbols()), ImmutableSet.copyOf(correlatedJoinNode.getOutputSymbols())));
for (Symbol inputSymbol : Sets.intersection(ImmutableSet.copyOf(correlatedJoinNode.getInput().getOutputSymbols()), ImmutableSet.copyOf(correlatedJoinNode.getOutputSymbols()))) {
assignments.put(inputSymbol, new IfExpression(correlatedJoinNode.getFilter(), inputSymbol.toSymbolReference(), new NullLiteral()));
}
ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), joinNode, assignments.build());
return Result.ofPlanNode(projectNode);
}
// no support for FULL correlated join on condition other than TRUE
return Result.empty();
}
use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.
the class TestTypeValidator method testValidTypeOnlyCoercion.
@Test
public void testValidTypeOnlyCoercion() {
Expression expression = new Cast(columnB.toSymbolReference(), toSqlType(BIGINT));
Assignments assignments = Assignments.builder().put(symbolAllocator.newSymbol(expression, BIGINT), expression).put(symbolAllocator.newSymbol(columnE.toSymbolReference(), VARCHAR), // implicit coercion from varchar(3) to varchar
columnE.toSymbolReference()).build();
PlanNode node = new ProjectNode(newId(), baseTableScan, assignments);
assertTypesValid(node);
}
use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.
the class TestPushProjectionIntoTableScan method createMockFactory.
private MockConnectorFactory createMockFactory(Map<String, ColumnHandle> assignments, Optional<MockConnectorFactory.ApplyProjection> applyProjection) {
List<ColumnMetadata> metadata = assignments.entrySet().stream().map(entry -> new ColumnMetadata(entry.getKey(), ((TpchColumnHandle) entry.getValue()).getType())).collect(toImmutableList());
MockConnectorFactory.Builder builder = MockConnectorFactory.builder().withListSchemaNames(connectorSession -> ImmutableList.of(TEST_SCHEMA)).withListTables((connectorSession, schema) -> TEST_SCHEMA.equals(schema) ? ImmutableList.of(TEST_SCHEMA_TABLE) : ImmutableList.of()).withGetColumns(schemaTableName -> metadata).withGetTableProperties((session, tableHandle) -> {
MockConnectorTableHandle mockTableHandle = (MockConnectorTableHandle) tableHandle;
if (mockTableHandle.getTableName().getTableName().equals(TEST_TABLE)) {
return new ConnectorTableProperties(TupleDomain.all(), Optional.of(new ConnectorTablePartitioning(PARTITIONING_HANDLE, ImmutableList.of(column("col", VARCHAR)))), Optional.empty(), Optional.empty(), ImmutableList.of());
}
return new ConnectorTableProperties();
});
if (applyProjection.isPresent()) {
builder = builder.withApplyProjection(applyProjection.get());
}
return builder.build();
}
use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.
the class TestPushProjectionThroughExchange method testSkipIdentityProjectionIfOutputPresent.
@Test
public void testSkipIdentityProjectionIfOutputPresent() {
// In the following example, the Projection over Exchange has got an identity assignment (a -> a).
// The Projection is pushed down to Exchange's source, and the identity assignment is translated into
// a0 -> a. The assignment is added to the pushed-down Projection because the input symbol 'a' is
// required by the Exchange as a partitioning symbol.
// When all the assignments from the parent Projection are added to the pushed-down Projection,
// this assignment is omitted. Otherwise the doubled assignment would cause an error.
tester().assertThat(new PushProjectionThroughExchange()).on(p -> {
Symbol a = p.symbol("a");
Symbol aTimes5 = p.symbol("a_times_5");
return p.project(Assignments.of(aTimes5, new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Operator.MULTIPLY, new SymbolReference("a"), new LongLiteral("5")), a, a.toSymbolReference()), p.exchange(e -> e.addSource(p.values(a)).addInputsSet(a).fixedHashDistributionParitioningScheme(ImmutableList.of(a), ImmutableList.of(a))));
}).matches(exchange(strictProject(ImmutableMap.of("a_0", expression("a"), "a_times_5", expression("a * 5")), values(ImmutableList.of("a")))));
// In the following example, the Projection over Exchange has got an identity assignment (b -> b).
// The Projection is pushed down to Exchange's source, and the identity assignment is translated into
// a0 -> a. The assignment is added to the pushed-down Projection because the input symbol 'a' is
// required by the Exchange as a partitioning symbol.
// When all the assignments from the parent Projection are added to the pushed-down Projection,
// this assignment is omitted. Otherwise the doubled assignment would cause an error.
tester().assertThat(new PushProjectionThroughExchange()).on(p -> {
Symbol a = p.symbol("a");
Symbol bTimes5 = p.symbol("b_times_5");
Symbol b = p.symbol("b");
return p.project(Assignments.of(bTimes5, new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Operator.MULTIPLY, new SymbolReference("b"), new LongLiteral("5")), b, b.toSymbolReference()), p.exchange(e -> e.addSource(p.values(a)).addInputsSet(a).fixedHashDistributionParitioningScheme(ImmutableList.of(b), ImmutableList.of(b))));
}).matches(exchange(strictProject(ImmutableMap.of("a_0", expression("a"), "a_times_5", expression("a * 5")), values(ImmutableList.of("a")))));
}
use of io.trino.sql.planner.plan.Assignments in project trino by trinodb.
the class LogicalPlanner method getInsertPlan.
private RelationPlan getInsertPlan(Analysis analysis, Table table, Query query, TableHandle tableHandle, List<ColumnHandle> insertColumns, Optional<TableLayout> newTableLayout, Optional<WriterTarget> materializedViewRefreshWriterTarget) {
TableMetadata tableMetadata = metadata.getTableMetadata(session, tableHandle);
Map<NodeRef<LambdaArgumentDeclaration>, Symbol> lambdaDeclarationToSymbolMap = buildLambdaDeclarationToSymbolMap(analysis, symbolAllocator);
RelationPlanner planner = new RelationPlanner(analysis, symbolAllocator, idAllocator, lambdaDeclarationToSymbolMap, plannerContext, Optional.empty(), session, ImmutableMap.of());
RelationPlan plan = planner.process(query, null);
ImmutableList.Builder<Symbol> builder = ImmutableList.builder();
for (int i = 0; i < plan.getFieldMappings().size(); i++) {
if (!plan.getDescriptor().getFieldByIndex(i).isHidden()) {
builder.add(plan.getFieldMappings().get(i));
}
}
List<Symbol> visibleFieldMappings = builder.build();
Map<String, ColumnHandle> columns = metadata.getColumnHandles(session, tableHandle);
Assignments.Builder assignments = Assignments.builder();
boolean supportsMissingColumnsOnInsert = metadata.supportsMissingColumnsOnInsert(session, tableHandle);
ImmutableList.Builder<ColumnMetadata> insertedColumnsBuilder = ImmutableList.builder();
for (ColumnMetadata column : tableMetadata.getColumns()) {
if (column.isHidden()) {
continue;
}
Symbol output = symbolAllocator.newSymbol(column.getName(), column.getType());
int index = insertColumns.indexOf(columns.get(column.getName()));
if (index < 0) {
if (supportsMissingColumnsOnInsert) {
continue;
}
Expression cast = new Cast(new NullLiteral(), toSqlType(column.getType()));
assignments.put(output, cast);
insertedColumnsBuilder.add(column);
} else {
Symbol input = visibleFieldMappings.get(index);
Type tableType = column.getType();
Type queryType = symbolAllocator.getTypes().get(input);
if (queryType.equals(tableType) || typeCoercion.isTypeOnlyCoercion(queryType, tableType)) {
assignments.put(output, input.toSymbolReference());
} else {
Expression cast = noTruncationCast(input.toSymbolReference(), queryType, tableType);
assignments.put(output, cast);
}
insertedColumnsBuilder.add(column);
}
}
ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), plan.getRoot(), assignments.build());
List<ColumnMetadata> insertedColumns = insertedColumnsBuilder.build();
List<Field> fields = insertedColumns.stream().map(column -> Field.newUnqualified(column.getName(), column.getType())).collect(toImmutableList());
Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields)).build();
plan = new RelationPlan(projectNode, scope, projectNode.getOutputSymbols(), Optional.empty());
plan = planner.addRowFilters(table, plan, failIfPredicateIsNotMeet(metadata, session, PERMISSION_DENIED, AccessDeniedException.PREFIX + "Cannot insert row that does not match to a row filter"), node -> {
Scope accessControlScope = analysis.getAccessControlScope(table);
// hidden fields are not accessible in insert
return Scope.builder().like(accessControlScope).withRelationType(accessControlScope.getRelationId(), accessControlScope.getRelationType().withOnlyVisibleFields()).build();
});
List<String> insertedTableColumnNames = insertedColumns.stream().map(ColumnMetadata::getName).collect(toImmutableList());
String catalogName = tableHandle.getCatalogName().getCatalogName();
TableStatisticsMetadata statisticsMetadata = metadata.getStatisticsCollectionMetadataForWrite(session, catalogName, tableMetadata.getMetadata());
if (materializedViewRefreshWriterTarget.isPresent()) {
return createTableWriterPlan(analysis, plan.getRoot(), plan.getFieldMappings(), materializedViewRefreshWriterTarget.get(), insertedTableColumnNames, insertedColumns, newTableLayout, statisticsMetadata);
}
InsertReference insertTarget = new InsertReference(tableHandle, insertedTableColumnNames.stream().map(columns::get).collect(toImmutableList()));
return createTableWriterPlan(analysis, plan.getRoot(), plan.getFieldMappings(), insertTarget, insertedTableColumnNames, insertedColumns, newTableLayout, statisticsMetadata);
}
Aggregations