Skip to content

Commit

Permalink
MONDRIAN: Fix bug MONDRIAN-1047, "IllegalArgumentException when cube …
Browse files Browse the repository at this point in the history
…has closure

    tables and many levels".

[git-p4: depot-paths = "//open/mondrian/": change = 14829]
  • Loading branch information
julianhyde committed Dec 9, 2011
1 parent 5ba7721 commit 7cbbafe
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 20 deletions.
13 changes: 9 additions & 4 deletions src/main/mondrian/rolap/RolapCube.java
Expand Up @@ -150,10 +150,6 @@ private RolapCube(
if (! isCache) {
star.setCacheAggregations(isCache);
}
closureColumnBitKey =
BitKey.Factory.makeBitKey(star.getColumnCount());
} else {
closureColumnBitKey = null;
}

if (getLogger().isDebugEnabled()) {
Expand Down Expand Up @@ -210,6 +206,15 @@ private RolapCube(
registerDimension(dimension);
}

// Initialize closure bit key only when we know how many columns are in
// the star.
if (! isVirtual()) {
closureColumnBitKey =
BitKey.Factory.makeBitKey(star.getColumnCount());
} else {
closureColumnBitKey = null;
}

schema.addCube(this);
}

Expand Down
24 changes: 8 additions & 16 deletions testsrc/main/mondrian/test/PerformanceTest.java
Expand Up @@ -345,7 +345,14 @@ public void testBigResultsWithBigSchemaPerforms() {
TestContext testContext =
TestContext.instance().createSubstitutingCube(
"Sales",
extraGenders(1000),
TestContext.repeatString(
1000,
"<Dimension name=\"Gender%d \" foreignKey=\"customer_id\">"
+ " <Hierarchy hasAll=\"true\" allMemberName=\"All Gender\" primaryKey=\"customer_id\">"
+ " <Table name=\"customer\"/>"
+ " <Level name=\"Gender\" column=\"gender\" uniqueMembers=\"true\"/>"
+ " </Hierarchy>"
+ "</Dimension>"),
null);
String mdx =
"with "
Expand All @@ -371,21 +378,6 @@ public void testBigResultsWithBigSchemaPerforms() {
printDuration("testBigResultsWithBigSchemaPerforms", start);
}

private String extraGenders(final int numGenders) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < numGenders;i++) {
builder.append(
String.format(
"<Dimension name=\"Gender%d \" foreignKey=\"customer_id\">"
+ "<Hierarchy hasAll=\"true\" allMemberName=\"All Gender\" primaryKey=\"customer_id\">"
+ " <Table name=\"customer\"/>"
+ " <Level name=\"Gender\" column=\"gender\" uniqueMembers=\"true\"/>"
+ " </Hierarchy>"
+ "</Dimension>", i));
}
return builder.toString();
}

/**
* Runs a query that performs a lot of in-memory calculation.
*
Expand Down
36 changes: 36 additions & 0 deletions testsrc/main/mondrian/test/SchemaTest.java
Expand Up @@ -4283,5 +4283,41 @@ public void testCollapsedError() throws Exception {
"select {[Product].[Product Family].Members} on rows, {[Measures].[Unit Sales]} on columns from [Foo]",
"Too many errors, '1', while loading/reloading aggregates.");
}

/**
* Test case for bug
* <a href="http://jira.pentaho.com/browse/MONDRIAN-1047">MONDRIAN-1047,
* "IllegalArgumentException when cube has closure tables and many
* levels"</a>.
*/
public void testBugMondrian1047() {
// Test case only works under MySQL, due to how columns are quoted.
switch (TestContext.instance().getDialect().getDatabaseProduct()) {
case MYSQL:
break;
default:
return;
}
TestContext testContext =
TestContext.instance().createSubstitutingCube(
"HR",
TestContext.repeatString(
100,
"<Dimension name='Position %1$d' foreignKey='employee_id'>\n"
+ " <Hierarchy hasAll='true' allMemberName='All Position' primaryKey='employee_id'>\n"
+ " <Table name='employee'/>\n"
+ " <Level name='Position Title' uniqueMembers='false' ordinalColumn='position_id'>\n"
+ " <KeyExpression><SQL dialect='generic'>`position_title` + %1$d</SQL></KeyExpression>\n"
+ " </Level>\n"
+ " </Hierarchy>\n"
+ "</Dimension>"),
null);
testContext.assertQueryReturns(
"select from [HR]",
"Axis #0:\n"
+ "{}\n"
+ "$39,431.67");
}
}

// End SchemaTest.java
19 changes: 19 additions & 0 deletions testsrc/main/mondrian/test/TestContext.java
Expand Up @@ -1979,6 +1979,25 @@ public static String levelName(
return hierarchyName(dimension, hierarchy) + ".[" + level + "]";
}

/**
* Returns count copies of a string. Format strings within string are
* substituted, per {@link String#format}.
*
* @param count Number of copies
* @param format String template
* @return Multiple copies of a string
*/
public static String repeatString(
final int count,
String format)
{
final Formatter formatter = new Formatter();
for (int i = 0; i < count; i++) {
formatter.format(format, i);
}
return formatter.toString();
}

//~ Inner classes ----------------------------------------------------------

public static class SnoopingSchemaProcessor
Expand Down

0 comments on commit 7cbbafe

Please sign in to comment.