use of io.prestosql.sql.tree.Cast in project hetu-core by openlookeng.
the class AggregationRewriteWithCube method rewrite.
public PlanNode rewrite(AggregationNode originalAggregationNode, PlanNode filterNode) {
QualifiedObjectName starTreeTableName = QualifiedObjectName.valueOf(cubeMetadata.getCubeName());
TableHandle cubeTableHandle = metadata.getTableHandle(session, starTreeTableName).orElseThrow(() -> new CubeNotFoundException(starTreeTableName.toString()));
Map<String, ColumnHandle> cubeColumnsMap = metadata.getColumnHandles(session, cubeTableHandle);
TableMetadata cubeTableMetadata = metadata.getTableMetadata(session, cubeTableHandle);
List<ColumnMetadata> cubeColumnMetadataList = cubeTableMetadata.getColumns();
// Add group by
List<Symbol> groupings = new ArrayList<>(originalAggregationNode.getGroupingKeys().size());
for (Symbol symbol : originalAggregationNode.getGroupingKeys()) {
Object column = symbolMappings.get(symbol.getName());
if (column instanceof ColumnHandle) {
groupings.add(new Symbol(((ColumnHandle) column).getColumnName()));
}
}
Set<String> cubeGroups = cubeMetadata.getGroup();
boolean exactGroupsMatch = false;
if (groupings.size() == cubeGroups.size()) {
exactGroupsMatch = groupings.stream().map(Symbol::getName).map(String::toLowerCase).allMatch(cubeGroups::contains);
}
CubeRewriteResult cubeRewriteResult = createScanNode(originalAggregationNode, filterNode, cubeTableHandle, cubeColumnsMap, cubeColumnMetadataList, exactGroupsMatch);
PlanNode planNode = cubeRewriteResult.getTableScanNode();
// Add filter node
if (filterNode != null) {
Expression expression = castToExpression(((FilterNode) filterNode).getPredicate());
expression = rewriteExpression(expression, rewrittenMappings);
planNode = new FilterNode(idAllocator.getNextId(), planNode, castToRowExpression(expression));
}
if (!exactGroupsMatch) {
Map<Symbol, Symbol> cubeScanToAggOutputMap = new HashMap<>();
// Rewrite AggregationNode using Cube table
ImmutableMap.Builder<Symbol, AggregationNode.Aggregation> aggregationsBuilder = ImmutableMap.builder();
for (CubeRewriteResult.AggregatorSource aggregatorSource : cubeRewriteResult.getAggregationColumns()) {
ColumnHandle cubeColHandle = cubeRewriteResult.getTableScanNode().getAssignments().get(aggregatorSource.getScanSymbol());
ColumnMetadata cubeColumnMetadata = cubeRewriteResult.getSymbolMetadataMap().get(aggregatorSource.getScanSymbol());
Type type = cubeColumnMetadata.getType();
AggregationSignature aggregationSignature = cubeMetadata.getAggregationSignature(cubeColumnMetadata.getName()).orElseThrow(() -> new ColumnNotFoundException(new SchemaTableName(starTreeTableName.getSchemaName(), starTreeTableName.getObjectName()), cubeColHandle.getColumnName()));
String aggFunction = COUNT.getName().equals(aggregationSignature.getFunction()) ? "sum" : aggregationSignature.getFunction();
SymbolReference argument = toSymbolReference(aggregatorSource.getScanSymbol());
FunctionHandle functionHandle = metadata.getFunctionAndTypeManager().lookupFunction(aggFunction, TypeSignatureProvider.fromTypeSignatures(type.getTypeSignature()));
cubeScanToAggOutputMap.put(aggregatorSource.getScanSymbol(), aggregatorSource.getOriginalAggSymbol());
aggregationsBuilder.put(aggregatorSource.getOriginalAggSymbol(), new AggregationNode.Aggregation(new CallExpression(aggFunction, functionHandle, type, ImmutableList.of(OriginalExpressionUtils.castToRowExpression(argument))), ImmutableList.of(OriginalExpressionUtils.castToRowExpression(argument)), false, Optional.empty(), Optional.empty(), Optional.empty()));
}
List<Symbol> groupingKeys = originalAggregationNode.getGroupingKeys().stream().map(Symbol::getName).map(rewrittenMappings::get).collect(Collectors.toList());
planNode = new AggregationNode(idAllocator.getNextId(), planNode, aggregationsBuilder.build(), singleGroupingSet(groupingKeys), ImmutableList.of(), AggregationNode.Step.SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty());
AggregationNode aggNode = (AggregationNode) planNode;
if (!cubeRewriteResult.getAvgAggregationColumns().isEmpty()) {
if (!cubeRewriteResult.getComputeAvgDividingSumByCount()) {
Map<Symbol, Expression> aggregateAssignments = new HashMap<>();
for (CubeRewriteResult.AggregatorSource aggregatorSource : cubeRewriteResult.getAggregationColumns()) {
aggregateAssignments.put(aggregatorSource.getOriginalAggSymbol(), toSymbolReference(aggregatorSource.getScanSymbol()));
}
planNode = new ProjectNode(idAllocator.getNextId(), aggNode, new Assignments(aggregateAssignments.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> castToRowExpression(entry.getValue())))));
} else {
// If there was an AVG aggregation, map it to AVG = SUM/COUNT
Map<Symbol, Expression> projections = new HashMap<>();
aggNode.getGroupingKeys().forEach(symbol -> projections.put(symbol, toSymbolReference(symbol)));
aggNode.getAggregations().keySet().stream().filter(symbol -> symbolMappings.containsValue(symbol.getName())).forEach(aggSymbol -> projections.put(aggSymbol, toSymbolReference(aggSymbol)));
// Add AVG = SUM / COUNT
for (CubeRewriteResult.AverageAggregatorSource avgAggSource : cubeRewriteResult.getAvgAggregationColumns()) {
Symbol sumSymbol = cubeScanToAggOutputMap.get(avgAggSource.getSum());
Symbol countSymbol = cubeScanToAggOutputMap.get(avgAggSource.getCount());
Type avgResultType = typeProvider.get(avgAggSource.getOriginalAggSymbol());
ArithmeticBinaryExpression division = new ArithmeticBinaryExpression(ArithmeticBinaryExpression.Operator.DIVIDE, new Cast(toSymbolReference(sumSymbol), avgResultType.getTypeSignature().toString()), new Cast(toSymbolReference(countSymbol), avgResultType.getTypeSignature().toString()));
projections.put(avgAggSource.getOriginalAggSymbol(), division);
}
planNode = new ProjectNode(idAllocator.getNextId(), aggNode, new Assignments(projections.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> castToRowExpression(entry.getValue())))));
}
}
}
// Safety check to remove redundant symbols and rename original column names to intermediate names
if (!planNode.getOutputSymbols().equals(originalAggregationNode.getOutputSymbols())) {
// Map new symbol names to the old symbols
Map<Symbol, Expression> assignments = new HashMap<>();
Set<Symbol> planNodeOutput = new HashSet<>(planNode.getOutputSymbols());
for (Symbol originalAggOutputSymbol : originalAggregationNode.getOutputSymbols()) {
if (!planNodeOutput.contains(originalAggOutputSymbol)) {
// Must be grouping key
assignments.put(originalAggOutputSymbol, toSymbolReference(rewrittenMappings.get(originalAggOutputSymbol.getName())));
} else {
// Should be an expression and must have the same name in the new plan node
assignments.put(originalAggOutputSymbol, toSymbolReference(originalAggOutputSymbol));
}
}
planNode = new ProjectNode(idAllocator.getNextId(), planNode, new Assignments(assignments.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> castToRowExpression(entry.getValue())))));
}
return planNode;
}
use of io.prestosql.sql.tree.Cast in project hetu-core by openlookeng.
the class SetOperationNodeTranslator method appendMarkers.
private static PlanNode appendMarkers(PlanNodeIdAllocator idAllocator, PlanSymbolAllocator planSymbolAllocator, PlanNode source, int markerIndex, List<Symbol> markers, Map<Symbol, SymbolReference> projections) {
Assignments.Builder assignments = Assignments.builder();
// add existing intersect symbols to projection
for (Map.Entry<Symbol, SymbolReference> entry : projections.entrySet()) {
Symbol symbol = planSymbolAllocator.newSymbol(entry.getKey().getName(), planSymbolAllocator.getTypes().get(entry.getKey()));
assignments.put(symbol, castToRowExpression(entry.getValue()));
}
// add extra marker fields to the projection
for (int i = 0; i < markers.size(); ++i) {
Expression expression = (i == markerIndex) ? TRUE_LITERAL : new Cast(new NullLiteral(), StandardTypes.BOOLEAN);
assignments.put(planSymbolAllocator.newSymbol(markers.get(i).getName(), BOOLEAN), castToRowExpression(expression));
}
return new ProjectNode(idAllocator.getNextId(), source, assignments.build());
}
use of io.prestosql.sql.tree.Cast in project hetu-core by openlookeng.
the class TransformExistsApplyToLateralNode method rewriteToDefaultAggregation.
private PlanNode rewriteToDefaultAggregation(ApplyNode parent, Context context) {
Symbol count = context.getSymbolAllocator().newSymbol(COUNT.toString(), BIGINT);
Symbol exists = getOnlyElement(parent.getSubqueryAssignments().getSymbols());
return new LateralJoinNode(parent.getId(), parent.getInput(), new ProjectNode(context.getIdAllocator().getNextId(), new AggregationNode(context.getIdAllocator().getNextId(), parent.getSubquery(), ImmutableMap.of(count, new Aggregation(new CallExpression("count", functionResolution.countFunction(), BIGINT, ImmutableList.of(), Optional.empty()), ImmutableList.of(), false, Optional.empty(), Optional.empty(), Optional.empty())), globalAggregation(), ImmutableList.of(), AggregationNode.Step.SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty()), Assignments.of(exists, castToRowExpression(new ComparisonExpression(GREATER_THAN, toSymbolReference(count), new Cast(new LongLiteral("0"), BIGINT.toString()))))), parent.getCorrelation(), INNER, TRUE_LITERAL, parent.getOriginSubquery());
}
use of io.prestosql.sql.tree.Cast in project hetu-core by openlookeng.
the class QueryPlanner method coerce.
private Map<Symbol, RowExpression> coerce(Iterable<? extends Expression> expressions, PlanBuilder subPlan, TranslationMap translations) {
ImmutableMap.Builder<Symbol, RowExpression> projections = ImmutableMap.builder();
for (Expression expression : expressions) {
Type type = analysis.getType(expression);
Type coercion = analysis.getCoercion(expression);
Symbol symbol = planSymbolAllocator.newSymbol(expression, firstNonNull(coercion, type));
Expression rewritten = subPlan.rewrite(expression);
if (coercion != null) {
rewritten = new Cast(rewritten, coercion.getTypeSignature().toString(), false, typeCoercion.isTypeOnlyCoercion(type, coercion));
}
projections.put(symbol, castToRowExpression(rewritten));
translations.put(expression, symbol);
}
return projections.build();
}
use of io.prestosql.sql.tree.Cast in project hetu-core by openlookeng.
the class QueryPlanner method planDeleteRowAsInsert.
public UpdateDeleteRelationPlan planDeleteRowAsInsert(Delete node) {
Table table = node.getTable();
RelationType descriptor = analysis.getOutputDescriptor(node.getTable());
TableHandle handle = analysis.getTableHandle(node.getTable());
ColumnHandle rowIdHandle = analysis.getRowIdHandle(table);
Type rowIdType = metadata.getColumnMetadata(session, handle, rowIdHandle).getType();
ImmutableList.Builder<Symbol> outputSymbols = ImmutableList.builder();
ImmutableMap.Builder<Symbol, ColumnHandle> columnsBuilder = ImmutableMap.builder();
ColumnMetadata rowIdColumnMetadata = metadata.getColumnMetadata(session, handle, rowIdHandle);
ImmutableList.Builder<Field> fields = ImmutableList.builder();
ImmutableList.Builder<Field> projectionFields = ImmutableList.builder();
Symbol orderBySymbol = null;
// add table columns
for (Field field : descriptor.getAllFields()) {
Symbol symbol = planSymbolAllocator.newSymbol(field.getName().get(), field.getType());
outputSymbols.add(symbol);
ColumnHandle column = analysis.getColumn(field);
columnsBuilder.put(symbol, column);
fields.add(field);
ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, handle, column);
if (columnMetadata.isRequired()) {
projectionFields.add(field);
}
if (field.getName().toString().contains("rowId")) {
projectionFields.add(field);
}
if (field.getName().toString().contains("tupleId")) {
projectionFields.add(field);
}
}
// create table scan
ImmutableMap<Symbol, ColumnHandle> columns = columnsBuilder.build();
PlanNode tableScan = TableScanNode.newInstance(idAllocator.getNextId(), handle, outputSymbols.build(), columns, ReuseExchangeOperator.STRATEGY.REUSE_STRATEGY_DEFAULT, new UUID(0, 0), 0, false);
Scope scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(fields.build())).build();
RelationPlan relationPlan = new RelationPlan(tableScan, scope, outputSymbols.build());
TranslationMap translations = new TranslationMap(relationPlan, analysis, lambdaDeclarationToSymbolMap);
translations.setFieldMappings(relationPlan.getFieldMappings());
PlanBuilder builder = new PlanBuilder(translations, relationPlan.getRoot());
Optional<RowExpression> predicate = Optional.empty();
if (node.getWhere().isPresent()) {
builder = filter(builder, node.getWhere().get(), node);
if (builder.getRoot() instanceof FilterNode) {
predicate = Optional.of(((FilterNode) builder.getRoot()).getPredicate());
}
}
Assignments.Builder assignments = Assignments.builder();
TableMetadata tableMetadata = metadata.getTableMetadata(session, handle);
for (Map.Entry<Symbol, ColumnHandle> entry : columns.entrySet()) {
ColumnMetadata column;
ColumnHandle columnHandle = entry.getValue();
Symbol input = entry.getKey();
if (columnHandle.getColumnName().equals(rowIdHandle.getColumnName())) {
column = rowIdColumnMetadata;
} else {
column = tableMetadata.getColumn(columnHandle.getColumnName());
}
if (column != rowIdColumnMetadata && (column.isHidden() || !column.isRequired())) {
// Skip unnecessary columns as well.
continue;
}
Symbol output = planSymbolAllocator.newSymbol(column.getName(), column.getType());
Type tableType = column.getType();
Type queryType = planSymbolAllocator.getTypes().get(input);
if (queryType.equals(tableType) || typeCoercion.isTypeOnlyCoercion(queryType, tableType)) {
assignments.put(output, castToRowExpression(toSymbolReference(input)));
} else {
Expression cast = new Cast(toSymbolReference(input), tableType.getTypeSignature().toString());
assignments.put(output, castToRowExpression(cast));
}
if (column == rowIdColumnMetadata) {
orderBySymbol = output;
}
}
ProjectNode projectNode = new ProjectNode(idAllocator.getNextId(), builder.getRoot(), assignments.build());
builder = new PlanBuilder(translations, projectNode);
scope = Scope.builder().withRelationType(RelationId.anonymous(), new RelationType(projectionFields.build())).build();
RelationPlan plan = new RelationPlan(builder.getRoot(), scope, projectNode.getOutputSymbols());
List<String> visibleTableColumnNames = tableMetadata.getColumns().stream().filter(c -> c.isRequired()).map(ColumnMetadata::getName).collect(Collectors.toList());
visibleTableColumnNames.add(rowIdColumnMetadata.getName());
return new UpdateDeleteRelationPlan(plan, visibleTableColumnNames, columns, predicate);
}
Aggregations