private SubPlanBuilder addDistributedAggregation( SubPlanBuilder plan, Map<Symbol, FunctionCall> aggregations, Map<Symbol, Signature> functions, Map<Symbol, Symbol> masks, List<Symbol> groupBy, Optional<Symbol> sampleWeight, double confidence) { Map<Symbol, FunctionCall> finalCalls = new HashMap<>(); Map<Symbol, FunctionCall> intermediateCalls = new HashMap<>(); Map<Symbol, Signature> intermediateFunctions = new HashMap<>(); Map<Symbol, Symbol> intermediateMask = new HashMap<>(); for (Map.Entry<Symbol, FunctionCall> entry : aggregations.entrySet()) { Signature signature = functions.get(entry.getKey()); FunctionInfo function = metadata.getFunction(signature); Symbol intermediateSymbol = allocator.newSymbol(function.getName().getSuffix(), function.getIntermediateType()); intermediateCalls.put(intermediateSymbol, entry.getValue()); intermediateFunctions.put(intermediateSymbol, signature); if (masks.containsKey(entry.getKey())) { intermediateMask.put(intermediateSymbol, masks.get(entry.getKey())); } // rewrite final aggregation in terms of intermediate function finalCalls.put( entry.getKey(), new FunctionCall( function.getName(), ImmutableList.<Expression>of( new QualifiedNameReference(intermediateSymbol.toQualifiedName())))); } // create partial aggregation plan AggregationNode partialAggregation = new AggregationNode( idAllocator.getNextId(), plan.getRoot(), groupBy, intermediateCalls, intermediateFunctions, intermediateMask, PARTIAL, sampleWeight, confidence); plan.setRoot( new SinkNode( idAllocator.getNextId(), partialAggregation, partialAggregation.getOutputSymbols())); // create final aggregation plan ExchangeNode source = new ExchangeNode( idAllocator.getNextId(), plan.getId(), plan.getRoot().getOutputSymbols()); AggregationNode finalAggregation = new AggregationNode( idAllocator.getNextId(), source, groupBy, finalCalls, functions, ImmutableMap.<Symbol, Symbol>of(), FINAL, Optional.<Symbol>absent(), confidence); if (groupBy.isEmpty()) { plan = createSingleNodePlan(finalAggregation).addChild(plan.build()); } else { plan.setHashOutputPartitioning(groupBy); plan = createFixedDistributionPlan(finalAggregation).addChild(plan.build()); } return plan; }
private InternalTable buildPartitions( Session session, String catalogName, Map<String, SerializableNativeValue> filters) { QualifiedTableName tableName = extractQualifiedTableName(catalogName, filters); InternalTable.Builder table = InternalTable.builder(informationSchemaTableColumns(TABLE_INTERNAL_PARTITIONS)); Optional<TableHandle> tableHandle = metadata.getTableHandle(session, tableName); checkArgument(tableHandle.isPresent(), "Table %s does not exist", tableName); Map<ColumnHandle, String> columnHandles = ImmutableBiMap.copyOf(metadata.getColumnHandles(session, tableHandle.get())).inverse(); List<TableLayoutResult> layouts = metadata.getLayouts( session, tableHandle.get(), Constraint.<ColumnHandle>alwaysTrue(), Optional.empty()); if (layouts.size() == 1) { TableLayout layout = Iterables.getOnlyElement(layouts).getLayout(); layout .getDiscretePredicates() .ifPresent( domains -> { int partitionNumber = 1; for (TupleDomain<ColumnHandle> domain : domains) { for (Entry<ColumnHandle, SerializableNativeValue> entry : domain.extractNullableFixedValues().entrySet()) { ColumnHandle columnHandle = entry.getKey(); String columnName = columnHandles.get(columnHandle); String value = null; if (entry.getValue().getValue() != null) { ColumnMetadata columnMetadata = metadata.getColumnMetadata(session, tableHandle.get(), columnHandle); try { FunctionInfo operator = metadata .getFunctionRegistry() .getCoercion(columnMetadata.getType(), VARCHAR); value = ((Slice) operator .getMethodHandle() .invokeWithArguments(entry.getValue().getValue())) .toStringUtf8(); } catch (OperatorNotFoundException e) { value = "<UNREPRESENTABLE VALUE>"; } catch (Throwable throwable) { throw Throwables.propagate(throwable); } } table.add( catalogName, tableName.getSchemaName(), tableName.getTableName(), partitionNumber, columnName, value); } partitionNumber++; } }); } return table.build(); }
/** Generates a function call with null handling, automatic binding of session parameter, etc. */ public ByteCodeNode generateCall(FunctionInfo function, List<ByteCodeNode> arguments) { Binding binding = callSiteBinder.bind(function.getMethodHandle()); return generateInvocation(context, function, arguments, binding); }