Package com.inadco.hbl.client.impl

Source Code of com.inadco.hbl.client.impl.PreparedAggregateQueryImpl

/*
*
*  Copyright © 2010, 2011 Inadco, Inc. All rights reserved.
*     Licensed under the Apache License, Version 2.0 (the "License");
*     you may not use this file except in compliance with the License.
*     You may obtain a copy of the License at
*         http://www.apache.org/licenses/LICENSE-2.0
*     Unless required by applicable law or agreed to in writing, software
*     distributed under the License is distributed on an "AS IS" BASIS,
*     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*     See the License for the specific language governing permissions and
*     limitations under the License.
*/
package com.inadco.hbl.client.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.tree.Tree;
import org.apache.commons.lang.Validate;
import org.apache.hadoop.hbase.client.HTablePool;

import com.inadco.hbl.api.AggregateFunctionRegistry;
import com.inadco.hbl.client.HblException;
import com.inadco.hbl.client.HblQueryClient;
import com.inadco.hbl.client.PreparedAggregateQuery;
import com.inadco.hbl.client.impl.scanner.ScanSpec;
import com.inadco.hbl.hblquery.ErrorAccumulator;
import com.inadco.hbl.hblquery.HBLQueryASTLexer;
import com.inadco.hbl.hblquery.HBLQueryASTParser;
import com.inadco.hbl.hblquery.HBLQueryPrep;

/**
* Prepared Aggregate Query ( {@link PreparedAggregateQuery} ) implementation .
* <P>
*
* @author dmitriy
*
*/

public class PreparedAggregateQueryImpl extends AggregateQueryImpl implements PreparedAggregateQuery {

    private HBLQueryASTParser    parser            = new HBLQueryASTParser(null);
    private HBLQueryASTLexer     lexer             = new HBLQueryASTLexer();
    private ErrorAccumulator     errors            = new ErrorAccumulator();
    private HBLQueryPrep         prepper           = null;
    private ErrorAccumulator     prepperErrors     = new ErrorAccumulator();
    private QueryPrepVisitor     qVisitor          = new QueryPrepVisitor(this);

    private Tree                 selectAST;
    private Map<Integer, Object> parameters        = new HashMap<Integer, Object>();
    private Map<Integer, Object> resultDefsByIndex = new HashMap<Integer, Object>();
    private Map<String, Object>  resultDefsByAlias = new LinkedHashMap<String, Object>();

    public PreparedAggregateQueryImpl(HblQueryClient client, ExecutorService es, HTablePool tpool) {
        super(client, es, tpool);
        parser.setErrorReporter(errors);
    }

    @Override
    public void prepare(String statement) throws HblException {

        // reset query params, etc.
        reset();
        selectAST = null;

        Validate.notNull(statement);
        lexer.reset();
        lexer.setCharStream(new ANTLRStringStream(statement));
        parser.reset();
        parser.setTokenStream(new CommonTokenStream(lexer));
        try {
            HBLQueryASTParser.select_return r = parser.select();
            selectAST = (Tree) r.getTree();
            // if (parser.getNumberOfSyntaxErrors() > 0)
            if (errors.getErrors().size() > 0) {
                throw new HblException(errors.formatErrors());
            }

        } catch (RecognitionException exc) {
            throw new HblException(exc.getMessage());
        }

    }

    @Override
    public void setHblParameter(int param, Object value) throws HblException {
        parameters.put(param, value);
    }

    protected void reset() {
        super.reset();
        parameters.clear();

        /*
         * this kind of better be part of prepare() step although right now we
         * allow parameterizing measure and dimension names there, so for now
         * unfortunately i have to keep construction of the result set attribute
         * map a part of execute() and reset it here for each new use of the
         * query.
         *
         * Actually we kind of lent this to the result set, so we just need to
         * create a new one. Of course in reality since the query is prepared,
         * this never has to change... but current AST walker initializes it
         * anyway.
         */

        resultDefsByAlias = new LinkedHashMap<String, Object>();
        resultDefsByIndex = new HashMap<Integer, Object>();

    }

    void assignASTParams() throws HblException {
        Validate.notNull(selectAST, "statement not prepared");
        if (prepper == null) {
            prepper = new HBLQueryPrep(new CommonTreeNodeStream(selectAST));
            prepper.setHblParams(parameters);
            prepper.setQueryVisitor(qVisitor);
            prepper.setErrorReporter(prepperErrors);
        } else {
            prepper.reset();
            prepper.setTreeNodeStream(new CommonTreeNodeStream(selectAST));
        }

        try {
            prepper.select();
            if (prepperErrors.getErrors().size() > 0)
                throw new HblException(prepperErrors.formatErrors());
        } catch (RecognitionException exc) {
            throw new HblException(exc.getMessage(), exc);
        }

    }

    @Override
    public List<ScanSpec> generateScanSpecs(Map<String, Integer> dimName2GroupKeyOffsetMap,
                                            Map<String, Integer> measureName2indexMap) throws IOException, HblException {
        assignASTParams();
        return super.generateScanSpecs(dimName2GroupKeyOffsetMap, measureName2indexMap);
    }

    @Override
    protected AggregateResultSetImpl createResultSet(List<ScanSpec> scanSpecs,
                                                     ExecutorService es,
                                                     HTablePool tpool,
                                                     AggregateFunctionRegistry afr,
                                                     Map<String, Integer> measureName2IndexMap,
                                                     Map<String, Integer> dimName2GroupKeyOffsetMap,
                                                     byte[] startSplitKey,
                                                     byte[] endSplitKey,
                                                     String enforcedCuboidTableName) throws IOException {
        return new PreparedAggregateResultSetImpl(
            scanSpecs,
            es,
            tpool,
            afr,
            measureName2IndexMap,
            dimName2GroupKeyOffsetMap,
            resultDefsByIndex,
            resultDefsByAlias,
            startSplitKey,
            endSplitKey,
            enforcedCuboidTableName);
    }

    /**
     * Add measure expression. Measure expression must have an aggregate
     * function, the measure name, and optional alias how to call that
     * expression in the result set.
     *
     * @param index
     * @param alias
     * @param funcName
     * @param measure
     */
    void addAggregateResultDef(int index, String alias, String funcName, String measure) {

        if (afr.findFunction(funcName) == null)
            throw new IllegalArgumentException(String.format("Unknown function name '%s'.", funcName));
        if (!cube.getMeasures().containsKey(measure))
            throw new IllegalArgumentException(String.format("Unknown measure %s.", measure));
        if (resultDefsByAlias.containsKey(alias))
            throw new IllegalArgumentException(String.format("Alias %s already exists.", alias));

        String[] def = new String[2];
        def[0] = measure;
        def[1] = funcName;
        resultDefsByIndex.put(index, def);
        resultDefsByAlias.put(alias, def);
    }

    /**
     * add dimension expression. Dimension expression can only consist of the
     * dimension name and optional alias. (Optionality is provided by query
     * parser, if it is not specified, then dimension name is used).
     *
     * @param index
     * @param alias
     * @param dim
     */
    void addAggregateResultDef(int index, String alias, String dim) {
        if (!cube.getDimensions().containsKey(dim))
            throw new IllegalArgumentException(String.format("Unknown dimension %s.", dim));
        if (resultDefsByAlias.containsKey(alias))
            throw new IllegalArgumentException(String.format("Alias %s already exists.", alias));
        resultDefsByIndex.put(index, dim);
        resultDefsByAlias.put(alias, dim);
    }

}
TOP

Related Classes of com.inadco.hbl.client.impl.PreparedAggregateQueryImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.