Commits

Grace Batumbya  committed 67037da

Fixes issue #18 Add support for ConnectionPool.

  • Participants
  • Parent commits d131894

Comments (0)

Files changed (6)

 Work in progress:
 
+* Issue #18 - Add support for ConnectionPool
+    * Implemented javax.sql.ConnectionPoolDataSource - javax.SQLiteConnectionPoolDataSource
 * Issue #27 - Allow user to specify busy-timeout when opening a database connection
     * Added support for sqlite3_busy_timeout
         1. Added configuration property "busy_timeout" to SQLiteConfig.
         1. setBinaryStream()
         2. setAsciiStream()
         3. setUnicodeStream()
+* Issue #60 - ExtendedCommand (e.g backup) not supported on Stmt.execute(String)
+* Issue #23 - getDate() returns wrong values
+    * Added support for specifying a date storage class. For more info <https://bitbucket.org/xerial/sqlite-jdbc/issue/23/getdate-returns-wrong-values>
+* Issue #54 - Implement PreparedStatement.setBinaryStream()
+    * Added support for InputStreams on PreparedStatement
+        1. setBinaryStream()
+        2. setAsciiStream()
+        3. setUnicodeStream()
 
 Release 3.7.15-SNAPSHOT-2
 * Fixed clean target to remove previous driver builds

File src/main/java/org/sqlite/SQLiteConnection.java

      * @see <a href="http://www.sqlite.org/c3ref/c_source_id.html">http://www.sqlite.org/c3ref/c_source_id.html</a>
      */
     String libversion() throws SQLException {
+        checkOpen();
+
         return db.libversion();
     }
 
      * @see java.sql.Connection#setTransactionIsolation(int)
      */
     public void setTransactionIsolation(int level) throws SQLException {
+        checkOpen();
+
         switch (level) {
         case TRANSACTION_SERIALIZABLE:
             db.exec("PRAGMA read_uncommitted = false;");
     }
 
     /**
+     * @throws SQLException 
      * @see java.sql.Connection#getMetaData()
      */
-    public DatabaseMetaData getMetaData() {
+    public DatabaseMetaData getMetaData() throws SQLException {
+        checkOpen();
+
         if (meta == null)
             meta = new MetaData(this);
         return meta;
      * @see java.sql.Connection#createStatement(int, int, int)
      */
     public Statement createStatement(int rst, int rsc, int rsh) throws SQLException {
+        checkOpen();
         checkCursor(rst, rsc, rsh);
+
         return new Stmt(this);
     }
 
      * @see java.sql.Connection#prepareStatement(java.lang.String, int, int, int)
      */
     public PreparedStatement prepareStatement(String sql, int rst, int rsc, int rsh) throws SQLException {
+        checkOpen();
         checkCursor(rst, rsc, rsh);
+
         return new PrepStmt(this, sql);
     }
 

File src/main/java/org/sqlite/javax/SQLiteConnectionPoolDataSource.java

+/*--------------------------------------------------------------------------
+ *  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 org.sqlite.javax;
+import java.sql.SQLException;
+import javax.sql.PooledConnection;
+
+import org.sqlite.SQLiteConfig;
+import org.sqlite.SQLiteDataSource;
+
+public class SQLiteConnectionPoolDataSource extends SQLiteDataSource implements javax.sql.ConnectionPoolDataSource {
+
+    /**
+     * Default constructor.
+     */
+    public SQLiteConnectionPoolDataSource () {
+        super();
+    }
+
+    /**
+     * Creates a data source based on the provided configuration.
+     * @param config The configuration for the data source.
+     */
+    public SQLiteConnectionPoolDataSource(SQLiteConfig config) {
+        super(config);
+    }
+
+    /**
+     * @see javax.sql.ConnectionPoolDataSource#getPooledConnection()
+     */
+    public PooledConnection getPooledConnection() throws SQLException {
+        return getPooledConnection(null, null);
+    }
+
+    /**
+     * @see javax.sql.ConnectionPoolDataSource#getPooledConnection(java.lang.String, java.lang.String)
+     */
+    public PooledConnection getPooledConnection(String user, String password) throws SQLException {
+        return new SQLitePooledConnection(getConnection(user, password));
+    }
+}

File src/main/java/org/sqlite/javax/SQLitePooledConnection.java

+/*--------------------------------------------------------------------------
+ *  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 org.sqlite.javax;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.ConnectionEventListener;
+import javax.sql.PooledConnection;
+
+public class SQLitePooledConnection implements PooledConnection {
+
+    protected Connection physicalConn;
+    protected volatile Connection handleConn;
+
+    protected List<ConnectionEventListener> listeners = new ArrayList<ConnectionEventListener>();
+
+    /**
+     * @param physical The physical Connection
+     */
+    protected SQLitePooledConnection(Connection physicalConn) {
+        this.physicalConn = physicalConn;
+    }
+
+    /**
+     * @see javax.sql.PooledConnection#close()
+     */
+    public void close() throws SQLException {
+        if (handleConn != null) {
+            listeners.clear();
+            handleConn.close();
+        }
+
+        if (physicalConn != null) {
+            try {
+                physicalConn.close();
+            } finally {
+                physicalConn = null;
+            }
+        }
+    }
+
+    /**
+     * @see javax.sql.PooledConnection#getConnection()
+     */
+    public Connection getConnection() throws SQLException {
+        if (handleConn != null)
+            handleConn.close();
+
+        handleConn = (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class},
+            new InvocationHandler() {
+                boolean isClosed;
+
+                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                    try {
+                        String name = method.getName();
+                        if ("close".equals(name)) {
+                            ConnectionEvent event = new ConnectionEvent(SQLitePooledConnection.this);
+
+                            for (int i = listeners.size() - 1; i >= 0; i--) {
+                                listeners.get(i).connectionClosed(event);
+                            }
+
+                            if (!physicalConn.getAutoCommit()) {
+                                physicalConn.rollback();
+                            }
+                            physicalConn.setAutoCommit(true);
+                            isClosed = true;
+
+                            return null; // don't close physical connection
+                        }
+                        else if ("isClosed".equals(name)) {
+                            if (!isClosed)
+                                isClosed = ((Boolean)method.invoke(physicalConn, args)).booleanValue();
+
+                            return isClosed;
+                        }
+
+                        if (isClosed) {
+                            throw new SQLException ("Connection is closed");
+                        }
+
+                        return method.invoke(physicalConn, args);
+                    }
+                    catch (SQLException e){
+                        if ("database connection closed".equals(e.getMessage())) {
+                            ConnectionEvent event = new ConnectionEvent(SQLitePooledConnection.this, e);
+
+                            for (int i = listeners.size() - 1; i >= 0; i--) {
+                                listeners.get(i).connectionErrorOccurred(event);
+                            }
+                        }
+
+                        throw e;
+                    }
+                    catch (InvocationTargetException ex) {
+                        throw ex.getCause();
+                    }
+                }
+            });
+
+        return handleConn;
+    }
+
+    /**
+     * @see javax.sql.PooledConnection#addConnectionEventListener(javax.sql.ConnectionEventListener)
+     */
+    public void addConnectionEventListener(ConnectionEventListener listener) {
+        listeners.add(listener);
+    }
+
+    /**
+     * @see javax.sql.PooledConnection#removeConnectionEventListener(javax.sql.ConnectionEventListener)
+     */
+    public void removeConnectionEventListener(ConnectionEventListener listener) {
+        listeners.remove(listener);
+    }
+}

