Search in sources :

Example 1 with AbstractListCalc

use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.

the class NonEmptyCrossJoinFunDef method compileCall.

public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
    final ListCalc listCalc1 = compiler.compileList(call.getArg(0));
    final ListCalc listCalc2 = compiler.compileList(call.getArg(1));
    return new AbstractListCalc(call, new Calc[] { listCalc1, listCalc2 }, false) {

        public TupleList evaluateList(Evaluator evaluator) {
            SchemaReader schemaReader = evaluator.getSchemaReader();
            // Evaluate the arguments in non empty mode, but remove from
            // the slicer any members that will be overridden by args to
            // the NonEmptyCrossjoin function. For example, in
            // 
            // SELECT NonEmptyCrossJoin(
            // [Store].[USA].Children,
            // [Product].[Beer].Children)
            // FROM [Sales]
            // WHERE [Store].[Mexico]
            // 
            // we want all beers, not just those sold in Mexico.
            final int savepoint = evaluator.savepoint();
            try {
                evaluator.setNonEmpty(true);
                for (Member member : ((RolapEvaluator) evaluator).getSlicerMembers()) {
                    if (getType().getElementType().usesHierarchy(member.getHierarchy(), true)) {
                        evaluator.setContext(member.getHierarchy().getAllMember());
                    }
                }
                NativeEvaluator nativeEvaluator = schemaReader.getNativeSetEvaluator(call.getFunDef(), call.getArgs(), evaluator, this);
                if (nativeEvaluator != null) {
                    evaluator.restore(savepoint);
                    return (TupleList) nativeEvaluator.execute(ResultStyle.LIST);
                }
                final TupleList list1 = listCalc1.evaluateList(evaluator);
                if (list1.isEmpty()) {
                    evaluator.restore(savepoint);
                    return list1;
                }
                final TupleList list2 = listCalc2.evaluateList(evaluator);
                TupleList result = mutableCrossJoin(list1, list2);
                // remove any remaining empty crossings from the result
                result = nonEmptyList(evaluator, result, call);
                return result;
            } finally {
                evaluator.restore(savepoint);
            }
        }

        public boolean dependsOn(Hierarchy hierarchy) {
            if (super.dependsOn(hierarchy)) {
                return true;
            }
            // expression from the inherited context.
            if (listCalc1.getType().usesHierarchy(hierarchy, true)) {
                return false;
            }
            if (listCalc2.getType().usesHierarchy(hierarchy, true)) {
                return false;
            }
            // whether a given tuple is empty, depends upon all dimensions.
            return true;
        }
    };
}
Also used : AbstractListCalc(mondrian.calc.impl.AbstractListCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) RolapEvaluator(mondrian.rolap.RolapEvaluator) RolapEvaluator(mondrian.rolap.RolapEvaluator)

Example 2 with AbstractListCalc

use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.

the class PeriodsToDateFunDef method compileCall.

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
    final LevelCalc levelCalc = call.getArgCount() > 0 ? compiler.compileLevel(call.getArg(0)) : null;
    final MemberCalc memberCalc = call.getArgCount() > 1 ? compiler.compileMember(call.getArg(1)) : null;
    final RolapHierarchy timeHierarchy = levelCalc == null ? ((RolapCube) compiler.getEvaluator().getCube()).getTimeHierarchy(getName()) : null;
    return new AbstractListCalc(call, new Calc[] { levelCalc, memberCalc }) {

        public TupleList evaluateList(Evaluator evaluator) {
            evaluator.getTiming().markStart(TIMING_NAME);
            try {
                final Member member;
                final Level level;
                if (levelCalc == null) {
                    member = evaluator.getContext(timeHierarchy);
                    level = member.getLevel().getParentLevel();
                } else {
                    level = levelCalc.evaluateLevel(evaluator);
                    if (memberCalc == null) {
                        member = evaluator.getContext(level.getHierarchy());
                    } else {
                        member = memberCalc.evaluateMember(evaluator);
                    }
                }
                return new UnaryTupleList(periodsToDate(evaluator, level, member));
            } finally {
                evaluator.getTiming().markEnd(TIMING_NAME);
            }
        }

        public boolean dependsOn(Hierarchy hierarchy) {
            if (super.dependsOn(hierarchy)) {
                return true;
            }
            if (memberCalc != null) {
                return false;
            } else if (levelCalc != null) {
                return levelCalc.getType().usesHierarchy(hierarchy, true);
            } else {
                return hierarchy == timeHierarchy;
            }
        }
    };
}
Also used : RolapHierarchy(mondrian.rolap.RolapHierarchy) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) RolapHierarchy(mondrian.rolap.RolapHierarchy)

