db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r616373 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/stmtcache/ testing/org/apache/derbyTesting/unitTests/junit/
Date Tue, 29 Jan 2008 15:13:09 GMT
Author: kristwaa
Date: Tue Jan 29 07:13:07 2008
New Revision: 616373

URL: http://svn.apache.org/viewvc?rev=616373&view=rev
Log:
DERBY-3324: JDBC statement cache implementation. This is the core cache functionality for
the JDBC statement cache feature. Nothing is enabled or used yet. Also note that the tests
are not enabled.
Patch file: derby-3324-1e-jdbc_statementcache.diff 

Added:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/
    db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java
  (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java
  (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java
  (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java
  (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java
  (with props)

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java?rev=616373&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java
(added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java
Tue Jan 29 07:13:07 2008
@@ -0,0 +1,166 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.stmtcache.JDBCStatementCache
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.derby.client.am.stmtcache;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * A cache for JDBC statement objects.
+ * <p>
+ * The entries in the cache contains objects implementing the
+ * <code>java.sql.PreparedStatement</code> interface, and they are inserted with
+ * a key object implementing the interface <code>StatementKey</code>. The cached
+ * objects can be either <code>java.sql.PreparedStatement</code> or
+ * <code>java.sql.CallableStatement</code>. These two should be separated by
+ * using different types of keys.
+ * <p>
+ * The cache only contains free statement objects, and on a successful request
+ * for a cached statement the statement is removed from the cache. The cache is
+ * not intended to hold duplicate statements. The physical prepared statement
+ * should be (re-)inserted into the cache when <code>close</code> is called on
+ * the logical prepared statement using it.
+ * <p>
+ * There is a maximum number of cached statements associated with the cache.
+ * If this number is exceeded, the oldest entry will be thrown out. One can
+ * always throw out an entry, because the fact that it is in the cache means it
+ * is free and not in use.
+ */
+//@ThreadSafe
+public final class JDBCStatementCache {
+
+    /** Structure holding the cached prepared statement objects. */
+    //@GuardedBy("this");
+    private final LinkedHashMap statements;
+
+    /**
+     * Creates a new, empty JDBC statement cache.
+     * 
+     * @param maxSize maximum number of statements in the cache
+     * 
+     * @throws IllegalArgumentException if <code>maxSize</code> is less than
one
+     */
+    public JDBCStatementCache(int maxSize) {
+        if (maxSize < 1) {
+            throw new IllegalArgumentException("maxSize must be positive: " +
+                    maxSize);
+        }
+        this.statements = new BoundedLinkedHashMap(maxSize);
+    }
+
+    /**
+     * Retrieves a cached prepared statement if one exists.
+     * 
+     * @param statementKey key for the prepared statement to look up
+     * @return A cached statement if one exists, <code>null</code> otherwise.
+     */
+    public synchronized PreparedStatement getCached(StatementKey statementKey) {
+        if (SanityManager.DEBUG) {
+            // Getting a null here indicates a programming error, but does not
+            // cause Derby to fail.
+            SanityManager.ASSERT(statementKey != null,
+                                 "statementKey is not supposed to be null");
+        }
+        return (PreparedStatement)this.statements.remove(statementKey);
+    }
+
+    /**
+     * Cache the prepared statement if it does not already exist.
+     * 
+     * @param statementKey key to insert prepared statement with
+     * @param ps prepared statement to cache
+     * @return <code>true</code> if added to the cache, <code>false</code>
if
+     *      not.
+     */
+    public synchronized boolean cacheStatement(
+                                        StatementKey statementKey,
+                                        PreparedStatement ps) {
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(statementKey != null,
+                                 "statementKey is not supposed to be null");
+            SanityManager.ASSERT(ps != null,
+                                 "ps is not supposed to be null");
+        }
+        final boolean alreadyCached = this.statements.containsKey(statementKey);
+        if (!alreadyCached) {
+            statements.put(statementKey, ps);
+        }
+        return !alreadyCached;
+    }
+
+    /**
+     * A {@link LinkedHashMap} with an upper bound on the number of entries.
+     * <p>
+     * If the maximum size is exceeded, the oldest entry is automatically
+     * removed after the new entry has been inserted.
+     */
+    //@NotThreadSafe
+    private static class BoundedLinkedHashMap extends LinkedHashMap {
+
+        /** Maximum number of entries. */
+        private final int maxSize;
+
+        /**
+         * Creates a bounded {@link LinkedHashMap} with the specified maximum
+         * size.
+         * <p>
+         * Iteration is by insertion-order.
+         * 
+         * @param maxCapacity maximum size of the map
+         */
+        public BoundedLinkedHashMap(int maxCapacity) {
+            super();
+            this.maxSize = maxCapacity;
+        }
+
+        /**
+         * Tells if an entry should be removed from the map.
+         * <p>
+         * If the cache has exceeded its maximum size, the oldest element will
+         * be marked for removal. The oldest element will be removed after the
+         * new element has been inserted.
+         * 
+         * @param eldest the element picked out for removal
+         * @return <code>true</code> if the element is to be removed,
+         *      <code>false</code> if not.
+         */
+        protected boolean removeEldestEntry(Map.Entry eldest) {
+            final boolean remove = size() > maxSize;
+            if (remove) {
+                try {
+                    ((PreparedStatement)eldest.getValue()).close();
+                } catch (SQLException ex) {
+                    // Ignore this exception in insane mode, throw an assertion
+                    // error if a sane build is run.
+                    if (SanityManager.DEBUG) {
+                        SanityManager.THROWASSERT("Failed to close prepared " +
+                                "statement marked for cache removal", ex);
+                    }
+                }
+            }
+            return remove;
+        }
+    } // End inner class BoundedLinkedHashMap
+} // End JDBCStatementCache

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/JDBCStatementCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java?rev=616373&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java
(added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java
Tue Jan 29 07:13:07 2008
@@ -0,0 +1,134 @@
+/*
+ 
+   Derby - Class org.apache.derby.client.am.stmtcache.StatementKey
+ 
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.derby.client.am.stmtcache;
+
+/**
+ * A key representing a <code>java.sql.PreparedStatement</code> or a
+ * <code>java.sql.CallableStatement</code>.
+ * <p>
+ * The key takes a number of statement related attributes into account, and is
+ * used to insert and look up cached statement objects in the JDBC statement
+ * cache.
+ * <p>
+ * Key instances are created by a statement key factory.
+ * 
+ * @see StatementKeyFactory
+ */
+//@Immutable
+public class StatementKey {
+
+    /** Tells if the key represents a <code>CallableStatement</code>. */
+    private final boolean isCallableStatement;
+    /** The SQL query of the statement. */
+    private final String sql;
+    /** The compilation schema for the statement. */
+    private final String schema;
+    /** The result set type for the statement. */
+    private final int type;
+    /** The result set concurrency for the statement. */
+    private final int concurrency;
+    /** Result set holdability for the statement. */
+    private final int holdability;
+    /** Tells if the associated statement returns auto-generated keys. */
+    private final int autogeneratedKeys;
+
+    /**
+     * Creates a statement key with all the common properties.
+     * 
+     * @param isCallableStatement <code>true</code> is this is a key for a
+     *      <code>java.sql.CallableStatement</code>
+     * @param sql SQL query string
+     * @param schema compilation schema
+     * @param rsType result set type
+     * @param rsConcurrency result set concurrency
+     * @param rsHoldability result set holdability
+     * @param autogeneratedKeys if auto-generated keys are returned
+     * 
+     * @throws IllegalArgumentException if <code>sql</code> and/or
+     *      <code>schema</code> is <code>null</code>
+     */
+    StatementKey(boolean isCallableStatement, String sql, String schema,
+            int rsType, int rsConcurrency, int rsHoldability,
+            int autogeneratedKeys) {
+        if (sql == null || schema == null) {
+            // Not localized (yet), because this should never reach the user.
+            throw new IllegalArgumentException(
+                    "sql and/or schema is <null>: sql=" + (sql == null) +
+                    ", schema=" + (schema == null));
+        }
+        this.isCallableStatement = isCallableStatement;
+        this.sql = sql;
+        this.schema = schema;
+        this.type = rsType;
+        this.concurrency = rsConcurrency;
+        this.holdability = rsHoldability;
+        this.autogeneratedKeys = autogeneratedKeys;
+    }
+
+    public boolean equals(Object obj) {
+        if (!(obj instanceof StatementKey)) {
+            return false;
+        }
+        final StatementKey other = (StatementKey)obj;
+        if (this.holdability != other.holdability) {
+            return false;
+        }
+        if (this.autogeneratedKeys != other.autogeneratedKeys) {
+            return false;
+        }
+        if (this.isCallableStatement != other.isCallableStatement) {
+            return false;
+        }
+        if (!this.schema.equals(other.schema)) {
+            return false;
+        }
+        if (!this.sql.equals(other.sql)) {
+            return false;
+        }
+        if (this.type != other.type) {
+            return false;
+        }
+        if (this.concurrency != other.concurrency) {
+            return false;
+        }
+        return true;
+    }
+
+    public int hashCode() {
+        int hash = 7;
+        hash = 47 * hash + (this.isCallableStatement ? 1 : 0);
+        hash = 47 * hash + this.sql.hashCode();
+        hash = 47 * hash + this.schema.hashCode();
+        hash = 47 * hash + this.type;
+        hash = 47 * hash + this.concurrency;
+        hash = 47 * hash + this.holdability;
+        hash = 47 * hash + this.autogeneratedKeys;
+        return hash;
+    }
+
+    public String toString() {
+        return "'" + sql + "' in '" + schema + "', rsh = " + holdability +
+                ", rst = " + type + ", rsc = " + concurrency +
+                ", autogenKeys = " + autogeneratedKeys +
+                ", isCallableStatement = " + isCallableStatement;
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKey.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java?rev=616373&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java
(added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java
Tue Jan 29 07:13:07 2008
@@ -0,0 +1,140 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.stmtcache.StatementKeyFactory
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.derby.client.am.stmtcache;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+/**
+ * A factory for creating JDBC statement keys for use with the JDBC statement
+ * cache.
+ * 
+ * @see JDBCStatementCache
+ */
+//@ThreadSafe
+public final class StatementKeyFactory {
+    
+    private static final boolean CALLABLE = true;
+    private static final boolean PREPARED = false;
+
+    /** Instantiation not allowed. */
+    private StatementKeyFactory() {};
+
+    /**
+     * Creates a key for a query with default settings.
+     * <p>
+     * Defaults are according to the JDBC standard; result set type will be
+     * <code>ResultSet.TYPE_FORWARD_ONLY</code>, concurrency will be
+     * <code>ResultSet.CONCUR_READ_ONLY</code> and the statement will not
+     * return auto-generated keys.
+     * 
+     * @param sql SQL query string
+     * @param schema current compilation schema
+     * @param holdability result set holdability
+     * @return A statement key.
+     */
+    public static StatementKey newPrepared(
+            String sql, String schema, int holdability) {
+        return new StatementKey(PREPARED, sql, schema,
+                ResultSet.TYPE_FORWARD_ONLY,
+                ResultSet.CONCUR_READ_ONLY,
+                holdability, Statement.NO_GENERATED_KEYS);
+    }
+
+    /**
+     * Creates a key for a query specifying whether auto-generated keys
+     * shall be returned.
+     * <p>
+     * Unspecified settings will be according to the JDBC standard; result set
+     * type will be <code>ResultSet.TYPE_FORWARD_ONLY</code>, concurrency will
+     * be <code>ResultSet.CONCUR_READ_ONLY</code>.
+     * 
+     * @param sql SQL query string
+     * @param schema current compilation schema
+     * @param holdability result set holdability
+     * @param autogeneratedKeys tells whether or not to reutrn auto-generated
+     *      keys
+     * @return A statement key.
+     */
+    public static StatementKey newPrepared(
+            String sql, String schema, int holdability, int autogeneratedKeys) {
+        return new StatementKey(PREPARED, sql, schema,
+                                ResultSet.TYPE_FORWARD_ONLY,
+                                ResultSet.CONCUR_READ_ONLY,
+                                holdability, autogeneratedKeys);
+    }
+
+    /**
+     * Creates a key for a query specifying result set type and concurrency.
+     * <p>
+     * The returned key is for a statement not returning auto-generated keys.
+     * 
+     * @param sql SQL query string
+     * @param schema current compilation schema
+     * @param holdability result set holdability
+     * @param rst result set type
+     * @param rsc result set concurrency level
+     * @return A statement key.
+     */
+    public static StatementKey newPrepared(
+            String sql, String schema, int holdability, int rst, int rsc) {
+        return new StatementKey(PREPARED, sql, schema, rst, rsc, holdability,
+                                Statement.NO_GENERATED_KEYS);
+    }
+
+    /**
+     * Creates a key for a callable statement.
+     * <p>
+     * Unspecified settings will be according to the JDBC standard; result set
+     * type will be <code>ResultSet.TYPE_FORWARD_ONLY</code>, concurrency will
+     * be <code>ResultSet.CONCUR_READ_ONLY</code>.
+     * 
+     * @param sql SQL query string
+     * @param schema current compilation schema
+     * @param holdability result set holdability
+     * @return A statement key.
+     */
+    public static StatementKey newCallable(
+            String sql, String schema, int holdability) {
+        return newCallable(sql, schema, holdability,
+                ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+    }
+
+    /**
+     * Creates a key for a callable statement specifying result set type and
+     * concurrency.
+     * <p>
+     * The returned key is for a statement not returning auto-generated keys.
+     * 
+     * @param sql SQL query string
+     * @param schema current compilation schema
+     * @param holdability result set holdability
+     * @param rst result set type
+     * @param rsc result set concurrency level
+     * @return A statement key.
+     */
+    public static StatementKey newCallable(
+            String sql, String schema, int holdability, int rst, int rsc) {
+        return new StatementKey(CALLABLE, sql, schema, rst, rsc, holdability,
+                                Statement.NO_GENERATED_KEYS);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/stmtcache/StatementKeyFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java?rev=616373&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java
Tue Jan 29 07:13:07 2008
@@ -0,0 +1,142 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.junit.JDBCStatementCacheTest
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.derbyTesting.unitTests.junit;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import junit.framework.Test;
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+import org.apache.derby.client.am.stmtcache.StatementKeyFactory;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Tests basic operation of the JDBC prepared statement object cache and the
+ * keys used to operate on it.
+ */
+public class JDBCStatementCacheTest
+        extends BaseJDBCTestCase {
+
+    public JDBCStatementCacheTest(String name) {
+        super(name);
+    }
+
+    /**
+     * Make sure a negative or zero max size is not allowed, as this will in
+     * effect be no caching but with an overhead.
+     * <p>
+     * The overhead would come from always throwing out the newly inserted
+     * element.
+     */
+    public void testCreateCacheWithZeroOrNegativeMaxSize() {
+        try {
+            new JDBCStatementCache(-10);
+            fail("Negative max size should not be allowed");
+        } catch (IllegalArgumentException iae) {
+            // As expected
+        }
+        try {
+            new JDBCStatementCache(0);
+            fail("Zero max size should not be allowed");
+        } catch (IllegalArgumentException iae) {
+            // As expected
+        }
+    }
+
+    /**
+     * Test basic insertion into the cache.
+     * 
+     * @throws SQLException if obtaining a PreparedStatement fails
+     */
+    public void testBasicInsertion()
+            throws SQLException {
+        String sql = "values 1";
+        JDBCStatementCache cache = new JDBCStatementCache(10);
+        PreparedStatement ps = prepareStatement(sql);
+        StatementKey key = StatementKeyFactory.newPrepared(sql, "app", 1);
+        assertTrue(cache.cacheStatement(key, ps));
+        assertEquals(ps, cache.getCached(key));
+    }
+
+    /**
+     * Test insertion of a duplicate key.
+     * 
+     * @throws SQLException if obtaining a PreparedStatement fails
+     */
+    public void testBasicDuplicateKeyInsertion()
+            throws SQLException {
+        String sql = "values 1";
+        JDBCStatementCache cache = new JDBCStatementCache(10);
+        PreparedStatement ps = prepareStatement(sql);
+        StatementKey key = StatementKeyFactory.newPrepared(sql, "app", 1);
+        assertTrue(cache.cacheStatement(key, ps));
+        // Duplicates shall not be inserted.
+        assertFalse(cache.cacheStatement(key, ps));
+        assertEquals(ps, cache.getCached(key));
+    }
+
+    /**
+     * Make sure requesting a cached callable statement does not return a
+     * <code>PreparedStatement</code> object.
+     * 
+     * @throws SQLException if creating database resources fail
+     */
+    public void testBasicCallableVsPrepared()
+            throws SQLException {
+        String sql = "values 7";
+        String schema = "MYAPP";
+        int rsh = 1;
+        JDBCStatementCache cache = new JDBCStatementCache(10);
+        PreparedStatement ps = prepareStatement(sql);
+        StatementKey key = StatementKeyFactory.newPrepared(sql, schema, rsh);
+        assertTrue(cache.cacheStatement(key, ps));
+        StatementKey callKey =
+                StatementKeyFactory.newCallable(sql, schema, rsh);
+        assertNotSame(ps, cache.getCached(callKey));
+        CallableStatement cs = prepareCall(sql);
+        // No entry should exists yet.
+        assertNull(cache.getCached(callKey));
+        // New callable statements should be inserted.
+        assertTrue(cache.cacheStatement(callKey, cs));
+        // Make sure we get the same object back.
+        assertSame(cs, cache.getCached(callKey));
+        // Make sure we don't get a callable when we ask for a prepared.
+        assertNotSame(cs, cache.getCached(key));
+    }
+
+    /**
+     * Returns the appropriate tests.
+     * <p>
+     * Run only client/server, because the code being tested does not live
+     * in the embedded driver (yet).
+     * 
+     * @return A suite of tests (may be empty).
+     */
+    public static Test suite() {
+        // Run only client/server, because the code being tested does not live
+        // in the embedded driver (yet).
+        return TestConfiguration.clientServerSuite(
+                JDBCStatementCacheTest.class);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/JDBCStatementCacheTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java?rev=616373&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java
(added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java
Tue Jan 29 07:13:07 2008
@@ -0,0 +1,176 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.junit.StatementKeyFactoryTest
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.apache.derbyTesting.unitTests.junit;
+
+import java.sql.ResultSet;
+import java.sql.Statement;
+import junit.framework.Test;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+import org.apache.derby.client.am.stmtcache.StatementKeyFactory;
+import org.apache.derbyTesting.junit.BaseTestCase;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test that statement key equality is correct, and that the factory produces
+ * correct keys.
+ * <p>
+ * Objects implementing {@link StatementKey} is crucial for correct
+ * operation of the JDBC statement object cache.
+ * 
+ * @see org.apache.derby.client.am.stmtcache.JDBCStatementCache
+ */
+public class StatementKeyFactoryTest
+        extends BaseTestCase {
+
+    public StatementKeyFactoryTest(String name) {
+        super(name);
+    }
+
+    /**
+     * Creating keys with <code>null</code> for required information should
+     * fail, as it can lead to NPEs in the key implementations and/or the wrong
+     * statement to be fetched from the cache.
+     */
+    public void testCreationBasicWithNulls() {
+        try {
+            StatementKeyFactory.newPrepared(null, null, 0);
+            fail("Creation with <null> should have failed");
+        } catch (IllegalArgumentException iae) {
+            // As expected
+        }
+        try {
+            StatementKeyFactory.newPrepared(null, "app", 0);
+            fail("Creation with <null> should have failed");
+        } catch (IllegalArgumentException iae) {
+            // As expected
+        }
+        try {
+            StatementKeyFactory.newPrepared("values 1", null, 0);
+            fail("Creation with <null> should have failed");
+        } catch (IllegalArgumentException iae) {
+            // As expected
+        }
+    }
+
+    public void testCreationBasic() {
+        StatementKey stdKey = StatementKeyFactory.newPrepared("values 1", "APP", 
+                                            ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        StatementKey key = StatementKeyFactory.newPrepared(
+                "select * from sys.systables", "APP", 
+                                            ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        assertFalse(key.equals(stdKey));
+        assertFalse(stdKey.equals(key));
+    }
+
+    public void testEqualityBasic() {
+        StatementKey key1 = StatementKeyFactory.newPrepared(
+                "select * from sys.systables", "APP", 
+                                            ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        StatementKey key2 = StatementKeyFactory.newPrepared(
+                "select * from sys.systables", "APP", 
+                                            ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        StatementKey key3 = StatementKeyFactory.newPrepared(
+                "select * from sys.systables", "APP", 
+                                            ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        assertTrue(key1.equals(key2));
+        assertTrue(key2.equals(key1));
+        assertTrue(key2.equals(key3));
+        assertTrue(key1.equals(key3));
+    }
+
+    public void testEqualityDefaultNoAutoGenKey() {
+        int holdability = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        StatementKey basicKey = StatementKeyFactory.newPrepared(
+                "values 2", "APP", holdability);
+        StatementKey simplifiedKey = StatementKeyFactory.newPrepared(
+                "values 2", "APP", holdability, Statement.NO_GENERATED_KEYS);
+        assertTrue(basicKey.equals(simplifiedKey));
+        assertTrue(simplifiedKey.equals(basicKey));
+    }
+
+    public void testEqualityNoAutoVsAutoGenKey() {
+        int holdability = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        StatementKey basicKey = StatementKeyFactory.newPrepared(
+                "values 2", "APP", holdability);
+        StatementKey autoKey = StatementKeyFactory.newPrepared(
+                "values 2", "APP", holdability, Statement.RETURN_GENERATED_KEYS);
+        assertFalse(basicKey.equals(autoKey));
+        assertFalse(autoKey.equals(basicKey));
+    }
+
+    public void testUnequalityVarious() {
+        String sql = "select * from sys.systables";
+        String schema = "APP";
+        int rsh = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        int rst = ResultSet.TYPE_SCROLL_INSENSITIVE;
+        int rsc = ResultSet.CONCUR_UPDATABLE;
+        int auto = Statement.RETURN_GENERATED_KEYS;
+        // Create a one key of each type, all different from each other.
+        StatementKey[] keys = new StatementKey[] {
+            StatementKeyFactory.newPrepared(sql, schema, rsh),
+            StatementKeyFactory.newPrepared(sql, schema, rsh, auto),
+            StatementKeyFactory.newPrepared(sql, schema, rsh, rst, rsc),
+            StatementKeyFactory.newCallable(sql, schema, rsh),
+            StatementKeyFactory.newCallable(sql, schema, rsh, rst, rsc)};
+        for (int outer=0; outer < keys.length; outer++) {
+            StatementKey current = keys[outer];
+            for (int inner=0; inner < keys.length; inner++) {
+                if (outer != inner) {
+                    if (current.equals(keys[inner])) {
+                        fail("[" + current.toString() + "] should not equal [" +
+                                keys[inner].toString() + "]");
+                    }
+                } else {
+                    // Should equal itself.
+                    assertTrue(current.equals(keys[inner]));
+                }
+            }
+        }
+    }
+
+    public void testCallableVsPrepared() {
+        String sql = "select colA, colB from mytable";
+        String schema = "SOMEAPP";
+        int holdability = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        StatementKey callable =
+                StatementKeyFactory.newCallable(sql, schema, holdability);
+        StatementKey prepared =
+                StatementKeyFactory.newPrepared(sql, schema, holdability);
+        assertFalse(callable.equals(prepared));
+        assertFalse(prepared.equals(callable));
+    }
+
+    /**
+     * Returns the appropriate tests.
+     * <p>
+     * Run only client/server, because the code being tested does not live
+     * in the embedded driver (yet).
+     * 
+     * @return A suite of tests (may be empty).
+     */
+    public static Test suite() {
+        // Run only client/server, because the code being tested does not live
+        // in the embedded driver (yet).
+        return TestConfiguration.clientServerSuite(
+                StatementKeyFactoryTest.class);
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/junit/StatementKeyFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message