File src/test/java/org/sqlite/AllTests.java

     ReadUncommittedTest.class,
     RSMetaDataTest.class,
     SQLiteDataSourceTest.class,
+    SQLiteConnectionPoolDataSourceTest.class,
     SQLiteJDBCLoaderTest.class,
     StatementTest.class,
     TransactionTest.class,

File src/test/java/org/sqlite/SQLiteConnectionPoolDataSourceTest.java

+/*--------------------------------------------------------------------------
+ *  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 org.sqlite;
+
+import static org.junit.Assert.*;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.sql.ConnectionPoolDataSource;
+import javax.sql.PooledConnection;
+
+import org.junit.Test;
+import org.sqlite.javax.SQLiteConnectionPoolDataSource;
+
+public class SQLiteConnectionPoolDataSourceTest {
+
+    @Test
+    public void connectionTest () throws SQLException {
+        ConnectionPoolDataSource ds = new SQLiteConnectionPoolDataSource();
+
+        PooledConnection pooledConn = ds.getPooledConnection();
+
+        Connection handle = pooledConn.getConnection();
+        assertFalse(handle.isClosed());
+        assertTrue(handle.createStatement().execute("select 1"));
+
+        Connection handle2 = pooledConn.getConnection();
+        assertTrue(handle.isClosed());
+        try {
+            handle.createStatement().execute("select 1");
+            fail();
+        }
+        catch (SQLException e) {
+            assertEquals("Connection is closed", e.getMessage());
+        }
+
+        assertTrue(handle2.createStatement().execute("select 1"));
+        handle2.close();
+
+        handle = pooledConn.getConnection();
+        assertTrue(handle.createStatement().execute("select 1"));
+
+        pooledConn.close();
+        assertTrue(handle.isClosed());
+    }
+}