Package org.hsqldb

Source Code of org.hsqldb.ParserCommand

/* Copyright (c) 2001-2010, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


package org.hsqldb;

import org.hsqldb.HsqlNameManager.HsqlName;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.HsqlArrayList;
import org.hsqldb.lib.HsqlList;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.persist.HsqlDatabaseProperties;
import org.hsqldb.result.Result;
import org.hsqldb.result.ResultProperties;
import org.hsqldb.store.ValuePool;
import org.hsqldb.types.Charset;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;

/**
* Parser for session and management statements
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 1.9.0
* @since 1.9.0
*/
public class ParserCommand extends ParserDDL {

    ParserCommand(Session session, Scanner t) {
        super(session, t);
    }

    Statement compileStatement(int props) {

        Statement cs = compilePart(props);

        if (token.tokenType == Tokens.X_ENDPARSE) {
            if (cs.getSchemaName() == null) {
                cs.setSchemaHsqlName(session.getCurrentSchemaHsqlName());
            }

            return cs;
        }

        throw unexpectedToken();
    }

    HsqlArrayList compileStatements(String sql, Result cmd) {

        HsqlArrayList list = new HsqlArrayList();
        Statement     cs   = null;

        reset(sql);

        while (true) {
            if (token.tokenType == Tokens.X_ENDPARSE) {
                break;
            }

            cs = compilePart(cmd.getExecuteProperties());

            if (!cs.isExplain
                    && cs.getParametersMetaData().getColumnCount() > 0) {
                throw Error.error(ErrorCode.X_42575);
            }

            list.add(cs);
        }

        int returnType = cmd.getStatementType();

        if (returnType != StatementTypes.RETURN_ANY) {
            int group = cs.getGroup();

            if (group == StatementTypes.X_SQL_DATA) {
                if (returnType == StatementTypes.RETURN_COUNT) {
                    throw Error.error(ErrorCode.X_07503);
                }
            } else if (returnType == StatementTypes.RETURN_RESULT) {
                throw Error.error(ErrorCode.X_07504);
            }
        }

        return list;
    }

    private Statement compilePart(int props) {

        Statement cs;

        compileContext.reset();
        setParsePosition(getPosition());

        if (token.tokenType == Tokens.X_STARTPARSE) {
            read();
        }

        switch (token.tokenType) {

            // DQL
            case Tokens.WITH :
            case Tokens.OPENBRACKET :
            case Tokens.SELECT :
            case Tokens.TABLE : {
                cs = compileCursorSpecification(props);

                break;
            }
            case Tokens.VALUES : {
                cs = compileShortCursorSpecification(props);

                break;
            }

            // DML
            case Tokens.INSERT : {
                cs = compileInsertStatement(RangeVariable.emptyArray);

                break;
            }
            case Tokens.UPDATE : {
                cs = compileUpdateStatement(RangeVariable.emptyArray);

                break;
            }
            case Tokens.MERGE : {
                cs = compileMergeStatement(RangeVariable.emptyArray);

                break;
            }
            case Tokens.DELETE : {
                cs = compileDeleteStatement(RangeVariable.emptyArray);

                break;
            }
            case Tokens.TRUNCATE : {
                cs = compileDeleteStatement(RangeVariable.emptyArray);

                break;
            }

            // PROCEDURE
            case Tokens.CALL : {
                cs = compileCallStatement(
                    session.sessionContext.sessionVariablesRange, false);

                break;
            }

            // SQL SESSION
            case Tokens.SET :
                cs = compileSet();
                break;

            case Tokens.START :
                cs = compileStartTransaction();
                break;

            case Tokens.COMMIT :
                cs = compileCommit();
                break;

            case Tokens.ROLLBACK :
                cs = compileRollback();
                break;

            case Tokens.SAVEPOINT :
                cs = compileSavepoint();
                break;

            case Tokens.RELEASE :
                cs = compileReleaseSavepoint();
                break;

            // DDL
            case Tokens.CREATE :
                cs = compileCreate();
                break;

            case Tokens.ALTER :
                cs = compileAlter();
                break;

            case Tokens.DROP :
                cs = compileDrop();
                break;

            case Tokens.GRANT :
            case Tokens.REVOKE :
                cs = compileGrantOrRevoke();
                break;

            case Tokens.COMMENT :
                cs = compileComment();
                break;

            // HSQL SESSION
            case Tokens.LOCK :
                cs = compileLock();
                break;

            case Tokens.CONNECT :
                cs = compileConnect();
                break;

            case Tokens.DISCONNECT :
                cs = compileDisconnect();
                break;

            // HSQL COMMAND
            case Tokens.SCRIPT :
                cs = compileScript();
                break;

            case Tokens.SHUTDOWN :
                cs = compileShutdown();
                break;

            case Tokens.BACKUP :
                cs = compileBackup();
                break;

            case Tokens.CHECKPOINT :
                cs = compileCheckpoint();
                break;

            case Tokens.EXPLAIN :
                cs = compileExplainPlan();
                break;

            case Tokens.DECLARE :
                cs = compileDeclare();
                break;

            default :
                throw unexpectedToken();
        }

        if (cs.type != StatementTypes.SET_SESSION_AUTHORIZATION) {
            cs.setSQL(getLastPart());
        }

        if (token.tokenType == Tokens.SEMICOLON) {
            read();
        } else if (token.tokenType == Tokens.X_ENDPARSE) {}

        return cs;
    }

