The bug you identified when using the Descendants() function is more general than just in named sets, and is probably more general than just using Descendants().  <div><br></div><div>SqlConstraintFactory will return a SqlContextConstraint, even if the current context is not nonempty.  Executing the query you posted will result in a SCC being used when evaluating the tuple list, which causes native non empty behavior.  I think a SqlContextConstraint should only be used in a non empty context.</div>

<div><br></div><div>For other MDX functions (like .Children and .Members) there is an upstream check for nonempty, which causes a null context to be passed to SqlConstraintFactory.  If SqlConstraintFactory finds a null context it will return a DefaultMemberContextConstraint, resulting in the desired set.</div>

<div><br></div><div>I think the simplest solution here would be to add a check for non empty context in the SqlConstraintFactory methods.</div><div><br></div><div><br></div><div><div><div class="gmail_quote">On Thu, May 14, 2009 at 8:04 PM, wenjin huang <span dir="ltr">&lt;<a href="mailto:wenjin.huang@gmail.com">wenjin.huang@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div>Hi, </div>
<div> </div>
<div>Thank you for your reply.</div>
<div> </div>
<div>We did some testing to sync the nonEmpty flag for root.slicerEvaluator with its parent/caller RoalEvalutor. We tried the change below in RolapResultEvaluatorRoot.evaluateNamedSet() method. With this change, The .Children call will only return Non Empty children when it is specified inside of NON EMPTY set. Since this change only applies to .Children and Descendants function, it doesn&#39;t break any unit tests so far.</div>

<div class="im">

