]> source.dussan.org Git - iciql.git/commitdiff
Add support for SQLite 3.8.7
authorJames Moger <james.moger@gitblit.com>
Mon, 3 Nov 2014 16:05:52 +0000 (11:05 -0500)
committerJames Moger <james.moger@gitblit.com>
Mon, 3 Nov 2014 17:51:16 +0000 (12:51 -0500)
.classpath
README.markdown
build.moxie
src/main/java/com/iciql/Db.java
src/main/java/com/iciql/IciqlException.java
src/main/java/com/iciql/SQLDialectSQLite.java [new file with mode: 0644]
src/site/index.mkd
src/site/jaqu_comparison.mkd
src/test/java/com/iciql/test/IciqlSuite.java
src/test/java/com/iciql/test/UpgradesTest.java

index 7e0f9a74bc6f1e649ba12e8dab4223c8ddd01a08..4431ee53d52be7ab1621b6c81be12c60e34c9d53 100644 (file)
@@ -8,6 +8,7 @@
        <classpathentry kind="lib" path="ext/derby-10.11.1.1.jar" />
        <classpathentry kind="lib" path="ext/mysql-connector-java-5.1.33.jar" />
        <classpathentry kind="lib" path="ext/postgresql-9.3-1102-jdbc4.jar" sourcepath="ext/src/postgresql-9.3-1102-jdbc4.jar" />
+       <classpathentry kind="lib" path="ext/sqlite-jdbc-3.8.7.jar" sourcepath="ext/src/sqlite-jdbc-3.8.7.jar" />
        <classpathentry kind="lib" path="ext/slf4j-api-1.6.1.jar" sourcepath="ext/src/slf4j-api-1.6.1.jar" />
        <classpathentry kind="lib" path="ext/commons-pool-1.5.6.jar" sourcepath="ext/src/commons-pool-1.5.6.jar" />
        <classpathentry kind="lib" path="ext/commons-dbcp-1.4.jar" sourcepath="ext/src/commons-dbcp-1.4.jar" />
index 4c2b2c7721401c3d2a3627b6f5a6b61eb1b805d6..63ec22a77529b15d594397be171a1ce45e8dfea8 100644 (file)
@@ -12,7 +12,7 @@ iciql **is**...
 iciql **is not**...\r
 \r
 - a complete alternative to JDBC\r