    private Statement compileDeclare() {

        Statement    cs;
        ColumnSchema variables[];

        cs = compileDeclareLocalTableOrNull();

        if (cs != null) {
            return cs;
        }

        variables = readLocalVariableDeclarationOrNull();

        if (variables != null) {
            Object[] args = new Object[]{ variables };

            cs = new StatementSession(StatementTypes.DECLARE_VARIABLE, args);

            return cs;
        }

        cs = compileDeclareCursor();

        return cs;
    }

    private Statement compileScript() {

        String name = null;

        read();

        if (token.tokenType == Tokens.X_VALUE) {
            name = readQuotedString();
        }

        Object[] args = new Object[]{ name };
        Statement cs = new StatementCommand(StatementTypes.DATABASE_SCRIPT,
                                            args);
        HsqlName[] names =
            database.schemaManager.getCatalogAndBaseTableNames();

        cs.readTableNames = names;

        return cs;
    }

    private Statement compileConnect() {

        String userName;
        String password = null;

        read();
        readThis(Tokens.USER);
        checkIsSimpleName();

        userName = token.tokenString;

        read();
        readThis(Tokens.PASSWORD);

        password = readPassword();

        Expression[] args = new Expression[] {
            new ExpressionValue(userName, Type.SQL_VARCHAR),
            new ExpressionValue(password, Type.SQL_VARCHAR)
        };
        Statement cs =
            new StatementSession(StatementTypes.SET_SESSION_AUTHORIZATION,
                                 args);

        return cs;
    }

