Skip to content

Commit

Permalink
MONDRIAN: Share stars between measures and even cubes.
Browse files Browse the repository at this point in the history
[git-p4: depot-paths = "//open/mondrian/": change = 137]
  • Loading branch information
julianhyde committed Sep 10, 2002
1 parent fbe1f52 commit 969bba2
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 78 deletions.
65 changes: 8 additions & 57 deletions src/main/mondrian/rolap/RolapCube.java
Expand Up @@ -231,19 +231,13 @@ void register()
}
RolapStoredMeasure[] storedMeasures = new RolapStoredMeasure[v.size()];
v.copyInto(storedMeasures);
// create a star for each measure (todo: pool them)
// create measures (and stars for them, if necessary)
for (int i = 0; i < storedMeasures.length; i++) {
RolapStoredMeasure storedMeasure = storedMeasures[i];
RolapStar star = new RolapStar();
star.jdbcConnection =
((RolapConnection) getConnection()).jdbcConnection;
Vector tablesVector = new Vector();
// create a fact table
RolapStar.Table factTable = star.factTable = new RolapStar.Table(
new MondrianDef.Table(
this.factSchema, this.factTable, this.getAlias()),
null, null);
star.factTable.star = star;
RolapStar star = RolapStar.Pool.instance().getOrCreateStar(
(RolapConnection) getConnection(), this.factSchema,
this.factTable, this.getAlias());
RolapStar.Measure measure = new RolapStar.Measure();
measure.table = star.factTable;
measure.name = storedMeasure.column;
Expand All @@ -267,10 +261,10 @@ void register()
continue; // e.g. [Measures] hierarchy
}
RolapStar.Condition joinCondition = new RolapStar.Condition(
factTable.getAlias(), hierarchyUsage.foreignKey,
star.factTable.getAlias(), hierarchyUsage.foreignKey,
hierarchy.primaryKeyTable, hierarchy.primaryKey);
RolapStar.Table table = addJoin(
relation, factTable, joinCondition);
RolapStar.Table table = star.factTable.addJoin(
relation, joinCondition);
RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
for (int l = 0; l < levels.length; l++) {
RolapLevel level = levels[l];
Expand All @@ -287,7 +281,7 @@ void register()
column.name = nameColumn.name;
column.isNumeric = (level.flags & RolapLevel.NUMERIC) != 0;
table.columns.add(column);
factTable.star.mapLevelToColumn.put(level, column);
star.mapLevelToColumn.put(level, column);
} else {
Util.newInternal("bad exp type " + level.nameExp);
}
Expand All @@ -301,49 +295,6 @@ void register()
}
}

private static RolapStar.Table addJoin(
MondrianDef.Relation relation, RolapStar.Table parentTable,
RolapStar.Condition joinCondition) {
if (relation instanceof MondrianDef.Table) {
MondrianDef.Table table = (MondrianDef.Table) relation;
RolapStar.Table starTable = parentTable.findChild(table);
if (starTable == null) {
starTable = new RolapStar.Table(
table, parentTable, joinCondition);
starTable.star = parentTable.star;
parentTable.children.add(starTable);
}
return starTable;
} else if (relation instanceof MondrianDef.Join) {
MondrianDef.Join join = (MondrianDef.Join) relation;
RolapStar.Table leftTable = addJoin(
join.left, parentTable, joinCondition);
String leftAlias = join.leftAlias;
if (leftAlias == null) {
leftAlias = join.left.getAlias();
if (leftAlias == null) {
throw Util.newError(
"missing leftKeyAlias in " + relation);
}
}
String rightAlias = join.rightAlias;
if (rightAlias == null) {
rightAlias = join.right.getAlias();
if (rightAlias == null) {
throw Util.newError(
"missing rightKeyAlias in " + relation);
}
}
joinCondition = new RolapStar.Condition(
leftAlias, join.leftKey, rightAlias, join.rightKey);
RolapStar.Table rightTable = addJoin(
join.right, leftTable, joinCondition);
return rightTable;
} else {
throw Util.newInternal("bad relation type " + relation);
}
}

