Search in sources :

Example 1 with UnresolvedFunCall

use of mondrian.mdx.UnresolvedFunCall in project mondrian by pentaho.

the class ParserTest method testMultipleAxes.

public void testMultipleAxes() throws Exception {
    TestParser p = createParser();
    String query = "select {[axis0mbr]} on axis(0), " + "{[axis1mbr]} on axis(1) from cube";
    assertNull("Test parser should return null query", p.parseInternal(null, query, false, funTable, false));
    QueryAxis[] axes = p.getAxes();
    assertEquals("Number of axes", 2, axes.length);
    assertEquals("Axis index name must be correct", AxisOrdinal.StandardAxisOrdinal.forLogicalOrdinal(0).name(), axes[0].getAxisName());
    assertEquals("Axis index name must be correct", AxisOrdinal.StandardAxisOrdinal.forLogicalOrdinal(1).name(), axes[1].getAxisName());
    query = "select {[axis1mbr]} on aXiS(1), " + "{[axis0mbr]} on AxIs(0) from cube";
    assertNull("Test parser should return null query", p.parseInternal(null, query, false, funTable, false));
    assertEquals("Number of axes", 2, axes.length);
    assertEquals("Axis index name must be correct", AxisOrdinal.StandardAxisOrdinal.forLogicalOrdinal(0).name(), axes[0].getAxisName());
    assertEquals("Axis index name must be correct", AxisOrdinal.StandardAxisOrdinal.forLogicalOrdinal(1).name(), axes[1].getAxisName());
    Exp colsSetExpr = axes[0].getSet();
    assertNotNull("Column tuples", colsSetExpr);
    UnresolvedFunCall fun = (UnresolvedFunCall) colsSetExpr;
    Id arg0 = (Id) (fun.getArgs()[0]);
    Id.NameSegment id = (Id.NameSegment) arg0.getElement(0);
    assertEquals("Correct member on axis", "axis0mbr", id.name);
    Exp rowsSetExpr = axes[1].getSet();
    assertNotNull("Row tuples", rowsSetExpr);
    fun = (UnresolvedFunCall) rowsSetExpr;
    arg0 = (Id) (fun.getArgs()[0]);
    id = (Id.NameSegment) arg0.getElement(0);
    assertEquals("Correct member on axis", "axis1mbr", id.name);
}
Also used : UnresolvedFunCall(mondrian.mdx.UnresolvedFunCall)

Example 2 with UnresolvedFunCall

use of mondrian.mdx.UnresolvedFunCall in project mondrian by pentaho.

the class Util method lookup.

/**
 * Converts an identifier into an expression by resolving its parts into
 * an OLAP object (dimension, hierarchy, level or member) within the
 * context of a query.
 *
 * <p>If <code>allowProp</code> is true, also allows property references
 * from valid members, for example
 * <code>[Measures].[Unit Sales].FORMATTED_VALUE</code>.
 * In this case, the result will be a {@link ResolvedFunCall}.
 *
 * @param q Query expression belongs to
 * @param schemaReader Schema reader
 * @param segments Parts of the identifier
 * @param allowProp Whether to allow property references
 * @return OLAP object or property reference
 */
public static Exp lookup(Query q, SchemaReader schemaReader, List<Id.Segment> segments, boolean allowProp) {
    // First, look for a calculated member defined in the query.
    final String fullName = quoteMdxIdentifier(segments);
    // Look for any kind of object (member, level, hierarchy,
    // dimension) in the cube. Use a schema reader without restrictions.
    final SchemaReader schemaReaderSansAc = schemaReader.withoutAccessControl().withLocus();
    final Cube cube = q.getCube();
    OlapElement olapElement = schemaReaderSansAc.lookupCompound(cube, segments, false, Category.Unknown);
    if (olapElement != null) {
        Role role = schemaReader.getRole();
        if (!role.canAccess(olapElement)) {
            olapElement = null;
        }
        if (olapElement instanceof Member) {
            olapElement = schemaReader.substitute((Member) olapElement);
        }
    }
    if (olapElement == null) {
        if (allowProp && segments.size() > 1) {
            List<Id.Segment> segmentsButOne = segments.subList(0, segments.size() - 1);
            final Id.Segment lastSegment = last(segments);
            final String propertyName = lastSegment instanceof Id.NameSegment ? ((Id.NameSegment) lastSegment).getName() : null;
            final Member member = (Member) schemaReaderSansAc.lookupCompound(cube, segmentsButOne, false, Category.Member);
            if (member != null && propertyName != null && isValidProperty(propertyName, member.getLevel())) {
                return new UnresolvedFunCall(propertyName, Syntax.Property, new Exp[] { createExpr(member) });
            }
            final Level level = (Level) schemaReaderSansAc.lookupCompound(cube, segmentsButOne, false, Category.Level);
            if (level != null && propertyName != null && isValidProperty(propertyName, level)) {
                return new UnresolvedFunCall(propertyName, Syntax.Property, new Exp[] { createExpr(level) });
            }
        }
        // hierarchy by incrementally truncating the name of the element
        if (q.ignoreInvalidMembers()) {
            int nameLen = segments.size() - 1;
            olapElement = null;
            while (nameLen > 0 && olapElement == null) {
                List<Id.Segment> partialName = segments.subList(0, nameLen);
                olapElement = schemaReaderSansAc.lookupCompound(cube, partialName, false, Category.Unknown);
                nameLen--;
            }
            if (olapElement != null) {
                olapElement = olapElement.getHierarchy().getNullMember();
            } else {
                throw MondrianResource.instance().MdxChildObjectNotFound.ex(fullName, cube.getQualifiedName());
            }
        } else {
            throw MondrianResource.instance().MdxChildObjectNotFound.ex(fullName, cube.getQualifiedName());
        }
    }
    // keep track of any measure members referenced; these will be used
    // later to determine if cross joins on virtual cubes can be
    // processed natively
    q.addMeasuresMembers(olapElement);
    return createExpr(olapElement);
}
Also used : UnresolvedFunCall(mondrian.mdx.UnresolvedFunCall) KeySegment(org.olap4j.mdx.KeySegment) IdentifierSegment(org.olap4j.mdx.IdentifierSegment) NameSegment(org.olap4j.mdx.NameSegment) RolapCube(mondrian.rolap.RolapCube) RolapLevel(mondrian.rolap.RolapLevel) RolapMember(mondrian.rolap.RolapMember)

