use of org.teiid.query.function.aggregate.AggregateFunction in project teiid by teiid.
the class WindowFunctionProjectNode method buildResults.
/**
* Build the results by maintaining indexes that either map
* rowid->values
* or
* rowid->partitionid and partitionid->values
*
* TODO use the size hint for tree balancing
*/
private void buildResults() throws TeiidComponentException, TeiidProcessingException, FunctionExecutionException, ExpressionEvaluationException {
List<Map.Entry<WindowSpecification, WindowSpecificationInfo>> specs = new ArrayList<Map.Entry<WindowSpecification, WindowSpecificationInfo>>(windows.entrySet());
for (int specIndex = 0; specIndex < specs.size(); specIndex++) {
Map.Entry<WindowSpecification, WindowSpecificationInfo> entry = specs.get(specIndex);
WindowSpecificationInfo info = entry.getValue();
IndexedTupleSource specificationTs = tb.createIndexedTupleSource();
boolean multiGroup = false;
int[] partitionIndexes = null;
int[] orderIndexes = null;
// if there is partitioning or ordering, then sort
if (!info.orderType.isEmpty()) {
multiGroup = true;
int[] sortKeys = new int[info.orderType.size()];
int i = 0;
if (!info.groupIndexes.isEmpty()) {
for (Integer sortIndex : info.groupIndexes) {
sortKeys[i++] = sortIndex;
}
partitionIndexes = Arrays.copyOf(sortKeys, info.groupIndexes.size());
}
if (!info.sortIndexes.isEmpty()) {
for (Integer sortIndex : info.sortIndexes) {
sortKeys[i++] = sortIndex;
}
orderIndexes = Arrays.copyOfRange(sortKeys, info.groupIndexes.size(), info.groupIndexes.size() + info.sortIndexes.size());
}
if (!info.functions.isEmpty()) {
// $NON-NLS-1$
ElementSymbol key = new ElementSymbol("rowId");
key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
// $NON-NLS-1$
ElementSymbol value = new ElementSymbol("partitionId");
value.setType(DataTypeManager.DefaultDataClasses.INTEGER);
List<ElementSymbol> elements = Arrays.asList(key, value);
partitionMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
}
SortUtility su = new SortUtility(null, Mode.SORT, this.getBufferManager(), this.getConnectionID(), tb.getSchema(), info.orderType, info.nullOrderings, sortKeys);
su.setWorkingBuffer(tb);
su.setNonBlocking(true);
TupleBuffer sorted = su.sort();
specificationTs = sorted.createIndexedTupleSource(true);
}
List<AggregateFunction> aggs = initializeAccumulators(info.functions, specIndex, false);
List<AggregateFunction> rowValueAggs = initializeAccumulators(info.rowValuefunctions, specIndex, true);
int groupId = 0;
List<?> lastRow = null;
while (specificationTs.hasNext()) {
List<?> tuple = specificationTs.nextTuple();
if (multiGroup) {
if (lastRow != null) {
boolean samePartition = GroupingNode.sameGroup(partitionIndexes, tuple, lastRow) == -1;
if (!aggs.isEmpty() && (!samePartition || GroupingNode.sameGroup(orderIndexes, tuple, lastRow) != -1)) {
saveValues(specIndex, aggs, groupId, samePartition, false);
groupId++;
}
saveValues(specIndex, rowValueAggs, lastRow.get(lastRow.size() - 1), samePartition, true);
}
if (!aggs.isEmpty()) {
List<Object> partitionTuple = Arrays.asList(tuple.get(tuple.size() - 1), groupId);
partitionMapping[specIndex].insert(partitionTuple, InsertMode.NEW, -1);
}
}
for (AggregateFunction function : aggs) {
function.addInput(tuple, getContext());
}
for (AggregateFunction function : rowValueAggs) {
function.addInput(tuple, getContext());
}
lastRow = tuple;
}
if (lastRow != null) {
saveValues(specIndex, aggs, groupId, true, false);
saveValues(specIndex, rowValueAggs, lastRow.get(lastRow.size() - 1), true, true);
}
}
}
use of org.teiid.query.function.aggregate.AggregateFunction in project teiid by teiid.
the class WindowFunctionProjectNode method saveValues.
private void saveValues(int specIndex, List<AggregateFunction> aggs, Object id, boolean samePartition, boolean rowValue) throws FunctionExecutionException, ExpressionEvaluationException, TeiidComponentException, TeiidProcessingException {
if (aggs.isEmpty()) {
return;
}
List<Object> row = new ArrayList<Object>(aggs.size() + 1);
row.add(id);
for (AggregateFunction function : aggs) {
row.add(function.getResult(getContext()));
if (!samePartition) {
function.reset();
}
}
if (rowValue) {
rowValueMapping[specIndex].insert(row, InsertMode.NEW, -1);
} else {
valueMapping[specIndex].insert(row, InsertMode.ORDERED, -1);
}
}
use of org.teiid.query.function.aggregate.AggregateFunction in project teiid by teiid.
the class WindowFunctionProjectNode method initializeAccumulators.
/**
* @param functions
* @param specIndex
* @param rowValues
* @return
*/
private List<AggregateFunction> initializeAccumulators(List<WindowFunctionInfo> functions, int specIndex, boolean rowValues) {
List<AggregateFunction> aggs = new ArrayList<AggregateFunction>(functions.size());
if (functions.isEmpty()) {
return aggs;
}
List<ElementSymbol> elements = new ArrayList<ElementSymbol>(functions.size());
// $NON-NLS-1$
ElementSymbol key = new ElementSymbol("key");
key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
elements.add(key);
for (WindowFunctionInfo wfi : functions) {
aggs.add(GroupingNode.initAccumulator(wfi.function.getFunction(), this, expressionIndexes));
Class<?> outputType = wfi.function.getType();
if (wfi.function.getFunction().getAggregateFunction() == Type.LEAD || wfi.function.getFunction().getAggregateFunction() == Type.LAG) {
outputType = DataTypeManager.getArrayType(DataTypeManager.DefaultDataClasses.OBJECT);
}
// $NON-NLS-1$
ElementSymbol value = new ElementSymbol("val");
value.setType(outputType);
elements.add(value);
}
if (!rowValues) {
valueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
} else {
rowValueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
}
return aggs;
}
use of org.teiid.query.function.aggregate.AggregateFunction in project teiid by teiid.
the class TestGroupingNode method test1.
// ################################## ACTUAL TESTS ################################
@Test
public void test1() throws Exception {
BufferManager mgr = BufferManagerFactory.getStandaloneBufferManager();
// Set up
GroupingNode node = new GroupingNode(1);
List outputElements = new ArrayList();
// $NON-NLS-1$
ElementSymbol col1 = new ElementSymbol("col1");
col1.setType(Integer.class);
// $NON-NLS-1$
ElementSymbol col2 = new ElementSymbol("col2");
col2.setType(Integer.class);
outputElements.add(col1);
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("COUNT", false, null));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("COUNT", false, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("COUNT", true, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("SUM", false, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("SUM", true, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("AVG", false, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("AVG", true, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("MIN", false, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("MIN", true, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("MAX", false, col2));
// $NON-NLS-1$ //$NON-NLS-2$
outputElements.add(new AggregateSymbol("MAX", true, col2));
node.setElements(outputElements);
List groupingElements = new ArrayList();
groupingElements.add(col1);
node.setOrderBy(new OrderBy(groupingElements).getOrderByItems());
// $NON-NLS-1$ //$NON-NLS-2$
CommandContext context = new CommandContext("pid", "test", null, null, 1);
List[] expected = new List[] { Arrays.asList(new Object[] { null, new Integer(2), new Integer(1), new Integer(1), new Long(3), new Long(3), new BigDecimal(3.0), new BigDecimal(3.0), new Integer(3), new Integer(3), new Integer(3), new Integer(3) }), Arrays.asList(new Object[] { new Integer(0), new Integer(1), new Integer(1), new Integer(1), new Long(4), new Long(4), new BigDecimal(4.0), new BigDecimal(4.0), new Integer(4), new Integer(4), new Integer(4), new Integer(4) }), Arrays.asList(new Object[] { new Integer(1), new Integer(1), new Integer(1), new Integer(1), new Long(2), new Long(2), new BigDecimal(2.0), new BigDecimal(2.0), new Integer(2), new Integer(2), new Integer(2), new Integer(2) }), Arrays.asList(new Object[] { new Integer(2), new Integer(4), new Integer(4), new Integer(2), new Long(5), new Long(3), new BigDecimal(1.25), new BigDecimal(1.5), new Integer(1), new Integer(1), new Integer(2), new Integer(2) }), Arrays.asList(new Object[] { new Integer(3), new Integer(1), new Integer(1), new Integer(1), new Long(0), new Long(0), new BigDecimal(0.0), new BigDecimal(0.0), new Integer(0), new Integer(0), new Integer(0), new Integer(0) }), Arrays.asList(new Object[] { new Integer(4), new Integer(3), new Integer(2), new Integer(2), new Long(5), new Long(5), new BigDecimal(2.5), new BigDecimal(2.5), new Integer(2), new Integer(2), new Integer(3), new Integer(3) }), Arrays.asList(new Object[] { new Integer(5), new Integer(1), new Integer(1), new Integer(1), new Long(3), new Long(3), new BigDecimal(3.0), new BigDecimal(3.0), new Integer(3), new Integer(3), new Integer(3), new Integer(3) }), Arrays.asList(new Object[] { new Integer(6), new Integer(2), new Integer(2), new Integer(2), new Long(7), new Long(7), new BigDecimal(3.5), new BigDecimal(3.5), new Integer(3), new Integer(3), new Integer(4), new Integer(4) }) };
helpProcess(mgr, node, context, expected, null);
// ensure that the distinct input type is correct
AggregateFunction[][] functions = node.getFunctions();
AggregateFunction countDist = functions[5][0];
SortingFilter dup = (SortingFilter) countDist;
assertEquals(DataTypeManager.DefaultDataClasses.INTEGER, dup.getElements().get(0).getType());
}
Aggregations