Example 3 with AbstractListCalc

use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.

the class TopBottomCountFunDef method compileCall.

public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
    // Compile the member list expression. Ask for a mutable list, because
    // we're going to sort it later.
    final ListCalc listCalc = compiler.compileList(call.getArg(0), true);
    final IntegerCalc integerCalc = compiler.compileInteger(call.getArg(1));
    final Calc orderCalc = call.getArgCount() > 2 ? compiler.compileScalar(call.getArg(2), true) : null;
    final int arity = call.getType().getArity();
    return new AbstractListCalc(call, new Calc[] { listCalc, integerCalc, orderCalc }) {

        public TupleList evaluateList(Evaluator evaluator) {
            // Use a native evaluator, if more efficient.
            // TODO: Figure this out at compile time.
            SchemaReader schemaReader = evaluator.getSchemaReader();
            NativeEvaluator nativeEvaluator = schemaReader.getNativeSetEvaluator(call.getFunDef(), call.getArgs(), evaluator, this);
            if (nativeEvaluator != null) {
                return (TupleList) nativeEvaluator.execute(ResultStyle.LIST);
            }
            int n = integerCalc.evaluateInteger(evaluator);
            if (n == 0 || n == mondrian.olap.fun.FunUtil.IntegerNull) {
                return TupleCollections.emptyList(arity);
            }
            TupleList list = listCalc.evaluateList(evaluator);
            assert list.getArity() == arity;
            if (list.isEmpty()) {
                return list;
            }
            if (orderCalc == null) {
                // REVIEW: Why require "instanceof AbstractList"?
                if (list instanceof AbstractList && list.size() <= n) {
                    return list;
                } else if (top) {
                    return list.subList(0, n);
                } else {
                    return list.subList(list.size() - n, list.size());
                }
            }
            return partiallySortList(evaluator, list, hasHighCardDimension(list), Math.min(n, list.size()));
        }

        private TupleList partiallySortList(Evaluator evaluator, TupleList list, boolean highCard, int n) {
            assert list.size() > 0;
            assert n <= list.size();
            if (highCard) {
                // sort list in chunks, collect the results
                // what is this really?
                final int chunkSize = 6400;
                TupleList allChunkResults = TupleCollections.createList(arity);
                for (int i = 0, next; i < list.size(); i = next) {
                    next = Math.min(i + chunkSize, list.size());
                    final TupleList chunk = list.subList(i, next);
                    TupleList chunkResult = partiallySortList(evaluator, chunk, false, n);
                    allChunkResults.addAll(chunkResult);
                }
                // one last sort, to merge and cull
                return partiallySortList(evaluator, allChunkResults, false, n);
            }
            // normal case: no need for chunks
            final int savepoint = evaluator.savepoint();
            try {
                switch(list.getArity()) {
                    case 1:
                        final List<Member> members = Sorter.partiallySortMembers(evaluator.push(), list.slice(0), orderCalc, n, top);
                        return new UnaryTupleList(members);
                    default:
                        final List<List<Member>> tuples = partiallySortTuples(evaluator.push(), list, orderCalc, n, top);
                        return new DelegatingTupleList(list.getArity(), tuples);
                }
            } finally {
                evaluator.restore(savepoint);
            }
        }

        public boolean dependsOn(Hierarchy hierarchy) {
            return anyDependsButFirst(getCalcs(), hierarchy);
        }

        private boolean hasHighCardDimension(TupleList l) {
            final List<Member> trial = l.get(0);
            for (Member m : trial) {
                if (m.getHierarchy().getDimension().isHighCardinality()) {
                    return true;
                }
            }
            return false;
        }
    };
}
Also used : AbstractList(java.util.AbstractList) SchemaReader(mondrian.olap.SchemaReader) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) Calc(mondrian.calc.Calc) IntegerCalc(mondrian.calc.IntegerCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) ListCalc(mondrian.calc.ListCalc) Evaluator(mondrian.olap.Evaluator) NativeEvaluator(mondrian.olap.NativeEvaluator) DelegatingTupleList(mondrian.calc.impl.DelegatingTupleList) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) Hierarchy(mondrian.olap.Hierarchy) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) IntegerCalc(mondrian.calc.IntegerCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) ListCalc(mondrian.calc.ListCalc) DelegatingTupleList(mondrian.calc.impl.DelegatingTupleList) AbstractList(java.util.AbstractList) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) List(java.util.List) Member(mondrian.olap.Member) NativeEvaluator(mondrian.olap.NativeEvaluator) DelegatingTupleList(mondrian.calc.impl.DelegatingTupleList)