Example 3 with UnresolvedFunCall

use of mondrian.mdx.UnresolvedFunCall in project mondrian by pentaho.

the class AbstractExpCompiler method registerParameter.

public ParameterSlot registerParameter(Parameter parameter) {
    ParameterSlot slot = parameterSlots.get(parameter);
    if (slot != null) {
        return slot;
    }
    int index = parameterSlots.size();
    ParameterSlotImpl slot2 = new ParameterSlotImpl(parameter, index);
    parameterSlots.put(parameter, slot2);
    slot2.value = parameter.getValue();
    // Compile the expression only AFTER the parameter has been
    // registered with a slot. Otherwise a cycle is possible.
    final Type type = parameter.getType();
    Exp defaultExp = parameter.getDefaultExp();
    Calc calc;
    if (type instanceof ScalarType) {
        if (!defaultExp.getType().equals(type)) {
            defaultExp = new UnresolvedFunCall("Cast", Syntax.Cast, new Exp[] { defaultExp, Literal.createSymbol(Category.instance.getName(TypeUtil.typeToCategory(type))) });
            defaultExp = getValidator().validate(defaultExp, true);
        }
        calc = compileScalar(defaultExp, true);
    } else {
        calc = compileAs(defaultExp, type, resultStyles);
    }
    slot2.setDefaultValueCalc(calc);
    return slot2;
}
Also used : LevelType(mondrian.olap.type.LevelType) DimensionType(mondrian.olap.type.DimensionType) UnresolvedFunCall(mondrian.mdx.UnresolvedFunCall)

Example 4 with UnresolvedFunCall

use of mondrian.mdx.UnresolvedFunCall in project mondrian by pentaho.

