001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2009-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap.fun;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractIterCalc;
014import mondrian.mdx.NamedSetExpr;
015import mondrian.mdx.ResolvedFunCall;
016import mondrian.olap.*;
017
018import java.util.List;
019
020
021/**
022 * Definition of the <code>AS</code> MDX operator.
023 *
024 * <p>Using <code>AS</code>, you can define an alias for an MDX expression
025 * anywhere it appears in a query, and use that alias as you would a calculated
026 * yet.
027 *
028 * @author jhyde
029 * @since Oct 7, 2009
030 */
031class AsFunDef extends FunDefBase {
032    public static final Resolver RESOLVER = new ResolverImpl();
033    private final Query.ScopedNamedSet scopedNamedSet;
034
035    /**
036     * Creates an AsFunDef.
037     *
038     * @param scopedNamedSet Named set definition
039     */
040    private AsFunDef(Query.ScopedNamedSet scopedNamedSet) {
041        super(
042            "AS",
043            "<Expression> AS <Name>",
044            "Assigns an alias to an expression",
045            "ixxn");
046        this.scopedNamedSet = scopedNamedSet;
047    }
048
049    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
050        // Argument 0, the definition of the set, has been resolved since the
051        // scoped named set was created. Implicit conversions, like converting
052        // a member to a set, have been performed. Use the new expression.
053        scopedNamedSet.setExp(call.getArg(0));
054
055        return new AbstractIterCalc(call, new Calc[0]) {
056            public TupleIterable evaluateIterable(
057                Evaluator evaluator)
058            {
059                final Evaluator.NamedSetEvaluator namedSetEvaluator =
060                    evaluator.getNamedSetEvaluator(scopedNamedSet, false);
061                return namedSetEvaluator.evaluateTupleIterable(evaluator);
062            }
063        };
064    }
065
066    private static class ResolverImpl extends ResolverBase {
067        public ResolverImpl() {
068            super("AS", null, null, Syntax.Infix);
069        }
070
071        public FunDef resolve(
072            Exp[] args,
073            Validator validator,
074            List<Conversion> conversions)
075        {
076            final Exp exp = args[0];
077            if (!validator.canConvert(
078                    0, args[0], Category.Set, conversions))
079            {
080                return null;
081            }
082
083            // By the time resolve is called, the id argument has already been
084            // resolved... to a named set, namely itself. That's not pretty.
085            // We'd rather it stayed as an id, and we'd rather that a named set
086            // was not visible in the scope that defines it. But we can work
087            // with this.
088            final String name =
089                ((NamedSetExpr) args[1]).getNamedSet().getName();
090
091            final Query.ScopedNamedSet scopedNamedSet =
092                (Query.ScopedNamedSet) ((NamedSetExpr) args[1]).getNamedSet();
093//                validator.getQuery().createScopedNamedSet(
094//                    name, (QueryPart) exp, exp);
095            return new AsFunDef(scopedNamedSet);
096        }
097    }
098}
099
100// End AsFunDef.java