/* // $Id: //guest/julian_hyde/mondrian/src/main/mondrian/rolap/RolapCube.java#1 $ // This software is subject to the terms of the Common Public License // Agreement, available at the following URL: // http://www.opensource.org/licenses/cpl.html. // (C) Copyright 2001-2002 Kana Software, Inc. and others. // All Rights Reserved. // You must accept the terms of that agreement to use this software. // // jhyde, 10 August, 2001 */ package mondrian.rolap; import mondrian.olap.*; import java.util.Hashtable; import java.util.Vector; import java.util.Properties; import java.sql.*; /** * <code>RolapCube</code> implements {@link Cube} for a ROLAP database. * * @author jhyde * @since 10 August, 2001 * @version $Id: //guest/julian_hyde/mondrian/src/main/mondrian/rolap/RolapCube.java#1 $ */ class RolapCube extends CubeBase { RolapHierarchy measuresHierarchy; Hashtable mapNameToMember = new Hashtable(); Hashtable mapElementToElement = new Hashtable(); /** For SQL generator. Name of fact table. */ String factTable; /** To access all measures stored in the fact table. */ CellReader cellReader; RolapCube( RolapConnection connection, MondrianDef.Schema xmlSchema, MondrianDef.Cube xmlCube) { this.connection = connection; this.name = xmlCube.name; this.factTable = xmlCube.factTable; this.dimensions = new RolapDimension[xmlCube.dimensions.length + 1]; RolapDimension measuresDimension = new RolapDimension(this, 0, "Measures"); this.dimensions[0] = measuresDimension; this.measuresHierarchy = measuresDimension.newHierarchy(null, false, null, null, null); RolapLevel measuresLevel = this.measuresHierarchy.newLevel( "MeasuresLevel", null); for (int i = 0; i < xmlCube.dimensions.length; i++) { MondrianDef.CubeDimension xmlCubeDimension = xmlCube.dimensions[i]; MondrianDef.Dimension xmlDimension = xmlCubeDimension.getDimension(xmlSchema); dimensions[i + 1] = new RolapDimension(this, i + 1, xmlDimension, xmlCubeDimension); } RolapMeasure measures[] = new RolapMeasure[ xmlCube.measures.length]; for (int i = 0; i < xmlCube.measures.length; i++) { measures[i] = RolapMeasure.create( null, measuresLevel, xmlCube.measures[i]); } this.measuresHierarchy.memberReader = new CacheMemberReader( new MeasureMemberSource(measuresHierarchy, measures)); init(); } /** * Creates a <code>RolapCube</code> from a virtual cube. **/ RolapCube( RolapConnection connection, MondrianDef.Schema xmlSchema, MondrianDef.VirtualCube xmlVirtualCube) { this.connection = connection; this.name = xmlVirtualCube.name; this.factTable = null; this.dimensions = new RolapDimension[ xmlVirtualCube.dimensions.length + 1]; RolapDimension measuresDimension = new RolapDimension( this, 0, "Measures"); this.dimensions[0] = measuresDimension; this.measuresHierarchy = measuresDimension.newHierarchy(null, false, null, null, null); this.measuresHierarchy.newLevel("MeasuresLevel", null); for (int i = 0; i < xmlVirtualCube.dimensions.length; i++) { MondrianDef.VirtualCubeDimension xmlCubeDimension = xmlVirtualCube.dimensions[i]; MondrianDef.Dimension xmlDimension = xmlCubeDimension.getDimension( xmlSchema); dimensions[i + 1] = new RolapDimension( this, i + 1, xmlDimension, xmlCubeDimension); } RolapMeasure measures[] = new RolapMeasure[ xmlVirtualCube.measures.length]; for (int i = 0; i < xmlVirtualCube.measures.length; i++) { // Lookup a measure in an existing cube. (Don't know whether it // will confuse things that this measure still points to its 'real' // cube.) MondrianDef.VirtualCubeMeasure xmlMeasure = xmlVirtualCube.measures[i]; Cube cube = connection.lookupCube(xmlMeasure.cubeName); Member[] cubeMeasures = cube.getMeasures(); for (int j = 0; j < cubeMeasures.length; j++) { if (cubeMeasures[j].getUniqueName().equals(xmlMeasure.name)) { measures[i] = (RolapMeasure) cubeMeasures[j]; break; } } if (measures[i] == null) { throw Util.newInternal( "could not find measure '" + xmlMeasure.name + "' in cube '" + xmlMeasure.cubeName + "'"); } } this.measuresHierarchy.memberReader = new CacheMemberReader( new MeasureMemberSource(measuresHierarchy, measures)); init(); } RolapCube(RolapConnection connection) { this.connection = connection; this.name = "Sales"; this.factTable = "sales_fact_1997"; this.dimensions = new RolapDimension[0]; RolapDimension dimension; RolapHierarchy hierarchy; RolapLevel level; dimension = newDimension("Measures"); hierarchy = dimension.newHierarchy(null, false, null, null, null); this.measuresHierarchy = hierarchy; level = hierarchy.newLevel("MeasuresLevel", null); RolapLevel measuresLevel = level; dimension = newDimension("Store"); hierarchy = dimension.newHierarchy( null, true, "SELECT * FROM \"store\"", "store_id", "store_id"); level = hierarchy.newLevel("Store Country", "store_country"); level = hierarchy.newLevel("Store State", "store_state"); level = hierarchy.newLevel("Store City", "store_city"); level = hierarchy.newLevel("Store Name", "store_name"); dimension = newDimension("Time"); hierarchy = dimension.newHierarchy( null, false, "SELECT * FROM \"time_by_day\"", "time_id", "time_id"); level = hierarchy.newLevel("Year", "the_year", null, RolapLevel.NUMERIC); level = hierarchy.newLevel("Quarter", "quarter"); level = hierarchy.newLevel("Month", "month_of_year", null, RolapLevel.NUMERIC); dimension = newDimension("Product"); hierarchy = dimension.newHierarchy( null, true, "SELECT * FROM \"product\", \"product_class\" " + "WHERE \"product\".\"product_class_id\" = \"product_class\".\"product_class_id\"", "product_id", "product_id"); level = hierarchy.newLevel("Product Family", "product_family"); level = hierarchy.newLevel("Product Department", "product_department"); level = hierarchy.newLevel("Product Category", "product_category"); level = hierarchy.newLevel("Product Subcategory", "product_subcategory"); level = hierarchy.newLevel("Brand Name", "brand_name"); level = hierarchy.newLevel("Product Name", "product_name"); dimension = newDimension("Promotion Media"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"promotion\"", "promotion_id", "promotion_id"); level = hierarchy.newLevel("Media Type", "media_type"); dimension = newDimension("Promotions"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"promotion\"", "promotion_id", "promotion_id"); level = hierarchy.newLevel("Promotion Name", "promotion_name"); dimension = newDimension("Customers"); hierarchy = dimension.newHierarchy(null, true, "SELECT *, \"fname\" + ' ' + \"lname\" as \"name\" FROM \"customer\"", "customer_id", "customer_id"); level = hierarchy.newLevel("Country", "country"); level = hierarchy.newLevel("State Province", "state_province"); level = hierarchy.newLevel("City", "city"); level = hierarchy.newLevel("Name", "name"); dimension = newDimension("Education Level"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"customer\"", "customer_id", "customer_id"); level = hierarchy.newLevel("Education Level", "education"); dimension = newDimension("Gender"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"customer\"", "customer_id", "customer_id"); level = hierarchy.newLevel("Gender", "gender"); dimension = newDimension("Marital Status"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"customer\"", "customer_id", "customer_id"); level = hierarchy.newLevel("Marital Status", "marital_status"); dimension = newDimension("Yearly Income"); hierarchy = dimension.newHierarchy(null, true, "SELECT * FROM \"customer\"", "customer_id", "customer_id"); level = hierarchy.newLevel("Yearly Income", "yearly_income"); this.measuresHierarchy.memberReader = new CacheMemberReader( new MeasureMemberSource( measuresHierarchy, new RolapMember[] { new RolapStoredMeasure(null, measuresLevel, "Unit Sales", "unit_sales", "sum", "#"), new RolapStoredMeasure(null, measuresLevel, "Store Cost", "store_cost", "sum", "Currency"), new RolapStoredMeasure(null, measuresLevel, "Store Sales", "store_sales", "sum", "Currency")})); init(); } private RolapDimension newDimension(String name) { RolapDimension dimension = new RolapDimension(this, dimensions.length, name); this.dimensions = (RolapDimension[]) RolapUtil.addElement( this.dimensions, dimension); return dimension; } void init() { for (int i = 0; i < dimensions.length; i++) { ((RolapDimension) dimensions[i]).init(); } this.cellReader = new AvidCellReader(this); if (false) { this.cellReader = new CachingCellReader(this, this.cellReader); } RolapAggregationManager.instance().register(this); } // implement NameResolver public Member lookupMemberFromCache(String s) { return (Member) mapNameToMember.get(s); } public void lookupMembers( Vector memberNames, Hashtable mapNameToMember) { throw new Error("unsupported"); } public Member[] getMemberChildren(Member[] parentOlapMembers) { if (parentOlapMembers.length == 0) { return new RolapMember[0]; } RolapHierarchy hierarchy = (RolapHierarchy) parentOlapMembers[0].getHierarchy(); for (int i = 1; i < parentOlapMembers.length; i++) { Util.assert( parentOlapMembers[i].getHierarchy() == hierarchy); } if (!(parentOlapMembers instanceof RolapMember[])) { Member[] old = parentOlapMembers; parentOlapMembers = new RolapMember[old.length]; System.arraycopy(old, 0, parentOlapMembers, 0, old.length); } return hierarchy.memberReader.getMemberChildren( (RolapMember[]) parentOlapMembers); } public Member[] getMembersForQuery( String sQuery, Vector calcMembers) { throw new Error("unsupported"); } String getAlias() { return "fact"; } }; class AvidCellReader implements CellReader { RolapCube cube; AvidCellReader(RolapCube cube) { this.cube = cube; } // implement CellReader public Object get(Evaluator evaluator) { RolapEvaluator rolapEvaluator = (RolapEvaluator) evaluator; return RolapAggregationManager.instance().getCell( rolapEvaluator.currentMembers); } }; class OldAvidCellReader implements CellReader { OldAvidCellReader() {} // implement CellReader public Object get(Evaluator evaluator) { RolapCube cube = (RolapCube) evaluator.getCube(); RolapConnection.SqlQuery sqlQuery = new RolapConnection.SqlQuery(); RolapDimension[] dimensions = (RolapDimension[]) cube.getDimensions(); for (int i = dimensions.length - 1; i >= 0; i--) { RolapMember member = (RolapMember) evaluator.getContext(dimensions[i]); RolapHierarchy hierarchy = (RolapHierarchy) member.getHierarchy(); hierarchy.memberReader.qualifyQuery(sqlQuery, member); } String sql = sqlQuery.toString(); Statement statement = null; ResultSet resultSet = null; try { if (RolapUtil.debugOut != null) { RolapUtil.debugOut.println( "AvidCellReader: executing sql [" + sql + "]"); } java.sql.Connection connection = ((RolapConnection) cube.getConnection()).jdbcConnection; statement = connection.createStatement(); resultSet = statement.executeQuery(sql); Object o = null; if (resultSet.next()) { o = resultSet.getObject(1); } if (o == null) { o = Util.nullValue; // convert to placeholder } return o; } catch (SQLException e) { throw Util.getRes().newInternal( e, "while computing measure; sql=[" + sql + "]"); } finally { try { if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } } catch (SQLException e) { // ignore } } } }; class MemberKey { RolapMember parent; Object value; MemberKey(RolapMember parent, Object value) { this.parent = parent; this.value = value; } // override Object public boolean equals(Object o) { if (!(o instanceof MemberKey)) { return false; } MemberKey other = (MemberKey) o; return other.parent == this.parent && other.value.equals(this.value); } // override Object public int hashCode() { return (parent == null ? 0 : parent.hashCode() << 16) ^ value.hashCode(); } }; // End RolapCube.java
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 1603 | Julian Hyde |
mondrian: Add Andreas' taglib; Rename 'mondrian.rolap.Util.assert' to 'assertTrue', because 'assert' is a keyword in jdk 1.4; Fix 'NON EMPTY'; JUnit framework for tests; Add Oracle dataset. |
||
#3 | 1576 | Julian Hyde |
mondrian: fix dataset (add column customer.ordinal); create dataset for oracle; get queries working on oracle; get format strings working; refactor out new packages mondrian.rolap.agg and mondrian.rolap.sql. |
||
#2 | 1496 | Julian Hyde |
Mondrian: Qualify table names with schemas. Add 'Hierarchy.schema', 'Cube.factSchema','Hierarchy.table' attributes. MondrianDef is now generated (so we need boot.jar). |
||
#1 | 1453 | Julian Hyde | mondrian: first source check-in |