use of mondrian.olap.NativeEvaluator in project mondrian by pentaho.
the class TopBottomCountFunDef method compileCall.
public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
// Compile the member list expression. Ask for a mutable list, because
// we're going to sort it later.
final ListCalc listCalc = compiler.compileList(call.getArg(0), true);
final IntegerCalc integerCalc = compiler.compileInteger(call.getArg(1));
final Calc orderCalc = call.getArgCount() > 2 ? compiler.compileScalar(call.getArg(2), true) : null;
final int arity = call.getType().getArity();
return new AbstractListCalc(call, new Calc[] { listCalc, integerCalc, orderCalc }) {
public TupleList evaluateList(Evaluator evaluator) {
// Use a native evaluator, if more efficient.
// TODO: Figure this out at compile time.
SchemaReader schemaReader = evaluator.getSchemaReader();
NativeEvaluator nativeEvaluator = schemaReader.getNativeSetEvaluator(call.getFunDef(), call.getArgs(), evaluator, this);
if (nativeEvaluator != null) {
return (TupleList) nativeEvaluator.execute(ResultStyle.LIST);
}
int n = integerCalc.evaluateInteger(evaluator);
if (n == 0 || n == mondrian.olap.fun.FunUtil.IntegerNull) {
return TupleCollections.emptyList(arity);
}
TupleList list = listCalc.evaluateList(evaluator);
assert list.getArity() == arity;
if (list.isEmpty()) {
return list;
}
if (orderCalc == null) {
// REVIEW: Why require "instanceof AbstractList"?
if (list instanceof AbstractList && list.size() <= n) {
return list;
} else if (top) {
return list.subList(0, n);
} else {
return list.subList(list.size() - n, list.size());
}
}
return partiallySortList(evaluator, list, hasHighCardDimension(list), Math.min(n, list.size()));
}
private TupleList partiallySortList(Evaluator evaluator, TupleList list, boolean highCard, int n) {
assert list.size() > 0;
assert n <= list.size();
if (highCard) {
// sort list in chunks, collect the results
// what is this really?
final int chunkSize = 6400;
TupleList allChunkResults = TupleCollections.createList(arity);
for (int i = 0, next; i < list.size(); i = next) {
next = Math.min(i + chunkSize, list.size());
final TupleList chunk = list.subList(i, next);
TupleList chunkResult = partiallySortList(evaluator, chunk, false, n);
allChunkResults.addAll(chunkResult);
}
// one last sort, to merge and cull
return partiallySortList(evaluator, allChunkResults, false, n);
}
// normal case: no need for chunks
final int savepoint = evaluator.savepoint();
try {
switch(list.getArity()) {
case 1:
final List<Member> members = Sorter.partiallySortMembers(evaluator.push(), list.slice(0), orderCalc, n, top);
return new UnaryTupleList(members);
default:
final List<List<Member>> tuples = partiallySortTuples(evaluator.push(), list, orderCalc, n, top);
return new DelegatingTupleList(list.getArity(), tuples);
}
} finally {
evaluator.restore(savepoint);
}
}
public boolean dependsOn(Hierarchy hierarchy) {
return anyDependsButFirst(getCalcs(), hierarchy);
}
private boolean hasHighCardDimension(TupleList l) {
final List<Member> trial = l.get(0);
for (Member m : trial) {
if (m.getHierarchy().getDimension().isHighCardinality()) {
return true;
}
}
return false;
}
};
}
use of mondrian.olap.NativeEvaluator in project mondrian by pentaho.
the class DrilldownLevelTopBottomFunDef method compileCall.
public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
// Compile the member list expression. Ask for a mutable list, because
// we're going to insert members into it later.
final ListCalc listCalc = compiler.compileList(call.getArg(0), true);
final IntegerCalc integerCalc = compiler.compileInteger(call.getArg(1));
final LevelCalc levelCalc = call.getArgCount() > 2 && call.getArg(2).getCategory() != Category.Empty ? compiler.compileLevel(call.getArg(2)) : null;
final Calc orderCalc = call.getArgCount() > 3 ? compiler.compileScalar(call.getArg(3), true) : new ValueCalc(new DummyExp(new ScalarType()));
return new AbstractListCalc(call, new Calc[] { listCalc, integerCalc, orderCalc }) {
public TupleList evaluateList(Evaluator evaluator) {
// Use a native evaluator, if more efficient.
// TODO: Figure this out at compile time.
SchemaReader schemaReader = evaluator.getSchemaReader();
NativeEvaluator nativeEvaluator = schemaReader.getNativeSetEvaluator(call.getFunDef(), call.getArgs(), evaluator, this);
if (nativeEvaluator != null) {
return (TupleList) nativeEvaluator.execute(ResultStyle.LIST);
}
TupleList list = listCalc.evaluateList(evaluator);
int n = integerCalc.evaluateInteger(evaluator);
if (n == FunUtil.IntegerNull || n <= 0) {
return list;
}
Level level;
if (levelCalc == null) {
level = null;
} else {
level = levelCalc.evaluateLevel(evaluator);
}
List<Member> result = new ArrayList<Member>();
assert list.getArity() == 1;
for (Member member : list.slice(0)) {
result.add(member);
if (level != null && member.getLevel() != level) {
if (level.getDimension() != member.getDimension()) {
throw newEvalException(DrilldownLevelTopBottomFunDef.this, "Level '" + level.getUniqueName() + "' not compatible with member '" + member.getUniqueName() + "'");
}
continue;
}
List<Member> children = schemaReader.getMemberChildren(member);
final int savepoint = evaluator.savepoint();
List<Member> sortedChildren;
try {
evaluator.setNonEmpty(false);
sortedChildren = Sorter.sortMembers(evaluator, children, children, orderCalc, top, true);
} finally {
evaluator.restore(savepoint);
}
int x = Math.min(n, sortedChildren.size());
for (int i = 0; i < x; i++) {
result.add(sortedChildren.get(i));
}
}
return new UnaryTupleList(result);
}
public boolean dependsOn(Hierarchy hierarchy) {
return anyDependsButFirst(getCalcs(), hierarchy);
}
};
}
use of mondrian.olap.NativeEvaluator in project mondrian by pentaho.
the class RolapNativeRegistry method createEvaluator.
/**
* Returns the matching NativeEvaluator or null if <code>fun</code> can not
* be executed in SQL for the given context and arguments.
*/
public NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) {
if (!isEnabled()) {
return null;
}
RolapNative rn = null;
readLock.lock();
try {
rn = nativeEvaluatorMap.get(fun.getName().toUpperCase());
} finally {
readLock.unlock();
}
if (rn == null) {
return null;
}
NativeEvaluator ne = rn.createEvaluator(evaluator, fun, args);
if (ne != null) {
if (listener != null) {
NativeEvent e = new NativeEvent(this, ne);
listener.foundEvaluator(e);
}
}
return ne;
}
Aggregations