Package com.foundationdb.sql.optimizer

Source Code of com.foundationdb.sql.optimizer.AISBinderContext$ViewReloader

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.sql.optimizer;

import com.foundationdb.sql.StandardException;
import com.foundationdb.sql.compiler.TypeComputer;
import com.foundationdb.sql.parser.CreateViewNode;
import com.foundationdb.sql.parser.SQLParser;
import com.foundationdb.sql.parser.SQLParserFeature;

import com.foundationdb.ais.model.AkibanInformationSchema;
import com.foundationdb.ais.model.TableName;
import com.foundationdb.ais.model.View;

import com.foundationdb.server.error.InvalidParameterValueException;
import com.foundationdb.server.error.ViewHasBadSubqueryException;

import com.foundationdb.server.types.service.TypesRegistryServiceImpl;

import java.util.*;

/** A schema, parser and binder with various client properties.
* Also caches view definitions.
*/
public class AISBinderContext
{
    public static final String CONFIG_PARSER_FEATURES = "parserFeatures";

    protected Properties properties;
    protected AkibanInformationSchema ais;
    protected SQLParser parser;
    protected String defaultSchemaName;
    protected AISBinder binder;
    protected TypeComputer typeComputer;
    protected Map<View,AISViewDefinition> viewDefinitions;

    /** When context is part of a larger object, such as a server session. */
    protected AISBinderContext() {
    }

    /** Standalone context used for loading views in tests and bootstrapping. */
    public AISBinderContext(AkibanInformationSchema ais, String defaultSchemaName) {
        this.ais = ais;
        this.defaultSchemaName = defaultSchemaName;
        properties = new Properties();
        properties.put("database", defaultSchemaName);
        initParser();       
        setBinderAndTypeComputer(new AISBinder(ais, defaultSchemaName),
                                 new FunctionsTypeComputer(TypesRegistryServiceImpl.createRegistryService()));
    }

    public Properties getProperties() {
        return properties;
    }

    public String getProperty(String key) {
        return properties.getProperty(key);
    }

    public String getProperty(String key, String defval) {
        return properties.getProperty(key, defval);
    }

    public void setProperty(String key, String value) {
        if (value == null)
            properties.remove(key);
        else
            properties.setProperty(key, value);
    }

    protected void setProperties(Properties properties) {
        this.properties = properties;
    }

    public AkibanInformationSchema getAIS() {
        return ais;
    }

    public SQLParser getParser() {
        return parser;
    }
   
    protected Set<SQLParserFeature> initParser() {
        Set<SQLParserFeature> parserFeatures = getParserFeatures();
        parser = new SQLParser();
        parser.getFeatures().clear();
        parser.getFeatures().addAll(parserFeatures);

        defaultSchemaName = getProperty("database");
        if (defaultSchemaName == null)
            defaultSchemaName = getProperty("user");
        // TODO: Any way / need to ask AIS if schema exists and report error?

        BindingNodeFactory.wrap(parser);

        return parserFeatures;
    }

    protected Set<SQLParserFeature> getParserFeatures() {
        Set<SQLParserFeature> features = new HashSet<>();
        String featuresStr = getProperty(CONFIG_PARSER_FEATURES);
        if (featuresStr != null) {
            String[] featureNames = featuresStr.split(",");
            for(String f : featureNames) {
                try {
                    features.add(SQLParserFeature.valueOf(f));
                } catch(IllegalArgumentException e) {
                    throw new InvalidParameterValueException("'" + f + "' for " + CONFIG_PARSER_FEATURES);
                }
            }
        }
        if (getBooleanProperty("parserInfixBit", false)) {
            features.add(SQLParserFeature.INFIX_BIT_OPERATORS);
        }
        if (getBooleanProperty("parserInfixLogical", false)) {
            features.add(SQLParserFeature.INFIX_LOGICAL_OPERATORS);
        }
        if (getBooleanProperty("columnAsFunc", false)) {
            features.add(SQLParserFeature.MYSQL_COLUMN_AS_FUNCS);
        }
        String prop = getProperty("parserDoubleQuoted", "identifier");
        if (prop.equals("string")) {
            features.add(SQLParserFeature.DOUBLE_QUOTED_STRING);
        } else if (!prop.equals("identifier")) {
            throw new InvalidParameterValueException("'" + prop + "' for parserDoubleQuoted");
        }
        return features;
    }