    private StatementCommand compileSetDefault() {

        read();

        switch (token.tokenType) {

            case Tokens.INITIAL : {
                read();
                readThis(Tokens.SCHEMA);

                HsqlName schema = database.schemaManager.getSchemaHsqlName(
                    token.tokenString);

                read();

                Object[] args = new Object[]{ schema };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_DEFAULT_INITIAL_SCHEMA, args);
            }
            case Tokens.RESULT : {
                read();
                readThis(Tokens.MEMORY);
                readThis(Tokens.ROWS);

                Integer  size = readIntegerObject();
                Object[] args = new Object[]{ size };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_RESULT_MEMORY_ROWS, args);
            }
            case Tokens.TABLE : {
                read();
                readThis(Tokens.TYPE);

                int type = TableBase.MEMORY_TABLE;

                switch (token.tokenType) {

                    case Tokens.MEMORY :
                        break;

                    case Tokens.CACHED :
                        type = TableBase.CACHED_TABLE;
                        break;

                    default :
                        throw unexpectedToken();
                }

                read();

                Object[] args = new Object[]{ ValuePool.getInt(type) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE, args);
            }
            case Tokens.ISOLATION : {
                read();
                readThis(Tokens.LEVEL);

                int level;

                switch (token.tokenType) {

                    case Tokens.READ :
                        read();
                        readThis(Tokens.COMMITTED);

                        level = SessionInterface.TX_READ_COMMITTED;
                        break;

                    case Tokens.SERIALIZABLE :
                        read();

                        level = SessionInterface.TX_SERIALIZABLE;
                        break;

                    default :
                        throw unexpectedToken();
                }

                read();

                Object[] args = new Object[]{ ValuePool.getInt(level) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_DEFAULT_ISOLATION_LEVEL, args);
            }
            default :
                throw unexpectedToken();
        }
    }

    private StatementCommand compileSetProperty() {

        read();

        String                 property;
        Object                 value;
        HsqlDatabaseProperties props = database.getProperties();

        checkIsSimpleName();
        checkIsDelimitedIdentifier();

        property = token.tokenString;

        boolean isboolean  = props.isBoolean(token.tokenString);
        boolean isintegral = props.isIntegral(token.tokenString);
        boolean isstring   = props.isString(token.tokenString);

        if (!(isboolean || isintegral || isstring)) {
            throw Error.error(ErrorCode.X_42555, property);
        }

        int typeCode = isboolean ? Types.SQL_BOOLEAN
                                 : isintegral ? Types.SQL_INTEGER
                                              : Types.SQL_CHAR;

        read();

        if (token.tokenType == Tokens.TRUE) {
            value = Boolean.TRUE;

            if (!isboolean) {
                throw Error.error(ErrorCode.X_42563, token.tokenString);
            }
        } else if (token.tokenType == Tokens.FALSE) {
            value = Boolean.FALSE;

            if (!isboolean) {
                throw Error.error(ErrorCode.X_42563, token.tokenString);
            }
        } else {
            checkIsValue();

            value = token.tokenValue;

            if (token.dataType.typeCode != typeCode) {
                throw Error.error(ErrorCode.X_42563, token.tokenString);
            }
        }

        read();

        Object[] args = new Object[] {
            property, value
        };

        return new StatementCommand(StatementTypes.SET_DATABASE_PROPERTY,
                                    args);
    }

    private Statement compileSet() {

        int position = super.getPosition();

        session.setScripting(false);
        read();

        switch (token.tokenType) {

            case Tokens.CATALOG : {
                read();

                Expression e = XreadValueSpecificationOrNull();

                if (e == null) {
                    HsqlName name = readSchemaName();
                    Object[] args = new Object[]{ name };

                    return new StatementSession(StatementTypes.SET_CATALOG,
                                                args);
                }

                if (!e.getDataType().isCharacterType()) {
                    throw Error.error(ErrorCode.X_0P000);
                }

                if (e.getType() != OpTypes.VALUE
                        && (e.getType() != OpTypes.SQL_FUNCTION
                            || !((FunctionSQL) e).isValueFunction())) {
                    throw Error.error(ErrorCode.X_0P000);
                }

                Expression[] args = new Expression[]{ e };

                return new StatementSession(StatementTypes.SET_CATALOG, args);
            }
            case Tokens.SCHEMA : {
                read();

                Expression e = XreadValueSpecificationOrNull();

                if (e == null) {
                    HsqlName name = readSchemaName();
                    Object[] args = new Object[]{ name };

                    return new StatementSession(StatementTypes.SET_SCHEMA,
                                                args);
                }

                if (!e.getDataType().isCharacterType()) {
                    throw Error.error(ErrorCode.X_0P000);
                }

                if (e.getType() != OpTypes.VALUE
                        && (e.getType() != OpTypes.SQL_FUNCTION
                            || !((FunctionSQL) e).isValueFunction())) {
                    throw Error.error(ErrorCode.X_0P000);
                }

                Expression[] args = new Expression[]{ e };

                return new StatementSession(StatementTypes.SET_SCHEMA, args);
            }
            case Tokens.TIME : {
                read();

                return compileSetTimeZone();
            }
            case Tokens.ROLE : {
                read();

                return compileSetRole();
            }
            case Tokens.SESSION : {
                read();

                return compileSessionSettings();
            }
            case Tokens.TRANSACTION : {
                read();

                Object[] args = processTransactionCharacteristics();

                if (args[0] == null && args[1] == null) {
                    throw unexpectedToken();
                }

                return new StatementSession(StatementTypes.SET_TRANSACTION,
                                            args);
            }
            case Tokens.AUTOCOMMIT : {
                read();

                Boolean  mode = processTrueOrFalseObject();
                Object[] args = new Object[]{ mode };

                return new StatementSession(
                    StatementTypes.SET_SESSION_AUTOCOMMIT, args);
            }

            // deprecated
            case Tokens.READONLY : {
                read();

                Boolean  readonly = processTrueOrFalseObject();
                Object[] args     = new Object[]{ readonly };

                return new StatementSession(
                    StatementTypes.SET_SESSION_CHARACTERISTICS, args);
            }
            case Tokens.IGNORECASE : {
                read();

                Boolean  mode = processTrueOrFalseObject();
                Object[] args = new Object[]{ mode };

                return new StatementSession(
                    StatementTypes.SET_SESSION_SQL_IGNORECASE, args);
            }
            case Tokens.MAXROWS : {
                read();

                Integer  size = readIntegerObject();
                Object[] args = new Object[]{ size };

                return new StatementSession(
                    StatementTypes.SET_SESSION_RESULT_MAX_ROWS, args);
            }

            // for backward compatibility
            case Tokens.DEFAULT : {
                read();
                readThis(Tokens.TABLE);
                readThis(Tokens.TYPE);

                int type = TableBase.MEMORY_TABLE;

                switch (token.tokenType) {

                    case Tokens.MEMORY :
                        break;

                    case Tokens.CACHED :
                        type = TableBase.CACHED_TABLE;
                        break;

                    default :
                        throw unexpectedToken();
                }

                read();

                Object[] args = new Object[]{ ValuePool.getInt(type) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_DEFAULT_TABLE_TYPE, args);
            }
            case Tokens.TABLE : {
                read();

                Table    t    = readTableName();
                Object[] args = new Object[] {
                    t.getName(), null
                };

                switch (token.tokenType) {

                    default : {
                        throw unexpectedToken();
                    }
                    case Tokens.SOURCE :
                        read();

                        return compileTextTableSource(t);

                    case Tokens.READ : {
                        read();

                        boolean readonly = false;

                        if (token.tokenType == Tokens.WRITE) {
                            read();
                        } else {
                            readThis(Tokens.ONLY);

                            readonly = true;
                        }

                        args[1] = Boolean.valueOf(readonly);

                        return new StatementCommand(
                            StatementTypes.SET_TABLE_READONLY, args, null,
                            t.getName());
                    }

                    // deprecated
                    case Tokens.READONLY : {
                        read();

                        Boolean readonly = processTrueOrFalseObject();

                        args[1] = readonly;

                        return new StatementCommand(
                            StatementTypes.SET_TABLE_READONLY, args, null,
                            t.getName());
                    }
                    case Tokens.INDEX : {
                        String value;

                        read();
                        checkIsValue();

                        value = token.tokenString;

                        read();

                        args[1] = value;

                        return new StatementCommand(
                            StatementTypes.SET_TABLE_INDEX, args);
                    }
                    case Tokens.TYPE : {
                        read();

                        int newType;

                        if (token.tokenType == Tokens.CACHED) {
                            newType = TableBase.CACHED_TABLE;
                        } else if (token.tokenType == Tokens.MEMORY) {
                            newType = TableBase.MEMORY_TABLE;
                        } else {
                            throw super.unexpectedToken();
                        }

                        read();

                        args[1] = new Integer(newType);

                        return new StatementCommand(
                            StatementTypes.SET_TABLE_TYPE, args, null,
                            t.getName());
                    }
                }
            }
/*
            case Tokens.CHECKPOINT : {
                read();
                readThis(Tokens.DEFRAG);

                int      size = readInteger();
                Object[] args = new Object[]{ new Integer(size) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_FILES_DEFRAG, args, null,
                    null);
            }
*/
            case Tokens.WRITE_DELAY : {
                read();

                int delay = 0;

                if (token.tokenType == Tokens.TRUE) {
                    delay = database.getProperties().getDefaultWriteDelay();

                    read();
                } else if (token.tokenType == Tokens.FALSE) {
                    delay = 0;

                    read();
                } else {
                    delay = this.readInteger();

                    if (delay < 0) {
                        delay = 0;
                    }

                    if (token.tokenType == Tokens.MILLIS) {
                        read();
                    } else {
                        delay *= 1000;
                    }
                }

                Object[] args = new Object[]{ new Integer(delay) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_FILES_WRITE_DELAY, args, null,
                    null);
            }
            case Tokens.PASSWORD : {
                String password;

                read();

                password = readPassword();

                Object[] args = new Object[] {
                    null, password
                };

                return new StatementCommand(StatementTypes.SET_USER_PASSWORD,
                                            args);
            }
            case Tokens.INITIAL : {
                read();
                readThis(Tokens.SCHEMA);

                HsqlName schema;

                if (token.tokenType == Tokens.DEFAULT) {
                    schema = null;
                } else {
                    schema = database.schemaManager.getSchemaHsqlName(
                        token.tokenString);
                }

                read();

                Object[] args = new Object[] {
                    null, schema
                };

                return new StatementCommand(
                    StatementTypes.SET_USER_INITIAL_SCHEMA, args);
            }
            case Tokens.FILES : {
                return compileSetFilesProperty();
            }
            case Tokens.DATABASE : {
                return compileSetDatabaseProperty();
            }
            case Tokens.PROPERTY : {
                return compileSetProperty();
            }
            default : {
                rewind(position);

                return compileSetStatement(
                    session.sessionContext.sessionVariablesRange);
            }
        }
    }

    StatementCommand compileSetDatabaseProperty() {

        read();

        String name;

        checkDatabaseUpdateAuthorisation();

        switch (token.tokenType) {

            case Tokens.COLLATION : {
                read();
                checkIsSimpleName();

                name = token.tokenString;

                read();

                Object[] args = new Object[]{ name };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_SQL_COLLATION, args, null,
                    null);
            }
            case Tokens.DEFAULT : {
                return compileSetDefault();
            }
            case Tokens.EVENT : {
                read();
                readThis(Tokens.LOG);
                readThis(Tokens.LEVEL);

                Integer  value = readIntegerObject();
                Object[] args  = new Object[]{ value };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_FILES_EVENT_LOG, args, null,
                    null);
            }
            case Tokens.GC : {
                read();

                Integer  size = readIntegerObject();
                Object[] args = new Object[]{ size };

                return new StatementCommand(StatementTypes.SET_DATABASE_GC,
                                            args, null, null);
            }
            case Tokens.REFERENTIAL : {
                read();
                readThis(Tokens.INTEGRITY);

                boolean  mode = processTrueOrFalse();
                Object[] args = new Object[]{ Boolean.valueOf(mode) };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_SQL_REFERENTIAL_INTEGRITY,
                    args, null, null);
            }
            case Tokens.SQL : {
                read();

                int     type = 0;
                Boolean flag = null;

                switch (token.tokenType) {

                    case Tokens.REFERENCES :
                        read();

                        type = StatementTypes.SET_DATABASE_SQL_REFERENCES;
                        flag = processTrueOrFalseObject();
                        break;


                    case Tokens.SIZE :
                        read();

                        type = StatementTypes.SET_DATABASE_SQL_STRICT_SIZE;
                        flag = processTrueOrFalseObject();
                        break;

                    case Tokens.NAMES :
                        read();

                        type = StatementTypes.SET_DATABASE_SQL_STRICT_NAMES;
                        flag = processTrueOrFalseObject();
                        break;

                    default :
                        unexpectedToken();
                }

                Object[] args = new Object[]{ flag };

                return new StatementCommand(type, args, null, null);
            }
            case Tokens.TEXT : {
                read();
                readThis(Tokens.TABLE);
                readThis(Tokens.DEFAULTS);

                String   source = readQuotedString();
                Object[] args   = new Object[]{ source };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_TEXT_SOURCE, args, null, null);
            }
            case Tokens.TRANSACTION : {
                read();
                readThis(Tokens.CONTROL);

                int mode = TransactionManager.LOCKS;

                switch (token.tokenType) {

                    case Tokens.MVCC :
                        read();

                        mode = TransactionManager.MVCC;
                        break;

                    case Tokens.MVLOCKS :
                        read();

                        mode = TransactionManager.MVLOCKS;
                        break;

                    case Tokens.LOCKS :
                        read();

                        mode = TransactionManager.LOCKS;
                        break;
                }

                Object[] args = new Object[]{ ValuePool.getInt(mode) };
                StatementCommand cs = new StatementCommand(
                    StatementTypes.SET_DATABASE_TRANSACTION_CONTROL, args,
                    null, null);
                HsqlName[] names =
                    database.schemaManager.getCatalogAndBaseTableNames();

                cs.writeTableNames = names;

                return cs;
            }
            case Tokens.UNIQUE : {
                read();
                readThis(Tokens.NAME);
                isUndelimitedSimpleName();

                name = token.tokenString;

                read();

                /** @todo - only digits, letters and underscore */
                if (name.length() != 16) {
                    throw Error.error(ErrorCode.X_42555);
                }

                if (!Charset.isInSet(name, Charset.unquotedIdentifier)
                        || !Charset.startsWith(name,
                                               Charset.uppercaseLetters)) {
                    throw Error.error(ErrorCode.X_42501);
                }

                Object[] args = new Object[]{ name };

                return new StatementCommand(
                    StatementTypes.SET_DATABASE_UNIQUE_NAME, args, null, null);
            }
            default : {
                throw unexpectedToken();
            }
        }
    }

    StatementCommand compileSetFilesProperty() {

        read();

        String  name;
        int     type  = 0;
        Boolean flag  = null;
        Integer value = null;

        checkDatabaseUpdateAuthorisation();

        switch (token.tokenType) {

            case Tokens.LOCK : {
                read();

                flag = processTrueOrFalseObject();
                type = StatementTypes.SET_DATABASE_FILES_LOCK;

                break;
            }
            case Tokens.CACHE : {
                read();

                if (readIfThis(Tokens.SIZE)) {
                    value = readIntegerObject();
                    type  = StatementTypes.SET_DATABASE_FILES_CACHE_SIZE;
                } else if (readIfThis(Tokens.ROWS)) {
                    value = readIntegerObject();
                    type  = StatementTypes.SET_DATABASE_FILES_CACHE_ROWS;
                }

                break;
            }
            case Tokens.SCALE : {
                read();

                value = readIntegerObject();
                type  = StatementTypes.SET_DATABASE_FILES_SCALE;

                break;
            }
            case Tokens.LOB : {
                read();
                readThis(Tokens.SCALE);

                value = readIntegerObject();
                type  = StatementTypes.SET_DATABASE_FILES_LOBS_SCALE;

                break;
            }
            case Tokens.DEFRAG : {
                read();

                type  = StatementTypes.SET_DATABASE_FILES_DEFRAG;
                value = readIntegerObject();

                break;
            }
            case Tokens.NIO : {
                read();

                type = StatementTypes.SET_DATABASE_FILES_NIO;
                flag = processTrueOrFalseObject();

                break;
            }
            case Tokens.BACKUP : {
                read();

                type = StatementTypes.SET_DATABASE_FILES_BACKUP_INCREMENT;

                readThis(Tokens.INCREMENT);

                flag = processTrueOrFalseObject();

                break;
            }
            case Tokens.LOG : {
                read();

                if (token.tokenType == Tokens.SIZE) {
                    readThis(Tokens.SIZE);

                    type  = StatementTypes.SET_DATABASE_FILES_LOG_SIZE;
                    value = readIntegerObject();
                } else {
                    type = StatementTypes.SET_DATABASE_FILES_LOG;
                    flag = processTrueOrFalseObject();
                }

                break;
            }
            case Tokens.TEMP : {
                read();
                readThis(Tokens.PATH);

                type  = StatementTypes.SET_DATABASE_FILES_TEMP_PATH;
                value = readIntegerObject();

                break;
            }
            case Tokens.WRITE : {
                read();
                readThis(Tokens.DELAY);

                type = StatementTypes.SET_DATABASE_FILES_WRITE_DELAY;

                int delay = 0;

                if (token.tokenType == Tokens.TRUE) {
                    delay = database.getProperties().getDefaultWriteDelay();

                    read();
                } else if (token.tokenType == Tokens.FALSE) {
                    delay = 0;

                    read();
                } else {
                    delay = this.readInteger();

                    if (delay < 0) {
                        delay = 0;
                    }

                    if (token.tokenType == Tokens.MILLIS) {
                        read();
                    } else {
                        delay *= 1000;
                    }
                }

                value = new Integer(delay);

                break;
            }
            default :
                throw unexpectedToken();
        }

        Object[] args = new Object[]{ flag == null ? (Object) value
                                                   : (Object) flag };

        return new StatementCommand(type, args, database.getCatalogName(),
                                    null);
    }

    Object[] processTransactionCharacteristics() {

        int      level    = 0;
        boolean  readonly = false;
        Object[] args     = new Object[2];

        outerloop:
        while (true) {
            switch (token.tokenType) {

                case Tokens.READ : {
                    if (args[0] != null) {
                        throw unexpectedToken();
                    }

                    read();

                    if (token.tokenType == Tokens.ONLY) {
                        read();

                        readonly = true;
                    } else {
                        readThis(Tokens.WRITE);

                        readonly = false;
                    }

                    args[0] = Boolean.valueOf(readonly);

                    break;
                }
                case Tokens.ISOLATION : {
                    if (args[1] != null) {
                        throw unexpectedToken();
                    }

                    read();
                    readThis(Tokens.LEVEL);

                    switch (token.tokenType) {

                        case Tokens.SERIALIZABLE :
                            read();

                            level = SessionInterface.TX_SERIALIZABLE;
                            break;

                        case Tokens.READ :
                            read();

                            if (token.tokenType == Tokens.COMMITTED) {
                                read();

                                level = SessionInterface.TX_READ_COMMITTED;
                            } else if (token.tokenType == Tokens.UNCOMMITTED) {
                                read();

                                level = SessionInterface.TX_READ_UNCOMMITTED;
                            } else {
                                throw unexpectedToken();
                            }
                            break;

                        case Tokens.REPEATABLE :
                            read();
                            readThis(Tokens.READ);

                            level = SessionInterface.TX_REPEATABLE_READ;
                            break;

                        default :
                            throw unexpectedToken();
                    }

                    args[1] = new Integer(level);

                    break;
                }
                case Tokens.COMMA : {
                    if (args[0] == null && args[1] == null) {
                        throw unexpectedToken();
                    }

                    read();

                    break;
                }
                default : {
                    break outerloop;
                }
            }
        }

        if (!readonly && level == 1) {
            throw unexpectedToken(Tokens.T_WRITE);
        }

        return args;
    }

    /**
     * Retrieves boolean value corresponding to the next token.
     *
     * @return   true if next token is "TRUE"; false if next token is "FALSE"
     * @throws  HsqlException if the next token is neither "TRUE" or "FALSE"
     */
    private boolean processTrueOrFalse() {

        if (token.namePrefix != null) {
            throw unexpectedToken();
        }

        if (token.tokenType == Tokens.TRUE) {
            read();

            return true;
        } else if (token.tokenType == Tokens.FALSE) {
            read();

            return false;
        } else {
            throw unexpectedToken();
        }
    }

    private Boolean processTrueOrFalseObject() {

        if (token.namePrefix != null) {
            throw unexpectedToken();
        }

        if (token.tokenType == Tokens.TRUE) {
            read();

            return Boolean.TRUE;
        } else if (token.tokenType == Tokens.FALSE) {
            read();

            return Boolean.FALSE;
        } else {
            throw unexpectedToken();
        }
    }

    /**
     * Responsible for  handling the execution of COMMIT [WORK]
     *
     * @throws  HsqlException
     */
    private Statement compileCommit() {

        boolean chain = false;

        read();
        readIfThis(Tokens.WORK);

        if (token.tokenType == Tokens.AND) {
            read();

            if (token.tokenType == Tokens.NO) {
                read();
            } else {
                chain = true;
            }

            readThis(Tokens.CHAIN);
        }

        String    sql  = getLastPart();
        Object[]  args = new Object[]{ Boolean.valueOf(chain) };
        Statement cs = new StatementSession(StatementTypes.COMMIT_WORK, args);

        return cs;
    }

    private Statement compileStartTransaction() {

        read();
        readThis(Tokens.TRANSACTION);

        Object[] args = processTransactionCharacteristics();
        Statement cs = new StatementSession(StatementTypes.START_TRANSACTION,
                                            args);

        return cs;
    }

    private Statement compileLock() {

        read();
        readThis(Tokens.TABLE);

        OrderedHashSet readSet  = new OrderedHashSet();
        OrderedHashSet writeSet = new OrderedHashSet();

        outerloop:
        while (true) {
            Table table = readTableName();

            switch (token.tokenType) {

                case Tokens.READ :
                    read();
                    readSet.add(table.getName());
                    break;

                case Tokens.WRITE :
                    read();
                    writeSet.add(table.getName());
                    break;

                default :
                    throw unexpectedToken();
            }

            if (token.tokenType == Tokens.COMMA) {
                read();

                continue;
            }

            break outerloop;
        }

        HsqlName[] writeTableNames = new HsqlName[writeSet.size()];

        writeSet.toArray(writeTableNames);
        readSet.removeAll(writeTableNames);

        HsqlName[] readTableNames = new HsqlName[readSet.size()];

        readSet.toArray(readTableNames);

        Statement cs =
            new StatementSession(StatementTypes.TRANSACTION_LOCK_TABLE,
                                 readTableNames, writeTableNames);

        return cs;
    }

    private Statement compileRollback() {

        boolean chain     = false;
        String  savepoint = null;

        read();

        if (token.tokenType == Tokens.TO) {
            read();
            readThis(Tokens.SAVEPOINT);
            checkIsSimpleName();

            savepoint = token.tokenString;

            read();

            String   sql  = getLastPart();
            Object[] args = new Object[]{ savepoint };
            Statement cs =
                new StatementSession(StatementTypes.ROLLBACK_SAVEPOINT, args);

            return cs;
        } else {
            if (token.tokenType == Tokens.WORK) {
                read();
            }

            if (token.tokenType == Tokens.AND) {
                read();

                if (token.tokenType == Tokens.NO) {
                    read();
                } else {
                    chain = true;
                }

                readThis(Tokens.CHAIN);
            }
        }

        String   sql  = getLastPart();
        Object[] args = new Object[]{ Boolean.valueOf(chain) };
        Statement cs = new StatementSession(StatementTypes.ROLLBACK_WORK,
                                            args);

        return cs;
    }

    private Statement compileSavepoint() {

        String name;

        read();
        checkIsSimpleName();

        name = token.tokenString;

        read();

        String   sql  = getLastPart();
        Object[] args = new Object[]{ name };

        return new StatementSession(StatementTypes.SAVEPOINT, args);
    }

    private Statement compileReleaseSavepoint() {

        read();
        readThis(Tokens.SAVEPOINT);

        String name = token.tokenString;

        read();

        String   sql  = getLastPart();
        Object[] args = new Object[]{ name };

        return new StatementSession(StatementTypes.RELEASE_SAVEPOINT, args);
    }

    private Statement compileSessionSettings() {

        switch (token.tokenType) {

            case Tokens.CHARACTERISTICS : {
                read();
                readThis(Tokens.AS);
                readThis(Tokens.TRANSACTION);

                Object[] args = processTransactionCharacteristics();

                return new StatementSession(
                    StatementTypes.SET_SESSION_CHARACTERISTICS, args);
            }
            case Tokens.AUTHORIZATION : {
                read();

                Expression e = XreadValueSpecificationOrNull();

                if (e == null) {
                    throw Error.error(ErrorCode.X_42584);
                }

                e.resolveTypes(session, null);

                if (e.isUnresolvedParam()) {
                    e.dataType = Type.SQL_VARCHAR;
                }

                if (e.dataType == null || !e.dataType.isCharacterType()) {
                    throw Error.error(ErrorCode.X_42563);
                }

                Expression[] args = new Expression[] {
                    e, null
                };

                return new StatementSession(
                    StatementTypes.SET_SESSION_AUTHORIZATION, args);
            }
            case Tokens.RESULT : {
                read();
                readThis(Tokens.MEMORY);
                readThis(Tokens.ROWS);

                Integer  size = readIntegerObject();
                Object[] args = new Object[]{ size };

                return new StatementCommand(
                    StatementTypes.SET_SESSION_RESULT_MEMORY_ROWS, args);
            }
            default :
                throw unexpectedToken();
        }
    }

    private Statement compileSetRole() {

        Expression e;

        if (token.tokenType == Tokens.NONE) {
            read();

            e = new ExpressionValue(null, Type.SQL_VARCHAR);
        } else {
            e = XreadValueSpecificationOrNull();

            if (e == null) {
                throw Error.error(ErrorCode.X_2A000);
            }

            if (!e.getDataType().isCharacterType()) {
                throw Error.error(ErrorCode.X_0P000);
            }

            if (e.getType() != OpTypes.VALUE
                    && (e.getType() != OpTypes.SQL_FUNCTION
                        || !((FunctionSQL) e).isValueFunction())) {
                throw Error.error(ErrorCode.X_0P000);
            }
        }

        String sql = getLastPart();

        return new StatementSession(StatementTypes.SET_ROLE,
                                    new Expression[]{ e });
    }

    private Statement compileSetTimeZone() {

        Expression e;

        readThis(Tokens.ZONE);

        if (token.tokenType == Tokens.LOCAL) {
            read();

            e = new ExpressionValue(null, Type.SQL_INTERVAL_HOUR_TO_MINUTE);
        } else {
            e = XreadIntervalValueExpression();

            HsqlList unresolved =
                e.resolveColumnReferences(RangeVariable.emptyArray, null);

            ExpressionColumn.checkColumnsResolved(unresolved);
            e.resolveTypes(session, null);

            if (e.dataType == null) {
                throw Error.error(ErrorCode.X_42563);
            }

            if (e.dataType.typeCode != Types.SQL_INTERVAL_HOUR_TO_MINUTE) {
                throw Error.error(ErrorCode.X_42563);
            }
        }

        String sql = getLastPart();

        return new StatementSession(StatementTypes.SET_TIME_ZONE,
                                    new Expression[]{ e });
    }

    private Statement compileShutdown() {

        int closemode;

        session.checkAdmin();

        closemode = Database.CLOSEMODE_NORMAL;

        read();

        switch (token.tokenType) {

            case Tokens.IMMEDIATELY :
                closemode = Database.CLOSEMODE_IMMEDIATELY;

                read();
                break;

            case Tokens.COMPACT :
                closemode = Database.CLOSEMODE_COMPACT;

                read();
                break;

            case Tokens.SCRIPT :
                closemode = Database.CLOSEMODE_SCRIPT;

                read();
                break;

            // only semicolon is accepted here
        }

        if (token.tokenType == Tokens.SEMICOLON) {
            read();
        }

        if (token.tokenType != Tokens.X_ENDPARSE) {
            throw unexpectedToken();
        }

        String   sql  = getLastPart();
        Object[] args = new Object[]{ new Integer(closemode) };
        Statement cs = new StatementCommand(StatementTypes.DATABASE_SHUTDOWN,
                                            args, null, null);

        return cs;
    }

    private Statement compileBackup() {

        read();
        readThis(Tokens.DATABASE);
        readThis(Tokens.TO);

        String  path         = readQuotedString();
        Boolean blockingMode = null;    // Default to non-blocking
        Boolean scriptMode   = null;    // Default to non-script
        Boolean compression  = null;    // Defaults to compressed

        outerLoop:
        while (true) {
            switch (token.tokenType) {

                case Tokens.BLOCKING :
                    if (blockingMode != null) {
                        throw unexpectedToken();
                    }

                    blockingMode = Boolean.TRUE;

                    read();
                    break;

                case Tokens.SCRIPT :
                    if (scriptMode != null) {
                        throw unexpectedToken();
                    }

                    scriptMode = Boolean.TRUE;

                    read();
                    break;

                case Tokens.COMPRESSED :
                    if (compression != null) {
                        throw unexpectedToken();
                    }

                    compression = Boolean.TRUE;

                    read();
                    break;

                case Tokens.NOT :
                    read();

                    if (token.tokenType == Tokens.COMPRESSED) {
                        if (compression != null) {
                            throw unexpectedToken();
                        }

                        compression = Boolean.FALSE;

                        read();
                    } else if (token.tokenType == Tokens.BLOCKING) {
                        blockingMode = Boolean.FALSE;

                        read();
                    } else {
                        throw unexpectedToken();
                    }
                    break;

                default :
                    break outerLoop;
            }
        }

        /**
         * @todo: This block is TEMPORARY.  Will be removed when we implement
         * Non-Blocking and SCRIPT mode.
         */
        if (scriptMode != null) {
            throw unsupportedFeature("SCRIPT");
        }

        scriptMode = Boolean.FALSE;

        if (blockingMode == null) {
            throw unexpectedTokenRequire("BLOCKING");
        }

        if (compression == null) {
            compression = Boolean.TRUE;
        }

        Object[] args = new Object[] {
            path, blockingMode, scriptMode, compression,
        };
        Statement cs = new StatementCommand(StatementTypes.DATABASE_BACKUP,
                                            args);
        HsqlName[] names =
            database.schemaManager.getCatalogAndBaseTableNames();

        cs.writeTableNames = names;

        return cs;
    }

    private Statement compileCheckpoint() {

        boolean defrag = false;

        read();

        if (token.tokenType == Tokens.DEFRAG) {
            defrag = true;

            read();
        } else if (token.tokenType == Tokens.SEMICOLON) {
            read();

            // only semicolon is accepted here
        }

        if (token.tokenType != Tokens.X_ENDPARSE) {
            throw unexpectedToken();
        }

        String sql = getLastPart();

        return getCheckpointStatement(database, defrag);
    }

    public static Statement getCheckpointStatement(Database database,
            boolean defrag) {

        Object[] args = new Object[]{ Boolean.valueOf(defrag) };
        Statement cs = new StatementCommand(StatementTypes.DATABASE_CHECKPOINT,
                                            args);
        HsqlName[] names =
            database.schemaManager.getCatalogAndBaseTableNames();

        cs.writeTableNames = names;

        return cs;
    }

    private Statement compileDisconnect() {

        read();

        String sql = Tokens.T_DISCONNECT;
        Statement cs = new StatementSession(StatementTypes.DISCONNECT,
                                            (Object[]) null);

        return cs;
    }

    private Statement compileExplainPlan() {

        Statement cs;

        read();
        readThis(Tokens.PLAN);
        readThis(Tokens.FOR);

        cs = compilePart(ResultProperties.defaultPropsValue);

        cs.setDescribe();

        return cs;
    }

    private Statement compileTextTableSource(Table t) {

        boolean  isSourceHeader = false;
        boolean  isDesc         = false;
        String   source;
        Object[] args = new Object[5];

        args[0] = t.getName();

        if (!t.isText()) {
            Exception e = Error.error(ErrorCode.X_S0522);
        }

        // SET TABLE <table> SOURCE ON
        if (token.tokenType == Tokens.ON) {
            read();

            String sql = getLastPart();

            args[1] = Boolean.TRUE;

            return new StatementCommand(StatementTypes.SET_TABLE_SOURCE, args,
                                        null, t.getName());
        } else if (token.tokenType == Tokens.OFF) {
            read();

            String sql = getLastPart();

            args[1] = Boolean.FALSE;

            return new StatementCommand(StatementTypes.SET_TABLE_SOURCE, args,
                                        null, t.getName());
        } else if (token.tokenType == Tokens.HEADER) {
            read();

            isSourceHeader = true;
        }

        if (token.tokenType == Tokens.X_DELIMITED_IDENTIFIER) {
            source = token.tokenString;

            read();
        } else {
            source = readQuotedString();
        }

        if (!isSourceHeader && token.tokenType == Tokens.DESC) {
            isDesc = true;

            read();
        }

        String sql = getLastPart();

        args[2] = source;
        args[3] = Boolean.valueOf(isDesc);
        args[4] = Boolean.valueOf(isSourceHeader);

        int type = isSourceHeader ? StatementTypes.SET_TABLE_SOURCE_HEADER
                                  : StatementTypes.SET_TABLE_SOURCE;

        return new StatementCommand(type, args, null, t.getName());
    }
}
TOP

Related Classes of org.hsqldb.ParserCommand

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.