All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.ucanaccess.jdbc.AbstractExecute Maven / Gradle / Ivy

Go to download

An open source pure Java JDBC Driver implementation which allows Java developers and JDBC client programs (e.g., Open Office, Libre Office, Squirrel SQL) to read/write Microsoft Access databases.

There is a newer version: 5.0.1
Show newest version
/*
Copyright (c) 2012 Marco Amadei.

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 net.ucanaccess.jdbc;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Locale;

import net.ucanaccess.commands.DDLCommandEnlist;
import net.ucanaccess.converters.Metadata;
import net.ucanaccess.converters.SQLConverter;
import net.ucanaccess.converters.SQLConverter.DDLType;
import net.ucanaccess.jdbc.FeatureNotSupportedException.NotSupportedMessage;
import net.ucanaccess.jdbc.UcanaccessSQLException.ExceptionMessages;
import net.ucanaccess.util.HibernateSupport;

public abstract class AbstractExecute {
    protected enum CommandType {
        BATCH,
        NO_ARGUMENTS,
        PREPARED_STATEMENT,
        UPDATABLE_RESULTSET,
        WITH_AUTO_GENERATED_KEYS,
        WITH_COLUMNS_NAME,
        WITH_INDEXES
    }

    //CHECKSTYLE:OFF
    protected int               autoGeneratedKeys;
    protected String[]          columnNames;
    protected CommandType       commandType;
    protected int[]             indexes;
    protected String            sql;
    //CHECKSTYLE:ON
    private UcanaccessResultSet resultSet;

    private UcanaccessStatement statement;

    protected AbstractExecute(UcanaccessPreparedStatement _statement) {
        this.statement = _statement;
        this.commandType = CommandType.PREPARED_STATEMENT;
    }

    protected AbstractExecute(UcanaccessResultSet _resultSet) {
        this.resultSet = _resultSet;
        this.statement = _resultSet.getWrappedStatement();
        this.commandType = CommandType.UPDATABLE_RESULTSET;
    }

    public AbstractExecute(UcanaccessStatement _statement) {
        this.statement = _statement;
    }

    protected AbstractExecute(UcanaccessStatement _statement, String _sql) {
        this(_statement);
        this.commandType = CommandType.NO_ARGUMENTS;
        this.sql = _sql;
    }

    protected AbstractExecute(UcanaccessStatement _statement, String _sql, int _autoGeneratedKeys) {
        this(_statement, _sql);
        this.autoGeneratedKeys = _autoGeneratedKeys;
        this.commandType = CommandType.WITH_AUTO_GENERATED_KEYS;
    }

    protected AbstractExecute(UcanaccessStatement _statement, String _sql, int[] _indexes) {
        this(_statement, _sql);
        this.indexes = _indexes;
        this.commandType = CommandType.WITH_INDEXES;
    }

    protected AbstractExecute(UcanaccessStatement _statement, String _sql, String[] _columnNames) {
        this(_statement, _sql);
        this.columnNames = _columnNames;
        this.commandType = CommandType.WITH_COLUMNS_NAME;
    }

    private Object enableDiasable(DDLType ddlType) throws SQLException, IOException {
        String tn = ddlType.getDBObjectName();
        if (tn.startsWith("[") && tn.endsWith("]")) {
            tn = tn.substring(1, tn.length() - 1);
        }
        UcanaccessConnection conn = (UcanaccessConnection) this.statement.getConnection();
        Metadata mtd = new Metadata(conn.getHSQLDBConnection());
        String rtn = mtd.getTableName(tn);
        if (rtn == null) {
            throw new UcanaccessSQLException(ExceptionMessages.TABLE_DOESNT_EXIST, tn);
        }
        boolean inable = ddlType.equals(DDLType.ENABLE_AUTOINCREMENT);
        conn.getDbIO().getTable(rtn).setAllowAutoNumberInsert(!inable);
        return (this instanceof Execute) ? false : 0;
    }

    private int count(String tableName) throws SQLException {
        UcanaccessConnection conn = (UcanaccessConnection) this.statement.getConnection();
        Statement st = null;
        ResultSet rs = null;
        try {
            st = conn.createStatement();
            rs = st.executeQuery("select count(*) from " + tableName);
            rs.next();
            return rs.getInt(1);
        } finally {
            if (rs != null) {
                rs.close();
            }
            if (st != null) {
                st.close();
            }
        }
    }

    private SQLException checkDDLException() throws SQLException {
        UcanaccessConnection conn = (UcanaccessConnection) this.statement.getConnection();
        PreparedStatement ps = null;
        try {
            // hsqldb as parser by using an unexecuted PreparedStatement: my latest trick
            ps = conn.getHSQLDBConnection().prepareStatement(SQLConverter.convertSQL(sql).getSql());
        } catch (SQLException ex) {
            return ex;
        } finally {
            if (ps != null) {
                ps.close();
            }
        }
        return new FeatureNotSupportedException(NotSupportedMessage.NOT_SUPPORTED_YET);
    }

    private Object addDDLCommand() throws SQLException {
        Object ret;
        try {
            DDLType ddlType = SQLConverter.getDDLType(sql);
            if (ddlType == null) {
                throw checkDDLException();
            }

            if (DDLType.DROP_FOREIGN_KEY.equals(ddlType)) {
                if (!HibernateSupport.isActive()) {
                    throw new UnsupportedOperationException(
                            "DROP CONSTRAINT is only supported for Hibernate hbm2ddl.auto \"create\"");
                }
            }

            if (DDLType.ADD_COLUMN.equals(ddlType)) {

                if (SQLConverter.couldNeedDefault(ddlType.getColumnDefinition())) {
                    String cn = ddlType.getSecondDBObjectName();
                    String tn = ddlType.getDBObjectName();
                    int count = count(ddlType.getDBObjectName());
                    if (count > 0) {
                        throw new UcanaccessSQLException(ExceptionMessages.DEFAULT_NEEDED, cn, tn, count);
                    }

                }
            }

            String sql0 = (ddlType.equals(DDLType.ADD_COLUMN))
                    ? SQLConverter.convertSQL(SQLConverter.convertAddColumn(ddlType.getDBObjectName(),
                            ddlType.getSecondDBObjectName(), ddlType.getColumnDefinition())).getSql()
                    : SQLConverter.convertSQL(sql).getSql();

            boolean enDis = ddlType.in(DDLType.ENABLE_AUTOINCREMENT, DDLType.DISABLE_AUTOINCREMENT);
            this.statement.setEnableDisable(enDis);
            if (enDis) {
                return enableDiasable(ddlType);
            }

            String ddlExpr = null;
            if (ddlType.in(DDLType.CREATE_TABLE, DDLType.CREATE_TABLE_AS_SELECT)) {
                ddlExpr = SQLConverter.convertCreateTable(sql0);
            } else if (ddlType.equals(DDLType.CREATE_FOREIGN_KEY)) {
                String constraintName = ddlType.getSecondDBObjectName();
                if (constraintName == null) {
                    ddlExpr = sql0;
                } else {
                    if (constraintName.startsWith("[") && constraintName.endsWith("]")) {
                        constraintName = constraintName.substring(1, constraintName.length() - 1);
                    }
                    String tableName = ddlType.getDBObjectName();
                    if (tableName.startsWith("[") && tableName.endsWith("]")) {
                        tableName = tableName.substring(1, tableName.length() - 1);
                    }
                    UcanaccessConnection conn = (UcanaccessConnection) this.statement.getConnection();
                    Metadata mtd = new Metadata(conn.getHSQLDBConnection());
                    tableName = mtd.getEscapedTableName(tableName);
                    if (tableName == null) {
                        throw new UcanaccessSQLException(ExceptionMessages.TABLE_DOESNT_EXIST, tableName);
                    }
                    ddlExpr = sql0.replaceFirst("(?i)\\s+ADD\\s+CONSTRAINT\\s+.*\\s+FOREIGN\\s+KEY\\s+",
                            " ADD CONSTRAINT \"" + tableName + "_" + constraintName.toUpperCase(Locale.US)
                                    + "\" FOREIGN KEY ");
                }
            } else if (ddlType.equals(DDLType.DROP_FOREIGN_KEY)) {
                String constraintName = ddlType.getSecondDBObjectName();
                if (constraintName == null) {
                    throw new UcanaccessSQLException();
                } else {
                    if (constraintName.startsWith("[") && constraintName.endsWith("]")) {
                        constraintName = constraintName.substring(1, constraintName.length() - 1);
                    }
                    String tableName = ddlType.getDBObjectName();
                    if (tableName.startsWith("[") && tableName.endsWith("]")) {
                        tableName = tableName.substring(1, tableName.length() - 1);
                    }
                    UcanaccessConnection conn = (UcanaccessConnection) this.statement.getConnection();
                    Metadata mtd = new Metadata(conn.getHSQLDBConnection());
                    tableName = mtd.getEscapedTableName(tableName);
                    if (tableName == null) {
                        throw new UcanaccessSQLException(ExceptionMessages.TABLE_DOESNT_EXIST, tableName);
                    }
                    ddlExpr = sql0.replaceFirst("(?i)\\s+DROP\\s+CONSTRAINT\\s+.*",
                            " DROP CONSTRAINT \"" + tableName + "_" + constraintName.toUpperCase(Locale.US) + "\"");
                }
            } else {
                ddlExpr = sql0;
            }

            ret = (this instanceof Execute) ? statement.getWrapped().execute(ddlExpr)
                    : statement.getWrapped().executeUpdate(ddlExpr);

            DDLCommandEnlist ddle = new DDLCommandEnlist();
            ddle.enlistDDLCommand(SQLConverter.restoreWorkAroundFunctions(sql), ddlType);
        } catch (Exception e) {
            throw new SQLException(e);
        }
        return ret;
    }

    private boolean checkDDL() {
        return SQLConverter.checkDDL(this.sql);
    }

    public Object executeBase() throws SQLException {
        UcanaccessConnection conn = (UcanaccessConnection) statement.getConnection();
        UcanaccessConnection.setCtxConnection(conn);

        if (this.commandType.equals(CommandType.BATCH)) {
            UcanaccessConnection.setCtxExecId(UcanaccessConnection.BATCH_ID);
        } else {
            UcanaccessConnection.setCtxExecId(Math.random() + "");
        }
        Object retv;

        if (checkDDL()) {
            retv = addDDLCommand();
        } else {
            try {
                retv = executeWrapped();
            } catch (SQLException e) {
                if (conn.getAutoCommit()) {
                    conn.rollback();
                }
                throw e;
            }
        }
        if (conn.getAutoCommit()) {
            conn.commit();
        }

        return retv;
    }

    public abstract Object executeWrapped() throws SQLException;

    ResultSet getWrappedResultSet() {
        return resultSet.getWrapped();
    }

    Statement getWrappedStatement() {
        return statement.getWrapped();
    }

    void setStatement(UcanaccessStatement _statement) {
        this.statement = _statement;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy