[Mondrian] RE: Eigenbase perforce change 11171 for review

Julian Hyde jhyde at pentaho.com
Mon Jun 16 05:59:19 EDT 2008


I can understand why you want that behavior, but I don't think it's useful
to anyone besides LucidEra. As such, it shouldn't be in the Connection
interface. Can you think of a way to get it out of the public API? Maybe you
could add a parser or validator factory, and access it via a new connect
string parameter.

If you simply want to use the parser for validation purposes, you might
consider using olap4j's parser & validator. The goals of the olap4j parser
are to be extensible to handle a variety of mdx dialects, and to work in
client environments with minimal dependencies, so it might be better for
these purposes.

Julian

> -----Original Message-----
> From: Rushan Chen [mailto:rchen at lucidera.com] 
> Sent: Monday, June 16, 2008 12:49 AM
> To: jhyde at pentaho.com
> Cc: mondrian at pentaho.org
> Subject: Re: Eigenbase perforce change 11171 for review
> 
> 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_le
> ading_analyst_firm_9apr.php>
> 
> Beagle Research: LucidEra is a CRM WizKid
> <http://www.lucidera.com/company/press_releases/lucidera_crm_w
> izkid_awards_26mar.php>
> 
> JMP Securities: LucidEra is in the Hot 100
> <http://www.lucidera.com/company/press_releases/jmp_hot_100_be
> st_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