Skip to content

Commit

Permalink
MONDRIAN - Fixed bug #1575584. Need to compare members hierarchically
Browse files Browse the repository at this point in the history
       when doing inexact matching.

[git-p4: depot-paths = "//open/mondrian/": change = 7922]
  • Loading branch information
Zelaine Fong committed Oct 13, 2006
1 parent 7c47136 commit f44e805
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/main/mondrian/olap/fun/FunUtil.java
Expand Up @@ -1332,7 +1332,7 @@ public static int compareHierarchically(
* 1 if m1 collates after m2,
* 0 if m1 == m2.
*/
static int compareSiblingMembers(Member m1, Member m2) {
public static int compareSiblingMembers(Member m1, Member m2) {
// calculated members collate after non-calculated
final boolean calculated1 = m1.isCalculatedInQuery();
final boolean calculated2 = m2.isCalculatedInQuery();
Expand Down
36 changes: 10 additions & 26 deletions src/main/mondrian/rolap/RolapLevel.java
Expand Up @@ -446,32 +446,16 @@ public OlapElement lookupChild(
SchemaReader schemaReader, String name, int matchType)
{
Member[] levelMembers = schemaReader.getLevelMembers(this, true);
int bestMatch = -1;
for (int i = 0; i < levelMembers.length; i++) {
int rc = levelMembers[i].getName().compareTo(name);
if (rc == 0) {
return levelMembers[i];
}
if (matchType == MatchType.BEFORE) {
if (rc < 0 &&
(bestMatch == -1 ||
levelMembers[i].getName().compareTo(
levelMembers[bestMatch].getName()) > 0))
{
bestMatch = i;
}
} else if (matchType == MatchType.AFTER) {
if (rc > 0 &&
(bestMatch == -1 ||
levelMembers[i].getName().compareTo(
levelMembers[bestMatch].getName()) < 0))
{
bestMatch = i;
}
}
}
if (matchType != MatchType.EXACT && bestMatch != -1) {
return levelMembers[bestMatch];
if (levelMembers.length > 0) {
Member parent = levelMembers[0].getParentMember();
return
RolapUtil.findBestMemberMatch(
levelMembers,
(RolapMember) parent,
this,
name,
matchType,
false);
}
return null;
}
Expand Down
38 changes: 9 additions & 29 deletions src/main/mondrian/rolap/RolapSchemaReader.java
Expand Up @@ -300,35 +300,15 @@ public Member lookupMemberChildByName(
(RolapMember)parent, childName) :
sqlConstraintFactory.getMemberChildrenConstraint(null);
Member[] children = internalGetMemberChildren(parent, constraint);
int bestMatch = -1;
for (int i = 0; i < children.length; i++){
final Member child = children[i];
int rc = Util.compareName(child.getName(), childName);
if (rc == 0) {
return child;
}
if (matchType == MatchType.BEFORE) {
if (rc < 0 &&
(bestMatch == -1 ||
Util.compareName(
child.getName(),
children[bestMatch].getName()) > 0))
{
bestMatch = i;
}
} else if (matchType == MatchType.AFTER) {
if (rc > 0 &&
(bestMatch == -1 ||
Util.compareName(
child.getName(),
children[bestMatch].getName()) < 0))
{
bestMatch = i;
}
}
}
if (matchType != MatchType.EXACT && bestMatch != -1) {
return children[bestMatch];
if (children.length > 0) {
return
RolapUtil.findBestMemberMatch(
children,
(RolapMember) parent,
((RolapMember) children[0]).getRolapLevel(),
childName,
matchType,
true);
}
} catch (NumberFormatException e) {
// this was thrown in SqlQuery#quote(boolean numeric, Object value). This happens when
Expand Down
73 changes: 73 additions & 0 deletions src/main/mondrian/rolap/RolapUtil.java
Expand Up @@ -13,6 +13,7 @@

package mondrian.rolap;
import mondrian.olap.*;
import mondrian.olap.fun.FunUtil;
import mondrian.resource.MondrianResource;

import org.apache.log4j.Logger;
Expand Down Expand Up @@ -307,6 +308,78 @@ public static ExpCompiler createDependencyTestingCompiler(
ExpCompiler compiler) {
return new RolapDependencyTestingEvaluator.DteCompiler(compiler);
}

/**
* Locates a member specified by its member name, from an array of
* members. If an exact match isn't found, but a matchType of BEFORE
* or AFTER is specified, then the closest matching member is returned.
*
* @param members array of members to search from
* @param parent parent member corresponding to the member being searched
* for
* @param level level of the member
* @param searchName member name
* @param matchType match type
* @param caseInsensitive if true, use case insensitive search (if
* applicable) when when doing exact searches
*
* @return matching member (if it exists) or the closest matching one
* in the case of a BEFORE or AFTER search
*/
public static Member findBestMemberMatch(
Member[] members,
RolapMember parent,
RolapLevel level,
String searchName,
int matchType,
boolean caseInsensitive)
{
// create a member corresponding to the member we're trying
// to locate so we can use it to hierarchically compare against
// the members array
RolapMember searchMember = new RolapMember(parent, level, searchName);
int bestMatch = -1;
for (int i = 0; i < members.length; i++){
int rc;
final Member member = members[i];
if (matchType == MatchType.EXACT) {
if (caseInsensitive) {
rc = Util.compareName(member.getName(), searchName);
} else {
rc = member.getName().compareTo(searchName);
}
} else {
rc =
FunUtil.compareSiblingMembers(
member,
searchMember);
}
if (rc == 0) {
return member;
}
if (matchType == MatchType.BEFORE) {
if (rc < 0 &&
(bestMatch == -1 ||
FunUtil.compareSiblingMembers(
member, members[bestMatch]) > 0))
{
bestMatch = i;
}
} else if (matchType == MatchType.AFTER) {
if (rc > 0 &&
(bestMatch == -1 ||
FunUtil.compareSiblingMembers(
member, members[bestMatch]) < 0))
{
bestMatch = i;
}
}
}
if (matchType != MatchType.EXACT && bestMatch != -1) {
return members[bestMatch];
}
return null;
}

/**
* Writes to a string and also to an underlying writer.
Expand Down

0 comments on commit f44e805

Please sign in to comment.