[Mondrian] Re: Eigenbase perforce change 11171 for review

Rushan Chen rchen at lucidera.com
Mon Jun 16 03:48:31 EDT 2008


Hi Julian,

This change is related to the change I made in earlier checkins(11154, 
11157).

The use case for these changes, including 11171, is to support a client 
program(in our case a UI client) to validate user constructed calculated 
measures. At this time, we want to only allow simple arithmetics in user 
constructed calc measures, hence the need for a customizable function 
table. We also want to disallow references to invalid measure names. 
However, this ability is controlled by two singleton global 
properties(ignoreInvalidMembers/ignoreInvalidMembersDuringQuery). We 
want the validation client to catch invalid measures regardless of the 
global setting for this property which can be shared by other 
clients(connections) that want to keep the current property value. The 
only way to control this per connection is via the Connection interface.

I think it is possible to change these properties to be associated with 
a connection and controlled by the client via the connect-string. I need 
to make sure that this is can be made to be backward compatible because 
now global settings alone does not affect the behavior.

Finally, have you come across user cases like the above that SSAS would 
handle?

Rushan

Julian Hyde wrote:
> Rushan,
>
> This change extends one of mondrian's main public interfaces, Connection,
> with the FunTable class, which was not intended for use by callers of the
> public API.
>
> Can you explain the use cases you are trying to solve using customized
> parsing, then maybe we can figure out how to expose this functionality.
>
> Also, I have a feeling that SSAS addresses some of those use cases, in which
> case, we should study what SSAS does be as compatible as possible.
>
> Maybe some of this behavior would more naturally be exposed through
> connect-string parameters and system properties. That would make this
> behavior available through XMLA and olap4j as well as to users calling
> mondrian's native API.
>
> Julian
>
>   
>> -----Original Message-----
>> From: Rushan Chen [mailto:rchen at lucidera.com] 
>> Sent: Friday, June 13, 2008 12:22 PM
>> To: Ajit Joglekar; Andreas Voss; Bart Pappyn; Julian Hyde; 
>> John V. Sichi; Matt Campbell; Rushan Chen; Robin Tharappel; 
>> Sam Birney; Will Gorman; Zelaine Fong
>> Subject: Eigenbase perforce change 11171 for review
>>
>> http://p4web.eigenbase.org/@md=d&c=6PU@//11171?ac=10
>>
>> Change 11171 by rchen at rchen.fao.eigenbase on 2008/06/13 12:20:38
>>
>> 	MONDRIAN: Expose parser behavior control for allowing invalid
>> 	members via the Connection interface.
>>
>> Affected files ...
>>
>> ... //open/mondrian/src/main/mondrian/olap/Connection.java#15 edit
>> ... //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#21 edit
>> ... //open/mondrian/src/main/mondrian/olap/Parser.cup#40 edit
>> ... //open/mondrian/src/main/mondrian/olap/Query.java#110 edit
>> ... 
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#5 edit
>> ... //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#36 edit
>> ... //open/mondrian/testsrc/main/mondrian/olap/QueryTest.java#2 edit
>>
>> Differences ...
>>
>> ==== 
>> //open/mondrian/src/main/mondrian/olap/Connection.java#15 (ktext) ====
>>
>> 2c2
>> < // $Id: //open/mondrian/src/main/mondrian/olap/Connection.java#14 $
>> ---
>>     
>>> // $Id: //open/mondrian/src/main/mondrian/olap/Connection.java#15 $
>>>       
>> 25c25
>> <  * @version $Id: 
>> //open/mondrian/src/main/mondrian/olap/Connection.java#14 $
>> ---
>>     
>>>  * @version $Id: 
>>>       
>> //open/mondrian/src/main/mondrian/olap/Connection.java#15 $
>> 83c83,84
>> <      * Parses a query, with specified function table
>> ---
>>     
>>>      * Parses a query, with specified function table and 
>>>       
>> the mode for strict 
>>     
>>>      * validation(if true then invalid members are not ignored).
>>>       
>> 85c86
>> <     Query parseQuery(String s, FunTable funTable);
>> ---
>>     
>>>     Query parseQuery(String s, FunTable funTable, boolean 
>>>       
>> strictValidation);
>>
>> ==== 
>> //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#21 
>> (ktext) ====
>>
>> 2c2
>> < // $Id: 
>> //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#20 $
>> ---
>>     
>>> // $Id: 
>>>       
>> //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#21 $
>> 26c26
>> <  * @version $Id: 
>> //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#20 $
>> ---
>>     
>>>  * @version $Id: 
>>>       
>> //open/mondrian/src/main/mondrian/olap/ConnectionBase.java#21 $
>> 59c59
>> <         return parseQuery(s, null, false);
>> ---
>>     
>>>         return parseQuery(s, null, false, false);
>>>       
>> 63c63
>> <         return parseQuery(s, null, load);
>> ---
>>     
>>>         return parseQuery(s, null, load, false);
>>>       
>> 66,67c66,67
>> <     public Query parseQuery(String s, FunTable funTable) {
>> <         return parseQuery(s, funTable, false);
>> ---
>>     
>>>     public Query parseQuery(String s, FunTable funTable, 
>>>       
>> boolean strictValidation) {
>>     
>>>         return parseQuery(s, funTable, false, strictValidation);
>>>       
>> 89c89
>> <     private Query parseQuery(String query, FunTable cftab, 
>> boolean load) {
>> ---
>>     
>>>     private Query parseQuery(String query, FunTable cftab, 
>>>       
>> boolean load, boolean strictValidation) {
>> 109c109
>> <             Query q = parser.parseInternal(this, query, 
>> debug, funTable, load);
>> ---
>>     
>>>             Query q = parser.parseInternal(this, query, 
>>>       
>> debug, funTable, load, strictValidation);
>>
>> ==== //open/mondrian/src/main/mondrian/olap/Parser.cup#40 (ktext) ====
>>
>> 2c2
>> < // $Id: //open/mondrian/src/main/mondrian/olap/Parser.cup#39 $
>> ---
>>     
>>> // $Id: //open/mondrian/src/main/mondrian/olap/Parser.cup#40 $
>>>       
>> 25c25
>> <     // Generated from $Id: 
>> //open/mondrian/src/main/mondrian/olap/Parser.cup#39 $
>> ---
>>     
>>>     // Generated from $Id: 
>>>       
>> //open/mondrian/src/main/mondrian/olap/Parser.cup#40 $
>> 30a31
>>     
>>>     private boolean strictValidation;
>>>       
>> 50c51,52
>> <         boolean load)
>> ---
>>     
>>>         boolean load,
>>>         boolean strictValidation)
>>>       
>> 57a60
>>     
>>>         this.strictValidation = strictValidation;
>>>       
>> 159c162
>> <             mdxConnection, formulae, axes, cube, 
>> slicerAxis, cellProps, load);
>> ---
>>     
>>>             mdxConnection, formulae, axes, cube, 
>>>       
>> slicerAxis, cellProps, load, strictValidation);
>>
>> ==== //open/mondrian/src/main/mondrian/olap/Query.java#110 
>> (ktext) ====
>>
>> 2c2
>> < // $Id: //open/mondrian/src/main/mondrian/olap/Query.java#109 $
>> ---
>>     
>>> // $Id: //open/mondrian/src/main/mondrian/olap/Query.java#110 $
>>>       
>> 56c56
>> <  * @version $Id: 
>> //open/mondrian/src/main/mondrian/olap/Query.java#109 $
>> ---
>>     
>>>  * @version $Id: 
>>>       
>> //open/mondrian/src/main/mondrian/olap/Query.java#110 $
>> 153a154,158
>>     
>>>      * If true, enforce validation even when 
>>>       
>> ignoreInvalidMembers is set.
>>     
>>>      */
>>>     private boolean strictValidation;
>>>     
>>>     /**
>>>       
>> 176c181,182
>> <             boolean load) {
>> ---
>>     
>>>             boolean load,
>>>             boolean strictValidation) {
>>>       
>> 185c191,192
>> <             load);
>> ---
>>     
>>>             load,
>>>             strictValidation);
>>>       
>> 199c206,207
>> <             boolean load) {
>> ---
>>     
>>>             boolean load,
>>>             boolean strictValidation) {
>>>       
>> 215a224
>>     
>>>         this.strictValidation = strictValidation;
>>>       
>> 302c311,312
>> <                 load);
>> ---
>>     
>>>                 load,
>>>                 strictValidation);
>>>       
>> 435,438c445,447
>> <         return
>> <             (load && props.IgnoreInvalidMembers.get())
>> <             ||
>> <             (!load && props.IgnoreInvalidMembersDuringQuery.get());
>> ---
>>     
>>>         return 
>>>             !strictValidation &&
>>>             ((load && props.IgnoreInvalidMembers.get()) || 
>>>       
>> (!load && props.IgnoreInvalidMembersDuringQuery.get()));
>>
>> ==== 
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#5 (ktext) ====
>>
>> 2c2
>> < // $Id: 
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#4 $
>> ---
>>     
>>> // $Id: 
>>>       
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#5 $
>> 21c21
>> <  * @version $Id: 
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#4 $
>> ---
>>     
>>>  * @version $Id: 
>>>       
>> //open/mondrian/testsrc/main/mondrian/olap/CustomizedParserTes
>> t.java#5 $
>> 55c55,56
>> <     private Query 
>> getParsedQueryForExpr(CustomizedFunctionTable cftab, String expr) {
>> ---
>>     
>>>     private Query getParsedQueryForExpr(
>>>         CustomizedFunctionTable cftab, String expr, boolean 
>>>       
>> strictValidation) {
>> 57c58
>> <         Query q = getConnection().parseQuery(mdx, cftab);
>> ---
>>     
>>>         Query q = getConnection().parseQuery(mdx, cftab, 
>>>       
>> strictValidation);
>> 60a62,65
>>     
>>>     private Query 
>>>       
>> getParsedQueryForExpr(CustomizedFunctionTable cftab, String expr) {
>>     
>>>         return getParsedQueryForExpr(cftab, expr, false);
>>>     }
>>>
>>>       
>> 152a158,197
>>     
>>>     public void testMissingObjectFailWithStrict() {
>>>         testMissingObject(true);
>>>     }
>>>
>>>     public void testMissingObjectSucceedWithoutStrict() {
>>>         testMissingObject(false);
>>>     }
>>>
>>>     private void testMissingObject(boolean strictValidation) {
>>>         Set<String> functionNameSet = new HashSet<String>();
>>>         functionNameSet.add("+");
>>>         CustomizedFunctionTable cftab = 
>>>       
>> getCustomizedFunctionTable(functionNameSet);
>>     
>>>         MondrianProperties properties = 
>>>       
>> MondrianProperties.instance();
>>     
>>>         boolean oldIgnoreInvalidMembers = 
>>>             properties.IgnoreInvalidMembers.get();
>>>         boolean oldIgnoreInvalidMembersDuringQuery = 
>>>             properties.IgnoreInvalidMembersDuringQuery.get();
>>>                     
>>>         try {
>>>             properties.IgnoreInvalidMembers.set(true);
>>>             properties.IgnoreInvalidMembersDuringQuery.set(true);
>>>             Query q = 
>>>                 getParsedQueryForExpr(cftab, 
>>>       
>> "'[Measures].[Store Cost] + [Measures].[Unit Salese]'", 
>> strictValidation);
>>     
>>>             q.resolve(q.createValidator(cftab));
>>>             // Shouldn't reach here if strictValidation
>>>             fail("Expected error does not occur when 
>>>       
>> strictValidation is set:" + strictValidation);
>>     
>>>         } catch (Throwable e) {
>>>             
>>>       
>> properties.IgnoreInvalidMembers.set(oldIgnoreInvalidMembers);
>>     
>>>             
>>>       
>> properties.IgnoreInvalidMembersDuringQuery.set(oldIgnoreInvali
>> dMembersDuringQuery);
>>     
>>>             if (strictValidation) {
>>>                 checkErrorMsg(e,
>>>                 "Mondrian Error:MDX object 
>>>       
>> '[Measures].[Unit Salese]' not found in cube 'Sales'");
>>     
>>>             } else {
>>>                 checkErrorMsg(e,
>>>                 "Expected error does not occur when 
>>>       
>> strictValidation is set:" + strictValidation);                
>>     
>>>             }
>>>         }
>>>     }
>>>
>>>       
>> ==== 
>> //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#36 
>> (ktext) ====
>>
>> 2c2
>> < // $Id: 
>> //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#35 $
>> ---
>>     
>>> // $Id: 
>>>       
>> //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#36 $
>> 25c25
>> <  * @version $Id: 
>> //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#35 $
>> ---
>>     
>>>  * @version $Id: 
>>>       
>> //open/mondrian/testsrc/main/mondrian/olap/ParserTest.java#36 $
>> 53c53
>> <         Query query = p.parseInternal(null, q, false, 
>> funTable, false);
>> ---
>>     
>>>         Query query = p.parseInternal(null, q, false, 
>>>       
>> funTable, false, false);
>> 122c122
>> <             p.parseInternal(null, query, false, funTable, false);
>> ---
>>     
>>>             p.parseInternal(null, query, false, funTable, 
>>>       
>> false, false);
>> 142c142
>> <             p.parseInternal(null, query, false, funTable, false));
>> ---
>>     
>>>             p.parseInternal(null, query, false, funTable, 
>>>       
>> false, false));
>> 156c156
>> <             p.parseInternal(null, query, false, funTable, false));
>> ---
>>     
>>>             p.parseInternal(null, query, false, funTable, 
>>>       
>> false, false));
>> 310c310,311
>> <             final Query query = 
>> p.parseInternal(getConnection(), mdx, false, funTable, false);
>> ---
>>     
>>>             final Query query = 
>>>                 p.parseInternal(getConnection(), mdx, 
>>>       
>> false, funTable, false, false);
>> 421c422
>> <         final Query query = p.parseInternal(null, mdx, 
>> false, funTable, false);
>> ---
>>     
>>>         final Query query = p.parseInternal(null, mdx, 
>>>       
>> false, funTable, false, false);
>> 437c438
>> <         final Query query = p.parseInternal(null, mdx, 
>> false, funTable, false);
>> ---
>>     
>>>         final Query query = p.parseInternal(null, mdx, 
>>>       
>> false, funTable, false, false);
>>
>> ==== 
>> //open/mondrian/testsrc/main/mondrian/olap/QueryTest.java#2 
>> (ktext) ====
>>
>> 2c2
>> < // $Id: 
>> //open/mondrian/testsrc/main/mondrian/olap/QueryTest.java#1 $
>> ---
>>     
>>> // $Id: 
>>>       
>> //open/mondrian/testsrc/main/mondrian/olap/QueryTest.java#2 $
>> 36c36
>> <                 null, cellProps, false);
>> ---
>>     
>>>                 null, cellProps, false, false);
>>>       
>> 38c38
>> <                 null, new QueryPart[0], false);
>> ---
>>     
>>>                 null, new QueryPart[0], false, false);
>>>       
>
>   


-- 
Rushan Chen

www.lucidera.com<http://www.lucidera.com/>

Gartner: LucidEra is a business intelligence "Cool Vendor
<http://www.lucidera.com/company/press_releases/cool_Vendor_leading_analyst_firm_9apr.php>

Beagle Research: LucidEra is a CRM WizKid
<http://www.lucidera.com/company/press_releases/lucidera_crm_wizkid_awards_26mar.php>

JMP Securities: LucidEra is in the Hot 100
<http://www.lucidera.com/company/press_releases/jmp_hot_100_best_apr2.php>

-------------------------------------------------------------------------------
This message and any files or text attached to it are intended only for
the recipients named above, and contain information that may be
confidential or privileged. If you are not an intended recipient, or you
have reason to believe that you received this message in error, you must
not read, copy, use or disclose this communication. Please also notify
the sender by replying to this message, and then delete all copies of it
from your system. Thank you.






More information about the Mondrian mailing list