sqlmembersource.java

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

JAVA
1,093
字号
    public void getMemberChildren(RolapMember parentMember, List children) {
        Connection jdbcConnection;
        try {
            jdbcConnection = dataSource.getConnection();
        } catch (SQLException e) {
            throw Util.newInternal(
                e, "Error while creating connection from data source");
        }
        try {
            getMemberChildren(parentMember, children, jdbcConnection);
        } finally {
            try {
                jdbcConnection.close();
            } catch (SQLException e) {
                // ignore
            }
        }
    }

    private void getMemberChildren(RolapMember parentMember,
                                   List children,
                                   Connection jdbcConnection) {
        String sql;
        boolean parentChild;
        final RolapLevel parentLevel = (RolapLevel) parentMember.getLevel();
        RolapLevel childLevel;
        if (parentLevel.getParentExp() != null) {
            sql = makeChildMemberSqlPC(parentMember, jdbcConnection);
            parentChild = true;
            childLevel = parentLevel;
        } else {
            RolapLevel[] levels = (RolapLevel[]) hierarchy.getLevels();
            int childDepth = parentLevel.getDepth() + 1;
            if (childDepth >= levels.length) {
                // member is at last level, so can have no children
                return;
            }
            childLevel = levels[childDepth];
            if (childLevel.getParentExp() != null) {
                sql = makeChildMemberSql_PCRoot(parentMember, jdbcConnection);
                parentChild = true;
            } else {
                sql = makeChildMemberSql(parentMember, jdbcConnection);
                parentChild = false;
            }
        }
        ResultSet resultSet = null;
        try {
            resultSet = RolapUtil.executeQuery(
                jdbcConnection, sql, "SqlMemberSource.getMemberChildren");

            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));
                }

                Object value = resultSet.getObject(1);
                if (value == null) {
                    value = RolapUtil.sqlNullValue;
                }
                Object captionValue;
                if (childLevel.hasCaptionColumn()){
                    captionValue=resultSet.getObject(2);
                } else {
                    captionValue = null;
                }
                Object key = cache.makeKey(parentMember, value);
                RolapMember member = cache.getMember(key);
                if (member == null) {
                    member = makeMember(
                            parentMember, childLevel, value, captionValue,
                            parentChild, resultSet, key, 1);
                }
                if (value == RolapUtil.sqlNullValue) {
                    addAsOldestSibling(children, member);
                } else {
                    children.add(member);
                }
            }
        } 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
            }
        }
    }

    private RolapMember makeMember(
            RolapMember parentMember,
            RolapLevel childLevel,
            Object value,
            Object captionValue,
            boolean parentChild,
            ResultSet resultSet,
            Object key,
            int columnOffset)
            throws SQLException {

        RolapMember member = new RolapMember(parentMember, childLevel, value);
        if (childLevel.getOrdinalExp() != childLevel.getKeyExp()) {
            member.setOrdinal(lastOrdinal++);
        }
        if (captionValue != null) {
            member.setCaption(captionValue.toString());
        }
        if (parentChild) {
            // Create a 'public' and a 'data' member. The public member is
            // calculated, and its value is the aggregation of the data member
            // and all of the children. The children and the data member belong
            // to the parent member; the data member does not have any
            // children.
            final RolapParentChildMember parentChildMember =
                childLevel.hasClosedPeer() ?
                    new RolapParentChildMember(
                            parentMember, childLevel, value, member)
                    : new RolapParentChildMemberNoClosure(
                            parentMember, childLevel, value, member);

            member = parentChildMember;
        }
        Property[] properties = childLevel.getProperties();
        for (int j = 0; j < properties.length; j++) {
            Property property = properties[j];
            member.setProperty(
                    property.getName(),
                    resultSet.getObject(columnOffset + j + 1));
        }
        cache.putMember(key, member);
        return member;
    }

    /**
     * Generates the SQL to find all root members of a parent-child hierarchy.
     * For example, <blockquote>
     *
     * <pre>SELECT "employee_id"
     * FROM "employee"
     * WHERE "supervisor_id" IS NULL
     * GROUP BY "employee_id"</pre>
     * </blockquote> retrieves the root members of the <code>[Employee]</code>
     * hierarchy.
     *
     * <p>Currently, parent-child hierarchies may have only one level (plus the
     * 'All' level).
     */
    private String makeChildMemberSql_PCRoot(RolapMember member,
                                             Connection jdbcConnection) {
        SqlQuery sqlQuery = newQuery(jdbcConnection,
            "while generating query to retrieve children of parent/child hierarchy member " + member);
        Util.assertTrue(member.isAll(), "In the current implementation, parent/child hierarchies must have only one level (plus the 'All' level).");

        RolapLevel level = (RolapLevel) member.getLevel().getChildLevel();

        Util.assertTrue(!level.isAll(), "all level cannot be parent-child");
        Util.assertTrue(level.isUnique(), "parent-child level '"
            + level + "' must be unique");

        hierarchy.addToFrom(sqlQuery, level.getParentExp());
        String parentId = level.getParentExp().getExpression(sqlQuery);
        StringBuffer condition = new StringBuffer(64);
        condition.append(parentId);
        if (level.getNullParentValue() == null ||
                level.getNullParentValue().equalsIgnoreCase("NULL")) {
            condition.append(" IS NULL");
        } else {
            // Quote the value if it doesn't seem to be a number.
            try {
                Util.discard(Double.parseDouble(level.getNullParentValue()));
                condition.append(" = ");
                condition.append(level.getNullParentValue());
            } catch (NumberFormatException e) {
                condition.append(" = ");
                Util.singleQuoteString(level.getNullParentValue(), condition);
            }
        }
        sqlQuery.addWhere(condition.toString());
        hierarchy.addToFrom(sqlQuery, level.getKeyExp());
        String childId = level.getKeyExp().getExpression(sqlQuery);
        sqlQuery.addSelect(childId);
        sqlQuery.addGroupBy(childId);
        hierarchy.addToFrom(sqlQuery, level.getOrdinalExp());
        String orderBy = level.getOrdinalExp().getExpression(sqlQuery);
        sqlQuery.addOrderBy(orderBy);
        if (!orderBy.equals(childId)) {
            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();
    }

    /**
     * Generates the SQL statement to access the children of
     * <code>member</code> in a parent-child hierarchy. For example,
     * <blockquote>
     *
     * <pre>SELECT "employee_id"
     * FROM "employee"
     * WHERE "supervisor_id" = 5</pre>
     * </blockquote> retrieves the children of the member
     * <code>[Employee].[5]</code>. See also {@link #makeLevelSql}.
     **/
    private String makeChildMemberSqlPC(RolapMember member,
                                        Connection jdbcConnection) {
        SqlQuery sqlQuery = newQuery(jdbcConnection,
            "while generating query to retrieve children of parent/child hierarchy member " + member);
        RolapLevel level = (RolapLevel) member.getLevel();

        Util.assertTrue(!level.isAll(), "all level cannot be parent-child");
        Util.assertTrue(level.isUnique(), "parent-child level '"
            + level + "' must be unique");

        hierarchy.addToFrom(sqlQuery, level.getParentExp());
        String parentId = level.getParentExp().getExpression(sqlQuery);
        sqlQuery.addWhere(parentId, " = ", member.quoteKeyForSql());

        hierarchy.addToFrom(sqlQuery, level.getKeyExp());
        String childId = level.getKeyExp().getExpression(sqlQuery);
        sqlQuery.addSelect(childId);
        sqlQuery.addGroupBy(childId);
        hierarchy.addToFrom(sqlQuery, level.getOrdinalExp());
        String orderBy = level.getOrdinalExp().getExpression(sqlQuery);
        sqlQuery.addOrderBy(orderBy);
        if (!orderBy.equals(childId)) {
            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();
    }

    // implement MemberReader
    public RolapMember getLeadMember(RolapMember member, int n) {
        throw new UnsupportedOperationException();
    }

    public void getMemberRange(RolapLevel level,
                               RolapMember startMember,
                               RolapMember endMember,
                               List memberList) {
        throw new UnsupportedOperationException();
    }

    public int compare(RolapMember m1,
                       RolapMember m2,
                       boolean siblingsAreEqual) {
        throw new UnsupportedOperationException();
    }

    public void getMemberDescendants(RolapMember member,
                                     List result,
                                     RolapLevel level,
                                     boolean before,
                                     boolean self,
                                     boolean after) {
        throw new UnsupportedOperationException();
    }

    /**
     * Member of a parent-child dimension which has a closure table.
     *
     * <p>When looking up cells, this member will automatically be converted
     * to a corresponding member of the auxiliary dimension which maps onto
     * the closure table.
     */
    private static class RolapParentChildMember extends RolapMember {
        private final RolapMember dataMember;
        private int depth = 0;
        public RolapParentChildMember(RolapMember parentMember,
                                      RolapLevel childLevel,
                                      Object value,
                                      RolapMember dataMember) {
            super(parentMember, childLevel, value);
            this.dataMember = dataMember;
            this.depth = (parentMember != null)
                ? parentMember.getDepth() + 1
                : 0;
        }

        public Member getDataMember() {
            return dataMember;
        }

        public Object getPropertyValue(String name) {
            if (name.equals(Property.CONTRIBUTING_CHILDREN.name)) {
                List list = new ArrayList();
                list.add(dataMember);
                RolapHierarchy hierarchy = (RolapHierarchy) getHierarchy();
                hierarchy.memberReader.getMemberChildren(this, list);
                return list;
            } else {
                return super.getPropertyValue(name);
            }
        }

        /**
         * @return the members's depth
         * @see mondrian.olap.Member#getDepth()
         */
        public int getDepth() {
            return depth;
        }
    }

    /**
     * Member of a parent-child dimension which has no closure table.
     *
     * <p>This member is calculcated. When you ask for its value, it returns
     * an expression which aggregates the values of its child members.
     * This calculation is very inefficient, and we can only support
     * aggregatable measures ("count distinct" is non-aggregatable).
     * Unfortunately it's the best we can do without a closure table.
     */
    private static class RolapParentChildMemberNoClosure
        extends RolapParentChildMember {

        public RolapParentChildMemberNoClosure(RolapMember parentMember,
                RolapLevel childLevel, Object value, RolapMember dataMember) {
            super(parentMember, childLevel, value, dataMember);
        }

        public boolean isCalculated() {
            return true;
        }

        public Exp getExpression() {
            final RolapHierarchy hierarchy = (RolapHierarchy) getHierarchy();
            return hierarchy.getAggregateChildrenExpression();
        }
    }
}

// End SqlMemberSource.java

⌨️ 快捷键说明

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