Skip to content

Commit

Permalink
MONDRIAN: Fix bug 688481 (range function applied to large dimension h…
Browse files Browse the repository at this point in the history
…angs).

[git-p4: depot-paths = "//open/mondrian/": change = 308]
  • Loading branch information
julianhyde committed Feb 19, 2003
1 parent 2d3d541 commit 70c4270
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 252 deletions.
30 changes: 30 additions & 0 deletions src/main/mondrian/olap/Util.java
Expand Up @@ -311,19 +311,49 @@ public static RuntimeException newError(Throwable e, String message) {
/**
* Checks that a precondition (declared using the javadoc <code>@pre</code>
* tag) is satisfied.
*
* @param b The value of executing the condition
*/
public static void assertPrecondition(boolean b) {
assertTrue(b);
}

/**
* Checks that a precondition (declared using the javadoc <code>@pre</code>
* tag) is satisfied. For example,
*
* <blockquote><pre>void f(String s) {
* Util.assertPrecondition(s != null, "s != null");
* ...
* }</pre></blockquote>
*
* @param b The value of executing the condition
* @param condition The text of the condition
*/
public static void assertPrecondition(boolean b, String condition) {
assertTrue(b, condition);
}

/**
* Checks that a postcondition (declared using the javadoc
* <code>@post</code> tag) is satisfied.
*
* @param b The value of executing the condition
*/
public static void assertPostcondition(boolean b) {
assertTrue(b);
}

/**
* Checks that a postcondition (declared using the javadoc
* <code>@post</code> tag) is satisfied.
*
* @param b The value of executing the condition
*/
public static void assertPostcondition(boolean b, String condition) {
assertTrue(b, condition);
}

public static MondrianResource getRes() {
return MondrianResource.instance();
}
Expand Down
269 changes: 140 additions & 129 deletions src/main/mondrian/olap/fun/BuiltinFunTable.java

Large diffs are not rendered by default.

22 changes: 3 additions & 19 deletions src/main/mondrian/rolap/CacheMemberReader.java
Expand Up @@ -209,25 +209,9 @@ public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
if (siblingsAreEqual && m1.getParentMember() == m2.getParentMember()) {
return 0;
}
// Members are stored in hierarchical order.
int pos1 = -1, pos2 = -1;
for (int i = 0; i < members.length; i++) {
RolapMember member = members[i];
if (member == m1) {
pos1 = i;
}
if (member == m2) {
pos2 = i;
}
}
if (pos1 == -1) {
throw Util.newInternal(m1 + " not found among members");
}
if (pos2 == -1) {
throw Util.newInternal(m2 + " not found among members");
}
Util.assertTrue(pos1 != pos2);
return pos1 < pos2 ? -1 : 1;
Util.assertTrue(members[m1.ordinal] == m1);
Util.assertTrue(members[m2.ordinal] == m2);
return m1.ordinal < m2.ordinal ? -1 : 1;
}
}

Expand Down
61 changes: 0 additions & 61 deletions src/main/mondrian/rolap/CachingCellReader.java

This file was deleted.

