Skip to content

Commit

Permalink
MONDRIAN: fixes for MONDRIAN-496 and MONDRIAN-557, as well as some te…
Browse files Browse the repository at this point in the history
…st cleanup in order to get the test suite passing with aggregates enabled

[git-p4: depot-paths = "//open/mondrian-release/3.1/": change = 13251]
  • Loading branch information
Will Gorman committed Dec 19, 2009
1 parent 5f0d873 commit 75759a2
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 112 deletions.
184 changes: 98 additions & 86 deletions src/main/mondrian/rolap/aggmatcher/AggTableManager.java
Expand Up @@ -188,108 +188,120 @@ private void loadRolapStarAggregates() throws SQLException {
try {
DefaultRules rules = DefaultRules.getInstance();
JdbcSchema db = getJdbcSchema();
// loads tables, not their columns
db.load();
// if we don't synchronize this on the db object,
// we may end up getting a Concurrency exception due to
// calls to other instances of AggTableManager.finalCleanUp()
synchronized (db) {
// fix for MONDRIAN-496
// flush any existing usages of the jdbc schema, so we
// don't accidentally use another star's metadata
db.flushUsages();

// loads tables, not their columns
db.load();

loop:
for (RolapStar star : getStars()) {
// This removes any AggStars from any previous invocation of
// this method (if any)
star.prepareToLoadAggregates();

List<ExplicitRules.Group> aggGroups = getAggGroups(star);
for (ExplicitRules.Group group : aggGroups) {
group.validate(msgRecorder);
}

loop:
for (RolapStar star : getStars()) {
// This removes any AggStars from any previous invocation of
// this method (if any)
star.prepareToLoadAggregates();
String factTableName = star.getFactTable().getAlias();

List<ExplicitRules.Group> aggGroups = getAggGroups(star);
for (ExplicitRules.Group group : aggGroups) {
group.validate(msgRecorder);
}
JdbcSchema.Table dbFactTable = db.getTable(factTableName);
if (dbFactTable == null) {
msgRecorder.reportWarning(
"No Table found for fact name="
+ factTableName);
continue loop;
}

String factTableName = star.getFactTable().getAlias();
// For each column in the dbFactTable, figure out it they
// are measure or foreign key columns

JdbcSchema.Table dbFactTable = db.getTable(factTableName);
if (dbFactTable == null) {
msgRecorder.reportWarning(
"No Table found for fact name="
+ factTableName);
continue loop;
}
bindToStar(dbFactTable, star, msgRecorder);
String schema = dbFactTable.table.schema;

// For each column in the dbFactTable, figure out it they are
// measure or foreign key columns
bindToStar(dbFactTable, star, msgRecorder);
String schema = dbFactTable.table.schema;

// Now look at all tables in the database and per table, first
// see if it is a match for an aggregate table for this fact
// table and second see if its columns match foreign key and
// level columns.
for (JdbcSchema.Table dbTable : db.getTables()) {
String name = dbTable.getName();

// Do the catalog schema aggregate excludes, exclude this
// table name.
if (ExplicitRules.excludeTable(name, aggGroups)) {
continue;
}
// Now look at all tables in the database and per table,
// first see if it is a match for an aggregate table for
// this fact table and second see if its columns match
// foreign key and level columns.

// First see if there is an ExplicitRules match. If so, then
// if all of the columns match up, then make an AggStar.
// On the other hand, if there is no ExplicitRules match,
// see if there is a Default match. If so and if all the
// columns match up, then also make an AggStar.
ExplicitRules.TableDef tableDef =
ExplicitRules.getIncludeByTableDef(name, aggGroups);

boolean makeAggStar = false;
// Is it handled by the ExplicitRules
if (tableDef != null) {
// load columns
dbTable.load();
makeAggStar = tableDef.columnsOK(
star,
dbFactTable,
dbTable,
msgRecorder);
}
if (! makeAggStar) {
// Is it handled by the DefaultRules
if (rules.matchesTableName(factTableName, name)) {
for (JdbcSchema.Table dbTable : db.getTables()) {
String name = dbTable.getName();

// Do the catalog schema aggregate excludes, exclude
// this table name.
if (ExplicitRules.excludeTable(name, aggGroups)) {
continue;
}

// First see if there is an ExplicitRules match. If so,
// then if all of the columns match up, then make an
// AggStar. On the other hand, if there is no
// ExplicitRules match, see if there is a Default
// match. If so and if all the columns match up, then
// also make an AggStar.
ExplicitRules.TableDef tableDef =
ExplicitRules.getIncludeByTableDef(name, aggGroups);

boolean makeAggStar = false;
// Is it handled by the ExplicitRules
if (tableDef != null) {
// load columns
dbTable.load();
makeAggStar = rules.columnsOK(
makeAggStar = tableDef.columnsOK(
star,
dbFactTable,
dbTable,
msgRecorder);
}
}

if (! makeAggStar) {
// Is it handled by the DefaultRules
if (rules.matchesTableName(factTableName, name)) {
// load columns
dbTable.load();
makeAggStar = rules.columnsOK(
star,
dbFactTable,
dbTable,
msgRecorder);
}
}

if (makeAggStar) {
dbTable.setTableUsageType(
JdbcSchema.TableUsageType.AGG);
String alias = null;
dbTable.table = new MondrianDef.Table(
schema,
name,
alias,
null); // don't know about table hints
AggStar aggStar = AggStar.makeAggStar(
star,
dbTable,
msgRecorder);
if (aggStar.getSize() > 0) {
star.addAggStar(aggStar);
} else {
getLogger().warn(
mres.AggTableZeroSize.str(
aggStar.getFactTable().getName(),
factTableName));
if (makeAggStar) {
dbTable.setTableUsageType(
JdbcSchema.TableUsageType.AGG);
String alias = null;
dbTable.table = new MondrianDef.Table(
schema,
name,
alias,
null); // don't know about table hints
AggStar aggStar = AggStar.makeAggStar(
star,
dbTable,
msgRecorder);
if (aggStar.getSize() > 0) {
star.addAggStar(aggStar);
} else {
getLogger().warn(
mres.AggTableZeroSize.str(
aggStar.getFactTable().getName(),
factTableName));
}
}
// Note: if the dbTable name matches but the columnsOK
// does not, then this is an error and the aggregate
// tables can not be loaded.
// We do not "reset" the column usages in the dbTable
// allowing it maybe to match another rule.
}
// Note: if the dbTable name matches but the columnsOK does
// not, then this is an error and the aggregate tables
// can not be loaded.
// We do not "reset" the column usages in the dbTable
// allowing it maybe to match another rule.
}
}
} catch (RecorderException ex) {
Expand Down
29 changes: 28 additions & 1 deletion src/main/mondrian/rolap/aggmatcher/JdbcSchema.java
Expand Up @@ -649,6 +649,14 @@ public int numberOfUsages() {
return usages.size();
}

/**
* flushes all star usage references
*/
public void flushUsages() {
usages.clear();
usageTypes.clear();
}

/**
* Return true if the column has at least one usage.
*/
Expand Down Expand Up @@ -824,6 +832,16 @@ public void load() throws SQLException {
loadColumns();
}

/**
* flushes all star usage references
*/
public void flushUsages() {
tableUsageType = TableUsageType.UNKNOWN;
for (Table.Column col : getColumns()) {
col.flushUsages();
}
}

/**
* Returns the name of the table.
*/
Expand Down Expand Up @@ -1078,7 +1096,7 @@ public void load() throws SQLException {
loadTables();
}

protected void clear() {
protected synchronized void clear() {
// keep the DataSource, clear/reset everything else
allTablesLoaded = false;
schema = null;
Expand Down Expand Up @@ -1145,6 +1163,15 @@ public synchronized Collection<Table> getTables() {
return getTablesMap().values();
}

/**
* flushes all star usage references
*/
public synchronized void flushUsages() {
for (Table table : getTables()) {
table.flushUsages();
}
}

/**
* Gets a table by name.
*/
Expand Down
7 changes: 4 additions & 3 deletions testsrc/main/mondrian/olap/fun/FunctionTest.java
Expand Up @@ -2638,8 +2638,9 @@ public void testFirstInLevel5() {
executeQuery(
"select {[Time].[1997].[Q2].[4].Parent} on columns,"
+ "{[Gender].[M]} on rows from Sales");
Assert.assertTrue(result.getAxes()[0].getPositions().get(0).get(0)
.getName().equals("Q2"));
Assert.assertTrue(
result.getAxes()[0].getPositions().get(0).get(0)
.getName().equals("Q2"));
}

public void testAll5() {
Expand Down Expand Up @@ -6818,7 +6819,7 @@ public void testHierarchizeOrdinal() {

// clear the cache so that future tests don't fail that expect a
// specific set of cubes
connection.getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
}

public void testIntersect() {
Expand Down
18 changes: 10 additions & 8 deletions testsrc/main/mondrian/rolap/NonEmptyTest.java
Expand Up @@ -924,7 +924,7 @@ public void testExpandWithOneEmptyInput() {
}

public void testExpandWithTwoEmptyInputs() {
getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
propSaver.set(MondrianProperties.instance().ExpandNonNative, true);
// Query should return empty result.
checkNotNative(
Expand Down Expand Up @@ -1873,7 +1873,7 @@ public void testLookupMember2() {
* is not evaluated in NON EMPTY context.
*/
public void testCalcMemberWithNonEmptyCrossJoin() {
getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
Result result = executeQuery(
"with member [Measures].[CustomerCount] as \n"
+ "'Count(CrossJoin({[Product].[All Products]}, [Customers].[Name].Members))'\n"
Expand Down Expand Up @@ -1929,7 +1929,7 @@ public TestCase(
}

private Result run() {
getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
IntegerProperty monLimit =
MondrianProperties.instance().ResultLimit;
int oldLimit = monLimit.get();
Expand Down Expand Up @@ -2250,7 +2250,8 @@ public void testNonEmptyDescendants() {
// now we run the same query again, this time everything must come out
// of the cache
RolapNativeRegistry reg = getRegistry(con);
reg.setListener(new Listener() {
reg.setListener(
new Listener() {
public void foundEvaluator(NativeEvent e) {
}

Expand Down Expand Up @@ -3664,10 +3665,11 @@ private void checkNotNative(
{
mdx = TestContext.instance().upgradeQuery(mdx);

getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
Connection con = getTestContext().getFoodMartConnection(false);
RolapNativeRegistry reg = getRegistry(con);
reg.setListener(new Listener() {
reg.setListener(
new Listener() {
public void foundEvaluator(NativeEvent e) {
fail("should not be executed native");
}
Expand Down Expand Up @@ -3755,7 +3757,7 @@ private void checkNative(

mdx = TestContext.instance().upgradeQuery(mdx);

getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
try {
logger.debug("*** Native: " + mdx);
boolean reuseConnection = !freshConnection;
Expand Down Expand Up @@ -3789,7 +3791,7 @@ private void checkNative(
con.close();

logger.debug("*** Interpreter: " + mdx);
getConnection().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();
con = getTestContext().getFoodMartConnection(false);
reg = getRegistry(con);
listener.setFoundEvaluator(false);
Expand Down
7 changes: 3 additions & 4 deletions testsrc/main/mondrian/rolap/TestAggregationManager.java
Expand Up @@ -1241,7 +1241,7 @@ public void testOrdinalExprAggTuplesAndChildren() {
{
return;
}
AggregationManager.instance().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();

String cube = "<Cube name=\"Sales_Prod_Ord\">\n"
+ " <Table name=\"sales_fact_1997\"/>\n"
Expand Down Expand Up @@ -1385,8 +1385,7 @@ public void testAggregatingTuples() {
}

// flush cache, to be sure sql is executed

AggregationManager.instance().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();

// This first query verifies that simple collapsed levels in aggregate
// tables load as tuples correctly. The collapsed levels appear
Expand Down Expand Up @@ -1495,7 +1494,7 @@ public void testCollapsedChildren() {
}

// flush cache to be sure sql is executed
AggregationManager.instance().getCacheControl(null).flushSchemaCache();
TestContext.instance().flushSchemaCache();

SqlPattern[] patterns = {
new SqlPattern(
Expand Down

0 comments on commit 75759a2

Please sign in to comment.