/** * Computes the number of atomic cells in a cell identified by a list of members. * * <p>The method may be expensive. If the value is not in the cache, computes it immediately using * a database access. It uses an aggregate table if applicable, and puts the value into the cache. * * <p>Compare with {@link #evaluateAtomicCellCount(RolapEvaluator)}, which gets the value from the * cache but may lie (and generate a cache miss) if the value is not present. * * @param cube Cube * @param memberList Coordinate members of cell * @return Number of atomic cells in cell */ private static double computeAtomicCellCount(RolapCube cube, List<RolapMember> memberList) { // Implementation generates and executes a recursive MDX query. This // may not be the most efficient implementation, but achieves the // design goals of (a) immediacy, (b) cache use, (c) aggregate table // use. final StringBuilder buf = new StringBuilder(); buf.append("select from "); buf.append(cube.getUniqueName()); int k = 0; for (Member member : memberList) { if (member.isMeasure()) { member = cube.factCountMeasure; assert member != null : "fact count measure is required for writeback cubes"; } if (!member.equals(member.getHierarchy().getDefaultMember())) { if (k++ > 0) { buf.append(", "); } else { buf.append(" where ("); } buf.append(member.getUniqueName()); } } if (k > 0) { buf.append(")"); } final String mdx = buf.toString(); final RolapConnection connection = cube.getSchema().getInternalConnection(); final Query query = connection.parseQuery(mdx); final Result result = connection.execute(query); final Object o = result.getCell(new int[0]).getValue(); return o instanceof Number ? ((Number) o).doubleValue() : 0d; }
/** * Registers this Scenario with a Schema, creating a calulated member [Scenario].[{id}] for each * cube that has writeback enabled. (Currently a cube has writeback enabled iff it has a dimension * called "Scenario".) * * @param schema Schema */ void register(RolapSchema schema) { // Add a value to the [Scenario] dimension of every cube that has // writeback enabled. for (RolapCube cube : schema.getCubeList()) { for (RolapHierarchy hierarchy : cube.getHierarchies()) { if (isScenario(hierarchy)) { member = cube.createCalculatedMember(hierarchy, getId() + "", new ScenarioCalc(this)); assert member != null; } } } }
private void clearCache(RolapCube cube) { // Clear the cache for the Sales cube, so the query runs as if // for the first time. (TODO: Cleaner way to do this.) final Cube salesCube = getConnection().getSchema().lookupCube("Sales", true); RolapHierarchy hierarchy = (RolapHierarchy) salesCube.lookupHierarchy(new Id.NameSegment("Store", Id.Quoting.UNQUOTED), false); SmartMemberReader memberReader = (SmartMemberReader) hierarchy.getMemberReader(); MemberCacheHelper cacheHelper = memberReader.cacheHelper; cacheHelper.mapLevelToMembers.cache.clear(); cacheHelper.mapMemberToChildren.cache.clear(); // Flush the cache, to ensure that the query gets executed. cube.clearCachedAggregations(true); CacheControl cacheControl = getConnection().getCacheControl(null); final CacheControl.CellRegion measuresRegion = cacheControl.createMeasuresRegion(cube); cacheControl.flush(measuresRegion); }
/** * Creates a WritebackCell. * * @param cube Cube * @param members Members that form context * @param constrainedColumnsBitKey Bitmap of columns which have values * @param keyValues List of values, by bit position * @param newValue New value * @param currentValue Current value * @param allocationPolicy Allocation policy */ WritebackCell( RolapCube cube, List<RolapMember> members, BitKey constrainedColumnsBitKey, Object[] keyValues, double newValue, double currentValue, AllocationPolicy allocationPolicy) { assert keyValues.length == constrainedColumnsBitKey.cardinality(); Util.discard(cube); // not used currently Util.discard(constrainedColumnsBitKey); // not used currently Util.discard(keyValues); // not used currently this.newValue = newValue; this.currentValue = currentValue; this.allocationPolicy = allocationPolicy; this.atomicCellCount = computeAtomicCellCount(cube, members); // Build the array of members by ordinal. If a member is not // specified for a particular dimension, use the 'all' member (not // necessarily the same as the default member). final List<RolapHierarchy> hierarchyList = cube.getHierarchies(); this.membersByOrdinal = new Member[hierarchyList.size()]; for (int i = 0; i < membersByOrdinal.length; i++) { membersByOrdinal[i] = hierarchyList.get(i).getDefaultMember(); } for (RolapMember member : members) { final RolapHierarchy hierarchy = member.getHierarchy(); if (isScenario(hierarchy)) { assert member.isAll(); } // REVIEW The following works because Measures is the only // dimension whose members do not belong to RolapCubeDimension, // just a regular RolapDimension, but has ordinal 0. final int ordinal = hierarchy.getOrdinalInCube(); membersByOrdinal[ordinal] = member; } }
RolapNativeRegistry getRegistry(Connection connection) { RolapCube cube = (RolapCube) connection.getSchema().lookupCube("Sales", true); RolapSchemaReader schemaReader = (RolapSchemaReader) cube.getSchemaReader(); return schemaReader.getSchema().getNativeRegistry(); }