aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Moger <james.moger@gmail.com>2011-08-16 15:32:56 -0400
committerJames Moger <james.moger@gmail.com>2011-08-16 15:32:56 -0400
commitd95e16170d063c0b74d04e6636e8fddbfa120689 (patch)
treea8157992ef14cb8f4392b847fbc8892cb30245d5
parent8193609af00aa9529ed7b3090b5739c4e95b12c4 (diff)
downloadiciql-d95e16170d063c0b74d04e6636e8fddbfa120689.tar.gz
iciql-d95e16170d063c0b74d04e6636e8fddbfa120689.zip
Finished MySQL dialect; v5.0.51b 100% tested. Added Db.dropTable(T)
-rw-r--r--.classpath1
-rw-r--r--README.markdown7
-rw-r--r--docs/00_index.mkd6
-rw-r--r--docs/03_performance.mkd2
-rw-r--r--docs/05_releases.mkd11
-rw-r--r--src/com/iciql/Db.java42
-rw-r--r--src/com/iciql/IciqlException.java18
-rw-r--r--src/com/iciql/SQLDialect.java16
-rw-r--r--src/com/iciql/SQLDialectDefault.java11
-rw-r--r--src/com/iciql/SQLDialectDerby.java10
-rw-r--r--src/com/iciql/SQLDialectMySQL.java41
-rw-r--r--src/com/iciql/TableDefinition.java3
-rw-r--r--src/com/iciql/TableInspector.java6
-rw-r--r--src/com/iciql/build/Build.java10
-rw-r--r--src/com/iciql/util/StatementLogger.java25
-rw-r--r--tests/com/iciql/test/AnnotationsTest.java26
-rw-r--r--tests/com/iciql/test/ClobTest.java4
-rw-r--r--tests/com/iciql/test/IciqlSuite.java149
-rw-r--r--tests/com/iciql/test/ModelsTest.java83
-rw-r--r--tests/com/iciql/test/SamplesTest.java41
-rw-r--r--tests/com/iciql/test/UUIDTest.java8
-rw-r--r--tests/com/iciql/test/UpgradesTest.java134
-rw-r--r--tests/com/iciql/test/models/PrimitivesModel.java5
-rw-r--r--tests/com/iciql/test/models/ProductAnnotationOnly.java5
-rw-r--r--tests/com/iciql/test/models/SupportedTypes.java5
25 files changed, 477 insertions, 192 deletions
diff --git a/.classpath b/.classpath
index 1d41ba7..136c201 100644
--- a/.classpath
+++ b/.classpath
@@ -26,6 +26,7 @@
</classpathentry>
<classpathentry kind="lib" path="ext/hsqldb-2.2.4.jar"/>
<classpathentry kind="lib" path="ext/derby-10.8.1.2.jar"/>
+ <classpathentry kind="lib" path="ext/mysql-connector-java-5.1.15.jar"/>
<classpathentry kind="lib" path="ext/h2-1.3.159.jar" sourcepath="ext/h2-1.3.159-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/iciql/ext/h2-1.3.159-javadoc.jar!/"/>
diff --git a/README.markdown b/README.markdown
index 6c4f5e2..28aa424 100644
--- a/README.markdown
+++ b/README.markdown
@@ -20,12 +20,9 @@ Supported Databases (Unit-Tested)
- [H2](http://h2database.com) 1.3.159
- [HSQLDB](http://hsqldb.org) 2.2.4
- [Derby](http://db.apache.org/derby) 10.7.1.1 & 10.8.1.2
+- [MySQL](http://mysql.com) 5.0.51b
-Partially Supported Databases (not Unit-Tested)
--------
-- [MySQL](http://mysql.com)
-
-Support for others is planned and may only require creating a simple "dialect" class.
+Support for others is possible and may only require creating a simple "dialect" class.
License
-------
diff --git a/docs/00_index.mkd b/docs/00_index.mkd
index b3e8cbf..daf9c42 100644
--- a/docs/00_index.mkd
+++ b/docs/00_index.mkd
@@ -39,11 +39,9 @@ select * from products
- [H2](http://h2database.com) 1.3.159
- [HSQLDB](http://hsqldb.org) 2.2.4
- [Derby](http://db.apache.org/derby) 10.7.1.1 & 10.8.1.2
+- [MySQL](http://mysql.com) 5.0.51b
-### Partially Supported Databases (not Unit-Tested)
-- [MySQL](http://mysql.com)
-
-Support for others is planned and may only require creating a simple "dialect" class.
+Support for others is possible and may only require creating a simple "dialect" class.
### Java Runtime Requirement
diff --git a/docs/03_performance.mkd b/docs/03_performance.mkd
index a8922b7..7df050a 100644
--- a/docs/03_performance.mkd
+++ b/docs/03_performance.mkd
@@ -9,7 +9,7 @@ Performance of iciql statement generation is not currently benchmarked.
### iciql+database performance comparison
-The following data was generated by running the iciql test suite. The suite is almost completely single-threaded. All databases are run in embedded *memory-only* mode through a JDBC connection. Since the suite is running in memory-only mode, disk IO bottlenecks should be removed from the equation and the results should be measuring raw statement processing.
+The following data was generated by running the iciql test suite. The suite is almost completely single-threaded. All Java databases are run in embedded *memory-only* mode through a JDBC connection.
<pre>
%DBPERFORMANCE%
diff --git a/docs/05_releases.mkd b/docs/05_releases.mkd
index 91ef18f..8e0dfd6 100644
--- a/docs/05_releases.mkd
+++ b/docs/05_releases.mkd
@@ -6,13 +6,18 @@
**%VERSION%** ([zip](http://code.google.com/p/iciql/downloads/detail?name=%ZIP%)|[jar](http://code.google.com/p/iciql/downloads/detail?name=%JAR%)) &nbsp; *released %BUILDDATE%*
-- Disabled 2 concurrency unit tests since I believe they are flawed and do not yield reproducible results
+- Finished MySQL dialect implementation. MySQL 5.0.51b passes 100% of tests.
+- Added Db.dropTable(T) method
+
+### Older Releases
+
+**0.6.6** &nbsp; *released 2011-08-15*
+
+- Disabled two concurrency unit tests since I believe they are flawed and do not yield reproducible results
- Added Derby database dialect. Derby 10.7.1.1 and 10.8.1.2 pass 100% of tests.
- Implemented HSQL MERGE syntax. HSQL 2.2.4 fails 1 test which is a known [bug in HSQL](https://sourceforge.net/tracker/?func=detail&aid=3390047&group_id=23316&atid=378131)
- Updated to H2 1.3.159
-### Older Releases
-
**0.6.5** &nbsp; *released 2011-08-12*
- fixed failure of db.delete(PrimitiveModel) and db.update(PrimitiveModel)
diff --git a/src/com/iciql/Db.java b/src/com/iciql/Db.java
index bb087e4..09c26a1 100644
--- a/src/com/iciql/Db.java
+++ b/src/com/iciql/Db.java
@@ -38,6 +38,7 @@ import com.iciql.DbUpgrader.DefaultDbUpgrader;
import com.iciql.Iciql.IQTable;
import com.iciql.Iciql.IQVersion;
import com.iciql.util.JdbcUtils;
+import com.iciql.util.StatementLogger;
import com.iciql.util.StringUtils;
import com.iciql.util.Utils;
import com.iciql.util.WeakIdentityHashMap;
@@ -180,7 +181,10 @@ public class Db {
public <T> void insert(T t) {
Class<?> clazz = t.getClass();
- define(clazz).createTableIfRequired(this).insert(this, t, false);
+ long rc = define(clazz).createTableIfRequired(this).insert(this, t, false);
+ if (rc == 0) {
+ throw new IciqlException("Failed to insert {0}. Affected rowcount == 0.", t);
+ }
}
public <T> long insertAndGetKey(T t) {
@@ -236,6 +240,26 @@ public class Db {
}
@SuppressWarnings("unchecked")
+ public <T> int dropTable(Class<? extends T> modelClass) {
+ TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
+ SQLStatement stat = new SQLStatement(this);
+ getDialect().prepareDropTable(stat, def);
+ StatementLogger.drop(stat.getSQL());
+ int rc = 0;
+ try {
+ rc = stat.executeUpdate();
+ } catch (IciqlException e) {
+ if (e.getIciqlCode() != IciqlException.CODE_SCHEMA_NOT_FOUND
+ && e.getIciqlCode() != IciqlException.CODE_TABLE_NOT_FOUND) {
+ throw e;
+ }
+ }
+ // remove this model class from the table definition cache
+ classMap.remove(modelClass);
+ return rc;
+ }
+
+ @SuppressWarnings("unchecked")
public <T> List<T> buildObjects(Class<? extends T> modelClass, ResultSet rs) {
List<T> result = new ArrayList<T>();
TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
@@ -259,14 +283,18 @@ public class Db {
IQVersion model = dbUpgrader.getClass().getAnnotation(IQVersion.class);
if (model.value() > 0) {
DbVersion v = new DbVersion();
- DbVersion dbVersion =
// (SCHEMA="" && TABLE="") == DATABASE
- from(v).where(v.schemaName).is("").and(v.tableName).is("").selectFirst();
+ DbVersion dbVersion = from(v).where(v.schemaName).is("").and(v.tableName).is("")
+ .selectFirst();
if (dbVersion == null) {
// database has no version registration, but model specifies
// version: insert DbVersion entry and return.
DbVersion newDb = new DbVersion(model.value());
- insert(newDb);
+ // database is an older version than the model
+ boolean success = dbUpgrader.upgradeDatabase(this, 0, newDb.version);
+ if (success) {
+ insert(newDb);
+ }
} else {
// database has a version registration:
// check to see if upgrade is required.
@@ -293,8 +321,8 @@ public class Db {
// table is using iciql version tracking.
DbVersion v = new DbVersion();
String schema = StringUtils.isNullOrEmpty(model.schemaName) ? "" : model.schemaName;
- DbVersion dbVersion = from(v).where(v.schemaName).like(schema).and(v.tableName)
- .like(model.tableName).selectFirst();
+ DbVersion dbVersion = from(v).where(v.schemaName).is(schema).and(v.tableName)
+ .is(model.tableName).selectFirst();
if (dbVersion == null) {
// table has no version registration, but model specifies
// version: insert DbVersion entry
@@ -348,7 +376,7 @@ public class Db {
upgradeChecked.clear();
}
- SQLDialect getDialect() {
+ public SQLDialect getDialect() {
return dialect;
}
diff --git a/src/com/iciql/IciqlException.java b/src/com/iciql/IciqlException.java
index 7d6f152..524d184 100644
--- a/src/com/iciql/IciqlException.java
+++ b/src/com/iciql/IciqlException.java
@@ -27,9 +27,10 @@ public class IciqlException extends RuntimeException {
public static final int CODE_UNMAPPED_FIELD = 1;
public static final int CODE_DUPLICATE_KEY = 2;
- public static final int CODE_TABLE_NOT_FOUND = 3;
- public static final int CODE_TABLE_ALREADY_EXISTS = 4;
- public static final int CODE_INDEX_ALREADY_EXISTS = 5;
+ public static final int CODE_SCHEMA_NOT_FOUND = 3;
+ public static final int CODE_TABLE_NOT_FOUND = 4;
+ public static final int CODE_TABLE_ALREADY_EXISTS = 5;
+ public static final int CODE_INDEX_ALREADY_EXISTS = 6;
private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";
@@ -95,8 +96,17 @@ public class IciqlException extends RuntimeException {
// http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html
SQLException s = (SQLException) t;
String state = s.getSQLState();
- if ("23505".equals(state)) {
+ if ("23000".equals(state)) {
+ // MySQL
iciqlCode = CODE_DUPLICATE_KEY;
+ } else if ("23505".equals(state)) {
+ iciqlCode = CODE_DUPLICATE_KEY;
+ } else if ("42000".equals(state)) {
+ // MySQL
+ iciqlCode = CODE_DUPLICATE_KEY;
+ } else if ("42Y07".equals(state)) {
+ // Derby
+ iciqlCode = CODE_SCHEMA_NOT_FOUND;
} else if ("42X05".equals(state)) {
// Derby
iciqlCode = CODE_TABLE_NOT_FOUND;
diff --git a/src/com/iciql/SQLDialect.java b/src/com/iciql/SQLDialect.java
index 97d9fe9..6e6be25 100644
--- a/src/com/iciql/SQLDialect.java
+++ b/src/com/iciql/SQLDialect.java
@@ -36,6 +36,14 @@ public interface SQLDialect {
void configureDialect(String databaseName, DatabaseMetaData data);
/**
+ * Allows a dialect to substitute an SQL type.
+ *
+ * @param sqlType
+ * @return the dialect-safe type
+ */
+ String convertSqlType(String sqlType);
+
+ /**
* Returns a properly formatted table name for the dialect.
*
* @param schemaName
@@ -64,6 +72,14 @@ public interface SQLDialect {
<T> void prepareCreateTable(SQLStatement stat, TableDefinition<T> def);
/**
+ * Get the DROP TABLE statement.
+ *
+ * @param stat
+ * @param def
+ */
+ <T> void prepareDropTable(SQLStatement stat, TableDefinition<T> def);
+
+ /**
* Get the CREATE INDEX statement.
*
* @param schemaName
diff --git a/src/com/iciql/SQLDialectDefault.java b/src/com/iciql/SQLDialectDefault.java
index 69502c3..0b611e0 100644
--- a/src/com/iciql/SQLDialectDefault.java
+++ b/src/com/iciql/SQLDialectDefault.java
@@ -57,7 +57,8 @@ public class SQLDialectDefault implements SQLDialect {
* @param sqlType
* @return the SQL type or a preferred alternative
*/
- protected String convertSqlType(String sqlType) {
+ @Override
+ public String convertSqlType(String sqlType) {
return sqlType;
}
@@ -95,6 +96,14 @@ public class SQLDialectDefault implements SQLDialect {
}
@Override
+ public <T> void prepareDropTable(SQLStatement stat, TableDefinition<T> def) {
+ StatementBuilder buff = new StatementBuilder("DROP TABLE IF EXISTS "
+ + prepareTableName(def.schemaName, def.tableName));
+ stat.setSQL(buff.toString());
+ return;
+ }
+
+ @Override
public <T> void prepareCreateTable(SQLStatement stat, TableDefinition<T> def) {
StatementBuilder buff;
if (def.memoryTable && supportsMemoryTables()) {
diff --git a/src/com/iciql/SQLDialectDerby.java b/src/com/iciql/SQLDialectDerby.java
index 42f8cfd..019c285 100644
--- a/src/com/iciql/SQLDialectDerby.java
+++ b/src/com/iciql/SQLDialectDerby.java
@@ -33,7 +33,7 @@ public class SQLDialectDerby extends SQLDialectDefault {
}
@Override
- protected String convertSqlType(String sqlType) {
+ public String convertSqlType(String sqlType) {
if ("TINYINT".equals(sqlType)) {
// Derby does not have a TINYINT/BYTE type
return "SMALLINT";
@@ -82,6 +82,14 @@ public class SQLDialectDerby extends SQLDialectDefault {
}
@Override
+ public <T> void prepareDropTable(SQLStatement stat, TableDefinition<T> def) {
+ StatementBuilder buff = new StatementBuilder("DROP TABLE "
+ + prepareTableName(def.schemaName, def.tableName));
+ stat.setSQL(buff.toString());
+ return;
+ }
+
+ @Override
public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
diff --git a/src/com/iciql/SQLDialectMySQL.java b/src/com/iciql/SQLDialectMySQL.java
index a6c1218..1c1674a 100644
--- a/src/com/iciql/SQLDialectMySQL.java
+++ b/src/com/iciql/SQLDialectMySQL.java
@@ -16,6 +16,7 @@
package com.iciql;
+import com.iciql.TableDefinition.FieldDefinition;
import com.iciql.TableDefinition.IndexDefinition;
import com.iciql.util.StatementBuilder;
@@ -25,7 +26,7 @@ import com.iciql.util.StatementBuilder;
public class SQLDialectMySQL extends SQLDialectDefault {
@Override
- protected String convertSqlType(String sqlType) {
+ public String convertSqlType(String sqlType) {
if (sqlType.equals("CLOB")) {
return "TEXT";
}
@@ -75,16 +76,36 @@ public class SQLDialectMySQL extends SQLDialectDefault {
buff.append(prepareColumnName(col));
}
buff.append(") ");
+ stat.setSQL(buff.toString().trim());
+ }
- // USING
- switch (index.type) {
- case HASH:
- buff.append("USING HASH");
- break;
- case UNIQUE_HASH:
- buff.append("USING HASH");
- break;
+ @Override
+ public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,
+ TableDefinition<T> def, Object obj) {
+ StatementBuilder buff = new StatementBuilder("INSERT INTO ");
+ buff.append(prepareTableName(schemaName, tableName)).append(" (");
+ buff.resetCount();
+ for (FieldDefinition field : def.fields) {
+ buff.appendExceptFirst(", ");
+ buff.append(field.columnName);
}
- stat.setSQL(buff.toString().trim());
+ buff.resetCount();
+ buff.append(") VALUES (");
+ for (FieldDefinition field : def.fields) {
+ buff.appendExceptFirst(", ");
+ buff.append('?');
+ Object value = def.getValue(obj, field);
+ stat.addParameter(value);
+ }
+ buff.append(") ON DUPLICATE KEY UPDATE ");
+ buff.resetCount();
+ for (FieldDefinition field : def.fields) {
+ buff.appendExceptFirst(", ");
+ buff.append(field.columnName);
+ buff.append("=VALUES(");
+ buff.append(field.columnName);
+ buff.append(')');
+ }
+ stat.setSQL(buff.toString());
}
} \ No newline at end of file
diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java
index 4d9fec2..251f098 100644
--- a/src/com/iciql/TableDefinition.java
+++ b/src/com/iciql/TableDefinition.java
@@ -573,7 +573,8 @@ public class TableDefinition<T> {
try {
stat.executeUpdate();
} catch (IciqlException e) {
- if (e.getIciqlCode() != IciqlException.CODE_INDEX_ALREADY_EXISTS) {
+ if (e.getIciqlCode() != IciqlException.CODE_INDEX_ALREADY_EXISTS
+ && e.getIciqlCode() != IciqlException.CODE_DUPLICATE_KEY) {
throw e;
}
}
diff --git a/src/com/iciql/TableInspector.java b/src/com/iciql/TableInspector.java
index dc28956..093055c 100644
--- a/src/com/iciql/TableInspector.java
+++ b/src/com/iciql/TableInspector.java
@@ -433,13 +433,13 @@ public class TableInspector {
if (!isNullOrEmpty(schema)) {
if (isNullOrEmpty(def.schemaName)) {
remarks.add(consider(table, "SCHEMA",
- format("@{0}(name={1})", IQSchema.class.getSimpleName(), schema)));
+ format("@{0}(\"{1}\")", IQSchema.class.getSimpleName(), schema)));
} else if (!schema.equalsIgnoreCase(def.schemaName)) {
remarks.add(error(
table,
"SCHEMA",
- format("@{0}(name={1}) != {2}", IQSchema.class.getSimpleName(), def.schemaName,
- schema)).throwError(throwError));
+ format("@{0}(\"{1}\") != {2}", IQSchema.class.getSimpleName(), def.schemaName, schema))
+ .throwError(throwError));
}
}
diff --git a/src/com/iciql/build/Build.java b/src/com/iciql/build/Build.java
index 0102739..8dfd7df 100644
--- a/src/com/iciql/build/Build.java
+++ b/src/com/iciql/build/Build.java
@@ -58,6 +58,7 @@ public class Build {
downloadFromApache(MavenObject.H2, BuildType.COMPILETIME);
downloadFromApache(MavenObject.HSQLDB, BuildType.RUNTIME);
downloadFromApache(MavenObject.DERBY, BuildType.RUNTIME);
+ downloadFromApache(MavenObject.MYSQL, BuildType.RUNTIME);
downloadFromApache(MavenObject.JCOMMANDER, BuildType.RUNTIME);
downloadFromApache(MavenObject.JCOMMANDER, BuildType.COMPILETIME);
downloadFromApache(MavenObject.MARKDOWNPAPERS, BuildType.RUNTIME);
@@ -170,9 +171,9 @@ public class Build {
"219a3540f3b27d7cc3b1d91d6ea046cd8723290e", "0bb50eec177acf0e94d58e0cf07262fe5164331d",
"c7adc475ca40c288c93054e0f4fe58f3a98c0cb5");
- public static final MavenObject H2 = new MavenObject("com/h2database", "h2", "1.3.159",
- "dd89f939661eb5593909584e1c243db0c25de130", "4d953bf765e8a13c7e06ca51165438338966c698",
- "4c79ed03f994820a1a873150c8a9f13c667784d3");
+ public static final MavenObject H2 = new MavenObject("com/h2database", "h2", "1.3.158",
+ "4bac13427caeb32ef6e93b70101e61f370c7b5e2", "6bb165156a0831879fa7797df6e18bdcd4421f2d",
+ "446d3f58c44992534cb54f67134532d95961904a");
public static final MavenObject HSQLDB = new MavenObject("org/hsqldb", "hsqldb", "2.2.4",
"6a6e040b07f5ee409fc825f1c5e5b574b1fa1428", "", "");
@@ -180,6 +181,9 @@ public class Build {
public static final MavenObject DERBY = new MavenObject("org/apache/derby", "derby", "10.8.1.2",
"2f8717d96eafe3eef3de445ba653f142d54ddab1", "", "");
+ public static final MavenObject MYSQL = new MavenObject("mysql", "mysql-connector-java", "5.1.15",
+ "0fbc80454d27cc65f3addfa516707e9f8e60c3eb", "", "");
+
public static final MavenObject JUNIT = new MavenObject("junit", "junit", "4.8.2",
"c94f54227b08100974c36170dcb53329435fe5ad", "", "");
diff --git a/src/com/iciql/util/StatementLogger.java b/src/com/iciql/util/StatementLogger.java
index 0504c98..b11a5f9 100644
--- a/src/com/iciql/util/StatementLogger.java
+++ b/src/com/iciql/util/StatementLogger.java
@@ -22,6 +22,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
+import com.iciql.IciqlException;
+
/**
* Utility class to optionally log generated statements to StatementListeners.<br>
* Statement logging is disabled by default.
@@ -35,7 +37,7 @@ public class StatementLogger {
* Enumeration of the different statement types that are logged.
*/
public enum StatementType {
- STAT, TOTAL, CREATE, INSERT, UPDATE, MERGE, DELETE, SELECT;
+ STAT, TOTAL, CREATE, INSERT, UPDATE, MERGE, DELETE, SELECT, DROP;
}
/**
@@ -61,19 +63,20 @@ public class StatementLogger {
private static final AtomicLong UPDATE_COUNT = new AtomicLong();
private static final AtomicLong MERGE_COUNT = new AtomicLong();
private static final AtomicLong DELETE_COUNT = new AtomicLong();
+ private static final AtomicLong DROP_COUNT = new AtomicLong();
/**
* Activates the Console Logger.
*/
public static void activateConsoleLogger() {
- LISTENERS.add(CONSOLE);
+ registerListener(CONSOLE);
}
/**
* Deactivates the Console Logger.
*/
public static void deactivateConsoleLogger() {
- LISTENERS.remove(CONSOLE);
+ unregisterListener(CONSOLE);
}
/**
@@ -91,7 +94,9 @@ public class StatementLogger {
* @param listener
*/
public static void unregisterListener(StatementListener listener) {
- LISTENERS.remove(listener);
+ if (!LISTENERS.remove(listener)) {
+ throw new IciqlException("Failed to remove statement listener {0}", listener);
+ }
}
public static void create(String statement) {
@@ -124,6 +129,11 @@ public class StatementLogger {
logStatement(StatementType.SELECT, statement);
}
+ public static void drop(String statement) {
+ DROP_COUNT.incrementAndGet();
+ logStatement(StatementType.DROP, statement);
+ }
+
private static void logStatement(final StatementType type, final String statement) {
for (final StatementListener listener : LISTENERS) {
EXEC.execute(new Runnable() {
@@ -158,9 +168,13 @@ public class StatementLogger {
return SELECT_COUNT.longValue();
}
+ public static long getDropCount() {
+ return DROP_COUNT.longValue();
+ }
+
public static long getTotalCount() {
return getCreateCount() + getInsertCount() + getUpdateCount() + getDeleteCount() + getMergeCount()
- + getSelectCount();
+ + getSelectCount() + getDropCount();
}
public static void logStats() {
@@ -172,6 +186,7 @@ public class StatementLogger {
logStat(StatementType.MERGE, getMergeCount());
logStat(StatementType.DELETE, getDeleteCount());
logStat(StatementType.SELECT, getSelectCount());
+ logStat(StatementType.DROP, getDropCount());
logStatement(StatementType.STAT, "========================");
logStat(StatementType.TOTAL, getTotalCount());
}
diff --git a/tests/com/iciql/test/AnnotationsTest.java b/tests/com/iciql/test/AnnotationsTest.java
index 7e4e918..4f50d61 100644
--- a/tests/com/iciql/test/AnnotationsTest.java
+++ b/tests/com/iciql/test/AnnotationsTest.java
@@ -69,30 +69,24 @@ public class AnnotationsTest {
// test indexes are created, and columns are in the right order
DatabaseMetaData meta = db.getConnection().getMetaData();
boolean isH2 = meta.getDatabaseProductName().equals("H2");
- boolean isDerby = meta.getDatabaseProductName().equals("Apache Derby");
- ResultSet rs;
- if (isDerby) {
- // Derby defaults to USERNAME schema
- rs = meta.getIndexInfo(null, "SA", "ANNOTATEDPRODUCT", false, true);
- } else {
- // H2, HSQL default to PUBLIC schema
- rs = meta.getIndexInfo(null, "PUBLIC", "ANNOTATEDPRODUCT", false, true);
- }
+ String schema = IciqlSuite.getDefaultSchema(db);
+ ResultSet rs = meta.getIndexInfo(null, schema, "ANNOTATEDPRODUCT", false, true);
+
// first index is primary key index
// H2 gives this a testable name.
assertTrue(rs.next());
if (isH2) {
- assertStartsWith(rs.getString("INDEX_NAME"), "PRIMARY_KEY");
+ assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "PRIMARY_KEY");
}
assertTrue(rs.next());
- assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATEDPRODUCT_0");
- assertStartsWith(rs.getString("COLUMN_NAME"), "NAME");
+ assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "ANNOTATEDPRODUCT_0");
+ assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "NAME");
assertTrue(rs.next());
- assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATEDPRODUCT_0");
- assertStartsWith(rs.getString("COLUMN_NAME"), "CAT");
+ assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "ANNOTATEDPRODUCT_0");
+ assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "CAT");
assertTrue(rs.next());
- assertStartsWith(rs.getString("INDEX_NAME"), "NAMEIDX");
- assertStartsWith(rs.getString("COLUMN_NAME"), "NAME");
+ assertStartsWith(rs.getString("INDEX_NAME").toUpperCase(), "NAMEIDX");
+ assertStartsWith(rs.getString("COLUMN_NAME").toUpperCase(), "NAME");
assertFalse(rs.next());
}
diff --git a/tests/com/iciql/test/ClobTest.java b/tests/com/iciql/test/ClobTest.java
index 3b32dcb..49cee72 100644
--- a/tests/com/iciql/test/ClobTest.java
+++ b/tests/com/iciql/test/ClobTest.java
@@ -42,12 +42,14 @@ public class ClobTest {
db.executeUpdate(MessageFormat.format(create, "VARCHAR(255)"));
db.insertAll(StringRecord.getList());
testSimpleUpdate(db, "VARCHAR fail");
+ db.executeUpdate("DROP TABLE CLOB_TEST");
db.close();
db = IciqlSuite.openNewDb();
- db.executeUpdate(MessageFormat.format(create, "CLOB"));
+ db.executeUpdate(MessageFormat.format(create, db.getDialect().convertSqlType("CLOB")));
db.insertAll(StringRecord.getList());
testSimpleUpdate(db, "CLOB fail because of single quote artifacts");
+ db.executeUpdate("DROP TABLE CLOB_TEST");
db.close();
}
diff --git a/tests/com/iciql/test/IciqlSuite.java b/tests/com/iciql/test/IciqlSuite.java
index b91f3a4..0389d80 100644
--- a/tests/com/iciql/test/IciqlSuite.java
+++ b/tests/com/iciql/test/IciqlSuite.java
@@ -40,6 +40,20 @@ import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.iciql.Constants;
import com.iciql.Db;
+import com.iciql.test.models.BooleanModel;
+import com.iciql.test.models.ComplexObject;
+import com.iciql.test.models.Customer;
+import com.iciql.test.models.DefaultValuesModel;
+import com.iciql.test.models.EnumModels.EnumIdModel;
+import com.iciql.test.models.EnumModels.EnumOrdinalModel;
+import com.iciql.test.models.EnumModels.EnumStringModel;
+import com.iciql.test.models.Order;
+import com.iciql.test.models.PrimitivesModel;
+import com.iciql.test.models.Product;
+import com.iciql.test.models.ProductAnnotationOnly;
+import com.iciql.test.models.ProductInheritedAnnotation;
+import com.iciql.test.models.ProductMixedAnnotation;
+import com.iciql.test.models.SupportedTypes;
import com.iciql.util.StatementLogger;
import com.iciql.util.StatementLogger.StatementListener;
import com.iciql.util.StatementLogger.StatementType;
@@ -58,12 +72,13 @@ import com.iciql.util.StringUtils;
@RunWith(Suite.class)
@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class,
- RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UUIDTest.class })
+ RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UpgradesTest.class, UUIDTest.class })
public class IciqlSuite {
- private static final TestDb[] TEST_DBS = { new TestDb("H2", "jdbc:h2:mem:db{0,number,000}"),
- new TestDb("HSQL", "jdbc:hsqldb:mem:db{0,number,000}"),
- new TestDb("Derby", "jdbc:derby:memory:db{0,number,000};create=true") };
+ private static final TestDb[] TEST_DBS = { new TestDb("H2 (embedded)", "jdbc:h2:mem:db{0,number,000}"),
+ new TestDb("HSQL (embedded)", "jdbc:hsqldb:mem:db{0,number,000}"),
+ new TestDb("Derby (embedded)", "jdbc:derby:memory:db{0,number,000};create=true"),
+ new TestDb("MySQL (tcp/myisam)", "jdbc:mysql://localhost:3306/iciql") };
private static final TestDb DEFAULT_TEST_DB = TEST_DBS[0];
@@ -82,6 +97,13 @@ public class IciqlSuite {
value.startsWith(startsWith));
}
+ public static boolean equivalentTo(double expected, double actual) {
+ if (Double.compare(expected, actual) == 0) {
+ return true;
+ }
+ return Math.abs(expected - actual) <= 0.000001d;
+ }
+
/**
* Increment the database counter, open and create a new database.
*
@@ -93,7 +115,25 @@ public class IciqlSuite {
testUrl = DEFAULT_TEST_DB.url;
}
testUrl = MessageFormat.format(testUrl, openCount.incrementAndGet());
- return Db.open(testUrl, username, password);
+ Db db = Db.open(testUrl, username, password);
+
+ // drop tables
+ db.dropTable(BooleanModel.class);
+ db.dropTable(ComplexObject.class);
+ db.dropTable(Customer.class);
+ db.dropTable(DefaultValuesModel.class);
+ db.dropTable(EnumIdModel.class);
+ db.dropTable(EnumOrdinalModel.class);
+ db.dropTable(EnumStringModel.class);
+ db.dropTable(Order.class);
+ db.dropTable(PrimitivesModel.class);
+ db.dropTable(Product.class);
+ db.dropTable(ProductAnnotationOnly.class);
+ db.dropTable(ProductInheritedAnnotation.class);
+ db.dropTable(ProductMixedAnnotation.class);
+ db.dropTable(SupportedTypes.class);
+
+ return db;
}
/**
@@ -111,6 +151,15 @@ public class IciqlSuite {
}
/**
+ * Drops all tables from the current database.
+ *
+ * @return the current database
+ */
+ public static void dropAllTables(Db db) {
+
+ }
+
+ /**
* Returns the name of the underlying database engine for the Db object.
*
* @param db
@@ -146,6 +195,16 @@ public class IciqlSuite {
}
/**
+ * Returns true if the underlying database engine is MySQL.
+ *
+ * @param db
+ * @return true if underlying database engine is MySQL
+ */
+ public static boolean isMySQL(Db db) {
+ return IciqlSuite.getDatabaseEngineName(db).equals("MySQL");
+ }
+
+ /**
* Gets the default schema of the underlying database engine.
*
* @param db
@@ -155,7 +214,11 @@ public class IciqlSuite {
if (isDerby(db)) {
// Derby sets default schema name to username
return username.toUpperCase();
+ } else if (isMySQL(db)) {
+ // MySQL does not have schemas
+ return null;
}
+
return "PUBLIC";
}
@@ -206,8 +269,8 @@ public class IciqlSuite {
SuiteClasses suiteClasses = IciqlSuite.class.getAnnotation(SuiteClasses.class);
long quickestDatabase = Long.MAX_VALUE;
- String dividerMajor = buildDivider('*', 70);
- String dividerMinor = buildDivider('-', 70);
+ String dividerMajor = buildDivider('*', 79);
+ String dividerMinor = buildDivider('-', 79);
// Header
out.println(dividerMajor);
@@ -225,7 +288,7 @@ public class IciqlSuite {
showProperty("available processors", "" + Runtime.getRuntime().availableProcessors());
showProperty(
"available memory",
- MessageFormat.format("{0,number,#.0} GB", ((double) Runtime.getRuntime().maxMemory())
+ MessageFormat.format("{0,number,0.0} GB", ((double) Runtime.getRuntime().maxMemory())
/ (1024 * 1024)));
out.println();
@@ -246,32 +309,42 @@ public class IciqlSuite {
statementWriter.append("\n\n");
}
- System.setProperty("iciql.url", testDb.url);
- Result result = JUnitCore.runClasses(suiteClasses.value());
- testDb.runtime = result.getRunTime();
- if (testDb.runtime < quickestDatabase) {
- quickestDatabase = testDb.runtime;
- }
- testDb.statements = StatementLogger.getTotalCount() - lastCount;
- // reset total count for next database
- lastCount = StatementLogger.getTotalCount();
-
- out.println(MessageFormat.format(
- "{0} tests ({1} failures, {2} ignores) {3} statements in {4,number,0.000} secs",
- result.getRunCount(), result.getFailureCount(), result.getIgnoreCount(),
- testDb.statements, result.getRunTime() / 1000f));
-
- if (result.getFailureCount() == 0) {
- out.println();
+ if (testDb.getVersion().equals("OFFLINE")) {
+ // Database not available
+ out.println("Skipping. Could not find " + testDb.url);
} else {
- for (Failure failure : result.getFailures()) {
- out.println(MessageFormat.format("\n + {0}\n {1}\n", failure.getTestHeader(),
- failure.getMessage()));
+ // Test database
+ System.setProperty("iciql.url", testDb.url);
+ Result result = JUnitCore.runClasses(suiteClasses.value());
+ testDb.runtime = result.getRunTime();
+ if (testDb.runtime < quickestDatabase) {
+ quickestDatabase = testDb.runtime;
+ }
+ testDb.statements = StatementLogger.getTotalCount() - lastCount;
+ // reset total count for next database
+ lastCount = StatementLogger.getTotalCount();
+
+ out.println(MessageFormat.format(
+ "{0} tests ({1} failures, {2} ignores) {3} statements in {4,number,0.000} secs",
+ result.getRunCount(), result.getFailureCount(), result.getIgnoreCount(),
+ testDb.statements, result.getRunTime() / 1000f));
+
+ if (result.getFailureCount() == 0) {
+ out.println();
+ out.println(" 100% successful test suite run.");
+ out.println();
+ } else {
+ for (Failure failure : result.getFailures()) {
+ out.println(MessageFormat.format("\n + {0}\n {1}", failure.getTestHeader(),
+ failure.getMessage()));
+ }
+ out.println();
}
}
}
// Display runtime results sorted by performance leader
+ out.println();
out.println(dividerMajor);
out.println(MessageFormat.format("{0} {1} ({2}) test suite performance results", Constants.NAME,
Constants.VERSION, Constants.VERSION_DATE));
@@ -281,6 +354,12 @@ public class IciqlSuite {
@Override
public int compare(TestDb o1, TestDb o2) {
+ if (o1.runtime == 0) {
+ return 1;
+ }
+ if (o2.runtime == 0) {
+ return -1;
+ }
if (o1.runtime == o2.runtime) {
return 0;
}
@@ -292,11 +371,11 @@ public class IciqlSuite {
});
for (TestDb testDb : dbs) {
out.println(MessageFormat.format(
- "{0} {1} {2,number,0.0} stats/sec {3,number,0.000} secs ({4,number,#.0}x)",
- StringUtils.pad(testDb.name, 6, " ", true),
- StringUtils.pad(testDb.getVersion(), 22, " ", true),
- ((double) testDb.statements)/ (testDb.runtime/1000d), testDb.runtime / 1000f,
- ((double) testDb.runtime) / quickestDatabase));
+ "{0} {1} {2,number,0} stats/sec {3,number,0.000} secs ({4,number,0.0}x)",
+ StringUtils.pad(testDb.name, 20, " ", true),
+ StringUtils.pad(testDb.getVersion(), 22, " ", true), ((double) testDb.statements)
+ / (testDb.runtime / 1000d), testDb.runtime / 1000f, ((double) testDb.runtime)
+ / quickestDatabase));
}
// close PrintStream and restore System.err
@@ -362,8 +441,8 @@ public class IciqlSuite {
version = db.getConnection().getMetaData().getDatabaseProductVersion();
db.close();
return version;
- } catch (SQLException s) {
- version = "";
+ } catch (Throwable t) {
+ version = "OFFLINE";
}
}
return version;
diff --git a/tests/com/iciql/test/ModelsTest.java b/tests/com/iciql/test/ModelsTest.java
index 9bbf450..d2e02fa 100644
--- a/tests/com/iciql/test/ModelsTest.java
+++ b/tests/com/iciql/test/ModelsTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertTrue;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Before;
@@ -33,15 +32,12 @@ import org.junit.rules.ErrorCollector;
import com.iciql.Db;
import com.iciql.DbInspector;
-import com.iciql.DbUpgrader;
-import com.iciql.DbVersion;
-import com.iciql.Iciql.IQVersion;
import com.iciql.ValidationRemark;
import com.iciql.test.models.Product;
import com.iciql.test.models.ProductAnnotationOnly;
import com.iciql.test.models.ProductMixedAnnotation;
import com.iciql.test.models.SupportedTypes;
-import com.iciql.test.models.SupportedTypes.SupportedTypes2;
+import com.iciql.util.StringUtils;
/**
* Test that the mapping between classes and tables is done correctly.
@@ -72,13 +68,9 @@ public class ModelsTest {
@Test
public void testValidateModels() {
- boolean isH2 = IciqlSuite.isH2(db);
- boolean isDerby = IciqlSuite.isDerby(db);
String schemaName = IciqlSuite.getDefaultSchema(db);
-
DbInspector inspector = new DbInspector(db);
- validateModel(inspector, schemaName, new Product(), 3);
- validateModel(inspector, schemaName, new ProductAnnotationOnly(), (isH2 || isDerby) ? 2 : 3);
+ validateModel(inspector, schemaName, new ProductAnnotationOnly(), 2);
validateModel(inspector, schemaName, new ProductMixedAnnotation(), 4);
}
@@ -95,8 +87,14 @@ public class ModelsTest {
errorCollector.addError(new SQLException(remark.toString()));
}
}
- assertTrue(remarks.get(0).message.equals(MessageFormat.format("@IQSchema(name={0})", schemaName)));
- assertEquals(sb.toString(), expected, remarks.size());
+
+ if (StringUtils.isNullOrEmpty(schemaName)) {
+ // no schema expected
+ assertEquals(sb.toString(), expected - 1, remarks.size());
+ } else {
+ assertEquals(sb.toString(), expected, remarks.size());
+ assertEquals(MessageFormat.format("@IQSchema(\"{0}\")", schemaName), remarks.get(0).message);
+ }
}
@Test
@@ -133,65 +131,4 @@ public class ModelsTest {
assertEquals(1489, models.get(0).length());
}
}
-
- @Test
- public void testDatabaseUpgrade() {
- // insert a database version record
- db.insert(new DbVersion(1));
-
- TestDbUpgrader dbUpgrader = new TestDbUpgrader();
- db.setDbUpgrader(dbUpgrader);
-
- List<SupportedTypes> original = SupportedTypes.createList();
- db.insertAll(original);
-
- assertEquals(1, dbUpgrader.oldVersion.get());
- assertEquals(2, dbUpgrader.newVersion.get());
- }
-
- @Test
- public void testTableUpgrade() {
- Db db = IciqlSuite.openNewDb();
-
- // insert first, this will create version record automatically
- List<SupportedTypes> original = SupportedTypes.createList();
- db.insertAll(original);
-
- // reset the dbUpgrader (clears the update check cache)
- TestDbUpgrader dbUpgrader = new TestDbUpgrader();
- db.setDbUpgrader(dbUpgrader);
-
- SupportedTypes2 s2 = new SupportedTypes2();
-
- List<SupportedTypes2> types = db.from(s2).select();
- assertEquals(10, types.size());
- assertEquals(1, dbUpgrader.oldVersion.get());
- assertEquals(2, dbUpgrader.newVersion.get());
- db.close();
- }
-
- /**
- * A sample database upgrader class.
- */
- @IQVersion(2)
- class TestDbUpgrader implements DbUpgrader {
- final AtomicInteger oldVersion = new AtomicInteger(0);
- final AtomicInteger newVersion = new AtomicInteger(0);
-
- public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) {
- // just claims success on upgrade request
- oldVersion.set(fromVersion);
- newVersion.set(toVersion);
- return true;
- }
-
- public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
- // just claims success on upgrade request
- oldVersion.set(fromVersion);
- newVersion.set(toVersion);
- return true;
- }
-
- }
-
}
diff --git a/tests/com/iciql/test/SamplesTest.java b/tests/com/iciql/test/SamplesTest.java
index f16672a..17c2151 100644
--- a/tests/com/iciql/test/SamplesTest.java
+++ b/tests/com/iciql/test/SamplesTest.java
@@ -91,6 +91,7 @@ public class SamplesTest {
TestReverse check = db.from(new TestReverse()).selectFirst();
assertEquals(t.name, check.name);
assertEquals(t.id, check.id);
+ db.executeUpdate("DROP TABLE testreverse");
}
@Test
@@ -238,7 +239,8 @@ public class SamplesTest {
public void testIsNull() {
Product p = new Product();
String sql = db.from(p).whereTrue(isNull(p.productName)).getSQL();
- assertEquals("SELECT * FROM Product WHERE (productName IS NULL)", sql);
+ assertEquals("SELECT * FROM Product WHERE (" + db.getDialect().prepareColumnName("productName")
+ + " IS NULL)", sql);
}
@Test
@@ -258,11 +260,13 @@ public class SamplesTest {
public void testOrAndNot() {
Product p = new Product();
String sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();
- assertEquals("SELECT * FROM Product WHERE (NOT productName IS NULL)", sql);
+ String productName = db.getDialect().prepareColumnName("productName");
+ assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);
sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();
- assertEquals("SELECT * FROM Product WHERE (NOT productName IS NULL)", sql);
+ assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);
sql = db.from(p).whereTrue(db.test(p.productId).is(1)).getSQL();
- assertEquals("SELECT * FROM Product WHERE ((productId = ?))", sql);
+ String productId = db.getDialect().prepareColumnName("productId");
+ assertEquals("SELECT * FROM Product WHERE ((" + productId + " = ?))", sql);
}
@Test
@@ -316,8 +320,24 @@ public class SamplesTest {
.lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello")
.and(co.time).lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value)
.is(new BigDecimal("1")).getSQL();
- assertEquals("SELECT * FROM ComplexObject WHERE id = ? AND amount = ? "
- + "AND birthday < ? AND created < ? AND name = ? AND time < ? AND value = ?", sql);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("SELECT * FROM ComplexObject WHERE ");
+ sb.append(db.getDialect().prepareColumnName("id"));
+ sb.append(" = ? AND ");
+ sb.append(db.getDialect().prepareColumnName("amount"));
+ sb.append(" = ? AND ");
+ sb.append(db.getDialect().prepareColumnName("birthday"));
+ sb.append(" < ? AND ");
+ sb.append(db.getDialect().prepareColumnName("created"));
+ sb.append(" < ? AND ");
+ sb.append(db.getDialect().prepareColumnName("name"));
+ sb.append(" = ? AND ");
+ sb.append(db.getDialect().prepareColumnName("time"));
+ sb.append(" < ? AND ");
+ sb.append(db.getDialect().prepareColumnName("value"));
+ sb.append(" = ?");
+ assertEquals(sb.toString(), sql);
long count = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday)
.lessThan(new java.util.Date()).and(co.created)
@@ -340,7 +360,14 @@ public class SamplesTest {
return co.id == x && co.name.equals(name) && co.name.equals("hello");
}
}).getSQL();
- assertEquals("SELECT * FROM ComplexObject WHERE id=? AND ?=name AND 'hello'=name", sql);
+ StringBuilder sb = new StringBuilder();
+ sb.append("SELECT * FROM ComplexObject WHERE ");
+ sb.append(db.getDialect().prepareColumnName("id"));
+ sb.append("=? AND ?=");
+ sb.append(db.getDialect().prepareColumnName("name"));
+ sb.append(" AND 'hello'=");
+ sb.append(db.getDialect().prepareColumnName("name"));
+ assertEquals(sb.toString(), sql);
long count = db.from(co).where(new Filter() {
public boolean where() {
diff --git a/tests/com/iciql/test/UUIDTest.java b/tests/com/iciql/test/UUIDTest.java
index bc3bd12..9b88cb8 100644
--- a/tests/com/iciql/test/UUIDTest.java
+++ b/tests/com/iciql/test/UUIDTest.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.UUID;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -52,10 +53,9 @@ public class UUIDTest {
@Test
public void testUUIDs() throws Exception {
- if (!IciqlSuite.isH2(db)) {
- // do not test non-H2 databases
- return;
- }
+ // do not test non-H2 databases
+ Assume.assumeTrue(IciqlSuite.isH2(db));
+
List<UUIDRecord> originals = UUIDRecord.getList();
db.insertAll(originals);
UUIDRecord u = new UUIDRecord();
diff --git a/tests/com/iciql/test/UpgradesTest.java b/tests/com/iciql/test/UpgradesTest.java
new file mode 100644
index 0000000..d4c15e1
--- /dev/null
+++ b/tests/com/iciql/test/UpgradesTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2011 James Moger.
+ *
+ * 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 com.iciql.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import com.iciql.Db;
+import com.iciql.DbUpgrader;
+import com.iciql.Iciql.IQVersion;
+import com.iciql.test.models.Product;
+import com.iciql.test.models.SupportedTypes;
+import com.iciql.test.models.SupportedTypes.SupportedTypes2;
+
+/**
+ * Tests the database and table upgrade functions.
+ *
+ */
+public class UpgradesTest {
+
+ @Test
+ public void testDatabaseUpgrade() {
+ Db db = IciqlSuite.openNewDb();
+
+ List<Product> products = Product.getList();
+
+ // set the v1 upgrader and insert a record.
+ // this will trigger the upgrade.
+ V1DbUpgrader v1 = new V1DbUpgrader();
+ db.setDbUpgrader(v1);
+ db.insert(products.get(0));
+
+ // confirm that upgrade occurred
+ assertEquals(0, v1.oldVersion.get());
+ assertEquals(1, v1.newVersion.get());
+
+ // open a second connection to the database
+ // and then apply the v2 upgrade.
+ // For H2 its important to keep the first connection
+ // alive so that the database is not destroyed.
+ Db db2 = IciqlSuite.openCurrentDb();
+
+ // set the v2 upgrader and insert a record.
+ // this will trigger the upgrade.
+ V2DbUpgrader v2 = new V2DbUpgrader();
+ db2.setDbUpgrader(v2);
+ db2.insert(products.get(1));
+
+ // confirm that upgrade occurred
+ assertEquals(1, v2.oldVersion.get());
+ assertEquals(2, v2.newVersion.get());
+
+ db.executeUpdate("DROP TABLE iq_versions");
+ db.close();
+ db2.close();
+ }
+
+ @Test
+ public void testTableUpgrade() {
+ Db db = IciqlSuite.openNewDb();
+
+ // insert first, this will create version record automatically
+ List<SupportedTypes> original = SupportedTypes.createList();
+ db.insertAll(original);
+
+ // reset the dbUpgrader (clears the update check cache)
+ V2DbUpgrader dbUpgrader = new V2DbUpgrader();
+ db.setDbUpgrader(dbUpgrader);
+
+ SupportedTypes2 s2 = new SupportedTypes2();
+
+ List<SupportedTypes2> types = db.from(s2).select();
+ assertEquals(10, types.size());
+ assertEquals(1, dbUpgrader.oldVersion.get());
+ assertEquals(2, dbUpgrader.newVersion.get());
+ db.executeUpdate("DROP TABLE iq_versions");
+ db.close();
+ }
+
+ /**
+ * A sample database upgrader class.
+ */
+ class BaseDbUpgrader implements DbUpgrader {
+ final AtomicInteger oldVersion = new AtomicInteger(0);
+ final AtomicInteger newVersion = new AtomicInteger(0);
+
+ public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) {
+ // just claims success on upgrade request
+ oldVersion.set(fromVersion);
+ newVersion.set(toVersion);
+ return true;
+ }
+
+ public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
+ // just claims success on upgrade request
+ oldVersion.set(fromVersion);
+ newVersion.set(toVersion);
+ return true;
+ }
+ }
+
+ /**
+ * A sample V1 database upgrader class.
+ */
+ @IQVersion(1)
+ class V1DbUpgrader extends BaseDbUpgrader {
+ }
+
+ /**
+ * A sample V2 database upgrader class.
+ */
+ @IQVersion(2)
+ class V2DbUpgrader extends BaseDbUpgrader {
+ }
+
+}
diff --git a/tests/com/iciql/test/models/PrimitivesModel.java b/tests/com/iciql/test/models/PrimitivesModel.java
index 0affd28..44e8b9b 100644
--- a/tests/com/iciql/test/models/PrimitivesModel.java
+++ b/tests/com/iciql/test/models/PrimitivesModel.java
@@ -21,6 +21,7 @@ import java.util.Random;
import com.iciql.Iciql.IQColumn;
import com.iciql.Iciql.IQTable;
+import com.iciql.test.IciqlSuite;
/**
* Primitive types model.
@@ -67,8 +68,8 @@ public class PrimitivesModel {
same &= myShort == p.myShort;
same &= myByte == p.myByte;
same &= myBoolean == p.myBoolean;
- same &= myDouble == p.myDouble;
- same &= myFloat == p.myFloat;
+ same &= IciqlSuite.equivalentTo(myDouble, p.myDouble);
+ same &= IciqlSuite.equivalentTo(myFloat, p.myFloat);
return same;
}
diff --git a/tests/com/iciql/test/models/ProductAnnotationOnly.java b/tests/com/iciql/test/models/ProductAnnotationOnly.java
index 80bf0a1..e4de22d 100644
--- a/tests/com/iciql/test/models/ProductAnnotationOnly.java
+++ b/tests/com/iciql/test/models/ProductAnnotationOnly.java
@@ -34,12 +34,9 @@ import com.iciql.Iciql.IndexType;
@IQIndexes({ @IQIndex({ "name", "cat" }), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name") })
public class ProductAnnotationOnly {
- @IQColumn(autoIncrement = true)
- public Integer autoIncrement;
-
public String unmappedField;
- @IQColumn(name = "id")
+ @IQColumn(name = "id", autoIncrement = true)
public Integer productId;
@IQColumn(name = "cat", length = 15, trim = true)
diff --git a/tests/com/iciql/test/models/SupportedTypes.java b/tests/com/iciql/test/models/SupportedTypes.java
index 596af74..1aaa833 100644
--- a/tests/com/iciql/test/models/SupportedTypes.java
+++ b/tests/com/iciql/test/models/SupportedTypes.java
@@ -32,6 +32,7 @@ import com.iciql.Iciql.IQIndexes;
import com.iciql.Iciql.IQTable;
import com.iciql.Iciql.IQVersion;
import com.iciql.Iciql.IndexType;
+import com.iciql.test.IciqlSuite;
import com.iciql.test.models.EnumModels.Tree;
import com.iciql.util.Utils;
@@ -166,8 +167,8 @@ public class SupportedTypes {
same &= myShort.equals(s.myShort);
same &= myInteger.equals(s.myInteger);
same &= myLong.equals(s.myLong);
- same &= myFloat.equals(s.myFloat);
- same &= myDouble.equals(s.myDouble);
+ same &= IciqlSuite.equivalentTo(myFloat, s.myFloat);
+ same &= IciqlSuite.equivalentTo(myDouble, s.myDouble);
same &= myBigDecimal.compareTo(s.myBigDecimal) == 0;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
same &= df.format(myUtilDate).equals(df.format(s.myUtilDate));