public Exp validate(Exp exp, boolean scalar) { Exp resolved; try { resolved = (Exp) resolvedNodes.get(exp); } catch (ClassCastException e) { // A classcast exception will occur if there is a String // placeholder in the map. This is an internal error -- should // 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; }
@Override public void accept(GrammarItemVisitor visitor) { visitor.visitAssignStm(this); if (exp.handleProceedWith(visitor)) { exp.accept(visitor); } visitor.leaveAssignStm(this); }
/** * {@inheritDoc} * * <p>Overriding isJoinRequired() for native filters because we have to force a join to the fact * table if the filter expression references a measure. */ protected boolean isJoinRequired() { // Use a visitor and check all member expressions. // If any of them is a measure, we will have to // force the join to the fact table. If it is something // else then we don't really care. It will show up in // the evaluator as a non-all member and trigger the // join when we call RolapNativeSet.isJoinRequired(). final AtomicBoolean mustJoin = new AtomicBoolean(false); filterExpr.accept( new MdxVisitorImpl() { public Object visit(MemberExpr memberExpr) { if (memberExpr.getMember().isMeasure()) { mustJoin.set(true); return null; } return super.visit(memberExpr); } }); return mustJoin.get() || (getEvaluator().isNonEmpty() && super.isJoinRequired()); }