Package org.hsqldb

Source Code of org.hsqldb.StatementCompound

/* 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.HashMappedList;
import org.hsqldb.lib.HashSet;
import org.hsqldb.lib.OrderedHashSet;
import org.hsqldb.lib.OrderedIntHashSet;
import org.hsqldb.result.Result;
import org.hsqldb.result.ResultConstants;

/**
* Implementation of Statement for PSM compound statements.

* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 1.9.0
* @since 1.9.0
*/
public class StatementCompound extends Statement {

    final boolean       isLoop;
    HsqlName            label;
    StatementHandler[]  handlers = StatementHandler.emptyExceptionHandlerArray;
    boolean             hasUndoHandler;
    Statement           loopCursor;
    Statement[]         statements;
    StatementExpression condition;
    boolean             isAtomic;

    //
    ColumnSchema[]  variables = ColumnSchema.emptyArray;
    HashMappedList  scopeVariables;
    RangeVariable[] rangeVariables = RangeVariable.emptyArray;

    //
    public static final StatementCompound[] emptyStatementArray =
        new StatementCompound[]{};

    StatementCompound(int type, HsqlName label) {

        super(type, StatementTypes.X_SQL_CONTROL);

        this.label             = label;
        isTransactionStatement = false;

        switch (type) {

            case StatementTypes.LOOP :
            case StatementTypes.WHILE :
            case StatementTypes.REPEAT :
                isLoop = true;
                break;

            case StatementTypes.BEGIN_END :
            case StatementTypes.IF :
                isLoop = false;
                break;

            default :
                throw Error.runtimeError(ErrorCode.U_S0500,
                                         "StatementCompound");
        }
    }

    public String getSQL() {

/*
        StringBuffer sb = new StringBuffer();

        if (label != null) {
            sb.append(label.getStatementName()).append(':').append(' ');
        }

        switch (type) {

            case StatementTypes.LOOP :
                sb.append(Tokens.T_LOOP).append(' ');

                for (int i = 0; i < statements.length; i++) {
                    sb.append(statements[i].getSQL()).append(';');
                }

                sb.append(Tokens.T_END).append(' ').append(Tokens.T_LOOP);
                break;

            case StatementTypes.WHILE :
                sb.append(Tokens.T_WHILE).append(' ');
                sb.append(condition.getSQL()).append(' ').append(Tokens.T_DO);
                sb.append(' ');

                for (int i = 0; i < statements.length; i++) {
                    sb.append(statements[i].getSQL()).append(';');
                }

                sb.append(Tokens.T_END).append(' ').append(Tokens.T_WHILE);
                break;

            case StatementTypes.REPEAT :
                sb.append(Tokens.T_REPEAT).append(' ');

                for (int i = 0; i < statements.length; i++) {
                    sb.append(statements[i].getSQL()).append(';');
                }

                sb.append(Tokens.T_UNTIL).append(' ');
                sb.append(condition.getSQL()).append(' ');
                sb.append(Tokens.T_END).append(' ').append(Tokens.T_REPEAT);
                break;

            case StatementTypes.BEGIN_END :
                sb.append(Tokens.T_BEGIN).append(' ').append(Tokens.T_ATOMIC);
                sb.append(' ');

                for (int i = 0; i < handlers.length; i++) {
                    sb.append(handlers[i].getSQL()).append(';');
                }

                for (int i = 0; i < variables.length; i++) {
                    sb.append(Tokens.T_DECLARE).append(' ');
                    sb.append(variables[i].getSQL());

                    if (variables[i].hasDefault()) {
                        sb.append(' ').append(Tokens.T_DEFAULT).append(' ');
                        sb.append(variables[i].getDefaultSQL());
                    }

                    sb.append(';');
                }

                for (int i = 0; i < statements.length; i++) {
                    sb.append(statements[i].getSQL()).append(';');
                }

                sb.append(Tokens.T_END);
                break;

            case StatementTypes.IF :
                for (int i = 0; i < statements.length; i++) {
                    if (statements[i].type == StatementTypes.CONDITION) {
                        if (i != 0) {
                            sb.append(Tokens.T_ELSE).append(' ');
                        }

                        sb.append(Tokens.T_IF).append(' ');
                        sb.append(statements[i].getSQL()).append(' ');
                        sb.append(Tokens.T_THEN).append(' ');
                    } else {
                        sb.append(statements[i].getSQL()).append(';');
                    }
                }

                sb.append(Tokens.T_END).append(' ').append(Tokens.T_IF);
                break;
        }

        return sb.toString();
*/
        return sql;
    }

