com.antsdb.saltedfish.sql.mysql.InstructionGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.antsdb.saltedfish.sql.mysql.InstructionGenerator.java

Source

/*-------------------------------------------------------------------------------------------------
 _______ __   _ _______ _______ ______  ______
 |_____| | \  |    |    |______ |     \ |_____]
 |     | |  \_|    |    ______| |_____/ |_____]
    
 Copyright (c) 2016, antsdb.com and/or its affiliates. All rights reserved. *-xguo0<@
    
 This program is free software: you can redistribute it and/or modify it under the terms of the
 GNU Affero General Public License, version 3, as published by the Free Software Foundation.
    
 You should have received a copy of the GNU Affero General Public License along with this program.
 If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>
-------------------------------------------------------------------------------------------------*/
package com.antsdb.saltedfish.sql.mysql;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.commons.lang.StringUtils;

import com.antsdb.saltedfish.sql.CompileDdlException;
import com.antsdb.saltedfish.sql.DdlGenerator;
import com.antsdb.saltedfish.sql.Generator;
import com.antsdb.saltedfish.sql.GeneratorContext;
import com.antsdb.saltedfish.sql.OrcaException;
import com.antsdb.saltedfish.sql.Session;
import com.antsdb.saltedfish.sql.vdm.Instruction;
import com.antsdb.saltedfish.sql.vdm.Script;
import com.antsdb.saltedfish.sql.vdm.Statement;
import com.antsdb.saltedfish.sql.vdm.StatementWrapper;

import static com.antsdb.saltedfish.lexer.MysqlParser.*;

public class InstructionGenerator {
    static Map<Class<?>, Generator<ParseTree>> _generatorByName = new ConcurrentHashMap<>();

    // scan the tree for parameters and aggregate functions
    static void scan(GeneratorContext ctx, ParseTree node) {
        if (node instanceof TerminalNode) {
            if (node.getText().equals("?")) {
                ctx.addParameter((TerminalNode) node);
            }
        }
        if (node instanceof Function_nameContext) {
            if (node.getText().equalsIgnoreCase("sum")) {
                ctx.setHasAggregateFunctions(true);
            } else if (node.getText().equalsIgnoreCase("count")) {
                ctx.setHasAggregateFunctions(true);
            } else if (node.getText().equalsIgnoreCase("GROUP_CONCAT")) {
                ctx.setHasAggregateFunctions(true);
            } else if (node.getText().equalsIgnoreCase("max")) {
                ctx.setHasAggregateFunctions(true);
            } else if (node.getText().equalsIgnoreCase("min")) {
                ctx.setHasAggregateFunctions(true);
            }
        }
        for (int j = 0; j < node.getChildCount(); j++) {
            scan(ctx, node.getChild(j));
        }
    }

    static public Script generate(Session session, String text) throws OrcaException {
        ScriptContext scriptCtx = MysqlParserFactory.parse(text);
        GeneratorContext ctx = new GeneratorContext(session);
        scan(ctx, scriptCtx);
        Instruction code = (Instruction) generate(ctx, scriptCtx);
        Script script = new Script(code, ctx.getParameterCount(), ctx.getVariableCount(), text);
        return script;
    }

    static public Instruction generate(GeneratorContext ctx, ParseTree rule) throws OrcaException {
        Generator<ParseTree> generator = getGenerator(rule);
        Instruction code = generator.gen(ctx, rule);
        if (!ctx.isCompileDdl() && (generator instanceof DdlGenerator<?>)) {
            // run it if it is ddl statement otherwise following statements may fail to parse because of missing
            // objects
            CompileDdlException x = new CompileDdlException();
            x.nParameters = ctx.getParameterCount();
            throw x;
        } else if (code instanceof Statement) {
            Statement stmt = (Statement) code;
            StatementWrapper wrapper = new StatementWrapper(stmt, rule, generator);
            return wrapper;
        } else {
            return code;
        }
    }

    @SuppressWarnings("unchecked")
    static public Generator<ParseTree> getGenerator(ParseTree ctx) throws OrcaException {
        Class<?> klass = ctx.getClass();
        Generator<ParseTree> generator = _generatorByName.get(klass);
        if (generator == null) {
            String key = StringUtils.removeStart(klass.getSimpleName(), "MysqlParser$");
            key = StringUtils.removeEnd(key, "Context");
            key += "Generator";
            try {
                key = InstructionGenerator.class.getPackage().getName() + "." + key;
                Class<?> generatorClass = Class.forName(key);
                generator = (Generator<ParseTree>) generatorClass.newInstance();
                _generatorByName.put(klass, generator);
            } catch (Exception x) {
                throw new OrcaException("instruction geneartor is not found: " + key, x);
            }
        }
        return generator;
    }
}