use of io.prestosql.spi.plan.Assignments in project hetu-core by openlookeng.
the class TransformUncorrelatedInPredicateSubqueryToJoin method apply.
@Override
public Result apply(ApplyNode applyNode, Captures captures, Context context) {
if (applyNode.getSubqueryAssignments().size() != 1) {
return Result.empty();
}
Expression expression = castToExpression(getOnlyElement(applyNode.getSubqueryAssignments().getExpressions()));
InPredicate inPredicate;
if (expression instanceof InPredicate) {
inPredicate = (InPredicate) expression;
} else {
return Result.empty();
}
Symbol semiJoinSymbol = getOnlyElement(applyNode.getSubqueryAssignments().getSymbols());
JoinNode.EquiJoinClause equiJoinClause = new JoinNode.EquiJoinClause(SymbolUtils.from(inPredicate.getValue()), SymbolUtils.from(inPredicate.getValueList()));
List<Symbol> outputSymbols = new LinkedList<>(applyNode.getInput().getOutputSymbols());
outputSymbols.add(SymbolUtils.from(inPredicate.getValueList()));
AggregationNode distinctNode = new AggregationNode(context.getIdAllocator().getNextId(), applyNode.getSubquery(), ImmutableMap.of(), singleGroupingSet(applyNode.getSubquery().getOutputSymbols()), ImmutableList.of(), AggregationNode.Step.SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty());
JoinNode joinNode = new JoinNode(context.getIdAllocator().getNextId(), JoinNode.Type.RIGHT, distinctNode, applyNode.getInput(), ImmutableList.of(equiJoinClause), outputSymbols, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Collections.emptyMap());
Map<Symbol, RowExpression> assignments = new HashMap<>();
assignments.put(semiJoinSymbol, castToRowExpression(new IsNotNullPredicate(inPredicate.getValueList())));
for (Symbol symbol : applyNode.getInput().getOutputSymbols()) {
assignments.put(symbol, castToRowExpression(toSymbolReference(symbol)));
}
ProjectNode projectNode = new ProjectNode(context.getIdAllocator().getNextId(), joinNode, new Assignments(assignments));
return Result.ofPlanNode(projectNode);
}
use of io.prestosql.spi.plan.Assignments 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);
}
use of io.prestosql.spi.plan.Assignments in project hetu-core by openlookeng.
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().get()).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.putAll(AssignmentUtils.identityAsSymbolReferences(left.getRoot().getOutputSymbols()));
rightCoercions.putAll(AssignmentUtils.identityAsSymbolReferences(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 = planSymbolAllocator.newSymbol(identifier, type);
int leftField = joinAnalysis.getLeftJoinFields().get(i);
leftCoercions.put(leftOutput, castToRowExpression(new Cast(toSymbolReference(left.getSymbol(leftField)), type.getTypeSignature().toString(), 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 = planSymbolAllocator.newSymbol(identifier, type);
int rightField = joinAnalysis.getRightJoinFields().get(i);
rightCoercions.put(rightOutput, castToRowExpression(new Cast(toSymbolReference(right.getSymbol(rightField)), type.getTypeSignature().toString(), 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(), JoinNodeUtils.typeConvert(node.getType()), leftCoercion, rightCoercion, clauses.build(), ImmutableList.<Symbol>builder().addAll(leftCoercion.getOutputSymbols()).addAll(rightCoercion.getOutputSymbols()).build(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of());
// 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 = planSymbolAllocator.newSymbol(column, analysis.getType(column));
outputs.add(output);
assignments.put(output, castToRowExpression(new CoalesceExpression(toSymbolReference(leftJoinColumns.get(column)), toSymbolReference(rightJoinColumns.get(column)))));
}
for (int field : joinAnalysis.getOtherLeftFields()) {
Symbol symbol = left.getFieldMappings().get(field);
outputs.add(symbol);
assignments.put(symbol, castToRowExpression(toSymbolReference(symbol)));
}
for (int field : joinAnalysis.getOtherRightFields()) {
Symbol symbol = right.getFieldMappings().get(field);
outputs.add(symbol);
assignments.put(symbol, castToRowExpression(toSymbolReference(symbol)));
}
return new RelationPlan(new ProjectNode(idAllocator.getNextId(), join, assignments.build()), analysis.getScope(node), outputs.build());
}
use of io.prestosql.spi.plan.Assignments in project hetu-core by openlookeng.
the class TestStarTreeAggregationRule method testBuildSymbolMappings.
@Test
public void testBuildSymbolMappings() {
RowExpression rowExpression = planBuilder.variable(columnTotalprice.getName(), totalpriceHandle.getType());
FilterNode filterNode = new FilterNode(newId(), baseTableScan, rowExpression);
Assignments projectionAssignments = Assignments.builder().put(columnCustkey, planBuilder.variable(columnCustkey.getName(), custkeyHandle.getType())).build();
ProjectNode projectNode1 = new ProjectNode(newId(), filterNode, projectionAssignments);
List<ProjectNode> projectNodes = ImmutableList.of(projectNode1);
AggregationNode countAggNode = new AggregationNode(newId(), projectNode1, ImmutableMap.of(columnCustkey, new AggregationNode.Aggregation(Expressions.call("count", COUNT, DOUBLE, ImmutableList.of(planBuilder.variable(columnOrderkey.getName(), orderkeyHandle.getType()))), ImmutableList.of(planBuilder.variable(columnCustkey.getName(), custkeyHandle.getType())), true, Optional.empty(), Optional.empty(), Optional.empty())), singleGroupingSet(ImmutableList.of(columnOrderkey, columnOrderDate)), ImmutableList.of(), SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty());
Map<String, Object> columnMapping = CubeOptimizerUtil.buildSymbolMappings(countAggNode, projectNodes, Optional.of(filterNode), baseTableScan, baseTableMetadata);
assertEquals(columnMapping.size(), 4);
assertEquals(new ArrayList<>(columnMapping.keySet()).toString(), "[orderkey, custkey, totalprice, orderdate]");
assertTrue(columnMapping.values().containsAll(assignments.values()) && assignments.values().containsAll(columnMapping.values()));
// expression Literal
DoubleLiteral testDouble = new DoubleLiteral("1.0");
Assignments assignment2 = Assignments.builder().put(columnCustkey, OriginalExpressionUtils.castToRowExpression(testDouble)).build();
ProjectNode projectNode2 = new ProjectNode(newId(), filterNode, assignment2);
List<ProjectNode> projections2 = ImmutableList.of(projectNode2);
columnMapping = CubeOptimizerUtil.buildSymbolMappings(countAggNode, projections2, Optional.of(filterNode), baseTableScan, baseTableMetadata);
assertEquals(new ArrayList(columnMapping.values()).get(1), testDouble);
// expression Cast/SymbolReference
Cast testCast = new Cast(SymbolUtils.toSymbolReference(columnCustkey), StandardTypes.INTEGER);
Assignments assignment3 = Assignments.builder().put(columnCustkey, OriginalExpressionUtils.castToRowExpression(testCast)).build();
ProjectNode planNode3 = new ProjectNode(newId(), baseTableScan, assignment3);
List<ProjectNode> projections3 = ImmutableList.of(planNode3);
columnMapping = CubeOptimizerUtil.buildSymbolMappings(countAggNode, projections3, Optional.of(filterNode), baseTableScan, baseTableMetadata);
assertEquals(new ArrayList(columnMapping.values()).get(1), custkeyHandle);
// expression Cast/Literal
Cast testCast2 = new Cast(testDouble, StandardTypes.DOUBLE);
Assignments assignment4 = Assignments.builder().put(columnCustkey, OriginalExpressionUtils.castToRowExpression(testCast2)).build();
ProjectNode planNode4 = new ProjectNode(newId(), baseTableScan, assignment4);
List<ProjectNode> projections4 = ImmutableList.of(planNode4);
columnMapping = CubeOptimizerUtil.buildSymbolMappings(countAggNode, projections4, Optional.of(filterNode), baseTableScan, baseTableMetadata);
assertEquals(new ArrayList(columnMapping.values()).get(1), testDouble);
}
use of io.prestosql.spi.plan.Assignments in project hetu-core by openlookeng.
the class CubeOptimizer method rewriteNodeRecursively.
private PlanNode rewriteNodeRecursively(PlanNode node) {
if (node instanceof ProjectNode) {
ProjectNode projection = ((ProjectNode) node);
PlanNode rewritten = rewriteNodeRecursively(projection.getSource());
Assignments assignments = AssignmentUtils.identityAsSymbolReferences(rewritten.getOutputSymbols());
return new ProjectNode(context.getIdAllocator().getNextId(), rewritten, assignments);
} else if (node instanceof JoinNode) {
JoinNode localJoinNode = (JoinNode) node;
PlanNode rewrittenLeftChild = rewriteNodeRecursively(localJoinNode.getLeft());
PlanNode rewrittenRightChild = rewriteNodeRecursively(localJoinNode.getRight());
return rewriteJoinNode(localJoinNode, rewrittenLeftChild, rewrittenRightChild);
} else if (node instanceof TableScanNode) {
TableScanNode scanNode = (TableScanNode) node;
TableMetadata tableMetadata = metadata.getTableMetadata(context.getSession(), scanNode.getTable());
final String fqTableName = tableMetadata.getQualifiedName().toString();
final boolean isSourceTable = sourceTableName.equalsIgnoreCase(fqTableName);
// replace table scan with Cube table scan
TableScanNode rewrittenScanNode = isSourceTable ? cubeScanNode : scanNode;
final String rewrittenTableName = isSourceTable ? cubeTableMetadata.getQualifiedName().toString() : fqTableName;
rewrittenScanNode.getAssignments().forEach((symbol, colHandle) -> optimizedPlanMappings.put(new ColumnWithTable(rewrittenTableName, colHandle.getColumnName()), symbol));
return rewrittenScanNode;
} else {
throw new UnsupportedOperationException("Unexpected plan node. Expected TableScan, JoinNode or ProjectNode. Actual is " + node.getClass());
}
}
Aggregations