mondrian源码分析与说明 联系客服

发布时间 : 星期六 文章mondrian源码分析与说明更新完毕开始阅读bf3b867f2e3f5727a5e96245

每一个子接口有都有一个实现的虚基类:AbstractIntegerCalc, AbstractBooleanCalc, AbstractDoubleCalc, AbstractStringCalc, AbstractMemberCalc, AbstractLevelCalc, AbstractHierarchyCalc, AbstractDimensionCalc。

表达式(Expression)通常由表达式编译者(ExpCompiler)创建。对于一个给定的表达式通常有若干个evaluation策略,表达式编译者在编译过程中可以给我们一个选择的机会。

2.4. 包mondrian.olap—接口

Mondrian的核心包,定义了连接对象和完整的olap模型结构元对象,并且允许执行mdx查询语句。

2.4.1. mdx函数包

mondrian.olap.fun 定义了mdx内置的函数集。 函数(function)的定义: 参数 name 描述 函数名 例子 \\\a dimension.\signature 函数标志 description 函数描述 flags Encoding of the syntactic type, return type, and parameter types of this operator. The encoding is \described below. The flags field is an string which encodes the syntactic type, return type, and parameter types of this operator. The first character determines the syntactic type, as described by FunUtil.decodeSyntacticType(String). The second character determines the return type, as described by FunUtil.decodeReturnCategory(String).

The third and subsequence characters determine the types of the arguments arguments, as described by FunUtil.decodeParameterCategories(String).

For example, \property syntax (p) which returns a set (x) and takes a dimension (d) as its argument\

2.4.2. funCall

A FunCall is a function applied to a list of operands.

The parser creates function calls as an unresolved function call.

The validator converts it to a resolved function call, which has a function definition and extra

type information。参见:Mondrian.olap. ResolveFunCall UnresolveFunCall

2.4.3. Query类

用于mdx 查询。

2.4.3.1. 创建query

创建:Connection.parseQuery(java.lang.String)。

创建mondrian.olap.Parser类,基于java_cup实现,调用其parse或debug_parse()方法,里面最主要 是CUP$Parser$do_action()方法,内部针对所有语句词句做了解析。

其中case75:生成最后的mondrian.olap.Query对象,内部调用parser.makeQuery()方法,内部初始化时会再调用query的resolve,mondrian.olap.QueryAxis的resolve(),进而会执行数据库。

2.4.3.2. 执行query

执行:Connection.execute(mondrian.olap.Query) 返回结果: Result.

有些查询从缓存中读取,非常迅速。

当也有些需要花费些时间,这时可以通过MondrianProperties.QueryTimeout参数设置timeout。

如果想控制返回结果不至于太大,可以通过MondrianProperties.QueryLimit参数控制返回的cell数目。

在查询执行的任何时候,另一个进程都可以通过cancel()方法取消该查询,此时Connection.execute(Query)会抛出异常。

2.5. 包mondrian.rolap—计算层

实现最终的实际的olap数据访问功能,包括读取维度成员值和cell值。

2.5.1. 成员读取包MemberReader 2.5.1.1. 概述

包路径:Mondrian.rolap。

该部分的起点是RolapEvaluator类。当一个类似于“member.children”的成员表达式被请求时, RolapEvaluator将调用RolapSchemaReader对象. RolapSchemaReader将再负责调用各个MemberReader对象(每个维度一个memberReader)。在大部分场合下,将使用SmartMemberReader 来迅速返回所需要的维度成员值。

2.5.1.2. SmartMemberReader

SmartMemberReader实现了MemberReader接口,它实现了维度成员及其子成员的缓存,如果有一个成员位于缓存中,则还会有一个其子成员的列表。它同时缓存了level下的成员们。该类主要的成员有:

source:MemberReader,用于实际从数据库中读取维度成员值。 mapMemberToChildren:map,实现成员及其子成员的映射,

key为RolapMember,value为List

mapKeyToMember: map ,实现所有成员的缓存,其中的key为MemberKey mapLevelToMembers: map,实现级别及其所有成员的映射,

key为RolapLevel,value为List

上述的source其实为mondrian.rolap.SqlMemberSource类,该类中反过来又存储了SmartMemberReader对象,作为其cache成员属性。

成员读取过程:

? smartMemberReader.getMemberChildren(parentMembers,children,constrain);

? 最终通过source.getMemberChildren()…,其中反过来会把找到的children赋予

mapKeyToMember。

? 最终除了将结果返回在children输出参数中,同时也对mapMemberToChildren赋

值了。

另外,smartMemberReader.getMembersInlevel()实现了对mapLevelToMembers的缓存。在new RolapEvaluator()时被调用。在读取时会对成员进行order by(如果设置了ascending的话。) 2.5.2. 单元格读取CellReader 2.5.2.1. 概述

包路径:Mondrian.rolap。

Cells会被求值多次。第一次时, Evaluator使用FastBatchingCellReader来求值。当一个单元被求值时,evaluateCurrent()被调用。此时FastBatchingCellReader并没有被调用,而是为那个cell记录了一个 CellRequest并且return (not throw) an exception。在所有的cells都有了对应的CellRequests之后, Aggregation会生成 SQL,以一个单独的sql请求来载入所有的cells。然后由AggregatingCellReader 重新计算cells,从缓存中返回cells值。