void addToFrom(SqlQuery query) {
boolean failIfExists = false;
query.addFrom(
Expand Down
153 changes: 134 additions & 19 deletions src/main/mondrian/rolap/RolapStar.java
Expand Up @@ -22,6 +22,7 @@
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.io.PrintWriter;

/**
Expand All @@ -36,13 +37,25 @@
* @version $Id$
**/
public class RolapStar {
public Connection jdbcConnection;
RolapConnection connection;
Measure[] measures;
public Table factTable;
Table[] tables;
/** todo: better, the dimensional model should hold the mapping **/
Hashtable mapLevelToColumn = new Hashtable();

/**
* Please use {@link Pool#getOrCreateStar} to create a {@link
* RolapStar}.
*/
RolapStar(RolapConnection connection) {
this.connection = connection;
}

public Connection getJdbcConnection() {
return connection.jdbcConnection;
}

/**
* Reads a cell of <code>measure</code>, where <code>columns</code> are
* constrained to <code>values</code>. <code>values</code> must be the
Expand All @@ -56,7 +69,7 @@ Object getCell(CellRequest request)
Util.assertTrue(columns.length == values.length);
SqlQuery sqlQuery;
try {
sqlQuery = new SqlQuery(jdbcConnection.getMetaData());
sqlQuery = new SqlQuery(connection.jdbcConnection.getMetaData());
} catch (SQLException e) {
throw Util.getRes().newInternal(e, "while computing single cell");
}
Expand All @@ -83,7 +96,7 @@ Object getCell(CellRequest request)
ResultSet resultSet = null;
try {
resultSet = RolapUtil.executeQuery(
jdbcConnection, sql, "RolapStar.getCell");
connection.jdbcConnection, sql, "RolapStar.getCell");
Object o = null;
if (resultSet.next()) {
o = resultSet.getObject(1);
Expand All @@ -107,6 +120,22 @@ Object getCell(CellRequest request)
}
}

/**
* Helper method, returns whether <code>relation</code> is a table named
* <code>factTable.factSchema</code>.
*/
static boolean matchesTable(
MondrianDef.Relation relation, String schema, String table) {
if (relation instanceof MondrianDef.Table) {
MondrianDef.Table t = (MondrianDef.Table) relation;
if (t.name.equals(table) &&
Util.equals(t.schema, schema)) {
return true;
}
}
return false;
}

// static class Segment
// {
// Object[][] keys;
Expand Down Expand Up @@ -156,7 +185,7 @@ public int getCardinality()
SqlQuery sqlQuery;
try {
sqlQuery = new SqlQuery(
table.star.jdbcConnection.getMetaData());
table.star.connection.jdbcConnection.getMetaData());
} catch (SQLException e) {
throw Util.getRes().newInternal(
e,
Expand Down Expand Up @@ -185,7 +214,7 @@ public int getCardinality()
ResultSet resultSet = null;
try {
resultSet = RolapUtil.executeQuery(
table.star.jdbcConnection, sql,
table.star.connection.jdbcConnection, sql,
"RolapStar.Column.getCardinality");
Util.assertTrue(resultSet.next());
cardinality = resultSet.getInt(1);
Expand Down Expand Up @@ -216,9 +245,7 @@ public static class Measure extends Column
public static class Table
{
public RolapStar star;
private MondrianDef.Relation relation;
private String schema;
private String table;
MondrianDef.Relation relation;
public String primaryKey;
public String foreignKey;
ArrayList columns = new ArrayList();
Expand All @@ -234,34 +261,76 @@ public Table(
MondrianDef.Relation relation, Table parent,
Condition joinCondition) {
this.relation = relation;
if (relation instanceof MondrianDef.Table) {
MondrianDef.Table table = (MondrianDef.Table) relation;
this.schema = table.schema;
this.table = table.name;
} else {
throw Util.newInternal("todo:");
}
Util.assertTrue(
relation instanceof MondrianDef.Table,
"todo: allow dimension which is not a Table, " + relation);
this.parent = parent;
this.joinCondition = joinCondition;
Util.assertTrue((parent == null) == (joinCondition == null));
}
public String getAlias() {
return relation.getAlias();
}
/**
* Extends this 'leg' of the star by adding <code>relation</code>
* joined by <code>joinCondition</code>. If the same expression is
* already present, does not create it again.
*/
synchronized Table addJoin(
MondrianDef.Relation relation,
RolapStar.Condition joinCondition) {
if (relation instanceof MondrianDef.Table) {
MondrianDef.Table table = (MondrianDef.Table) relation;
RolapStar.Table starTable = findChild(table);
if (starTable == null) {
starTable = new RolapStar.Table(table, this, joinCondition);
starTable.star = this.star;
this.children.add(starTable);
}
return starTable;
} else if (relation instanceof MondrianDef.Join) {
MondrianDef.Join join = (MondrianDef.Join) relation;
RolapStar.Table leftTable = addJoin(join.left, joinCondition);
String leftAlias = join.leftAlias;
if (leftAlias == null) {
leftAlias = join.left.getAlias();
if (leftAlias == null) {
throw Util.newError(
"missing leftKeyAlias in " + relation);
}
}
String rightAlias = join.rightAlias;
if (rightAlias == null) {
rightAlias = join.right.getAlias();
if (rightAlias == null) {
throw Util.newError(
"missing rightKeyAlias in " + relation);
}
}
joinCondition = new RolapStar.Condition(
leftAlias, join.leftKey, rightAlias, join.rightKey);
RolapStar.Table rightTable = leftTable.addJoin(
join.right, joinCondition);
return rightTable;
} else {
throw Util.newInternal("bad relation type " + relation);
}
}

/**
* Returns a child table which maps onto a given relation, or null if
* there is none.
*/
public Table findChild(MondrianDef.Table table) {
for (int i = 0; i < children.size(); i++) {
Table childTable = (Table) children.get(i);
if (childTable.table.equals(table.name) &&
Util.equals(childTable.schema, table.schema)) {
return childTable;
Table child = (Table) children.get(i);
if (matchesTable(child.relation, table.schema, table.name)) {
return child;
}
}
return null;
}

/**
* Returns a descendant with a given alias, or null if none found.
*/
Expand Down Expand Up @@ -352,6 +421,52 @@ String toString(SqlQuery query) {
query.quoteIdentifier(table2, column2);
}
}

/**
* <code>Pool</code> is a registry for {@link RolapStar}s. It is a
* singleton.
*/
static class Pool {
private static Pool singleton;
private ArrayList stars = new ArrayList();

private Pool() {
}

/**
* Returns the singleton instance, creating it if necessary.
*/
synchronized static Pool instance() {
if (singleton == null) {
singleton = new Pool();
}
return singleton;
}

/**
* Looks up a {@link RolapStar}, creating it if it does not exist.
*
* <p> {@link RolapStar.Table#addJoin} works in a similar way.
*/
synchronized RolapStar getOrCreateStar(
RolapConnection connection, String factSchema,
String factTable, String alias) {
for (Iterator iterator = stars.iterator(); iterator.hasNext();) {
RolapStar star = (RolapStar) iterator.next();
if (star.connection == connection &&
matchesTable(star.factTable.relation, factSchema, factTable)) {
return star;
}
}
RolapStar star = new RolapStar(connection);
star.factTable = new Table(
new MondrianDef.Table(factSchema, factTable, alias),
null, null);
star.factTable.star = star;
stars.add(star);
return star;
}
}
}

// End RolapStar.java
4 changes: 2 additions & 2 deletions src/main/mondrian/rolap/agg/Segment.java
Expand Up @@ -214,7 +214,7 @@ SegmentDataset load()
SqlQuery sqlQuery;
try {
sqlQuery = new SqlQuery(
star.jdbcConnection.getMetaData());
star.getJdbcConnection().getMetaData());
} catch (SQLException e) {
throw Util.getRes().newInternal(e, "while loading segment");
}
Expand Down Expand Up @@ -246,7 +246,7 @@ SegmentDataset load()
ResultSet resultSet = null;
try {
resultSet = RolapUtil.executeQuery(
star.jdbcConnection, sql, "Segment.load");
star.getJdbcConnection(), sql, "Segment.load");
Vector rows = new Vector();
while (resultSet.next()) {
Object[] row = new Object[arity + 1];
Expand Down

0 comments on commit 969bba2

Please sign in to comment.