the class DescendantsFunDef method compileCall.

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
    final Type type0 = call.getArg(0).getType();
    if (type0 instanceof SetType) {
        final SetType setType = (SetType) type0;
        if (setType.getElementType() instanceof TupleType) {
            throw MondrianResource.instance().DescendantsAppliedToSetOfTuples.ex();
        }
        MemberType memberType = (MemberType) setType.getElementType();
        final Hierarchy hierarchy = memberType.getHierarchy();
        if (hierarchy == null) {
            throw MondrianResource.instance().CannotDeduceTypeOfSet.ex();
        }
        // Convert
        // Descendants(<set>, <args>)
        // into
        // Generate(<set>, Descendants(<dimension>.CurrentMember, <args>))
        Exp[] descendantsArgs = call.getArgs().clone();
        descendantsArgs[0] = new UnresolvedFunCall("CurrentMember", Syntax.Property, new Exp[] { new HierarchyExpr(hierarchy) });
        final ResolvedFunCall generateCall = (ResolvedFunCall) compiler.getValidator().validate(new UnresolvedFunCall("Generate", new Exp[] { call.getArg(0), new UnresolvedFunCall("Descendants", descendantsArgs) }), false);
        return generateCall.accept(compiler);
    }
    final MemberCalc memberCalc = compiler.compileMember(call.getArg(0));
    Flag flag = Flag.SELF;
    if (call.getArgCount() == 1) {
        flag = Flag.SELF_BEFORE_AFTER;
    }
    final boolean depthSpecified = call.getArgCount() >= 2 && call.getArg(1).getType() instanceof NumericType;
    final boolean depthEmpty = call.getArgCount() >= 2 && call.getArg(1).getType() instanceof EmptyType;
    if (call.getArgCount() >= 3) {
        flag = FunUtil.getLiteralArg(call, 2, Flag.SELF, Flag.class);
    }
    if (call.getArgCount() >= 2 && depthEmpty) {
        if (flag != Flag.LEAVES) {
            throw Util.newError("depth must be specified unless DESC_FLAG is LEAVES");
        }
    }
    if ((depthSpecified || depthEmpty) && flag.leaves) {
        final IntegerCalc depthCalc = depthSpecified ? compiler.compileInteger(call.getArg(1)) : null;
        return new AbstractListCalc(call, new Calc[] { memberCalc, depthCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                int depth = -1;
                if (depthCalc != null) {
                    depth = depthCalc.evaluateInteger(evaluator);
                    if (depth < 0) {
                        // no limit
                        depth = -1;
                    }
                }
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                descendantsLeavesByDepth(member, result, schemaReader, depth);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    } else if (depthSpecified) {
        final IntegerCalc depthCalc = compiler.compileInteger(call.getArg(1));
        final Flag flag1 = flag;
        return new AbstractListCalc(call, new Calc[] { memberCalc, depthCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                final int depth = depthCalc.evaluateInteger(evaluator);
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                descendantsByDepth(member, result, schemaReader, depth, flag1.before, flag1.self, flag1.after, evaluator);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    } else {
        final LevelCalc levelCalc = call.getArgCount() > 1 ? compiler.compileLevel(call.getArg(1)) : null;
        final Flag flag2 = flag;
        return new AbstractListCalc(call, new Calc[] { memberCalc, levelCalc }) {

            public TupleList evaluateList(Evaluator evaluator) {
                final Evaluator context = evaluator.isNonEmpty() ? evaluator : null;
                final Member member = memberCalc.evaluateMember(evaluator);
                List<Member> result = new ArrayList<Member>();
                final SchemaReader schemaReader = evaluator.getSchemaReader();
                final Level level = levelCalc != null ? levelCalc.evaluateLevel(evaluator) : member.getLevel();
                descendantsByLevel(schemaReader, member, level, result, flag2.before, flag2.self, flag2.after, flag2.leaves, context);
                hierarchizeMemberList(result, false);
                return new UnaryTupleList(result);
            }
        };
    }
}
Also used : NumericType(mondrian.olap.type.NumericType) SchemaReader(mondrian.olap.SchemaReader) EmptyType(mondrian.olap.type.EmptyType) ArrayList(java.util.ArrayList) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) UnresolvedFunCall(mondrian.mdx.UnresolvedFunCall) HierarchyExpr(mondrian.mdx.HierarchyExpr) Hierarchy(mondrian.olap.Hierarchy) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) IntegerCalc(mondrian.calc.IntegerCalc) SetType(mondrian.olap.type.SetType) TupleType(mondrian.olap.type.TupleType) ArrayList(java.util.ArrayList) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) List(java.util.List) Sorter.hierarchizeMemberList(mondrian.olap.fun.sort.Sorter.hierarchizeMemberList) Member(mondrian.olap.Member) Calc(mondrian.calc.Calc) LevelCalc(mondrian.calc.LevelCalc) MemberCalc(mondrian.calc.MemberCalc) IntegerCalc(mondrian.calc.IntegerCalc) AbstractListCalc(mondrian.calc.impl.AbstractListCalc) LevelCalc(mondrian.calc.LevelCalc) Evaluator(mondrian.olap.Evaluator) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) EmptyType(mondrian.olap.type.EmptyType) MemberType(mondrian.olap.type.MemberType) TupleType(mondrian.olap.type.TupleType) NumericType(mondrian.olap.type.NumericType) Type(mondrian.olap.type.Type) SetType(mondrian.olap.type.SetType) MemberType(mondrian.olap.type.MemberType) MemberCalc(mondrian.calc.MemberCalc) ResolvedFunCall(mondrian.mdx.ResolvedFunCall) Level(mondrian.olap.Level) Exp(mondrian.olap.Exp)

Aggregations

UnresolvedFunCall (mondrian.mdx.UnresolvedFunCall)4 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Calc (mondrian.calc.Calc)1 IntegerCalc (mondrian.calc.IntegerCalc)1 LevelCalc (mondrian.calc.LevelCalc)1 MemberCalc (mondrian.calc.MemberCalc)1 TupleList (mondrian.calc.TupleList)1 AbstractListCalc (mondrian.calc.impl.AbstractListCalc)1 UnaryTupleList (mondrian.calc.impl.UnaryTupleList)1 HierarchyExpr (mondrian.mdx.HierarchyExpr)1 ResolvedFunCall (mondrian.mdx.ResolvedFunCall)1 Evaluator (mondrian.olap.Evaluator)1 Exp (mondrian.olap.Exp)1 Hierarchy (mondrian.olap.Hierarchy)1 Level (mondrian.olap.Level)1 Member (mondrian.olap.Member)1 SchemaReader (mondrian.olap.SchemaReader)1 Sorter.hierarchizeMemberList (mondrian.olap.fun.sort.Sorter.hierarchizeMemberList)1 DimensionType (mondrian.olap.type.DimensionType)1