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

org.voltdb.jdbc.JDBC4Connection Maven / Gradle / Ivy

There is a newer version: 13.3.2-preview1
Show newest version
/* This file is part of VoltDB.
 * Copyright (C) 2008-2017 VoltDB Inc.
 *
 * 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 VoltDB.  If not, see .
 */

package org.voltdb.jdbc;

import java.io.IOException;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

import org.voltdb.client.ClientStats;
import org.voltdb.client.ClientStatsContext;

public class JDBC4Connection implements java.sql.Connection, IVoltDBConnection
{
    public static final String COMMIT_THROW_EXCEPTION = "jdbc.committhrowexception";
    public static final String ROLLBACK_THROW_EXCEPTION = "jdbc.rollbackthrowexception";
    public static final String QUERYTIMEOUT_UNIT = "jdbc.querytimeout.unit";

    protected final JDBC4ClientConnection NativeConnection;
    protected final String User;
    protected TimeUnit queryTimeOutUnit = TimeUnit.SECONDS;
    private boolean isClosed = false;
    private Properties props;
    private boolean autoCommit = true;

    public JDBC4Connection(JDBC4ClientConnection connection, Properties props)
    {
        this.NativeConnection = connection;
        this.props = props;
        this.User = this.props.getProperty("user", "");
        if (this.props.getProperty(JDBC4Connection.QUERYTIMEOUT_UNIT, "Seconds").equalsIgnoreCase("milliseconds")) {
            this.queryTimeOutUnit = TimeUnit.MILLISECONDS;
        }
    }

    private void checkClosed() throws SQLException
    {
        if (this.isClosed())
            throw SQLError.get(SQLError.CONNECTION_CLOSED);
    }

    // Clears all warnings reported for this Connection object.
    @Override
    public void clearWarnings() throws SQLException
    {
        checkClosed();
    }

    // Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.
    @Override
    public void close() throws SQLException
    {
        try
        {
            isClosed = true;
            JDBC4ClientConnectionPool.dispose(NativeConnection);
        }
        catch(Exception x)
        {
            throw SQLError.get(x);
        }
    }

    // Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.
    @Override
    public void commit() throws SQLException
    {
        checkClosed();
        if (props.getProperty(COMMIT_THROW_EXCEPTION, "true").equalsIgnoreCase("true")) {
            throw SQLError.noSupport();
        }
    }

    // Factory method for creating Array objects.
    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Constructs an object that implements the Blob interface.
    @Override
    public Blob createBlob() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Constructs an object that implements the Clob interface.
    @Override
    public Clob createClob() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Constructs an object that implements the NClob interface.
    @Override
    public NClob createNClob() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Constructs an object that implements the SQLXML interface.
    @Override
    public SQLXML createSQLXML() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a Statement object for sending SQL statements to the database.
    @Override
    public Statement createStatement() throws SQLException
    {
        checkClosed();
        try
        {
            return new JDBC4Statement(this);
        }
        catch(Exception x)
        {
            throw SQLError.get(x);
        }
    }

    /**
     * Check if the createStatement() options are supported
     *
     * See http://docs.oracle.com/javase/7/docs/api/index.html?java/sql/DatabaseMetaData.html
     *
     * The following flags are supported:
     *  - The type must either be TYPE_SCROLL_INSENSITIVE or TYPE_FORWARD_ONLY.
     *  - The concurrency must be CONCUR_READ_ONLY.
     *  - The holdability must be CLOSE_CURSORS_AT_COMMIT.
     *
     * @param resultSetType  JDBC result set type option
     * @param resultSetConcurrency  JDBC result set concurrency option
     * @param resultSetHoldability  JDBC result set holdability option
     * @throws SQLException  if not supported
     */
    private static void checkCreateStatementSupported(
            int resultSetType, int resultSetConcurrency, int resultSetHoldability)
                    throws SQLException
    {
        if (   (   (resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE
                &&  resultSetType != ResultSet.TYPE_FORWARD_ONLY))
            || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY
            || resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
            throw SQLError.noSupport();
        }
    }