-- designed to compete with more powerful database query tools like [jOOQ](http://jooq.sourceforge.net) or [Querydsl](http://source.mysema.com/display/querydsl/Querydsl)\r
+- designed to compete with more powerful database query tools like [jOOQ](http://jooq.sourceforge.net) or [QueryDSL](http://source.mysema.com/display/querydsl/Querydsl)\r
 - designed to compete with enterprise ORM tools like [Hibernate](http://www.hibernate.org) or [mybatis](http://www.mybatis.org)\r
 \r
 Supported Databases (Unit-Tested)\r
@@ -22,6 +22,7 @@ Supported Databases (Unit-Tested)
 - [Derby](http://db.apache.org/derby) 10.11\r
 - [MySQL](http://mysql.com) 5.6\r
 - [PostgreSQL](http://postgresql.org) 9.3\r
+- [SQLite](http://www.sqlite.org) 3.8\r
 \r
 Support for others is possible and may only require creating a simple "dialect" class.\r
 \r
@@ -37,7 +38,8 @@ iciql requires a Java 6 Runtime Environment (JRE) or a Java 6 Development Kit (J
 Getting help\r
 -------\r
 Read the online documentation available at the [iciql website](http://iciql.com)<br/>\r
-Issues, binaries, & sources @ [Google Code](http://code.google.com/p/iciql)\r
+Issues & sources @ [GitHub](http://github.com/gitblit/iciql)\r
+Binaries @ [Iciql Maven Repository](http://gitblit.github.io/iciql/maven/)\r
 \r
 Building iciql\r
 ----------------\r
index 2656e5d1c342d0b3251ee3c0d98ea3ef50fcf0b3..51034ccacebbbbac07eb8dd6a2ba9c14827b0c63 100644 (file)
@@ -87,6 +87,7 @@ properties: {
        derby.version : 10.11.1.1
        mysql.version : 5.6
        postgresql.version : 9.3
+       sqlite.version : 3.8.7
 }
 
 dependencies:
@@ -96,6 +97,7 @@ dependencies:
 - provided 'org.apache.derby:derby:${derby.version}'
 - provided 'mysql:mysql-connector-java:5.1.33'
 - provided 'org.postgresql:postgresql:9.3-1102-jdbc4'
+- provided 'org.xerial:sqlite-jdbc:${sqlite.version}'
 - provided 'org.slf4j:slf4j-api:1.6.1'
 - provided 'commons-pool:commons-pool:1.5.6'
 - provided 'commons-dbcp:commons-dbcp:1.4'
index 67e73b09a114dfe7d2f2efb9830b4a04a1ab7e07..23001d86041de3635e9c0af0aaf996df1a456d5f 100644 (file)
@@ -85,6 +85,7 @@ public class Db implements AutoCloseable {
                DIALECTS.put("MySQL", SQLDialectMySQL.class);\r
                DIALECTS.put("PostgreSQL", SQLDialectPostgreSQL.class);\r
            DIALECTS.put("Microsoft SQL Server", SQLDialectMSSQL.class);\r
+           DIALECTS.put("SQLite", SQLDialectSQLite.class);\r
        }\r
 \r
        private Db(Connection conn) {\r
index 3f27b733ef33bdce57dc80fa288eea16ac655b0c..3db62cfbc27bb35244a581ea6905dab21454dab1 100644 (file)
@@ -101,7 +101,7 @@ public class IciqlException extends RuntimeException {
                                // MySQL duplicate primary key on insert\r
                                iciqlCode = CODE_DUPLICATE_KEY;\r
                                if (s.getErrorCode() == 1217) {\r
-                                       iciqlCode = CODE_CONSTRAINT_VIOLATION;  \r
+                                       iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
                                }\r
                        } else if ("23505".equals(state)) {\r
                                // Derby duplicate primary key on insert\r
@@ -154,6 +154,24 @@ public class IciqlException extends RuntimeException {
                        } else if ("X0Y25".equals(state)) {\r
                                // Derby constraint violation\r
                                iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
+                       } else if (s.getMessage().startsWith("[SQLITE")) {\r
+                               // SQLite error codes\r
+                               final String msg = s.getMessage();\r
+                               switch (s.getErrorCode()) {\r
+                               case 1:\r
+                                       iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+                                       break;\r
+                               case 19:\r
+                                       if (msg.contains("UNIQUE")) {\r
+                                               iciqlCode = CODE_DUPLICATE_KEY;\r
+                                       } else {\r
+                                               iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
+                                       }\r
+                                       break;\r
+                               default:\r
+                                       iciqlCode = s.getErrorCode();\r
+                                       break;\r
+                               }\r
                        } else {\r
                                // uncharacterized SQL code, we can always rely on iciqlCode != 0 in IciqlException\r
                                iciqlCode = s.getErrorCode() == 0 ? CODE_UNCHARACTERIZED : s.getErrorCode();\r
diff --git a/src/main/java/com/iciql/SQLDialectSQLite.java b/src/main/java/com/iciql/SQLDialectSQLite.java
new file mode 100644 (file)
index 0000000..c9bf8ec
--- /dev/null
@@ -0,0 +1,115 @@
+/*\r
+ * Copyright 2014 James Moger.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.iciql;\r
+\r
+import com.iciql.TableDefinition.FieldDefinition;\r
+import com.iciql.TableDefinition.IndexDefinition;\r
+import com.iciql.util.IciqlLogger;\r
+import com.iciql.util.StatementBuilder;\r
+\r
+\r
+/**\r
+ * SQLite database dialect.\r
+ */\r
+public class SQLDialectSQLite extends SQLDialectDefault {\r
+\r
+       @Override\r
+       public boolean supportsSavePoints() {\r
+               return false;\r
+       }\r
+\r
+       @Override\r
+       public void configureDialect(Db db) {\r
+               super.configureDialect(db);\r
+               // enable foreign key constraint enforcement\r
+               db.executeUpdate("PRAGMA foreign_keys = ON;");\r
+       }\r
+\r
+       @Override\r
+       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+               return "CREATE TABLE IF NOT EXISTS";\r
+       }\r
+\r
+       @Override\r
+       protected <T> String prepareCreateView(TableDefinition<T> def) {\r
+               return "CREATE VIEW IF NOT EXISTS";\r
+       }\r
+\r
+       @Override\r
+       public <T> void prepareDropView(SQLStatement stat, TableDefinition<T> def) {\r
+               StatementBuilder buff = new StatementBuilder("DROP VIEW IF EXISTS "\r
+                               + prepareTableName(def.schemaName, def.tableName));\r
+               stat.setSQL(buff.toString());\r
+               return;\r
+       }\r
+\r
+       @Override\r
+       public void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName,\r
+                       IndexDefinition index) {\r
+               StatementBuilder buff = new StatementBuilder();\r
+               buff.append("CREATE ");\r
+               switch (index.type) {\r
+               case UNIQUE:\r
+                       buff.append("UNIQUE ");\r
+                       break;\r
+               case UNIQUE_HASH:\r
+                       buff.append("UNIQUE ");\r
+                       break;\r
+               default:\r
+                       IciqlLogger.warn("{0} does not support hash indexes", getClass().getSimpleName());\r
+               }\r
+               buff.append("INDEX IF NOT EXISTS ");\r
+               buff.append(index.indexName);\r
+               buff.append(" ON ");\r
+               // FIXME maybe we can use schemaName ?\r
+               // buff.append(prepareTableName(schemaName, tableName));\r
+               buff.append(tableName);\r
+               buff.append("(");\r
+               for (String col : index.columnNames) {\r
+                       buff.appendExceptFirst(", ");\r
+                       buff.append(prepareColumnName(col));\r
+               }\r
+               buff.append(") ");\r
+\r
+               stat.setSQL(buff.toString().trim());\r
+       }\r
+\r
+       @Override\r
+       public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,\r
+                       TableDefinition<T> def, Object obj) {\r
+               StatementBuilder buff = new StatementBuilder("INSERT OR REPLACE INTO ");\r
+               buff.append(prepareTableName(schemaName, tableName)).append(" (");\r
+               buff.resetCount();\r
+               for (FieldDefinition field : def.fields) {\r
+                       buff.appendExceptFirst(", ");\r
+                       buff.append(field.columnName);\r
+               }\r
+               buff.append(") ");\r
+               buff.resetCount();\r
+               buff.append("VALUES (");\r
+               for (FieldDefinition field : def.fields) {\r
+                       buff.appendExceptFirst(", ");\r
+                       buff.append('?');\r
+                       Object value = def.getValue(obj, field);\r
+                       Object parameter = serialize(value, field.typeAdapter);\r
+                       stat.addParameter(parameter);\r
+               }\r
+               buff.append(')');\r
+               stat.setSQL(buff.toString());\r
+       }\r
+\r
+}
\ No newline at end of file
index 7e489b31de08bdd97a5dbd7bfb486a1d2801d0e3..bddebd7b5e39c6d7c874d454bd078f43689a4e27 100644 (file)
@@ -12,7 +12,7 @@ iciql **is**...
 iciql **is not**...\r
 \r
 - a complete alternative to JDBC\r
-- designed to compete with more powerful database query tools like [jOOQ][jooq] or [Querydsl][querydsl]\r
+- designed to compete with more powerful database query tools like [jOOQ][jooq] or [QueryDSL][querydsl]\r
 - designed to compete with enterprise [ORM][orm] tools like [Hibernate][hibernate] or [mybatis][mybatis]\r
 \r
 ### Example Usage\r
@@ -42,6 +42,7 @@ select * from products
 - [Derby](http://db.apache.org/derby) ${derby.version}\r
 - [MySQL](http://mysql.com) ${mysql.version}\r
 - [PostgreSQL](http://postgresql.org) ${postgresql.version}\r
+- [SQLite](http://www.sqlite.org) ${sqlite.version}\r
 \r
 Support for others is possible and may only require creating a simple "dialect" class.\r
 \r
@@ -59,5 +60,4 @@ iciql is distributed under the terms of the [Apache Software Foundation license,
 [hibernate]: http://www.hibernate.org "Hibernate"\r
 [mybatis]: http://www.mybatis.org "mybatis"\r
 [github]: http://github.com/gitblit/iciql "iciql git repository"\r
-[googlecode]: http://code.google.com/p/iciql "iciql project management"\r
 [apachelicense]: http://www.apache.org/licenses/LICENSE-2.0 "Apache License, Version 2.0"
\ No newline at end of file
index 3a00e6dc14592b832fd68e8142ea21539dc972e1..e7afbf808d71daafb069a48e652cbafacb0f8f5d 100644 (file)
@@ -7,7 +7,7 @@ This is an overview of the fundamental differences between the original JaQu pro
 <tr><th></th><th>Iciql</th><th>JaQu</th></tr>\r
 <tr><th colspan="3">core</th></tr>\r
 <tr><td>deployment</td><td>small, discrete library</td><td>depends on H2 database jar file</td></tr>\r
-<tr><td>databases</td><td>H2, HSQL, Derby, MySQL, and PostreSQL</td><td>H2 only</td></tr>\r
+<tr><td>databases</td><td>H2, HSQL, Derby, MySQL, PostreSQL, and SQLite</td><td>H2 only</td></tr>\r
 <tr><td>logging</td><td>console, SLF4J, or custom logging</td><td>console logging</td></tr>\r
 <tr><td>exceptions</td><td>always includes generated statement in exception, when available</td><td>--</td></tr>\r
 <tr><td>column mappings</td><td>wildcard queries index result sets by column name</td><td>all result sets built by field index<br/>this can fail for wildcard queries</td></tr>\r
index c4189385cf02cee8c213dcd5c122e9eb94e947bd..4800b9a9c84bde03e78b9c45e64b92e54b70d1fb 100644 (file)
@@ -110,7 +110,11 @@ public class IciqlSuite {
                        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", "sa", "sa"),\r
-                       new TestDb("PostgreSQL", false, false, "jdbc:postgresql://localhost:5432/iciql", "sa", "sa") };\r
+                       new TestDb("PostgreSQL", false, false, "jdbc:postgresql://localhost:5432/iciql", "sa", "sa"),\r
+                       new TestDb("SQLite", true, true, "jdbc:sqlite:file:iciql?mode=memory&cache=shared"),\r
+                       new TestDb("SQLite", true, false, "jdbc:sqlite:"\r
+                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath())\r
+                       };\r
 \r
        private static final TestDb DEFAULT_TEST_DB = TEST_DBS[0];\r
 \r
@@ -255,6 +259,16 @@ public class IciqlSuite {
                return IciqlSuite.getDatabaseEngineName(db).equals("MySQL");\r
        }\r
 \r
+       /**\r
+        * Returns true if the underlying database engine is SQLite.\r
+        *\r
+        * @param db\r
+        * @return true if underlying database engine is SQLite\r
+        */\r
+       public static boolean isSQLite(Db db) {\r
+               return IciqlSuite.getDatabaseEngineName(db).equals("SQLite");\r
+       }\r
+\r
        /**\r
         * Gets the default schema of the underlying database engine.\r
         *\r
@@ -296,6 +310,7 @@ public class IciqlSuite {
                }\r
 \r
                deleteRecursively(baseFolder);\r
+               new File(baseFolder, "/sqlite").mkdirs();\r
 \r
                // Start the HSQL and H2 servers in-process\r
                org.hsqldb.Server hsql = startHSQL();\r
@@ -412,6 +427,20 @@ public class IciqlSuite {
                out.println(dividerMajor);\r
                out.println(MessageFormat.format("{0} {1} ({2}) test suite performance results", Constants.NAME,\r
                                Constants.VERSION, Constants.VERSION_DATE));\r
+\r
+               StringBuilder compressedSystem = new StringBuilder();\r
+               compressedSystem.append("      on ");\r
+               compressedSystem.append(System.getProperty("java.vendor"));\r
+               compressedSystem.append(' ');\r
+               compressedSystem.append(System.getProperty("java.runtime.version"));\r
+               compressedSystem.append(", ");\r
+               compressedSystem.append(System.getProperty("os.name"));\r
+               compressedSystem.append(' ');\r
+               compressedSystem.append(System.getProperty("os.version"));\r
+               compressedSystem.append(", ");\r
+               compressedSystem.append(System.getProperty("os.arch"));\r
+               out.println(compressedSystem.toString());\r
+\r
                out.println(dividerMajor);\r
                List<TestDb> dbs = Arrays.asList(TEST_DBS);\r
                Collections.sort(dbs);\r
index 7de691f6f5ca3c95fa4bd376a8ad3760bdb6b45a..4ab1ff1e51abb616f03d7be9ef797b6f441dedd5 100644 (file)
@@ -32,7 +32,7 @@ import com.iciql.test.models.SupportedTypes.SupportedTypes2;
 \r
 /**\r
  * Tests the database and table upgrade functions.\r
- * \r
+ *\r
  */\r
 public class UpgradesTest {\r
 \r
@@ -54,7 +54,7 @@ public class UpgradesTest {
 \r
                // open a second connection to the database\r
                // and then apply the v2 upgrade.\r
-               // For H2 its important to keep the first connection\r
+               // For an in-memory db its important to keep the first connection\r
                // alive so that the database is not destroyed.\r
                Db db2 = IciqlSuite.openCurrentDb();\r
 \r
@@ -72,7 +72,7 @@ public class UpgradesTest {
                db.close();\r
                db2.close();\r
        }\r
-       \r
+\r
        @Test\r
        public void testDatabaseInheritedUpgrade() {\r
                Db db = IciqlSuite.openNewDb();\r
@@ -91,7 +91,7 @@ public class UpgradesTest {
 \r
                // open a second connection to the database\r
                // and then apply the v2 upgrade.\r
-               // For H2 its important to keep the first connection\r
+               // For an in-memory db its important to keep the first connection\r
                // alive so that the database is not destroyed.\r
                Db db2 = IciqlSuite.openCurrentDb();\r
 \r
@@ -139,6 +139,7 @@ public class UpgradesTest {
                final AtomicInteger oldVersion = new AtomicInteger(0);\r
                final AtomicInteger newVersion = new AtomicInteger(0);\r
 \r
+               @Override\r
                public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) {\r
                        // just claims success on upgrade request\r
                        oldVersion.set(fromVersion);\r
@@ -146,6 +147,7 @@ public class UpgradesTest {
                        return true;\r
                }\r
 \r
+               @Override\r
                public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {\r
                        // just claims success on upgrade request\r
                        oldVersion.set(fromVersion);\r
@@ -168,7 +170,7 @@ public class UpgradesTest {
        class V2DbUpgrader extends BaseDbUpgrader {\r
        }\r
 \r
-       \r
+\r
        /**\r
         * A sample V2 database upgrader class which inherits its\r
         * version from the parent class.\r