[Mondrian] Problem moving UDF returning a list from 2.4 to 3.1.1

Eric McDermid mcdermid at stonecreek.com
Mon Aug 3 23:30:52 EDT 2009


Thanks for the fix, Julian.

Running the new code, I do find that i still run into the second issue  
I mentioned below (args[0] evaluating anonymous Iterable rather than a  
List).  Near as I can tell, the problem only occurs when passing a  
named set to the UDF.

I've created a simple reproduction case that demonstrates the problem,  
and created MONDRIAN-589 to track it.

  -- Eric

On Jul 31, 2009, at 9:10 PM, Eric McDermid wrote:

> Done.  Mondrian-588.
>
> I've also added some further notes in that description.  I  
> experimented this afternoon with changing UdfResolver to return an  
> object that implements AbstractMemberListCalc (rather than just  
> GenericCalc) if the compiler's preferred result type is a list.  I'm  
> not sure it's the right answer, and I've yet to run the full test  
> suite on it, but it does get me past the error.
>
> Unfortunately, when the Reverse UDF is actually executed,  
> "args[0].evaluate(eval)" returns an anonymous Iterable generated  
> from RolapNamedSetEvaluator.evaluateMemberIterable(), rather than a  
> List as used to be the case under 2.4, triggering a class cast  
> exception.  This has nothing to do with my workaround; I've seen it  
> prior to the change as well.
>
>  -- Eric
>
> On Jul 31, 2009, at 7:33 PM, Julian Hyde wrote:
>
>> I'll look into it over the weekend. Can you please log a bug.
>>
>> Julian
>>
>> From: mondrian-bounces at pentaho.org [mailto:mondrian-bounces at pentaho.org 
>> ] On Behalf Of Eric McDermid
>> Sent: Friday, July 31, 2009 10:36 AM
>> To: Mondrian developer mailing list
>> Subject: [Mondrian] Problem moving UDF returning a list from 2.4 to  
>> 3.1.1
>>
>> I'm having some trouble with a UDF returning a List that worked  
>> under 2.4, but fails with a parse error under 3.1.1.  I'm not sure  
>> whether the problem is a flaw in the UDF or in how the newer  
>> version of Mondrian is attempting to use it.
>>
>> Here's the function, which simply reverses the order of a set:
>>
>>   public class ReverseFunction implements UserDefinedFunction {
>> public Object execute(Evaluator eval, Argument[] args) {
>> List memberList = (List) args[0].evaluate(eval);
>> Collections.reverse(memberList);
>> return memberList;
>> }
>> public String getDescription() {
>> return "Reverses the order of a set";
>> }
>> public String getName() {
>> return "Reverse";
>> }
>> public Type[] getParameterTypes() {
>> return new Type[] {new SetType(MemberType.Unknown)};
>> }
>> public String[] getReservedWords() {
>> return null;
>> }
>> public Type getReturnType(Type[] arg0) {
>> return arg0[0];
>> }
>> public Syntax getSyntax() {
>> return Syntax.Function;
>> }
>>   }
>>
>> The stack trace for the underlying cause of the error is here:
>>
>> Caused by: mondrian.olap.MondrianException: Mondrian Error:Internal  
>> error: Cannot convert calc to list: mondrian.olap.fun.UdfResolver 
>> $CalcImpl at 315d04
>> at mondrian.resource.MondrianResource 
>> $_Def0.ex(MondrianResource.java:803)
>> at mondrian.olap.Util.newInternal(Util.java:1465)
>> at  
>> mondrian 
>> .calc.impl.AbstractExpCompiler.compileList(AbstractExpCompiler.java: 
>> 286)
>> at  
>> mondrian 
>> .calc.impl.BetterExpCompiler.compileList(BetterExpCompiler.java:77)
>> at  
>> mondrian 
>> .calc.impl.AbstractExpCompiler.compileList(AbstractExpCompiler.java: 
>> 260)
>> at mondrian.olap.fun.SetFunDef 
>> $MemberSetListCalc.createCalc(SetFunDef.java:147)
>> at mondrian.olap.fun.SetFunDef 
>> $MemberSetListCalc.compileSelf(SetFunDef.java:134)
>> at mondrian.olap.fun.SetFunDef 
>> $MemberSetListCalc.<init>(SetFunDef.java:120)
>> at mondrian.olap.fun.SetFunDef.compileCall(SetFunDef.java:89)
>> at mondrian.mdx.ResolvedFunCall.accept(ResolvedFunCall.java:152)
>> at  
>> mondrian 
>> .calc.impl.AbstractExpCompiler.compile(AbstractExpCompiler.java:79)
>> at  
>> mondrian 
>> .calc.impl.AbstractExpCompiler.compileAs(AbstractExpCompiler.java: 
>> 124)
>> at  
>> mondrian 
>> .calc.impl.AbstractExpCompiler.compileIter(AbstractExpCompiler.java: 
>> 311)
>> at mondrian.olap.QueryAxis.compile(QueryAxis.java:122)
>> at mondrian.olap.Query.compile(Query.java:519)
>> at mondrian.olap.Query.resolve(Query.java:456)
>> at mondrian.olap.Query.<init>(Query.java:231)
>> at mondrian.olap.Query.<init>(Query.java:187)
>> at mondrian.olap.Parser.makeQuery(Parser.java:870)
>> at mondrian.olap.CUP$Parser$actions.CUP$Parser 
>> $do_action(Parser.java:1764)
>> at mondrian.olap.Parser.do_action(Parser.java:699)
>> at java_cup.runtime.lr_parser.parse(lr_parser.java:569)
>> at mondrian.olap.Parser.parseInternal(Parser.java:772)
>>
>> The immediate problem is in AbstractExpCompiler.compileList().  It  
>> compiles the expression "Reverse([Requested Dates])", gets a  
>> mondrian.olap.fun.UdfResolver$CalcImpl instance as a result, then  
>> complains because said calc is neither null, a ListCalc, or an  
>> IterCalc.
>>
>> UDF documentation seems a little thin, and I've been unable to find  
>> an example of a UDF returning a list in either mondrian/udf or in  
>> UdfTest to use as a reference point.  Searching the archive, I do  
>> see that Pappyn Bart asked a somewhat similar question back in  
>> 2007, but I didn't see a clear resolution.
>>
>> Can anyone help me sort this problem out, or failing that at least  
>> point me to an example of a UDF that does successfully return a  
>> list that I can compare against?
>>
>>  -- Eric
>>
>>
>> _______________________________________________
>> Mondrian mailing list
>> Mondrian at pentaho.org
>> http://lists.pentaho.org/mailman/listinfo/mondrian
>
> _______________________________________________
> Mondrian mailing list
> Mondrian at pentaho.org
> http://lists.pentaho.org/mailman/listinfo/mondrian

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.pentaho.org/pipermail/mondrian/attachments/20090803/df86cda5/attachment.html 


More information about the Mondrian mailing list