/** * Creates a group-by plan for the underlying query. The grouping is determined by the specified * collection of group fields, and the aggregation is computed by the specified collection of * aggregation functions. * * @param p a plan for the underlying query * @param groupFlds the fields to group by. Can be empty, which means that all records are in a * single group. * @param aggFns the aggregation functions. Optional, can be null. * @param tx the calling transaction */ public GroupByPlan(Plan p, Set<String> groupFlds, Set<AggregationFn> aggFns, Transaction tx) { schema = new Schema(); this.groupFlds = groupFlds; if (!this.groupFlds.isEmpty()) { for (String fld : groupFlds) schema.add(fld, p.schema()); // sort records by group-by fields with default direction sp = new SortPlan(p, new ArrayList<String>(groupFlds), tx); } else // all records are in a single group, so p is already sorted sp = p; this.aggFns = aggFns; if (aggFns != null) for (AggregationFn fn : aggFns) { Type t = fn.isArgumentTypeDependent() ? p.schema().type(fn.argumentFieldName()) : fn.fieldType(); schema.addField(fn.fieldName(), t); } hist = groupByHistogram(p.histogram(), this.groupFlds, aggFns); }
/** * Returns the number of blocks required to compute the aggregation, which is one pass through the * sorted table. It does <em>not</em> include the one-time cost of materializing and sorting the * records. * * @see Plan#blocksAccessed() */ @Override public long blocksAccessed() { return sp.blocksAccessed(); }
/** * This method opens a sort plan for the specified plan. The sort plan ensures that the underlying * records will be appropriately grouped. * * @see Plan#open() */ @Override public Scan open() { Scan ss = sp.open(); return new GroupByScan(ss, groupFlds, aggFns); }