Example 4 with AbstractListCalc

use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.

the class ExtractFunDef method compileCall.

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
    List<Hierarchy> extractedHierarchyList = new ArrayList<Hierarchy>();
    List<Integer> extractedOrdinalList = new ArrayList<Integer>();
    findExtractedHierarchies(call.getArgs(), extractedHierarchyList, extractedOrdinalList);
    Util.assertTrue(extractedOrdinalList.size() == extractedHierarchyList.size());
    Exp arg = call.getArg(0);
    final ListCalc listCalc = compiler.compileList(arg, false);
    int inArity = arg.getType().getArity();
    final int outArity = extractedOrdinalList.size();
    if (inArity == 1) {
        // LHS is a set of members, RHS is the same hierarchy. Extract boils
        // down to eliminating duplicate members.
        Util.assertTrue(outArity == 1);
        return new DistinctFunDef.CalcImpl(call, listCalc);
    }
    final int[] extractedOrdinals = toIntArray(extractedOrdinalList);
    return new AbstractListCalc(call, new Calc[] { listCalc }) {

        public TupleList evaluateList(Evaluator evaluator) {
            TupleList result = TupleCollections.createList(outArity);
            TupleList list = listCalc.evaluateList(evaluator);
            Set<List<Member>> emittedTuples = new HashSet<List<Member>>();
            for (List<Member> members : list.project(extractedOrdinals)) {
                if (emittedTuples.add(members)) {
                    result.add(members);
                }
            }
            return result;
        }
    };
}
Also used : AbstractListCalc(mondrian.calc.impl.AbstractListCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc)

Example 5 with AbstractListCalc

use of mondrian.calc.impl.AbstractListCalc in project mondrian by pentaho.

the class LastPeriodsFunDef method compileCall.

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
    // Member defaults to [Time].currentmember
    Exp[] args = call.getArgs();
    final MemberCalc memberCalc;
    if (args.length == 1) {
        final RolapHierarchy timeHierarchy = ((RolapCube) compiler.getEvaluator().getCube()).getTimeHierarchy(getName());
        memberCalc = new HierarchyCurrentMemberFunDef.FixedCalcImpl(call, timeHierarchy);
    } else {
        memberCalc = compiler.compileMember(args[1]);
    }
    // Numeric Expression.
    final IntegerCalc indexValueCalc = compiler.compileInteger(args[0]);
    return new AbstractListCalc(call, new Calc[] { memberCalc, indexValueCalc }) {

        public TupleList evaluateList(Evaluator evaluator) {
            Member member = memberCalc.evaluateMember(evaluator);
            int indexValue = indexValueCalc.evaluateInteger(evaluator);
            return new UnaryTupleList(lastPeriods(member, evaluator, indexValue));
        }
    };
}
Also used : AbstractListCalc(mondrian.calc.impl.AbstractListCalc) RolapCube(mondrian.rolap.RolapCube) RolapHierarchy(mondrian.rolap.RolapHierarchy) UnaryTupleList(mondrian.calc.impl.UnaryTupleList)

Aggregations

AbstractListCalc (mondrian.calc.impl.AbstractListCalc)21 Evaluator (mondrian.olap.Evaluator)9 TupleList (mondrian.calc.TupleList)7 UnaryTupleList (mondrian.calc.impl.UnaryTupleList)7 Hierarchy (mondrian.olap.Hierarchy)6 Member (mondrian.olap.Member)6 ArrayList (java.util.ArrayList)5 ListCalc (mondrian.calc.ListCalc)5 List (java.util.List)4 Calc (mondrian.calc.Calc)4 IntegerCalc (mondrian.calc.IntegerCalc)4 SchemaReader (mondrian.olap.SchemaReader)4 Type (mondrian.olap.type.Type)4 LevelCalc (mondrian.calc.LevelCalc)3 Level (mondrian.olap.Level)3 MemberCalc (mondrian.calc.MemberCalc)2 StringCalc (mondrian.calc.StringCalc)2 ValueCalc (mondrian.calc.impl.ValueCalc)2 ResolvedFunCall (mondrian.mdx.ResolvedFunCall)2 Exp (mondrian.olap.Exp)2