sqlmembersource.java

来自「数据仓库展示程序」· Java 代码 · 共 1,093 行 · 第 1/3 页

JAVA
1,093
字号
                        member.setProperty(property.getName(),
                                        resultSet.getObject(column + 1));
                        column++;
                    }
                }
            }

            return RolapUtil.toArray(list);
        } catch (SQLException e) {
            throw Util.newInternal(e,
                    "while building member cache; sql=[" + sql + "]");
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.getStatement().close();
                    resultSet.close();
                }
            } catch (SQLException e) {
                // ignore
            }
        }
    }

    /**
     * Adds <code>member</code> just before the first element in
     * <code>list</code> which has the same parent.
     */
    private void addAsOldestSibling(List list, RolapMember member) {
        int i = list.size();
        while (--i >= 0) {
            RolapMember sibling = (RolapMember) list.get(i);
            if (sibling.getParentMember() != member.getParentMember()) {
                break;
            }
        }
        list.add(i + 1, member);
    }

    private String makeKeysSql(Connection jdbcConnection) {
        SqlQuery sqlQuery = newQuery(jdbcConnection,
                "while generating query to retrieve members of " + hierarchy);
        RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
        for (int i = 0; i < levels.length; i++) {
            RolapLevel level = levels[i];
            if (level.isAll()) {
                continue;
            }
            MondrianDef.Expression exp = level.getKeyExp();
            hierarchy.addToFrom(sqlQuery, exp);
            String expString = exp.getExpression(sqlQuery);
            sqlQuery.addSelect(expString);
            sqlQuery.addGroupBy(expString);
            exp = level.getOrdinalExp();
            hierarchy.addToFrom(sqlQuery, exp);
            expString = exp.getExpression(sqlQuery);
            sqlQuery.addOrderBy(expString);
            sqlQuery.addGroupBy(expString);

            RolapProperty[] properties = level.getRolapProperties();
            for (int j = 0; j < properties.length; j++) {
                RolapProperty property = properties[j];
                exp = property.getExp();
                hierarchy.addToFrom(sqlQuery, exp);
                expString = exp.getExpression(sqlQuery);
                sqlQuery.addSelect(expString);
                sqlQuery.addGroupBy(expString);
            }
        }
        return sqlQuery.toString();
    }

    /**
     * Generates the SQL statement to access members of <code>level</code>. For
     * example, <blockquote>
     * <pre>SELECT "country", "state_province", "city"
     * FROM "customer"
     * GROUP BY "country", "state_province", "city", "init", "bar"</pre>
     * </blockquote> accesses the "City" level of the "Customers"
     * hierarchy. Note that:<ul>
     *
     * <li><code>"country", "state_province"</code> are the parent keys;</li>
     *
     * <li><code>"city"</code> is the level key;</li>
     *
     * <li><code>"init", "bar"</code> are member properties.</li>
     * </ul>
     *
     * @pre !level.isAll()
     **/
    String makeLevelSql(RolapLevel level, Connection jdbcConnection) {
        Util.assertPrecondition(!level.isAll());
        SqlQuery sqlQuery = newQuery(jdbcConnection,
                "while generating query to retrieve members of level " + level);
        RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
        int levelDepth = level.getDepth();
        for (int i = 0; i <= levelDepth; i++) {
            RolapLevel level2 = levels[i];
            if (level2.isAll()) {
                continue;
            }
            hierarchy.addToFrom(sqlQuery, level2.getKeyExp());
            String keySql = level2.getKeyExp().getExpression(sqlQuery);
            sqlQuery.addSelect(keySql);
            sqlQuery.addGroupBy(keySql);
            hierarchy.addToFrom(sqlQuery, level2.getOrdinalExp());

            if (level2.hasCaptionColumn()) {
                MondrianDef.Expression captionExp = level2.getCaptionExp();
                hierarchy.addToFrom(sqlQuery, captionExp);
                String captionSql = captionExp.getExpression(sqlQuery);
                sqlQuery.addSelect(captionSql);
                sqlQuery.addGroupBy(captionSql);
            }

            String ordinalSql = level2.getOrdinalExp().getExpression(sqlQuery);
            sqlQuery.addGroupBy(ordinalSql);
            sqlQuery.addOrderBy(ordinalSql);
            RolapProperty[] properties = level2.getRolapProperties();
            for (int j = 0; j < properties.length; j++) {
                RolapProperty property = properties[j];
                String propSql = property.getExp().getExpression(sqlQuery);
                sqlQuery.addSelect(propSql);
                sqlQuery.addGroupBy(propSql);
            }
        }
        return sqlQuery.toString();
    }

    // implement MemberReader
    public List getMembersInLevel(RolapLevel level,
                                  int startOrdinal,
                                  int endOrdinal) {
        if (level.isAll()) {
            final String allMemberName = hierarchy.getAllMemberName();
            Object key = cache.makeKey(null, allMemberName);
            RolapMember root = cache.getMember(key);
            if (root == null) {
                root = new RolapMember(null, level, null, allMemberName,
                        Member.ALL_MEMBER_TYPE);
                root.setOrdinal(lastOrdinal++);
                cache.putMember(key, root);
                if (hierarchy.xmlHierarchy != null &&
                    hierarchy.xmlHierarchy.allMemberCaption != null &&
                    hierarchy.xmlHierarchy.allMemberCaption.length() > 0) {
                    root.setCaption(hierarchy.xmlHierarchy.allMemberCaption );
                }

            }
            List list = new ArrayList(1);
            list.add(root);
            return list;
        }
        final RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
        Connection jdbcConnection;
        try {
            jdbcConnection = dataSource.getConnection();
        } catch (SQLException e) {
            throw Util.newInternal(
                e, "Error while creating connection from data source");
        }
        try {
            return getMembersInLevel(level, jdbcConnection, levels);
        } finally {
            try {
                jdbcConnection.close();
            } catch (SQLException e) {
                // ignore
            }
        }
    }

    private List getMembersInLevel(RolapLevel level,
                                   Connection jdbcConnection,
                                   final RolapLevel[] levels) {
        String sql = makeLevelSql(level, jdbcConnection);
        ResultSet resultSet = null;
        try {
            resultSet = RolapUtil.executeQuery(jdbcConnection,
                                          sql,
                                          "SqlMemberSource.getMembersInLevel");
            List list = new ArrayList();
            final int levelDepth = level.getDepth();
            RolapMember allMember = null;
            if (hierarchy.hasAll()) {
                final List rootMembers = getRootMembers();
                Util.assertTrue(rootMembers.size() == 1);
                allMember = (RolapMember) rootMembers.get(0);
            }
            boolean parentChild = level.getParentExp() != null;

            // members[i] is the current member of level#i, and siblings[i]
            // is the current member of level#i plus its siblings
            RolapMember[] members = new RolapMember[levels.length];
            List[] siblings = new ArrayList[levels.length + 1];

            int limit = MondrianProperties.instance().ResultLimit.get();
            int nFetch = 0;

            while (resultSet.next()) {

                if (limit > 0 && limit < ++nFetch) {
                    // result limit exceeded, throw an exception
                    throw MondrianResource.instance().
                               MemberFetchLimitExceeded.ex(new Long(limit));
                }

                int column = 0;
                RolapMember member = null;
                for (int i = 0; i <= levelDepth; i++) {
                    RolapLevel childLevel = levels[i];
                    if (childLevel.isAll()) {
                        member = allMember;
                        continue;
                    }
                    Object value = resultSet.getObject(++column);
                    if (value == null) {
                        value = RolapUtil.sqlNullValue;
                    }
                    Object captionValue;
                    if (childLevel.hasCaptionColumn()) {
                        captionValue = resultSet.getObject(++column);
                    } else {
                        captionValue = null;
                    }
                    RolapMember parentMember = member;
                    Object key = cache.makeKey(parentMember, value);
                    member = cache.getMember(key);
                    if (member == null) {
                        member = makeMember(
                                parentMember, childLevel, value, captionValue,
                                parentChild, resultSet, key, column);
                    }
                    column += childLevel.getProperties().length;
                    if (member != members[i]) {
                        // Flush list we've been building.
                        List children = siblings[i + 1];
                        if (children != null) {
                            cache.putChildren(members[i], children);
                        }
                        // Start a new list, if the cache needs one. (We don't
                        // synchronize, so it's possible that the cache will
                        // have one by the time we complete it.)
                        if (i < levelDepth &&
                                !cache.hasChildren(member)) {
                            siblings[i + 1] = new ArrayList();
                        } else {
                            siblings[i + 1] = null; // don't bother building up a list
                        }
                        // Record new current member of this level.
                        members[i] = member;
                        // If we're building a list of siblings at this level,
                        // we haven't seen this one before, so add it.
                        if (siblings[i] != null) {
                            if (value == RolapUtil.sqlNullValue) {
                                addAsOldestSibling(siblings[i], member);
                            } else {
                                siblings[i].add(member);
                            }
                        }
                    }
                }
                list.add(member);
            }
            for (int i = 0; i < members.length; i++) {
                RolapMember member = members[i];
                final List children = siblings[i + 1];
                if (member != null && children != null) {
                    cache.putChildren(member, children);
                }
            }
            return list;
        } catch (Throwable e) {
            throw Util.newInternal(e,
                    "while populating member cache with members for level '" +
                    level.getUniqueName() + "'; sql=[" + sql + "]");
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.getStatement().close();
                    resultSet.close();
                }
            } catch (SQLException e) {
                // ignore
            }
        }
    }

    // implement MemberSource
    public List getRootMembers() {
        return getMembersInLevel(
                (RolapLevel) hierarchy.getLevels()[0],
                0,
                Integer.MAX_VALUE);
    }

    /**
     * Generates the SQL statement to access the children of
     * <code>member</code>. For example, <blockquote>
     *
     * <pre>SELECT "city"
     * FROM "customer"
     * WHERE "country" = 'USA'
     * AND "state_province" = 'BC'
     * GROUP BY "city"</pre>
     * </blockquote> retrieves the children of the member
     * <code>[Canada].[BC]</code>. See also {@link #makeLevelSql}.
     **/
    String makeChildMemberSql(RolapMember member, Connection jdbcConnection) {
        SqlQuery sqlQuery = newQuery(jdbcConnection,
                "while generating query to retrieve children of member "
                + member);
        for (RolapMember m = member; m != null; m = (RolapMember)
                 m.getParentMember()) {
            RolapLevel level = (RolapLevel) m.getLevel();
            if (level.isAll()) {
                continue;
            }
            hierarchy.addToFrom(sqlQuery, level.getKeyExp());
            String q = level.getKeyExp().getExpression(sqlQuery);
            sqlQuery.addWhere(q, " = ", m.quoteKeyForSql());
            if (level.isUnique()) {
                break; // no further qualification needed
            }
        }

        RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
        RolapLevel level = levels[member.getLevel().getDepth() + 1];
        hierarchy.addToFrom(sqlQuery, level.getKeyExp());
        String q = level.getKeyExp().getExpression(sqlQuery);
        sqlQuery.addSelect(q);
        sqlQuery.addGroupBy(q);

        if (level.hasCaptionColumn()){
            MondrianDef.Expression captionExp = level.getCaptionExp();
            hierarchy.addToFrom(sqlQuery, captionExp);
            String captionSql = captionExp.getExpression(sqlQuery);
            sqlQuery.addSelect(captionSql);
            sqlQuery.addGroupBy(captionSql);
        }

        hierarchy.addToFrom(sqlQuery, level.getOrdinalExp());
        String orderBy = level.getOrdinalExp().getExpression(sqlQuery);
        sqlQuery.addOrderBy(orderBy);
        if (!orderBy.equals(q)) {
            sqlQuery.addGroupBy(orderBy);
        }

        RolapProperty[] properties = level.getRolapProperties();
        for (int j = 0; j < properties.length; j++) {
            RolapProperty property = properties[j];
            final MondrianDef.Expression exp = property.getExp();
            hierarchy.addToFrom(sqlQuery, exp);
            final String s = exp.getExpression(sqlQuery);
            sqlQuery.addSelect(s);
            sqlQuery.addGroupBy(s);
        }
        return sqlQuery.toString();
    }

    public void getMemberChildren(List parentMembers, List children) {
        for (int i = 0; i < parentMembers.size(); i++) {
            getMemberChildren((RolapMember) parentMembers.get(i), children);
        }
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?