    public boolean getBooleanProperty(String key, boolean defval) {
        String prop = getProperty(key);
        if (prop == null) return defval;
        if (prop.equalsIgnoreCase("true"))
            return true;
        else if (prop.equalsIgnoreCase("false"))
            return false;
        else
            throw new InvalidParameterValueException("'" + prop + "' for " + key);
    }

    /** Get the non-default properties that were used to parse a view
     * definition, for example.
     * @see #initParser
     */
    public Properties getParserProperties(String schemaName) {
        Properties properties = new Properties();
        if (!defaultSchemaName.equals(schemaName))
            properties.put("database", defaultSchemaName);
        String prop = getProperty("parserInfixBit", "false");
        if (!"false".equals(prop))
            properties.put("parserInfixBit", prop);
        prop = getProperty("parserInfixLogical", "false");
        if (!"false".equals(prop))
            properties.put("parserInfixLogical", prop);
        prop = getProperty("columnAsFunc", "false");
        if (!"false".equals(prop))
            properties.put("columnAsFunc", prop);
        prop = getProperty("parserDoubleQuoted", "identifier");
        if (!"identifier".equals(prop))
            properties.put("parserDoubleQuoted", prop);
        return properties;
    }

    public String getDefaultSchemaName() {
        return defaultSchemaName;
    }

    public void setDefaultSchemaName(String defaultSchemaName) {
        this.defaultSchemaName = defaultSchemaName;
        if (binder != null)
            binder.setDefaultSchemaName(defaultSchemaName);
    }
   
    public AISBinder getBinder() {
        return binder;
    }

    public void setBinderAndTypeComputer(AISBinder binder, TypeComputer typeComputer) {
        this.binder = binder;
        binder.setContext(this);
        this.typeComputer = typeComputer;
        this.viewDefinitions = new HashMap<>();
    }

    protected void initBinder() {
        assert (binder == null);
        setBinderAndTypeComputer(new AISBinder(ais, defaultSchemaName), null);
    }

    /** Get view definition given the AIS view. */
    public AISViewDefinition getViewDefinition(View view) {
        AISViewDefinition viewdef = viewDefinitions.get(view);
        if (viewdef == null) {
            viewdef = new ViewReloader(view, this).getViewDefinition(view.getDefinition());
            viewDefinitions.put(view, viewdef);
        }
        return viewdef;
    }

    /** When reloading a view from AIS, we need to parse the
     * definition text again in the same parser environment as it was
     * originally defined. Also the present binder is in the middle of
     * something so we need a separate one.
     */
    protected static class ViewReloader extends AISBinderContext {
        public ViewReloader(View view, AISBinderContext parent) {
            ais = view.getAIS();
            properties = view.getDefinitionProperties();
            initParser();
            if (defaultSchemaName == null)
                defaultSchemaName = view.getName().getSchemaName();
            setBinderAndTypeComputer(new AISBinder(ais, defaultSchemaName),
                                     parent.typeComputer);
        }
    }

    /** Get view definition given the user's DDL. */
    public AISViewDefinition getViewDefinition(CreateViewNode ddl) {
        try {
            AISViewDefinition view = new AISViewDefinition(ddl, parser);
            // Just want the definition for result columns and table references.
            // If the view uses another view, the inner one is treated
            // like a table for those purposes.
            binder.bind(view.getSubquery(), false);
            if (typeComputer != null)
                view.getSubquery().accept(typeComputer);
            return view;
        }
        catch (StandardException ex) {
            throw new ViewHasBadSubqueryException(ddl.getObjectName().toString(),
                                                  ex.getMessage());
        }
    }

    /** Get view definition using stored copy of original DDL. */
    public AISViewDefinition getViewDefinition(String ddl) {
        AISViewDefinition view = null;
        try {
            view = new AISViewDefinition(ddl, parser);
            // Want a subquery that can be spliced in.
            // If the view uses another view, it gets expanded, too.
            binder.bind(view.getSubquery(), true);
            if (typeComputer != null)
                view.getSubquery().accept(typeComputer);
        }
        catch (StandardException ex) {
            String name = ddl;
            if (view != null)
                name = view.getName().toString();
            throw new ViewHasBadSubqueryException(name, ex.getMessage());
        }
        return view;
    }

    public boolean isAccessible(TableName object) {
        return isSchemaAccessible(object.getSchemaName());
    }

    public boolean isSchemaAccessible(String schemaName) {
        return true;
    }

}
TOP

Related Classes of com.foundationdb.sql.optimizer.AISBinderContext$ViewReloader

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.