]> source.dussan.org Git - iciql.git/commitdiff
Launch H2 and HSQL servers in test suite and include tcp benchmarks.
authorJames Moger <james.moger@gmail.com>
Wed, 17 Aug 2011 20:26:14 +0000 (16:26 -0400)
committerJames Moger <james.moger@gmail.com>
Wed, 17 Aug 2011 20:26:14 +0000 (16:26 -0400)
docs/03_performance.mkd
src/com/iciql/Iciql.java
src/com/iciql/SQLDialect.java
src/com/iciql/SQLDialectDefault.java
src/com/iciql/SQLDialectDerby.java
src/com/iciql/SQLDialectH2.java
src/com/iciql/SQLDialectHSQL.java
src/com/iciql/SQLDialectMySQL.java
src/com/iciql/SQLDialectPostgreSQL.java
tests/com/iciql/test/IciqlSuite.java
tests/com/iciql/test/UUIDTest.java

index 12c07a117789670ffffc53aef7c9de4bbe6d3746..377d222c8cfead3fdbde346ce5d4e7db3fa44db2 100644 (file)
@@ -9,7 +9,7 @@ Performance of iciql statement generation is not currently benchmarked.
 \r
 ### iciql+database performance comparison\r
 \r
-The following data was generated by running the *single-threaded* iciql test suite.  All database connections are pooled and re-used within each execution of the test suite using [Apache Commons DBCP](http://commons.apache.org/dbcp).\r
+The following data was generated by running the *single-threaded* iciql test suite.  All database connections are pooled and re-used within each execution of the test suite using [Apache Commons DBCP](http://commons.apache.org/dbcp).  All tables are created as CACHED when the database distinguishes between CACHED and MEMORY tables.\r
 \r
 Connections are pooled to normalize embedded database performance with out-of-process database performance.  Some of the Java embedded database configurations have a very high startup-time penalty.  Notably, H2 is slow to open a database and its performance is substantially affected if connection pooling is not enabled to keep the embedded database open.\r
 \r
index 7a0b58f2ca6cb7f05fa17d1dfb09900704f1e90f..9ca8bf7580ee6c02c5879c40b48d3c10a031ff55 100644 (file)
@@ -353,7 +353,7 @@ public interface Iciql {
                /**\r
                 * If true, this table is created as a memory table where data is\r
                 * persistent, but index data is kept in main memory. Valid only for H2\r
-                * databases. Default: false.\r
+                * and HSQL databases. Default: false.\r
                 */\r
                boolean memoryTable() default false;\r
        }\r
index 6e6be25c4dcce2e52018fef79ad01a0785336725..7c29d6172c35e07cd1c7ea4ab29b29c4cd278a39 100644 (file)
@@ -117,27 +117,6 @@ public interface SQLDialect {
         */
        void appendLimitOffset(SQLStatement stat, long limit, long offset);
 
-       /**
-        * Whether memory tables are supported.
-        * 
-        * @return true if they are
-        */
-       boolean supportsMemoryTables();
-
-       /**
-        * Whether IF NOT EXISTS notation is supported.
-        * 
-        * @return true if they are
-        */
-       boolean supportsIfNotExists();
-
-       /**
-        * Whether LIMIT/OFFSET notation is supported.
-        * 
-        * @return true if they are
-        */
-       boolean supportsLimitOffset();
-
        /**
         * Returns the preferred DATETIME class for the database.
         * <p>
index 4814fdd561338db42e39e252be612730f15dcc6a..58848c1f33438cf853b382be201283d2e87fcc4e 100644 (file)
@@ -68,21 +68,6 @@ public class SQLDialectDefault implements SQLDialect {
                return java.util.Date.class;\r
        }\r
 \r
-       @Override\r
-       public boolean supportsMemoryTables() {\r
-               return false;\r
-       }\r
-\r
-       @Override\r
-       public boolean supportsIfNotExists() {\r
-               return true;\r
-       }\r
-\r
-       @Override\r
-       public boolean supportsLimitOffset() {\r
-               return true;\r
-       }\r
-\r
        @Override\r
        public String prepareTableName(String schemaName, String tableName) {\r
                if (StringUtils.isNullOrEmpty(schemaName)) {\r
@@ -104,19 +89,15 @@ public class SQLDialectDefault implements SQLDialect {
                return;\r
        }\r
 \r
+       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+               return "CREATE TABLE";\r
+       }\r
+\r
        @Override\r
        public <T> void prepareCreateTable(SQLStatement stat, TableDefinition<T> def) {\r
-               StatementBuilder buff;\r
-               if (def.memoryTable && supportsMemoryTables()) {\r
-                       buff = new StatementBuilder("CREATE MEMORY TABLE ");\r
-               } else {\r
-                       buff = new StatementBuilder("CREATE TABLE ");\r
-               }\r
-\r
-               if (supportsIfNotExists()) {\r
-                       buff.append("IF NOT EXISTS ");\r
-               }\r
-\r
+               StatementBuilder buff = new StatementBuilder();\r
+               buff.append(prepareCreateTable(def));\r
+               buff.append(" ");\r
                buff.append(prepareTableName(def.schemaName, def.tableName)).append('(');\r
 \r
                boolean hasIdentityColumn = false;\r
index fd06844c58302275a58e5d6148ae51fca65be649..f954a7c85c81da4783dc8ce5b49b45b663e85f4b 100644 (file)
@@ -37,29 +37,16 @@ public class SQLDialectDerby extends SQLDialectDefault {
                return sqlType;\r
        }\r
 \r
-       @Override\r
-       public boolean supportsMemoryTables() {\r
-               return false;\r
-       }\r
-\r
-       @Override\r
-       public boolean supportsIfNotExists() {\r
-               return false;\r
-       }\r
-\r
-       @Override\r
-       public boolean supportsLimitOffset() {\r
-               // FETCH/OFFSET added in 10.5\r
-               return databaseVersion >= 10.5f;\r
-       }\r
-\r
        @Override\r
        public void appendLimitOffset(SQLStatement stat, long limit, long offset) {\r
-               if (offset > 0) {\r
-                       stat.appendSQL(" OFFSET " + offset + (offset == 1 ? " ROW" : " ROWS"));\r
-               }\r
-               if (limit > 0) {\r
-                       stat.appendSQL(" FETCH NEXT " + limit + (limit == 1 ? " ROW" : " ROWS") + " ONLY");\r
+               // FETCH/OFFSET added in 10.5\r
+               if (databaseVersion >= 10.5f) {\r
+                       if (offset > 0) {\r
+                               stat.appendSQL(" OFFSET " + offset + (offset == 1 ? " ROW" : " ROWS"));\r
+                       }\r
+                       if (limit > 0) {\r
+                               stat.appendSQL(" FETCH NEXT " + limit + (limit == 1 ? " ROW" : " ROWS") + " ONLY");\r
+                       }\r
                }\r
        }\r
 \r
index 6f74b458680e383d8509bee2339482c0edc9c97e..1da45f63e1318b7327a8aa52ab43968a167d85d4 100644 (file)
@@ -25,25 +25,33 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectH2 extends SQLDialectDefault {\r
 \r
+       /**\r
+        * CACHED tables are created by default. MEMORY tables are created upon\r
+        * request.\r
+        */\r
        @Override\r
-       public boolean supportsMemoryTables() {\r
-               return true;\r
+       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+               if (def.memoryTable) {\r
+                       return "CREATE MEMORY TABLE IF NOT EXISTS";\r
+               } else {\r
+                       return "CREATE CACHED TABLE IF NOT EXISTS";\r
+               }\r
        }\r
 \r
        @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,\r
-                       boolean isPrimaryKey) {\r
+       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
                String convertedType = convertSqlType(dataType);\r
                boolean isIdentity = false;\r
                if (isIntegerType(dataType)) {\r
                        if (isAutoIncrement && isPrimaryKey) {\r
                                buff.append("IDENTITY");\r
-                               isIdentity =  true;\r
+                               isIdentity = true;\r
                        } else if (isAutoIncrement) {\r
                                buff.append(convertedType);\r
                                buff.append(" AUTO_INCREMENT");\r
                        } else {\r
-                               buff.append(convertedType);     \r
+                               buff.append(convertedType);\r
                        }\r
                } else {\r
                        buff.append(convertedType);\r
index 3d72ac2fc7fdfcab5ee0ab564ec36f539114e179..9975be64b66e9221bbd0cef44bf6424d09669b32 100644 (file)
@@ -26,14 +26,22 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectHSQL extends SQLDialectDefault {\r
 \r
+       /**\r
+        * CACHED tables are created by default. MEMORY tables are created upon\r
+        * request.\r
+        */\r
        @Override\r
-       public boolean supportsMemoryTables() {\r
-               return true;\r
+       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+               if (def.memoryTable) {\r
+                       return "CREATE MEMORY TABLE IF NOT EXISTS";\r
+               } else {\r
+                       return "CREATE CACHED TABLE IF NOT EXISTS";\r
+               }\r
        }\r
 \r
        @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,\r
-                       boolean isPrimaryKey) {\r
+       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
                boolean isIdentity = false;\r
                String convertedType = convertSqlType(dataType);\r
                buff.append(convertedType);\r
index 0b2acf4cb5e9762633c5e8f1fff1fe5f67717863..7fa1fa9fac0dbba3c3bebb1c8f23d088bab2088a 100644 (file)
@@ -32,6 +32,10 @@ public class SQLDialectMySQL extends SQLDialectDefault {
                return sqlType;\r
        }\r
 \r
+       @Override\r
+       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+               return "CREATE TABLE IF NOT EXISTS";\r
+       }\r
        @Override\r
        public String prepareColumnName(String name) {\r
                return "`" + name + "`";\r
index 0874a4946716c15cfdfad85691db4184dbb23ff9..5b3ec71a8de2449fcaf3158c37019f45345e3f6a 100644 (file)
@@ -29,11 +29,6 @@ public class SQLDialectPostgreSQL extends SQLDialectDefault {
                return java.sql.Timestamp.class;\r
        }\r
 \r
-       @Override\r
-       public boolean supportsIfNotExists() {\r
-               return false;\r
-       }\r
-\r
        @Override\r
        public String convertSqlType(String sqlType) {\r
                if ("DOUBLE".equals(sqlType)) {\r
index d68e146f889660f9fe93b23b05002cb2c3a83593..88b8f339886dde676e93d842f8227f1549c19155 100644 (file)
@@ -32,6 +32,7 @@ import org.apache.commons.dbcp.DriverManagerConnectionFactory;
 import org.apache.commons.dbcp.PoolableConnectionFactory;\r
 import org.apache.commons.dbcp.PoolingDataSource;\r
 import org.apache.commons.pool.impl.GenericObjectPool;\r
+import org.hsqldb.persist.HsqlProperties;\r
 import org.junit.Assert;\r
 import org.junit.runner.JUnitCore;\r
 import org.junit.runner.Result;\r
@@ -89,24 +90,24 @@ public class IciqlSuite {
        private static final TestDb[] TEST_DBS = {\r
                        new TestDb("H2", true, true, "jdbc:h2:mem:iciql"),\r
                        new TestDb("H2", true, false, "jdbc:h2:file:testdbs/h2/iciql"),\r
+                       new TestDb("H2", false, false, "jdbc:h2:tcp://localhost/"\r
+                                       + new File(System.getProperty("user.dir")).getAbsolutePath() + "/testdbs/h2tcp/iciql"),\r
                        new TestDb("HSQL", true, true, "jdbc:hsqldb:mem:iciql"),\r
                        new TestDb("HSQL", true, false, "jdbc:hsqldb:file:testdbs/hsql/iciql"),\r
+                       new TestDb("HSQL", false, false, "jdbc:hsqldb:hsql://localhost/iciql"),\r
                        new TestDb("Derby", true, true, "jdbc:derby:memory:iciql;create=true"),\r
                        new TestDb("Derby", true, false, "jdbc:derby:directory:testdbs/derby/iciql;create=true"),\r
-                       new TestDb("MySQL", false, false, "jdbc:mysql://localhost:3306/iciql"),\r
-                       new TestDb("PostgreSQL", false, false, "jdbc:postgresql://localhost:5432/iciql") };\r
+                       new TestDb("MySQL", false, false, "jdbc:mysql://localhost:7000/iciql", "sa", "sa"),\r
+                       new TestDb("PostgreSQL", false, false, "jdbc:postgresql://localhost:5432/iciql", "sa", "sa") };\r
 \r
        private static final TestDb DEFAULT_TEST_DB = TEST_DBS[0];\r
 \r
        private static final PrintStream ERR = System.err;\r
 \r
-       private static String username = "sa";\r
-\r
-       private static String password = "sa";\r
-\r
        private static PrintStream out = System.out;\r
 \r
-       private static Map<String, PoolableConnectionFactory> connectionFactories = Utils.newSynchronizedHashMap();\r
+       private static Map<String, PoolableConnectionFactory> connectionFactories = Utils\r
+                       .newSynchronizedHashMap();\r
 \r
        private static Map<String, PoolingDataSource> dataSources = Utils.newSynchronizedHashMap();\r
 \r
@@ -134,15 +135,15 @@ public class IciqlSuite {
         * @return a fresh Db object\r
         */\r
        public static Db openNewDb() {\r
-               String testUrl = System.getProperty("iciql.url");\r
-               if (testUrl == null) {\r
-                       testUrl = DEFAULT_TEST_DB.url;\r
-               }\r
+               String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);\r
+               String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);\r
+               String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);\r
+\r
                Db db = null;\r
                PoolingDataSource dataSource = dataSources.get(testUrl);\r
                if (dataSource == null) {\r
-                       ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(testUrl, username,\r
-                                       password);\r
+                       ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(testUrl, testUser,\r
+                                       testPassword);\r
                        GenericObjectPool pool = new GenericObjectPool();\r
                        pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);\r
                        PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, pool, null,\r
@@ -178,11 +179,10 @@ public class IciqlSuite {
         * @return the current database\r
         */\r
        public static Db openCurrentDb() {\r
-               String testUrl = System.getProperty("iciql.url");\r
-               if (testUrl == null) {\r
-                       testUrl = DEFAULT_TEST_DB.url;\r
-               }\r
-               return Db.open(testUrl, username, password);\r
+               String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);\r
+               String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);\r
+               String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);\r
+               return Db.open(testUrl, testUser, testPassword);\r
        }\r
 \r
        /**\r
@@ -239,7 +239,7 @@ public class IciqlSuite {
        public static String getDefaultSchema(Db db) {\r
                if (isDerby(db)) {\r
                        // Derby sets default schema name to username\r
-                       return username.toUpperCase();\r
+                       return "SA";\r
                } else if (isMySQL(db)) {\r
                        // MySQL does not have schemas\r
                        return null;\r
@@ -272,6 +272,10 @@ public class IciqlSuite {
 \r
                deleteRecursively(new File("testdbs"));\r
 \r
+               // Start the HSQL and H2 servers in-process\r
+               org.hsqldb.Server hsql = startHSQL();\r
+               org.h2.tools.Server h2 = startH2();\r
+\r
                // Statement logging\r
                final FileWriter statementWriter;\r
                if (StringUtils.isNullOrEmpty(params.sqlStatementsFile)) {\r
@@ -342,9 +346,15 @@ public class IciqlSuite {
                                out.println("Skipping.  Could not find " + testDb.url);\r
                                out.println();\r
                        } else {\r
-                               // Test database\r
+                               // Setup system properties\r
                                System.setProperty("iciql.url", testDb.url);\r
+                               System.setProperty("iciql.user", testDb.username);\r
+                               System.setProperty("iciql.password", testDb.password);\r
+\r
+                               // Test database\r
                                Result result = JUnitCore.runClasses(suiteClasses.value());\r
+\r
+                               // Report results\r
                                testDb.runtime = result.getRunTime();\r
                                if (testDb.runtime < quickestDatabase) {\r
                                        quickestDatabase = testDb.runtime;\r
@@ -410,6 +420,8 @@ public class IciqlSuite {
                if (statementWriter != null) {\r
                        statementWriter.close();\r
                }\r
+               hsql.stop();\r
+               h2.stop();\r
                System.exit(0);\r
        }\r
 \r
@@ -456,6 +468,40 @@ public class IciqlSuite {
                f.delete();\r
        }\r
 \r
+       /**\r
+        * Start an HSQL tcp server.\r
+        * \r
+        * @return an HSQL server instance\r
+        * @throws Exception\r
+        */\r
+       private static org.hsqldb.Server startHSQL() throws Exception {\r
+               HsqlProperties p = new HsqlProperties();\r
+               String db = new File(System.getProperty("user.dir")).getAbsolutePath() + "/testdbs/hsqltcp/iciql";\r
+               p.setProperty("server.database.0", "file:" + db);\r
+               p.setProperty("server.dbname.0", "iciql");\r
+               // set up the rest of properties\r
+\r
+               // alternative to the above is\r
+               org.hsqldb.Server server = new org.hsqldb.Server();             \r
+               server.setProperties(p);\r
+               server.setLogWriter(null);\r
+               server.setErrWriter(null);\r
+               server.start();\r
+               return server;\r
+       }\r
+\r
+       /**\r
+        * Start the H2 tcp server.\r
+        * \r
+        * @return an H2 server instance\r
+        * @throws Exception\r
+        */\r
+       private static org.h2.tools.Server startH2() throws Exception {\r
+               org.h2.tools.Server server = org.h2.tools.Server.createTcpServer();\r
+               server.start();\r
+               return server;\r
+       }\r
+\r
        /**\r
         * Represents a test database url.\r
         */\r
@@ -464,15 +510,23 @@ public class IciqlSuite {
                boolean isEmbedded;\r
                boolean isMemory;\r
                final String url;\r
+               final String username;\r
+               final String password;\r
                String version;\r
                long runtime;\r
                long statements;\r
 \r
                TestDb(String name, boolean isEmbedded, boolean isMemory, String url) {\r
+                       this(name, isEmbedded, isMemory, url, "sa", "");\r
+               }\r
+\r
+               TestDb(String name, boolean isEmbedded, boolean isMemory, String url, String username, String password) {\r
                        this.name = name;\r
                        this.isEmbedded = isEmbedded;\r
                        this.isMemory = isMemory;\r
                        this.url = url;\r
+                       this.username = username;\r
+                       this.password = password;\r
                }\r
 \r
                double getRuntime() {\r
index 9b88cb806f2df4fbf6f358359437734ddb162d8c..bb09c9fc1d9a551aee327ae067f1a5a2035d6da0 100644 (file)
@@ -69,6 +69,7 @@ public class UUIDTest {
 
                UUIDRecord second = db.from(u).where(u.uuid).is(originals.get(1).uuid).selectFirst();
                assertTrue(originals.get(1).equivalentTo(second));
+               db.dropTable(UUIDRecord.class);
        }
 
        /**