    protected String describe(Session session, int blanks) {

        StringBuffer sb = new StringBuffer();

        sb.append('\n');

        for (int i = 0; i < blanks; i++) {
            sb.append(' ');
        }

        sb.append(Tokens.T_STATEMENT);

        return sb.toString();
    }

    public void setLocalDeclarations(Object[] declarations) {

        int varCount     = 0;
        int handlerCount = 0;

        for (int i = 0; i < declarations.length; i++) {
            if (declarations[i] instanceof ColumnSchema) {
                varCount++;
            } else {
                handlerCount++;
            }
        }

        variables    = new ColumnSchema[varCount];
        handlers     = new StatementHandler[handlerCount];
        varCount     = 0;
        handlerCount = 0;

        for (int i = 0; i < declarations.length; i++) {
            if (declarations[i] instanceof ColumnSchema) {
                variables[varCount++] = (ColumnSchema) declarations[i];
            } else {
                StatementHandler handler = (StatementHandler) declarations[i];

                handler.setParent(this);

                handlers[handlerCount++] = handler;

                if (handler.handlerType == StatementHandler.UNDO) {
                    hasUndoHandler = true;
                }
            }
        }

        setVariables();
        setHandlers();
    }

    public void setLoopStatement(Statement cursorStatement) {
        loopCursor = cursorStatement;
    }

    void setStatements(Statement[] statements) {

        for (int i = 0; i < statements.length; i++) {
            statements[i].setParent(this);
        }

        this.statements = statements;
    }

    public void setCondition(StatementExpression condition) {
        this.condition = condition;
    }

    public Result execute(Session session) {

        Result result;

        switch (type) {

            case StatementTypes.BEGIN_END : {
                initialiseVariables(session);

                result = executeBlock(session);

                break;
            }
            case StatementTypes.LOOP :
            case StatementTypes.WHILE :
            case StatementTypes.REPEAT : {
                result = executeLoop(session);

                break;
            }
            case StatementTypes.IF : {
                result = executeIf(session);

                break;
            }
            default :
                throw Error.runtimeError(ErrorCode.U_S0500,
                                         "StatementCompound");
        }

        if (result.isError()) {
            result.getException().setStatementType(group, type);
        }

        return result;
    }

    private Result executeBlock(Session session) {

        Result  result = Result.updateZeroResult;
        boolean push   = !root.isTrigger();

        if (push) {
            session.sessionContext.push();

            if (hasUndoHandler) {
                String name = HsqlNameManager.getAutoSavepointNameString(
                    session.actionTimestamp, session.sessionContext.depth);

                session.savepoint(name);
            }
        }

        for (int i = 0; i < statements.length; i++) {
            result = statements[i].execute(session);
            result = handleCondition(session, result);

            if (result.isError()) {
                break;
            }

            if (result.getType() == ResultConstants.VALUE
                    || result.getType() == ResultConstants.DATA) {
                break;
            }
        }

        if (result.getType() == ResultConstants.VALUE) {
            if (result.getErrorCode() == StatementTypes.LEAVE) {
                if (result.getMainString() == null) {
                    result = Result.updateZeroResult;
                } else if (label != null
                           && label.name.equals(result.getMainString())) {
                    result = Result.updateZeroResult;
                }
            }
        }

        if (push) {
            session.sessionContext.pop();
        }

        return result;
    }

