use of mondrian.calc.TupleCursor in project mondrian by pentaho.
the class RolapNamedSetEvaluator method ensureList.
/**
* Evaluates and saves the value of this named set, if it has not been evaluated already.
*/
private void ensureList(Evaluator evaluator) {
if (list != null) {
if (list == DUMMY_LIST) {
recursionCount++;
if (RECURSION_TOLERANCE > 0 && recursionCount > RECURSION_TOLERANCE) {
throw rrer.result.slicerEvaluator.newEvalException(null, "Illegal attempt to reference value of named set '" + namedSet.getName() + "' while evaluating itself");
}
}
return;
}
if (RolapResult.LOGGER.isDebugEnabled()) {
RolapResult.LOGGER.debug("Named set " + namedSet.getName() + ": starting evaluation");
}
// recursion detection
list = DUMMY_LIST;
try {
final Calc calc = rrer.getCompiled(namedSet.getExp(), false, ResultStyle.ITERABLE);
TupleIterable iterable = (TupleIterable) rrer.result.evaluateExp(calc, rrer.result.slicerEvaluator, evaluator);
// Axes can be in two forms: list or iterable. If iterable, we
// need to materialize it, to ensure that all cell values are in
// cache.
final TupleList rawList;
if (iterable instanceof TupleList) {
rawList = (TupleList) iterable;
} else {
rawList = TupleCollections.createList(iterable.getArity());
TupleCursor cursor = iterable.tupleCursor();
while (cursor.forward()) {
rawList.addCurrent(cursor);
}
}
if (RolapResult.LOGGER.isDebugEnabled()) {
RolapResult.LOGGER.debug(generateDebugMessage(calc, rawList));
}
// NamedSets are not supposed to depend on the current evaluation context but the
// way NamedSet evaluation was implemented in Mondrian, they could...
// So as a result, the nameset calc has to be profiled at the time of use instead
// of on close of the statement.
Util.explain(rrer.statement.getProfileHandler(), "NamedSet (" + namedSet.getName() + "):", calc, evaluator.getTiming());
// Wrap list so that currentOrdinal is updated whenever the list
// is accessed. The list is immutable, because we don't override
// AbstractList.set(int, Object).
this.list = rawList.withPositionCallback(this);
} finally {
if (this.list == DUMMY_LIST) {
this.list = null;
}
recursionCount = 0;
}
}
use of mondrian.calc.TupleCursor in project mondrian by pentaho.
the class Sorter method sortTuples.
/**
* Sorts a list of Tuples by the value of an applied expression. Stable sort.
*
* <p>Helper function for MDX functions TopCount, TopSum, TopPercent,
* BottomCount, BottomSum, BottomPercent, but not the MDX function Order.
*
* <p>NOTE: This function does not preserve the contents of the validator.
*
* <p>If you specify {@code tupleList}, the list is sorted in place, and
* tupleList is returned.
*
* @param evaluator Evaluator
* @param tupleIterable Iterator over tuples
* @param tupleList List of tuples, if known, otherwise null
* @param exp Expression to sort on
* @param desc Whether to sort descending
* @param brk Whether to break
* @param arity Number of members in each tuple
* @return sorted list (never null)
*/
public static TupleList sortTuples(Evaluator evaluator, TupleIterable tupleIterable, TupleList tupleList, Calc exp, boolean desc, boolean brk, int arity) {
// NOTE: This method does not implement the iterable/list concept
// as fully as sortMembers. This is because sortMembers evaluates all
// sort expressions up front. There, it is efficient to unravel the
// iterator and evaluate the sort expressions at the same time.
List<List<Member>> tupleArrayList;
if (tupleList == null) {
final TupleCursor cursor = tupleIterable.tupleCursor();
tupleArrayList = iterableToList(evaluator, cursor);
if (tupleArrayList.size() <= 1) {
return new DelegatingTupleList(tupleIterable.getArity(), tupleArrayList);
}
} else {
if (tupleList.size() <= 1) {
return tupleList;
}
tupleArrayList = tupleList;
}
@SuppressWarnings({ "unchecked" }) List<Member>[] tuples = tupleArrayList.toArray(new List[tupleArrayList.size()]);
final DelegatingTupleList result = new DelegatingTupleList(tupleIterable.getArity(), Arrays.asList(tuples));
Comparator<List<Member>> comparator;
if (brk) {
comparator = new TupleExpMemoComparator.BreakTupleComparator(evaluator, exp, arity);
if (desc) {
comparator = Collections.reverseOrder(comparator);
}
} else {
comparator = new HierarchicalTupleComparator(evaluator, exp, arity, desc);
}
Arrays.sort(tuples, comparator);
logTuples(tupleList, "Sorter.sortTuples");
return result;
}
use of mondrian.calc.TupleCursor in project mondrian by pentaho.
the class FunUtil method count.
public static int count(Evaluator evaluator, TupleIterable iterable, boolean includeEmpty) {
if (iterable == null) {
return 0;
}
if (includeEmpty) {
if (iterable instanceof TupleList) {
return ((TupleList) iterable).size();
} else {
int retval = 0;
TupleCursor cursor = iterable.tupleCursor();
while (cursor.forward()) {
retval++;
}
return retval;
}
} else {
int retval = 0;
TupleCursor cursor = iterable.tupleCursor();
while (cursor.forward()) {
cursor.setContext(evaluator);
if (!evaluator.currentIsEmpty()) {
retval++;
}
}
return retval;
}
}
use of mondrian.calc.TupleCursor in project mondrian by pentaho.
the class FunUtil method evaluateSet.
/**
* Evaluates {@code exp} (if defined) over {@code members} to generate a {@link List} of {@link SetWrapper} objects,
* which contains a {@link Double} value and meta information, unlike {@link #evaluateMembers}, which only produces
* values.
*
* @pre exp != null
*/
static SetWrapper evaluateSet(Evaluator evaluator, TupleIterable members, Calc calc) {
assert members != null;
assert calc != null;
assert calc.getType() instanceof ScalarType;
// todo: treat constant exps as evaluateMembers() does
SetWrapper retval = new SetWrapper();
final TupleCursor cursor = members.tupleCursor();
int currentIteration = 0;
Execution execution = evaluator.getQuery().getStatement().getCurrentExecution();
while (cursor.forward()) {
CancellationChecker.checkCancelOrTimeout(currentIteration++, execution);
cursor.setContext(evaluator);
Object o = calc.evaluate(evaluator);
if (o == null || o == Util.nullValue) {
retval.nullCount++;
} else if (o == RolapUtil.valueNotReadyException) {
// Carry on summing, so that if we are running in a
// BatchingCellReader, we find out all the dependent cells we
// need
retval.errorCount++;
} else if (o instanceof Number) {
retval.v.add(((Number) o).doubleValue());
} else {
retval.v.add(o);
}
}
return retval;
}
use of mondrian.calc.TupleCursor in project mondrian by pentaho.
the class RolapResult method evaluateExp.
/**
* Evaluates an expression. Intended for evaluating named sets.
*
* <p>
* Does not modify the contents of the evaluator.
*
* @param calc
* Compiled expression
* @param slicerEvaluator
* Evaluation context for slicers
* @param contextEvaluator
* Evaluation context (optional)
* @return Result
*/
Object evaluateExp(Calc calc, RolapEvaluator slicerEvaluator, Evaluator contextEvaluator) {
int attempt = 0;
RolapEvaluator evaluator = slicerEvaluator.push();
if (contextEvaluator != null && contextEvaluator.isEvalAxes()) {
evaluator.setEvalAxes(true);
}
final int savepoint = evaluator.savepoint();
boolean dirty = batchingReader.isDirty();
try {
while (true) {
evaluator.restore(savepoint);
evaluator.setCellReader(batchingReader);
Object preliminaryValue = calc.evaluate(evaluator);
if (preliminaryValue instanceof TupleIterable) {
// During the preliminary phase, we have to materialize the
// tuple lists or the evaluation lower down won't take into
// account all the tuples.
TupleIterable iterable = (TupleIterable) preliminaryValue;
final TupleCursor cursor = iterable.tupleCursor();
while (cursor.forward()) {
// ignore
}
}
if (!phase()) {
break;
} else {
// Clear invalid expression result so that the next
// evaluation will pick up the newly loaded aggregates.
evaluator.clearExpResultCache(false);
}
if (attempt++ > maxEvalDepth) {
throw Util.newInternal("Failed to load all aggregations after " + maxEvalDepth + "passes; there's probably a cycle");
}
}
// re-evaluate them.
if (dirty) {
batchingReader.setDirty(true);
}
evaluator.restore(savepoint);
evaluator.setCellReader(aggregatingReader);
final Object o = calc.evaluate(evaluator);
return o;
} finally {
evaluator.restore(savepoint);
}
}
Aggregations