Skip to content

Commit

Permalink
MONDRIAN: rewrite change 9695 per code review by Julian:
Browse files Browse the repository at this point in the history
"... There are a couple of problems with this fix, though. You assume that members' natural order is the same as their name (not the case for a time dimension [Time].[1997].[January], [Time].[1997].[February], ...); and you use a nested loops algorithm to sort the members, which I think is O(n ^ 2) in the size of the axis - unacceptable if an axis has say 1,000 members.

Can you rewrite your fix to use FunUtil.sortMembers() or something similar.
This uses a java.util.Comparator object which compares members using their natural order, and it uses the efficient sort methods provided by the JDK."

[git-p4: depot-paths = "//open/mondrian/": change = 9754]
  • Loading branch information
Chuck Reidmiller committed Aug 13, 2007
1 parent 50719b5 commit 2509481
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 38 deletions.
16 changes: 16 additions & 0 deletions src/main/mondrian/olap/QueryAxis.java
Expand Up @@ -33,6 +33,7 @@
public class QueryAxis extends QueryPart {

private boolean nonEmpty;
private boolean ordered;
private Exp exp;
private final AxisOrdinal axisOrdinal;

Expand Down Expand Up @@ -66,6 +67,7 @@ public QueryAxis(
this.axisOrdinal = axisDef;
this.subtotalVisibility = subtotalVisibility;
this.dimensionProperties = dimensionProperties;
this.ordered = false;
}

/**
Expand Down Expand Up @@ -166,6 +168,20 @@ public void setNonEmpty(boolean nonEmpty) {
this.nonEmpty = nonEmpty;
}

/**
* Returns whether the axis has the <code>ORDER</code> property set.
*/
public boolean isOrdered() {
return ordered;
}

/**
* Sets whether the axis has the <code>ORDER</code> property set.
*/
public void setOrdered(boolean ordered) {
this.ordered = ordered;
}

/**
* Returns the expression which is used to compute the value of this axis.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/olap/fun/FunUtil.java
Expand Up @@ -471,7 +471,7 @@ static void sortMembers(
*
* <p>NOTE: This function does not preserve the contents of the validator.
*/
static void sortTuples(
public static void sortTuples(
Evaluator evaluator,
List<Member[]> tuples,
Calc exp,
Expand Down
60 changes: 23 additions & 37 deletions src/main/mondrian/rolap/RolapResult.java
Expand Up @@ -21,6 +21,11 @@
import mondrian.util.Format;
import mondrian.util.ObjectPool;

import mondrian.olap.fun.FunUtil;
import mondrian.olap.type.ScalarType;
import mondrian.calc.DummyExp;
import mondrian.calc.impl.ValueCalc;

import org.apache.log4j.Logger;

import java.util.Collections;
Expand Down Expand Up @@ -572,7 +577,11 @@ Axis evalExecute(List<Member[]> nonAllMembers, int cnt,
for (Member m : nonAllMembers.get(cnt)) {
evaluator.setContext(m);
Axis a = evalExecute(nonAllMembers, cnt-1, evaluator, axis, calc);
axisResult = mergeAxes(axisResult, a);
boolean ordered = false;
if (axis != null) {
ordered = axis.isOrdered();
}
axisResult = mergeAxes(axisResult, a, evaluator, ordered);
}
}
return axisResult;
Expand Down Expand Up @@ -679,6 +688,9 @@ private Axis executeAxis(
evaluator.setNonEmpty(axis.isNonEmpty());
evaluator.setEvalAxes(true);
Object value = axisCalc.evaluate(evaluator);
if (axisCalc.getClass().getName().indexOf("OrderFunDef") != -1) {
axis.setOrdered(true);
}
evaluator.setNonEmpty(false);
if (value != null) {
// List or Iterable of Member or Member[]
Expand Down Expand Up @@ -1680,7 +1692,8 @@ public CellInfo lookup(int[] pos) {
}
}

static Axis mergeAxes(Axis axis1, Axis axis2) {
static Axis mergeAxes(Axis axis1, Axis axis2, RolapEvaluator evaluator,
boolean ordered) {
if (axis1 == null) {
return axis2;
}
Expand Down Expand Up @@ -1772,41 +1785,14 @@ static Axis mergeAxes(Axis axis1, Axis axis2) {
}
list.addAll(extras);

// if there are unique members on both axes, verify the member
// order and create a replacement sorted list if needed
if (list.size() > 0 && extras.size() > 0) {
String[] names = new String[list.size()];
int i = 0;
for (final Member memArray[]: list) {
StringBuilder name = new StringBuilder(100);
for (final Member mem: memArray) {
final String uniqueName = mem.getUniqueName();
name.append(uniqueName);
}
names[i] = name.toString();
i++;
}
String[] namesCopy = names.clone();
java.util.Arrays.sort(names);
if (!java.util.Arrays.equals(names, namesCopy)) {
// create a sorted list from the original list
List<Member[]> sortedList = new ArrayList<Member[]>();
for (int j = 0; j < names.length; j++) {
final String name = names[j];
for (final Member memArray[]: list) {
StringBuilder name2 = new StringBuilder(100);
for (final Member mem: memArray) {
final String uniqueName = mem.getUniqueName();
name2.append(uniqueName);
}
if (name.equals(name2.toString())) {
sortedList.add(memArray);
break;
}
}
}
return new RolapAxis.MemberArrayList(sortedList);
}
// if there are unique members on both axes and no order function,
// sort the list to ensure default order
if (list.size() > 0 && extras.size() > 0 && ordered == false) {
Member[] membs = list.get(0);
int membsSize = membs.length;
ValueCalc valCalc = new ValueCalc(new DummyExp(new ScalarType()));
FunUtil.sortTuples(evaluator, list, valCalc,
false, false, membsSize);
}

return new RolapAxis.MemberArrayList(list);
Expand Down

0 comments on commit 2509481

Please sign in to comment.