    private Result handleCondition(Session session, Result result) {

        String sqlState = null;

        if (result.isError()) {
            sqlState = result.getSubString();
        } else if (session.getLastWarning() != null) {
            sqlState = session.getLastWarning().getSQLState();
        } else {
            return result;
        }

        if (sqlState != null) {
            for (int i = 0; i < handlers.length; i++) {
                StatementHandler handler = handlers[i];

                session.clearWarnings();

                /**
                 * @todo - if condition is "transaction rollback" promote to
                 * top call level without any further action
                 * if condition is system related promote to top level
                 * schema manipulation conditions are never handled
                 */
                if (handler.handlesCondition(result.getSubString())) {
                    session.resetSchema();

                    switch (handler.handlerType) {

                        case StatementHandler.CONTINUE :
                            result = Result.updateZeroResult;
                            break;

                        case StatementHandler.UNDO :
                            session.rollbackToSavepoint();

                            result = Result.newPSMResult(StatementTypes.LEAVE,
                                                         label.name, null);
                            break;

                        case StatementHandler.EXIT :
                            result = Result.newPSMResult(StatementTypes.LEAVE,
                                                         null, null);
                            break;
                    }

                    Result actionResult = handler.statement.execute(session);

                    if (actionResult.isError()) {
                        result = actionResult;

                        handleCondition(session, result);
                    } else {
                        return result;
                    }
                }
            }

            if (parent != null) {

                // unhandled exception condition
                return parent.handleCondition(session, result);
            }
        }

        return result;
    }

    private Result executeLoop(Session session) {

        Result result = Result.updateZeroResult;

        while (true) {
            if (type == StatementTypes.WHILE) {
                result = condition.execute(session);

                if (result.isError()) {
                    break;
                }

                if (!Boolean.TRUE.equals(result.getValueObject())) {
                    result = Result.updateZeroResult;

                    break;
                }
            }

            for (int i = 0; i < statements.length; i++) {
                result = statements[i].execute(session);

                if (result.isError()) {
                    break;
                }

                if (result.getType() == ResultConstants.VALUE) {
                    break;
                }

                if (result.getType() == ResultConstants.DATA) {
                    break;
                }

            }

            if (result.isError()) {
                break;
            }

            if (result.getType() == ResultConstants.VALUE) {
                if (result.getErrorCode() == StatementTypes.ITERATE) {
                    if (result.getMainString() == null) {
                        continue;
                    }

                    if (label != null
                            && label.name.equals(result.getMainString())) {
                        continue;
                    }

                    break;
                }

                if (result.getErrorCode() == StatementTypes.LEAVE) {
                    if (result.getMainString() == null) {
                        result = Result.updateZeroResult;
                    }

                    if (label != null
                            && label.name.equals(result.getMainString())) {
                        result = Result.updateZeroResult;
                    }

                    break;
                }

                // return
                break;
            }

            if (result.getType() == ResultConstants.DATA) {
                break;
            }

            if (type == StatementTypes.REPEAT) {
                result = condition.execute(session);

                if (result.isError()) {
                    break;
                }

                if (Boolean.TRUE.equals(result.getValueObject())) {
                    result = Result.updateZeroResult;

                    break;
                }
            }
        }

        return result;
    }

    private Result executeIf(Session session) {

        Result  result  = Result.updateZeroResult;
        boolean execute = false;

        for (int i = 0; i < statements.length; i++) {
            if (statements[i].getType() == StatementTypes.CONDITION) {
                if (execute) {
                    break;
                }

                result = statements[i].execute(session);

                if (result.isError()) {
                    break;
                }

                Object value = result.getValueObject();

                execute = Boolean.TRUE.equals(value);

                i++;
            }

            result = Result.updateZeroResult;

            if (!execute) {
                continue;
            }

            result = statements[i].execute(session);

            if (result.isError()) {
                break;
            }

            if (result.getType() == ResultConstants.VALUE) {
                break;
            }
        }

        return result;
    }