    /**
     * Check if the createStatement() options are supported
     *
     * The following flags are supported:
     *  - The type must either be TYPE_SCROLL_INSENSITIVE or TYPE_FORWARD_ONLY.
     *  - The concurrency must be CONCUR_READ_ONLY.
     *
     * @param resultSetType  JDBC result set type option
     * @param resultSetConcurrency  JDBC result set concurrency option
     * @throws SQLException  if not supported
     */
    private static void checkCreateStatementSupported(
            int resultSetType, int resultSetConcurrency)
                    throws SQLException
    {
        checkCreateStatementSupported(resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT);
    }

    // Creates a Statement object that will generate ResultSet objects with the given type and concurrency.
    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
    {
        checkClosed();
        // Reject options that don't coincide with normal VoltDB behavior.
        checkCreateStatementSupported(resultSetType, resultSetConcurrency);
        return createStatement();
    }

    // Creates a Statement object that will generate ResultSet objects with the given type, concurrency, and holdability.
    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        checkClosed();
        // Reject options that don't coincide with normal VoltDB behavior.
        checkCreateStatementSupported(resultSetType, resultSetConcurrency, resultSetHoldability);
        return createStatement();
    }

    // Factory method for creating Struct objects.
    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Retrieves the current auto-commit mode for this Connection object.
    // We are always auto-committing, but if let's be consistent with the lying.
    @Override
    public boolean getAutoCommit() throws SQLException
    {
        checkClosed();
        return autoCommit;
    }

    // Retrieves this Connection object's current catalog name.
    @Override
    public String getCatalog() throws SQLException
    {
        checkClosed();
        return "";
    }

    // Returns a list containing the name and current value of each client info property supported by the driver.
    @Override
    public Properties getClientInfo() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Returns the value of the client info property specified by name.
    @Override
    public String getClientInfo(String name) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Retrieves the current holdability of ResultSet objects created using this Connection object.
    @Override
    public int getHoldability() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Retrieves a DatabaseMetaData object that contains metadata about the database to which this Connection object represents a connection.
    @Override
    public DatabaseMetaData getMetaData() throws SQLException
    {
        checkClosed();
        return new JDBC4DatabaseMetaData(this);
    }

    // Retrieves this Connection object's current transaction isolation level.
    @Override
    public int getTransactionIsolation() throws SQLException
    {
        checkClosed();
        return TRANSACTION_SERIALIZABLE;
    }

    // Retrieves the Map object associated with this Connection object.
    @Override
    public Map> getTypeMap() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Retrieves the first warning reported by calls on this Connection object.
    @Override
    public SQLWarning getWarnings() throws SQLException
    {
        checkClosed();
        return null;
    }

    // Retrieves whether this Connection object has been closed.
    @Override
    public boolean isClosed() throws SQLException
    {
        return isClosed;
    }

    // Retrieves whether this Connection object is in read-only mode.
    @Override
    public boolean isReadOnly() throws SQLException
    {
        checkClosed();
        return false;
    }

    // Returns true if the connection has not been closed and is still valid.
    @Override
    public boolean isValid(int timeout) throws SQLException
    {
        return !isClosed;
    }

    // Converts the given SQL statement into the system's native SQL grammar.
    @Override
    public String nativeSQL(String sql) throws SQLException
    {
        checkClosed();
        return sql; // Well...
    }

    // Creates a CallableStatement object for calling database stored procedures.
    @Override
    public CallableStatement prepareCall(String sql) throws SQLException
    {
        checkClosed();
        return new JDBC4CallableStatement(this, sql);
    }

    // Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency.
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
    {
        if (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE && resultSetConcurrency == ResultSet.CONCUR_READ_ONLY)
            return prepareCall(sql);
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a CallableStatement object that will generate ResultSet objects with the given type and concurrency.
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a PreparedStatement object for sending parameterized SQL statements to the database.
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException
    {
        checkClosed();
        return new JDBC4PreparedStatement(this, sql);
    }

    // Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys.
    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a PreparedStatement object that will generate ResultSet objects with the given type and concurrency.
    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
    {
        if ((resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE || resultSetType == ResultSet.TYPE_FORWARD_ONLY) &&
                resultSetConcurrency == ResultSet.CONCUR_READ_ONLY) {
            return prepareStatement(sql);
        }
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a PreparedStatement object that will generate ResultSet objects with the given type, concurrency, and holdability.
    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Removes the specified Savepoint and subsequent Savepoint objects from the current transaction.
    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object.
    @Override
    public void rollback() throws SQLException
    {
        checkClosed();
        if (props.getProperty(ROLLBACK_THROW_EXCEPTION, "true").equalsIgnoreCase("true")) {
            throw SQLError.noSupport();
        }
    }

    // Undoes all changes made after the given Savepoint object was set.
    @Override
    public void rollback(Savepoint savepoint) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Sets this connection's auto-commit mode to the given state.
    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException
    {
        checkClosed();
        // Always true - error out only if the client is trying to set somethign else
        if (!autoCommit && (props.getProperty(COMMIT_THROW_EXCEPTION, "true").equalsIgnoreCase("true"))) {
            throw SQLError.noSupport();
        }
        else {
            this.autoCommit = autoCommit;
        }
    }

    // Sets the given catalog name in order to select a subspace of this Connection object's database in which to work.
    @Override
    public void setCatalog(String catalog) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Sets the value of the connection's client info properties.
    @Override
    public void setClientInfo(Properties properties)
    {
        // No-op (key client properties cannot be changed after the connection has been opened anyways!)
    }

    // Sets the value of the client info property specified by name to the value specified by value.
    @Override
    public void setClientInfo(String name, String value)
    {
        // No-op (key client properties cannot be changed after the connection has been opened anyways!)
    }

    // Changes the default holdability of ResultSet objects created using this Connection object to the given holdability.
    @Override
    public void setHoldability(int holdability) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Puts this connection in read-only mode as a hint to the driver to enable database optimizations.
    @Override
    public void setReadOnly(boolean readOnly) throws SQLException
    {
        checkClosed();
        if (!Boolean.parseBoolean(props.getProperty("enableSetReadOnly","false"))){
            throw SQLError.noSupport();
        }
    }

    // Creates an unnamed savepoint in the current transaction and returns the new Savepoint object that represents it.
    @Override
    public Savepoint setSavepoint() throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Creates a savepoint with the given name in the current transaction and returns the new Savepoint object that represents it.
    @Override
    public Savepoint setSavepoint(String name) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Attempts to change the transaction isolation level for this Connection object to the one given.
    @Override
    public void setTransactionIsolation(int level) throws SQLException
    {
        checkClosed();
        if (level == TRANSACTION_SERIALIZABLE)
            return;
        throw SQLError.noSupport();
    }

    // Installs the given TypeMap object as the type map for this Connection object.
    @Override
    public void setTypeMap(Map> map) throws SQLException
    {
        checkClosed();
        throw SQLError.noSupport();
    }

    // Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does.
    @Override
    public boolean isWrapperFor(Class iface) throws SQLException
    {
        return iface.isInstance(this);
    }

    // Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy.
    @Override
    public  T unwrap(Class iface)    throws SQLException
    {
        try
        {
            return iface.cast(this);
        }
         catch (ClassCastException cce)
         {
            throw SQLError.get(SQLError.ILLEGAL_ARGUMENT, iface.toString());
        }
    }

    /**
     * Gets the new version of the performance statistics for this connection only.
     * @return A {@link ClientStatsContext} that correctly represents the client statistics.
     */
    @Override
    public ClientStatsContext createStatsContext() {
        return this.NativeConnection.getClientStatsContext();
    }

    // Save statistics to a file
    @Override
    public void saveStatistics(ClientStats stats, String file) throws IOException
    {
        this.NativeConnection.saveStatistics(stats, file);
    }

    public void setSchema(String schema) throws SQLException {
        throw SQLError.noSupport();
    }

    public String getSchema() throws SQLException {
        throw SQLError.noSupport();
    }

    public void abort(Executor executor) throws SQLException {
        throw SQLError.noSupport();
    }

    public void setNetworkTimeout(Executor executor, int milliseconds)
            throws SQLException {
        throw SQLError.noSupport();
    }

    public int getNetworkTimeout() throws SQLException {
        throw SQLError.noSupport();
    }

    @Override
    public void writeSummaryCSV(ClientStats stats, String path)
            throws IOException {
        this.NativeConnection.writeSummaryCSV(stats, path);

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy