use of io.trino.sql.tree.Row in project trino by trinodb.
the class PruneCountAggregationOverScalar method apply.
@Override
public Result apply(AggregationNode parent, Captures captures, Context context) {
if (!parent.hasDefaultOutput() || parent.getOutputSymbols().size() != 1) {
return Result.empty();
}
FunctionId countFunctionId = metadata.resolveFunction(context.getSession(), QualifiedName.of("count"), ImmutableList.of()).getFunctionId();
Map<Symbol, AggregationNode.Aggregation> assignments = parent.getAggregations();
for (Map.Entry<Symbol, AggregationNode.Aggregation> entry : assignments.entrySet()) {
AggregationNode.Aggregation aggregation = entry.getValue();
requireNonNull(aggregation, "aggregation is null");
ResolvedFunction resolvedFunction = aggregation.getResolvedFunction();
if (!countFunctionId.equals(resolvedFunction.getFunctionId())) {
return Result.empty();
}
}
if (!assignments.isEmpty() && isScalar(parent.getSource(), context.getLookup())) {
return Result.ofPlanNode(new ValuesNode(parent.getId(), parent.getOutputSymbols(), ImmutableList.of(new Row(ImmutableList.of(new GenericLiteral("BIGINT", "1"))))));
}
return Result.empty();
}
use of io.trino.sql.tree.Row in project trino by trinodb.
the class TestLogicalPlanner method testAllFieldsDereferenceFromNonDeterministic.
@Test
public void testAllFieldsDereferenceFromNonDeterministic() {
FunctionCall randomFunction = new FunctionCall(getQueryRunner().getMetadata().resolveFunction(TEST_SESSION, QualifiedName.of("rand"), ImmutableList.of()).toQualifiedName(), ImmutableList.of());
assertPlan("SELECT (x, x).* FROM (SELECT rand()) T(x)", any(project(ImmutableMap.of("output_1", expression("row[1]"), "output_2", expression("row[2]")), project(ImmutableMap.of("row", expression("ROW(\"rand\", \"rand\")")), values(ImmutableList.of("rand"), ImmutableList.of(ImmutableList.of(randomFunction)))))));
assertPlan("SELECT (rand(), rand()).* FROM (VALUES 1) t(x)", any(project(ImmutableMap.of("output_1", expression("r[1]"), "output_2", expression("r[2]")), values(ImmutableList.of("r"), ImmutableList.of(ImmutableList.of(new Row(ImmutableList.of(randomFunction, randomFunction))))))));
// Ensure the calls to rand() are not duplicated by the ORDER BY clause
assertPlan("SELECT (rand(), rand()).* FROM (VALUES 1, 2) t(x) ORDER BY 1", anyTree(node(SortNode.class, any(project(ImmutableMap.of("output_1", expression("row[1]"), "output_2", expression("row[2]")), values(ImmutableList.of("row"), ImmutableList.of(ImmutableList.of(new Row(ImmutableList.of(randomFunction, randomFunction))), ImmutableList.of(new Row(ImmutableList.of(randomFunction, randomFunction))))))))));
}
use of io.trino.sql.tree.Row in project trino by trinodb.
the class TestLogicalPlanner method testValuesCoercions.
@Test
public void testValuesCoercions() {
assertPlan("VALUES TINYINT '1', REAL '1'", CREATED, anyTree(values(ImmutableList.of("field"), ImmutableList.of(ImmutableList.of(new Cast(new GenericLiteral("TINYINT", "1"), toSqlType(REAL))), ImmutableList.of(new GenericLiteral("REAL", "1"))))));
// rows coerced by field
assertPlan("VALUES (TINYINT '1', REAL '1'), (DOUBLE '2', SMALLINT '2')", CREATED, anyTree(values(ImmutableList.of("field", "field0"), ImmutableList.of(ImmutableList.of(new Cast(new GenericLiteral("TINYINT", "1"), toSqlType(DOUBLE)), new GenericLiteral("REAL", "1")), ImmutableList.of(new GenericLiteral("DOUBLE", "2"), new Cast(new GenericLiteral("SMALLINT", "2"), toSqlType(REAL)))))));
// entry of type other than Row coerced as a whole
assertPlan("VALUES DOUBLE '1', CAST(ROW(2) AS row(bigint))", CREATED, anyTree(values(aliasToIndex(ImmutableList.of("field")), Optional.of(1), Optional.of(ImmutableList.of(new Row(ImmutableList.of(new GenericLiteral("DOUBLE", "1"))), new Cast(new Cast(new Row(ImmutableList.of(new LongLiteral("2"))), toSqlType(RowType.anonymous(ImmutableList.of(BIGINT)))), toSqlType(RowType.anonymous(ImmutableList.of(DOUBLE)))))))));
}
use of io.trino.sql.tree.Row in project trino by trinodb.
the class TestLogicalPlanner method testDoNotPlanUnreferencedRowPatternMeasures.
@Test
public void testDoNotPlanUnreferencedRowPatternMeasures() {
// row pattern measure `label` is not referenced
assertPlan("SELECT val OVER w " + " FROM (VALUES (1, 90)) t(id, value) " + " WINDOW w AS ( " + " ORDER BY id " + " MEASURES " + " RUNNING LAST(value) AS val, " + " CLASSIFIER() AS label " + " ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING " + " PATTERN (A+) " + " DEFINE A AS true " + " )", output(project(patternRecognition(builder -> builder.specification(specification(ImmutableList.of(), ImmutableList.of("id"), ImmutableMap.of("id", ASC_NULLS_LAST))).addMeasure("val", "LAST(value)", INTEGER).rowsPerMatch(WINDOW).frame(windowFrame(ROWS, CURRENT_ROW, Optional.empty(), UNBOUNDED_FOLLOWING, Optional.empty(), Optional.empty())).pattern(new IrQuantified(new IrLabel("A"), oneOrMore(true))).addVariableDefinition(new IrLabel("A"), "true"), values(ImmutableList.of("id", "value"), ImmutableList.of(ImmutableList.of(new LongLiteral("1"), new LongLiteral("90"))))))));
// row pattern measure `label` is not referenced
assertPlan("SELECT min(value) OVER w " + " FROM (VALUES (1, 90)) t(id, value) " + " WINDOW w AS ( " + " ORDER BY id " + " MEASURES CLASSIFIER() AS label " + " ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING " + " PATTERN (A+) " + " DEFINE A AS true " + " )", output(project(patternRecognition(builder -> builder.specification(specification(ImmutableList.of(), ImmutableList.of("id"), ImmutableMap.of("id", ASC_NULLS_LAST))).addFunction("min", functionCall("min", ImmutableList.of("value"))).rowsPerMatch(WINDOW).frame(windowFrame(ROWS, CURRENT_ROW, Optional.empty(), UNBOUNDED_FOLLOWING, Optional.empty(), Optional.empty())).pattern(new IrQuantified(new IrLabel("A"), oneOrMore(true))).addVariableDefinition(new IrLabel("A"), "true"), values(ImmutableList.of("id", "value"), ImmutableList.of(ImmutableList.of(new LongLiteral("1"), new LongLiteral("90"))))))));
}
use of io.trino.sql.tree.Row 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