/** * 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; }