use of mondrian.olap.type.Type in project mondrian by pentaho.
the class SqlConstraintUtilsTest method testIsSupportedExpressionForCalculatedMember.
// ~ Test methods ----------------------------------------------------------
public void testIsSupportedExpressionForCalculatedMember() {
Assert.assertEquals("null expression", false, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(null));
Exp memberExpr = new MemberExpr(Mockito.mock(Member.class));
Assert.assertEquals("MemberExpr", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(memberExpr));
Exp nullFunDefExpr = new ResolvedFunCall(new NullFunDef(), new Exp[] {}, new NullType());
Assert.assertEquals("ResolvedFunCall-NullFunDef", false, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(nullFunDefExpr));
// ResolvedFunCall arguments
final Exp argUnsupported = new ResolvedFunCall(new NullFunDef(), new Exp[] {}, new NullType());
final Exp argSupported = new MemberExpr(Mockito.mock(Member.class));
Assert.assertEquals(false, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(argUnsupported));
Assert.assertEquals(true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(argSupported));
final Exp[] noArgs = new Exp[] {};
final Exp[] args1Unsupported = new Exp[] { argUnsupported };
final Exp[] args1Supported = new Exp[] { argSupported };
final Exp[] args2Different = new Exp[] { argUnsupported, argSupported };
final ParenthesesFunDef parenthesesFunDef = new ParenthesesFunDef(Category.Member);
Type parenthesesReturnType = new DecimalType(1, 1);
Exp parenthesesExpr = new ResolvedFunCall(parenthesesFunDef, noArgs, parenthesesReturnType);
Assert.assertEquals("ResolvedFunCall-Parentheses()", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(parenthesesExpr));
parenthesesExpr = new ResolvedFunCall(parenthesesFunDef, args1Unsupported, parenthesesReturnType);
Assert.assertEquals("ResolvedFunCall-Parentheses(N)", false, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(parenthesesExpr));
parenthesesExpr = new ResolvedFunCall(parenthesesFunDef, args1Supported, parenthesesReturnType);
Assert.assertEquals("ResolvedFunCall-Parentheses(Y)", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(parenthesesExpr));
parenthesesExpr = new ResolvedFunCall(parenthesesFunDef, args2Different, parenthesesReturnType);
Assert.assertEquals("ResolvedFunCall-Parentheses(N,Y)", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(parenthesesExpr));
FunDef dummy = Mockito.mock(FunDef.class);
Mockito.doReturn(Syntax.Function).when(dummy).getSyntax();
Mockito.doReturn("dummy").when(dummy).getName();
FunDef aggregateFunDef = new AggregateFunDef(dummy);
Type aggregateReturnType = new DecimalType(1, 1);
Exp aggregateExpr = new ResolvedFunCall(aggregateFunDef, noArgs, aggregateReturnType);
Assert.assertEquals("ResolvedFunCall-Aggregate()", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(aggregateExpr));
aggregateExpr = new ResolvedFunCall(aggregateFunDef, args1Unsupported, aggregateReturnType);
Assert.assertEquals("ResolvedFunCall-Aggregate(N)", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(aggregateExpr));
aggregateExpr = new ResolvedFunCall(aggregateFunDef, args1Supported, aggregateReturnType);
Assert.assertEquals("ResolvedFunCall-Aggregate(Y)", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(aggregateExpr));
aggregateExpr = new ResolvedFunCall(aggregateFunDef, args2Different, aggregateReturnType);
Assert.assertEquals("ResolvedFunCall-Aggregate(N,Y)", true, SqlConstraintUtils.isSupportedExpressionForCalculatedMember(aggregateExpr));
}
use of mondrian.olap.type.Type in project mondrian by pentaho.
the class ValidatorImpl method validate.
public Exp validate(Exp exp, boolean scalar) {
Exp resolved;
try {
resolved = (Exp) resolvedNodes.get(exp);
} catch (ClassCastException e) {
// not occur for any query, valid or invalid.
throw Util.newInternal(e, "Infinite recursion encountered while validating '" + Util.unparse(exp) + "'");
}
if (resolved == null) {
try {
stack.push((QueryPart) exp);
// To prevent recursion, put in a placeholder while we're
// resolving.
resolvedNodes.put((QueryPart) exp, placeHolder);
resolved = exp.accept(this);
Util.assertTrue(resolved != null);
resolvedNodes.put((QueryPart) exp, (QueryPart) resolved);
} finally {
stack.pop();
}
}
if (scalar) {
final Type type = resolved.getType();
if (!TypeUtil.canEvaluate(type)) {
String exprString = Util.unparse(resolved);
throw MondrianResource.instance().MdxMemberExpIsSet.ex(exprString);
}
}
return resolved;
}
use of mondrian.olap.type.Type in project mondrian by pentaho.
the class AncestorFunDef method compileCall.
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final MemberCalc memberCalc = compiler.compileMember(call.getArg(0));
final Type type1 = call.getArg(1).getType();
if (type1 instanceof LevelType) {
final LevelCalc levelCalc = compiler.compileLevel(call.getArg(1));
return new AbstractMemberCalc(call, new Calc[] { memberCalc, levelCalc }) {
public Member evaluateMember(Evaluator evaluator) {
Level level = levelCalc.evaluateLevel(evaluator);
Member member = memberCalc.evaluateMember(evaluator);
int distance = member.getLevel().getDepth() - level.getDepth();
return ancestor(evaluator, member, distance, level);
}
};
} else {
final IntegerCalc distanceCalc = compiler.compileInteger(call.getArg(1));
return new AbstractMemberCalc(call, new Calc[] { memberCalc, distanceCalc }) {
public Member evaluateMember(Evaluator evaluator) {
int distance = distanceCalc.evaluateInteger(evaluator);
Member member = memberCalc.evaluateMember(evaluator);
return ancestor(evaluator, member, distance, null);
}
};
}
}
use of mondrian.olap.type.Type in project mondrian by pentaho.
the class GlobalFunTable method validateFunction.
/**
* Throws an error if a user-defined function does not adhere to the
* API.
*
* @param udf User defined function
*/
private void validateFunction(final UserDefinedFunction udf) {
// Check that the name is not null or empty.
final String udfName = udf.getName();
if (udfName == null || udfName.equals("")) {
throw Util.newInternal("User-defined function defined by class '" + udf.getClass() + "' has empty name");
}
// It's OK for the description to be null.
// final String description = udf.getDescription();
final Type[] parameterTypes = udf.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Type parameterType = parameterTypes[i];
if (parameterType == null) {
throw Util.newInternal("Invalid user-defined function '" + udfName + "': parameter type #" + i + " is null");
}
}
// It's OK for the reserved words to be null or empty.
// final String[] reservedWords = udf.getReservedWords();
// Test that the function returns a sensible type when given the FORMAL
// types. It may still fail when we give it the ACTUAL types, but it's
// impossible to check that now.
final Type returnType = udf.getReturnType(parameterTypes);
if (returnType == null) {
throw Util.newInternal("Invalid user-defined function '" + udfName + "': return type is null");
}
final Syntax syntax = udf.getSyntax();
if (syntax == null) {
throw Util.newInternal("Invalid user-defined function '" + udfName + "': syntax is null");
}
}
use of mondrian.olap.type.Type in project mondrian by pentaho.
the class CrossJoinArgFactory method checkFilterPredicateInIs.
/**
* Check whether the predicate is an IN or IS predicate and can be
* natively evaluated.
*
* @return the array of CrossJoinArg containing the predicate.
*/
private CrossJoinArg[] checkFilterPredicateInIs(RolapEvaluator evaluator, ResolvedFunCall predicateCall, boolean exclude) {
final boolean useIs;
if (predicateCall.getFunName().equals("IS")) {
useIs = true;
} else if (predicateCall.getFunName().equals("IN")) {
useIs = false;
} else {
// This predicate can not be natively evaluated.
return null;
}
Exp[] predArgs = predicateCall.getArgs();
if (predArgs.length != 2) {
return null;
}
// or Ancestor of those functions.
if (!(predArgs[0] instanceof ResolvedFunCall)) {
return null;
}
ResolvedFunCall predFirstArgCall = (ResolvedFunCall) predArgs[0];
if (predFirstArgCall.getFunDef().getName().equals("Ancestor")) {
Exp[] ancestorArgs = predFirstArgCall.getArgs();
if (!(ancestorArgs[0] instanceof ResolvedFunCall)) {
return null;
}
predFirstArgCall = (ResolvedFunCall) ancestorArgs[0];
}
// Now check that predFirstArgCall is a CurrentMember function that
// refers to the dimension being filtered
FunDef predFirstArgFun = predFirstArgCall.getFunDef();
if (!predFirstArgFun.getName().equals("CurrentMember")) {
return null;
}
Exp currentMemberArg = predFirstArgCall.getArg(0);
Type currentMemberArgType = currentMemberArg.getType();
// Input to CurremntMember should be either Dimension or Hierarchy type.
if (!(currentMemberArgType instanceof mondrian.olap.type.DimensionType || currentMemberArgType instanceof HierarchyType)) {
return null;
}
// It is not necessary to check currentMemberArg comes from the same
// dimension as one of the filterCJArgs, because query parser makes sure
// that currentMember always references dimensions in context.
// Check that predArgs[1] can be expressed as an MemberListCrossJoinArg.
Exp predSecondArg = predArgs[1];
Exp[] predSecondArgList;
FunDef predSecondArgFun;
CrossJoinArg[] predCJArgs;
if (useIs) {
// IS operator
if (!(predSecondArg instanceof MemberExpr)) {
return null;
}
// IS predicate only contains one member
// Make it into a list to be uniform with IN predicate.
predSecondArgFun = null;
predSecondArgList = new Exp[] { predSecondArg };
} else {
// IN operator
if (predSecondArg instanceof NamedSetExpr) {
NamedSet namedSet = ((NamedSetExpr) predSecondArg).getNamedSet();
predSecondArg = namedSet.getExp();
}
if (!(predSecondArg instanceof ResolvedFunCall)) {
return null;
}
ResolvedFunCall predSecondArgCall = (ResolvedFunCall) predSecondArg;
predSecondArgFun = predSecondArgCall.getFunDef();
predSecondArgList = predSecondArgCall.getArgs();
}
predCJArgs = checkEnumeration(evaluator, predSecondArgFun, predSecondArgList, exclude);
return predCJArgs;
}
Aggregations