    public void resolve(Session session) {

        for (int i = 0; i < statements.length; i++) {
            if (statements[i].getType() == StatementTypes.LEAVE
                    || statements[i].getType() == StatementTypes.ITERATE) {
                if (!findLabel((StatementSimple) statements[i])) {
                    throw Error.error(
                        ErrorCode.X_42508,
                        ((StatementSimple) statements[i]).label.name);
                }

                continue;
            }

            if (statements[i].getType() == StatementTypes.RETURN) {
                if (!root.isFunction()) {
                    throw Error.error(ErrorCode.X_42602, Tokens.T_RETURN);
                }
            }
        }

        for (int i = 0; i < statements.length; i++) {
            statements[i].resolve(session);
        }

        for (int i = 0; i < handlers.length; i++) {
            handlers[i].resolve(session);
        }

        OrderedHashSet writeTableNamesSet = new OrderedHashSet();
        OrderedHashSet readTableNamesSet  = new OrderedHashSet();
        OrderedHashSet set                = new OrderedHashSet();

        for (int i = 0; i < variables.length; i++) {
            set.addAll(variables[i].getReferences());
        }

        if (condition != null) {
            set.addAll(condition.getReferences());
            readTableNamesSet.addAll(condition.getTableNamesForRead());
        }

        for (int i = 0; i < statements.length; i++) {
            set.addAll(statements[i].getReferences());
            readTableNamesSet.addAll(statements[i].getTableNamesForRead());
            writeTableNamesSet.addAll(statements[i].getTableNamesForWrite());
        }

        for (int i = 0; i < handlers.length; i++) {
            set.addAll(handlers[i].getReferences());
            readTableNamesSet.addAll(handlers[i].getTableNamesForRead());
            writeTableNamesSet.addAll(handlers[i].getTableNamesForWrite());
        }

        readTableNamesSet.removeAll(writeTableNamesSet);

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

        readTableNamesSet.toArray(readTableNames);

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

        writeTableNamesSet.toArray(writeTableNames);

        references = set;
    }

    public void setRoot(Routine routine) {

        root = routine;
/*
        if (condition != null) {
            condition.setRoot(routine);
        }

        for (int i = 0; i < statements.length; i++) {
            statements[i].setRoot(routine);
        }
*/
    }

    public String describe(Session session) {
        return "";
    }

    public OrderedHashSet getReferences() {
        return references;
    }

    public void setAtomic(boolean atomic) {
        this.isAtomic = atomic;
    }

    //
    private void setVariables() {

        if (variables.length == 0) {
            if (parent == null) {
                rangeVariables = root.getParameterRangeVariables();
            } else {
                rangeVariables = parent.rangeVariables;
            }

            return;
        }

        HashMappedList list = new HashMappedList();

        if (parent != null) {
            for (int i = 0; i < parent.scopeVariables.size(); i++) {
                list.add(parent.scopeVariables.getKey(i),
                         parent.scopeVariables.get(i));
            }
        }

        for (int i = 0; i < variables.length; i++) {
            String  name  = variables[i].getName().name;
            boolean added = list.add(name, variables[i]);

            if (!added) {
                throw Error.error(ErrorCode.X_42606, name);
            }

            if (root.getParameterIndex(name) != -1) {
                throw Error.error(ErrorCode.X_42606, name);
            }
        }

        RangeVariable range = new RangeVariable(list, true);

        rangeVariables     = new RangeVariable[] {
            root.getParameterRangeVariables()[0], range
        };
        root.variableCount = list.size();
    }

    private void setHandlers() {

        if (handlers.length == 0) {
            return;
        }

        HashSet           statesSet = new HashSet();
        OrderedIntHashSet typesSet  = new OrderedIntHashSet();

        for (int i = 0; i < handlers.length; i++) {
            int[] types = handlers[i].getConditionTypes();

            for (int j = 0; j < types.length; j++) {
                if (!typesSet.add(types[j])) {
                    throw Error.error(ErrorCode.X_42601);
                }
            }

            String[] states = handlers[i].getConditionStates();

            for (int j = 0; j < states.length; j++) {
                if (!statesSet.add(states[j])) {
                    throw Error.error(ErrorCode.X_42601);
                }
            }
        }
    }

    private boolean findLabel(StatementSimple statement) {

        if (label != null && statement.label.name.equals(label.name)) {
            if (!isLoop && statement.getType() == StatementTypes.ITERATE) {
                return false;
            }

            return true;
        }

        if (parent == null) {
            return false;
        }

        return parent.findLabel(statement);
    }

    private void initialiseVariables(Session session) {

        Object[] vars   = session.sessionContext.routineVariables;
        int      offset = parent == null ? 0
                                         : parent.scopeVariables.size();

        for (int i = 0; i < variables.length; i++) {
            try {
                vars[offset + i] = variables[i].getDefaultValue(session);
            } catch (HsqlException e) {}
        }
    }

    public RangeVariable[] getRangeVariables() {
        return rangeVariables;
    }
}
TOP

Related Classes of org.hsqldb.StatementCompound

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.