<div> </div>
<div>RolapResult$RolapResultEvaluatorRoot.evaluateNamedSet(String, Exp) line: 1194  </div>
</div><div><br>        //Pass in nonEmpty flag from the caller/parent RoalEvalutor<br>        protected Object evaluateNamedSet(String name, Exp exp, <font color="#3333ff"><strong>boolean nonEmpty</strong></font>) {<br>            Object value = namedSetValues.get(name);<br>


            if (value == null) {<br>                final RolapEvaluator.RolapEvaluatorRoot root =<br>                    slicerEvaluator.root;<br>                final Calc calc = root.getCompiled(exp, false, ResultStyle.LIST);<br>


                </div>
<div>               <font color="#3333ff"><strong> //Sync the nonEmpty flag for root.slicerEvaluator with its parent/caller RoalEvalutor<br>                //Restrict the change only to .Children call and Descendants function.<br>


                //This flag will be used in the DescendantsFunDef.descendantsByDepth() method for Descendants function,<br>                //and the FunUtil.getNonEmptyMemberChildren() method for .Children call</strong></font><font color="#3333ff"><br>


<strong>                if (exp != null &amp;&amp; (exp.toString().indexOf(&quot;Descendants&quot;) &gt; 0 || exp.toString().indexOf(&quot;Children&quot;)&gt;0) )<br>                {<br>                  slicerEvaluator.setNonEmpty(nonEmpty);<br>


                  <br>                }<br></strong></font></div>
<div>It seems that the Descendants function with Mondrian 3.0.4 will only return Non Empty member children, even if it is not specified inside of NON EMPTY set. It will always join the fact table to only get the nonEmpty member children. It behaves in the opposite way of the .Children call. </div>



<div> </div>
<div>with set [#DataSet#] as &#39;Descendants([Product].[All Products], 4)&#39;<div class="im"><br>select {[Measures].[Store Invoice], [Measures].[Supply Time], [Measures].[Warehouse Cost], [Measures].[Warehouse Sales]} ON COLUMNS,<br>

</div><div class="im">{[#DataSet#]} ON ROWS<br>
from [Warehouse]<br>where ([Time].[1997].[Q4].[12])</div></div>
<div><br>If we apply the NonEmpty flag to DescendantsFunDef.descendantsByDepth(Member, List, SchemaReader, int, boolean, boolean, boolean, Evaluator) line: 163   like below. With this change and the change above, The Descendants function will also return empty member when it is not specified inside of NON EMPTY set.</div>



<div> </div>
<div>            if (context!= null &amp;&amp; context.isNonEmpty())<br>            {<br>             children = schemaReader.getMemberChildren(children, context);<br>            }<br>            else<br>            {<br>


             children = schemaReader.getMemberChildren(children);<br>            }<br>   </div>
<div>Any suggestions or thoughts on this fix? </div>
<div> </div>
<div>Thanks, </div>
<div>Wenjin</div><div><div></div><div class="h5">
<div> </div>
<div> </div>
<div class="gmail_quote">On Wed, May 13, 2009 at 4:12 AM, Julian Hyde <span dir="ltr">&lt;<a href="mailto:jhyde@pentaho.com" target="_blank">jhyde@pentaho.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="padding-left:1ex;margin:0px 0px 0px 0.8ex;border-left:#ccc 1px solid">This sounds similar to <a href="http://jira.pentaho.com/browse/MONDRIAN-506" target="_blank">http://jira.pentaho.com/browse/MONDRIAN-506</a> which you<br>


logged in February.<br><br>It also sounds like the issue I wrote about in this blog post:<br><a href="http://julianhyde.blogspot.com/2009/01/hard-won-lessons-in-mondrian-query.html" target="_blank">http://julianhyde.blogspot.com/2009/01/hard-won-lessons-in-mondrian-query.ht<br>


ml</a><br><br>If you read the blog post, you will see I had the same problem you did -<br>every time I changed something to get the query to perform, something else<br>broke.<br><br>So, read the blog post. My conclusions there are the best I have to offer<br>


right now.<br><br>Julian<br><br>&gt; -----Original Message-----<br>&gt; From: <a href="mailto:mondrian-bounces@pentaho.org" target="_blank">mondrian-bounces@pentaho.org</a><br>&gt; [mailto:<a href="mailto:mondrian-bounces@pentaho.org" target="_blank">mondrian-bounces@pentaho.org</a>] On Behalf Of Robin Tharappel<br>


&gt; Sent: Tuesday, May 12, 2009 12:49 PM<br>&gt; To: <a href="mailto:mondrian@pentaho.org" target="_blank">mondrian@pentaho.org</a><br>&gt; Subject: [Mondrian] .Children function not being evaluated<br>&gt; natively (no joinwith the fact table)<br>


&gt;<br>&gt; Hello,<br>&gt;<br>&gt; With Mondrian 3.0.4 it appears that the .children function is not<br>&gt; being evaluated natively when specified inside of NON EMPTY set. It<br>&gt; will return empty children as well.  This can be a performance problem<br>


&gt; if the dimension contains a large number of members at the children<br>&gt; level.  By joining the dimension table with the fact table the number<br>&gt; of members could be reduced . This is the MDX query with the<br>


&gt; FoodMart.xml.<br>&gt;<br>&gt;<br>&gt; with set [#DataSet#] as &#39;{[Product].[All Products].[Food].[Baking<br>&gt; Goods].[Baking Goods].Children}&#39;<br>&gt; select {[Measures].[Store Invoice], [Measures].[Supply Time],<br>


&gt; [Measures].[Warehouse Cost], [Measures].[Warehouse Sales]} ON COLUMNS,<br>&gt;  NON EMPTY Hierarchize({[#DataSet#]}) ON ROWS<br>&gt; from [Warehouse]<br>&gt; where ([Time].[1997].[Q4].[12])<br>&gt;<br>&gt;<br>&gt; The root cause of this problem is that for this expression<br>


&gt; &quot;[Product].[All Products].[Food].[Baking Goods].[Baking<br>&gt; Goods].Children&quot;, the RolapEvaluator&#39;s nonempty is true, but the<br>&gt; RolapEvaluator.root.slicerEvaluator&#39;s nonEmpty property is still<br>


&gt; false. They are out of sync.<br>&gt;<br>&gt; The RolapEvaluator.evaluateNamedSet(String, Exp) method will call the<br>&gt; root.evaluateNamedSet(String, Exp). And it will pass the<br>&gt; root.slicerEvaluator to the<br>


&gt; FunUtil.getNonEmptyMemberChildren(Evaluator, Member) method for the<br>&gt; .Children call, which will use this nonEmpty property of the<br>&gt; slicerEvalutor to determine weather to return the nonEmpty children or<br>


&gt; not.<br>&gt;<br>&gt;<br>&gt; But if I made this change in<br>&gt; RolapResult$RolapResultEvaluatorRoot.evaluateNamedSet(String, Exp)<br>&gt; line: 1194  to sync the slicerEvaluator&#39;s nonEmpty with Evaluator&#39;s<br>


&gt; nonEmpty value. It would break these three unit tests.<br>&gt;<br>&gt; testTopMetricWithThreeLevelHierarchy (mondrian.test.TopBottomTest<br>&gt; testTotalingWhenIgnoreUnrelatedDimensionsPropertyIsTrue(mondri<br>&gt; an.test.IgnoreUnrelatedDimensionsTest<br>


&gt; testIndependentSlicerMemberNonNative(mondrian.rolap.NonEmptyTest<br>&gt;<br>&gt;<br>&gt; Note that if the .Children function is replaced by an equivalent<br>&gt; Descendants function it will be evaluated by joining with the fact<br>


&gt; table. Any suggestion for this problem?<br>&gt;<br>&gt; Thanks<br>&gt;<br>&gt;<br>&gt;<br>&gt; The trace stack for the .Children call:<br>&gt; Thread [main] (Suspended)<br>&gt;             SqlMemberSource.chooseAggStar(MemberChildrenConstraint,<br>


&gt; RolapMember) line: 581<br>&gt;             SqlMemberSource.makeChildMemberSql(RolapMember,<br>&gt; DataSource, MemberChildrenConstraint) line: 502<br>&gt;             SqlMemberSource.getMemberChildren2(RolapMember,<br>


&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 836<br>&gt;             SqlMemberSource.getMemberChildren(RolapMember,<br>&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 770<br>&gt;             SqlMemberSource.getMemberChildren(List&lt;RolapMember&gt;,<br>


&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 745<br>&gt;             SmartMemberReader.readMemberChildren(List&lt;RolapMember&gt;,<br>&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 237<br>

&gt;             SmartMemberReader.getMemberChildren(List&lt;RolapMember&gt;,<br>
&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 201<br>&gt;<br>&gt; RolapCubeHierarchy$RolapCubeHierarchyMemberReader.readMemberCh<br>ildren(List&lt;RolapMember&gt;,<br>&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 472<br>


&gt;<br>&gt; RolapCubeHierarchy$RolapCubeHierarchyMemberReader.getMemberChi<br>ldren(List&lt;RolapMember&gt;,<br>&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 568<br>&gt;<br>&gt; RolapCubeHierarchy$RolapCubeHierarchyMemberReader(SmartMemberR<br>


eader).getMemberChildren(RolapMember,<br>&gt; List&lt;RolapMember&gt;, MemberChildrenConstraint) line: 169<br>&gt;<br>&gt; RolapCube$RolapCubeSchemaReader(RolapSchemaReader).internalGet<br>MemberChildren(Member,<br>&gt; MemberChildrenConstraint) line: 155     //Here is<br>


&gt; DefaultMemberChildrenConstraint<br>&gt;<br>&gt; RolapCube$RolapCubeSchemaReader(RolapSchemaReader).getMemberCh<br>&gt; ildren(Member,<br>&gt; Evaluator) line: 145       //Here the Evaluator is null<br>&gt;<br>&gt; RolapCube$RolapCubeSchemaReader(RolapSchemaReader).getMemberCh<br>


&gt; ildren(Member)<br>&gt; line: 139<br>&gt;<br>&gt; Query$QuerySchemaReader(DelegatingSchemaReader).getMemberChild<br>&gt; ren(Member)<br>&gt; line: 60<br>&gt;             FunUtil.getNonEmptyMemberChildren(Evaluator, Member) line:<br>


&gt; 1790<br>&gt;             BuiltinFunTable$30$1.evaluateList(Evaluator) line: 906<br>&gt;             SetFunDef$ListSetCalc$1.evaluateVoid(Evaluator) line: 131<br>&gt;             SetFunDef$ListSetCalc.evaluateList(Evaluator) line: 204<br>


&gt;<br>&gt; SetFunDef$ListSetCalc(AbstractListCalc).evaluate(Evaluator)<br>&gt; line: 67<br>&gt;             RolapResult.evaluateExp(Calc, RolapEvaluator) line: 794<br>&gt;             RolapResult.access$100(RolapResult, Calc, RolapEvaluator)<br>


&gt; line: 46<br>&gt;<br>&gt; RolapResult$RolapResultEvaluatorRoot.evaluateNamedSet(String,<br>&gt; Exp) line: 1194<br>&gt;             RolapEvaluator.evaluateNamedSet(String, Exp) line: 884<br>&gt;             NamedSetExpr$1.evaluateList(Evaluator) line: 78<br>


&gt;             SetFunDef$ListSetCalc$1.evaluateVoid(Evaluator) line: 131<br>&gt;             SetFunDef$ListSetCalc.evaluateList(Evaluator) line: 204<br>&gt;             HierarchizeFunDef$1.evaluateList(Evaluator) line: 48<br>


&gt;<br>&gt; HierarchizeFunDef$1(AbstractListCalc).evaluate(Evaluator) line: 67<br>&gt;             RolapResult.executeAxis(Evaluator, QueryAxis, Calc,<br>&gt; boolean, RolapResult$AxisMember) line: 694<br>&gt;             RolapResult.evalLoad(List&lt;Member[]&gt;, int, Evaluator,<br>


&gt; QueryAxis, Calc, AxisMember) line: 557<br>&gt;             RolapResult.loadMembers(List&lt;Member[]&gt;, RolapEvaluator,<br>&gt; QueryAxis, Calc, AxisMember) line: 532<br>&gt;             RolapResult.&lt;init&gt;(Query, boolean) line: 254<br>


&gt;             RolapConnection.execute(Query) line: 597<br>&gt;             CmdRunner.runQuery(String, boolean) line: 566<br>&gt;             CmdRunner.execute(String) line: 543<br>&gt;             CmdRunner.executeMdxCmd(String) line: 2243<br>


&gt;             CmdRunner.commandLoop(Reader, boolean) line: 872<br>&gt;             CmdRunner.commandLoop(File) line: 750<br>&gt;             CmdRunner.main(String[]) line: 2397<br>&gt;<br>&gt;    FunUtil.java<br>&gt;<br>


&gt;   public static Member[] getNonEmptyMemberChildren(<br>&gt;         Evaluator evaluator,<br>&gt;         Member member)<br>&gt;     {<br>&gt;         SchemaReader sr = evaluator.getSchemaReader();<br>&gt;         if (evaluator.isNonEmpty()) {<br>


&gt;             return sr.getMemberChildren(member, evaluator);<br>&gt;         } else {<br>&gt;             return sr.getMemberChildren(member);<br>&gt;         }<br>&gt;     }<br>&gt;<br>&gt; _______________________________________________<br>


&gt; Mondrian mailing list<br>&gt; <a href="mailto:Mondrian@pentaho.org" target="_blank">Mondrian@pentaho.org</a><br>&gt; <a href="http://lists.pentaho.org/mailman/listinfo/mondrian" target="_blank">http://lists.pentaho.org/mailman/listinfo/mondrian</a><br>


&gt;<br>&gt;<br>&gt;<br><br><br>_______________________________________________<br>Mondrian mailing list<br><a href="mailto:Mondrian@pentaho.org" target="_blank">Mondrian@pentaho.org</a><br><a href="http://lists.pentaho.org/mailman/listinfo/mondrian" target="_blank">http://lists.pentaho.org/mailman/listinfo/mondrian</a><br>


</blockquote></div><br>
</div></div><br>_______________________________________________<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" target="_blank">http://lists.pentaho.org/mailman/listinfo/mondrian</a><br>
<br></blockquote></div><br></div></div>