3 changes: 0 additions & 3 deletions src/main/mondrian/rolap/RolapCube.java
Expand Up @@ -229,9 +229,6 @@ void init()
localDimensionOrdinals[globalOrdinal] = i;
}
this.cellReader = AggregationManager.instance();
if (false) {
this.cellReader = new CachingCellReader(this, this.cellReader);
}
register();
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/mondrian/rolap/RolapMember.java
Expand Up @@ -26,6 +26,9 @@
*/
class RolapMember extends MemberBase
{
/** Ordinal of the member within the hierarchy. Some member readers do not
* use this property; in which case, they should leave it as its default,
* -1. */
int ordinal;
Object key;
/**
Expand All @@ -48,6 +51,7 @@ class RolapMember extends MemberBase
this.name = name;
this.caption = name;
this.key = key;
this.ordinal = -1;
this.memberType = 1; // adMemberRegular
this.uniqueName = (parentMember == null)
? Util.makeFqName(getHierarchy(), name)
Expand Down
127 changes: 98 additions & 29 deletions src/main/mondrian/rolap/SmartMemberReader.java
Expand Up @@ -229,9 +229,13 @@ private double getBenefit()
/**
* Reads the children of <code>member</code> into cache, and also into
* <code>result</code>.
*
* @param result Children are written here, in order
* @param members Members whose children to read
* @pre isSorted(members)
**/
private void readMemberChildren(ArrayList result, RolapMember[] members)
{
private void readMemberChildren(ArrayList result, RolapMember[] members) {
Util.assertPrecondition(isSorted(members), "isSorted(members)");
RolapMember[] children = source.getMemberChildren(members);
// Put them in a temporary hash table first. Register them later, when
// we know their size (hence their 'cost' to the cache pool).
Expand Down Expand Up @@ -262,6 +266,26 @@ private void readMemberChildren(ArrayList result, RolapMember[] members)
}
}

/**
* Returns true if every element of <code>members</code> is not null and is
* strictly less than the following element; false otherwise.
*/
public boolean isSorted(RolapMember[] members) {
if (members.length > 0 && members[0] == null) {
// Special case check for 0th element, just in case length == 1.
return false;
}
for (int i = 1; i < members.length; i++) {
RolapMember m0 = members[i - 1],
m1 = members[i];
if (m1 == null ||
compare(m0, m1, false) >= 0) {
return false;
}
}
return true;
}

// synchronization: Must synchronize, because uses mapMemberToChildren
public synchronized boolean hasChildren(RolapMember member) {
return mapMemberToChildren.get(member) != null;
Expand Down Expand Up @@ -350,52 +374,95 @@ public RolapMember getLeadMember(RolapMember member, int n)

public void getMemberRange(
RolapLevel level, RolapMember startMember, RolapMember endMember, List list) {
int startOrdinal = startMember.ordinal;
int endOrdinal = endMember.ordinal + 1;
Util.assertPrecondition(startMember != null, "startMember != null");
Util.assertPrecondition(endMember != null, "endMember != null");
Util.assertPrecondition(startMember.getLevel() == endMember.getLevel(),
"startMember.getLevel() == endMember.getLevel()");
if (compare(startMember, endMember, false) > 0) {
return;
}
list.add(startMember);
if (startMember == endMember) {
return;
}
SiblingIterator siblings = new SiblingIterator(this, startMember);
while (siblings.hasNext()) {
final RolapMember member = siblings.nextMember();
list.add(member);
if (member == endMember) {
return;
}
}
throw Util.newInternal("sibling iterator did not hit end point, start=" +
startMember + ", end=" + endMember);
}

public void _getMemberRange(
RolapLevel level, RolapMember startMember, RolapMember endMember, List list) {
// todo: Use a more efficient algorithm, which makes less use of
// bounds.
Util.assertTrue(level == startMember.getLevel());
Util.assertTrue(level == endMember.getLevel());
// "m" is the lowest member which is an ancestor of both "startMember"
// and "endMember". If "startMember" == "endMember", then "m" is
// "startMember".
RolapMember m = endMember;
while (m != null) {
if (m.ordinal < startMember.ordinal) {
if (compare(m, startMember, false) <= 0) {
break;
}
m = (RolapMember) m.getParentMember();
}
final RolapMember[] descendants = getDescendants(m, startMember.getLevel(), startOrdinal, endOrdinal);
for (int i = 0; i < descendants.length; i++) {
list.add(descendants[i]);
}
_getDescendants(m, startMember.getLevel(), startMember, endMember, list);
}

/**
* Returns the descendants of <code>member</code> at <code>level</code>
* whose ordinal is between <code>startOrdinal</code> and
* <code>endOrdinal</code>.
**/
private RolapMember[] getDescendants(
RolapMember member, Level level, int startOrdinal, int endOrdinal)
{
private void _getDescendants(
RolapMember member, Level level, RolapMember startMember,
RolapMember endMember, List result) {
// todo: Make algortihm more efficient: Use binary search.
RolapMember[] members = new RolapMember[] {member};
while (true) {
ArrayList children = new ArrayList();
getMemberChildren(children, members);
RolapMember[] childrenArray = RolapUtil.toArray(children);
int count = childrenArray.length, start = count, end = count;
for (int i = 0; i < count; i++) {
if (childrenArray[i].ordinal >= startOrdinal) {
start = i;
break;
int count = children.size(),
start,
end;
if (startMember == null) {
start = 0;
} else {
start = count;
for (int i = 0; i < count; i++) {
final RolapMember m = (RolapMember) children.get(i);
if (compare(m, startMember, false) >= 0) {
start = i;
break;
}
}
}
for (int i = start; i < count; i++) {
if (childrenArray[i].ordinal >= endOrdinal) {
end = i;
break;
if (endMember == null) {
end = count;
} else {
end = count;
for (int i = start; i < count; i++) {
final RolapMember m = (RolapMember) children.get(i);
if (compare(m, endMember, false) >= 0) {
end = i;
break;
}
}
}
members = new RolapMember[end - start];
System.arraycopy(childrenArray, start, members, 0, end - start);
if (members.length == 0 ||
members[0].getLevel() == level) {
return members;
List trimmedChildren = children.subList(start, end);
if (trimmedChildren.isEmpty() ||
((RolapMember) children.get(0)).getLevel() == level) {
result.addAll(trimmedChildren);
return;
}
members = (RolapMember[]) trimmedChildren.toArray(RolapUtil.emptyMemberArray);
}
}

Expand Down Expand Up @@ -438,9 +505,11 @@ public int compare(RolapMember m1, RolapMember m2, boolean siblingsAreEqual) {
int levelDepth1 = m1.getLevel().getDepth(),
levelDepth2 = m2.getLevel().getDepth();
if (levelDepth1 < levelDepth2) {
return compare(m1, (RolapMember) m2.getParentMember(), false);
final int c = compare(m1, (RolapMember) m2.getParentMember(), false);
return (c == 0) ? -1 : c;
} else if (levelDepth1 > levelDepth2) {
return compare((RolapMember) m1.getParentMember(), m2, false);
final int c = compare((RolapMember) m1.getParentMember(), m2, false);
return (c == 0) ? 1 : c;
} else {
return compare((RolapMember) m1.getParentMember(), (RolapMember) m2.getParentMember(), false);
}
Expand Down

0 comments on commit 70c4270

Please sign in to comment.