<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Thanks for the fix, Julian.</div><div><br></div><div>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.</div><div><br></div><div>I've created a simple reproduction case that demonstrates the problem, and created MONDRIAN-589 to track it.</div><div><br></div><div> -- Eric<br><div><br><div><div>On Jul 31, 2009, at 9:10 PM, Eric McDermid wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Done. Mondrian-588.<div><br></div><div>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. </div><div><br></div><div>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.</div><div><br></div><div> -- Eric</div><div><br><div><div>On Jul 31, 2009, at 7:33 PM, Julian Hyde wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"> <div style="WORD-WRAP: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space"> <div><span class="479463201-01082009"><font color="#000080" size="2" face="Lucida Sans">I'll look into it over the weekend. Can you please log a bug.</font></span></div> <div><span class="479463201-01082009"><font color="#000080" size="2" face="Lucida Sans"></font></span> </div> <div><span class="479463201-01082009"><font color="#000080" size="2" face="Lucida Sans">Julian</font></span></div><br> <blockquote style="BORDER-LEFT: #000080 2px solid; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; MARGIN-RIGHT: 0px" dir="ltr"> <div dir="ltr" lang="en-us" class="OutlookMessageHeader" align="left"> <hr tabindex="-1"> <font size="2" face="Tahoma"><b>From:</b> <a href="mailto:mondrian-bounces@pentaho.org">mondrian-bounces@pentaho.org</a> [<a href="mailto:mondrian-bounces@pentaho.org">mailto:mondrian-bounces@pentaho.org</a>] <b>On Behalf Of </b>Eric McDermid<br><b>Sent:</b> Friday, July 31, 2009 10:36 AM<br><b>To:</b> Mondrian developer mailing list<br><b>Subject:</b> [Mondrian] Problem moving UDF returning a list from 2.4 to 3.1.1<br></font><br></div> <div></div> <div>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. </div> <div><br></div> <div>Here's the function, which simply reverses the order of a set:</div> <div> <div><br></div> <div><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"> public class ReverseFunction implements UserDefinedFunction {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public Object execute(Evaluator eval, Argument[] args) {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">List memberList = (List) args[0].evaluate(eval);</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">Collections.reverse(memberList);</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return memberList;</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public String getDescription() {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return "Reverses the order of a set";</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public String getName() {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return "Reverse";</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public Type[] getParameterTypes() {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return new Type[] {new SetType(MemberType.Unknown)};</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public String[] getReservedWords() {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return null;</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public Type getReturnType(Type[] arg0) {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return arg0[0];</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">public Syntax getSyntax() {</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">return Syntax.Function;</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">}</span></font></div> <div><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"> }</span></font></div> <div><br></div> <div> <div>The stack trace for the underlying cause of the error is here:</div> <div><br></div> <div><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">Caused by: mondrian.olap.MondrianException: Mondrian Error:Internal error: Cannot convert calc to list: mondrian.olap.fun.UdfResolver$CalcImpl@315d04</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:803)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Util.newInternal(Util.java:1465)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.AbstractExpCompiler.compileList(AbstractExpCompiler.java:286)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.BetterExpCompiler.compileList(BetterExpCompiler.java:77)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.AbstractExpCompiler.compileList(AbstractExpCompiler.java:260)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.fun.SetFunDef$MemberSetListCalc.createCalc(SetFunDef.java:147)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.fun.SetFunDef$MemberSetListCalc.compileSelf(SetFunDef.java:134)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.fun.SetFunDef$MemberSetListCalc.<init>(SetFunDef.java:120)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.fun.SetFunDef.compileCall(SetFunDef.java:89)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.mdx.ResolvedFunCall.accept(ResolvedFunCall.java:152)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.AbstractExpCompiler.compile(AbstractExpCompiler.java:79)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.AbstractExpCompiler.compileAs(AbstractExpCompiler.java:124)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.calc.impl.AbstractExpCompiler.compileIter(AbstractExpCompiler.java:311)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.QueryAxis.compile(QueryAxis.java:122)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Query.compile(Query.java:519)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Query.resolve(Query.java:456)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Query.<init>(Query.java:231)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Query.<init>(Query.java:187)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Parser.makeQuery(Parser.java:870)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.CUP$Parser$actions.CUP$Parser$do_action(Parser.java:1764)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Parser.do_action(Parser.java:699)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at java_cup.runtime.lr_parser.parse(lr_parser.java:569)</span></font></div> <div><span style="WHITE-SPACE: pre" class="Apple-tab-span"><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span"></span></font></span><font class="Apple-style-span" size="3"><span style="FONT-SIZE: 11px" class="Apple-style-span">at mondrian.olap.Parser.parseInternal(Parser.java:772)</span></font></div> <div><br></div> <div>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.</div> <div><br></div> <div>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.</div> <div><br></div> <div>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?</div> <div><br></div> <div> -- Eric</div> <div><br></div> <div><br></div></div></div></blockquote></div> _______________________________________________<br>Mondrian mailing list<br><a href="mailto:Mondrian@pentaho.org">Mondrian@pentaho.org</a><br><a href="http://lists.pentaho.org/mailman/listinfo/mondrian">http://lists.pentaho.org/mailman/listinfo/mondrian</a><br></blockquote></div><br></div></div>_______________________________________________<br>Mondrian mailing list<br><a href="mailto:Mondrian@pentaho.org">Mondrian@pentaho.org</a><br>http://lists.pentaho.org/mailman/listinfo/mondrian<br></blockquote></div><br></div></div></body></html>