diff options
author | James Moger <james.moger@gmail.com> | 2011-08-16 15:32:56 -0400 |
---|---|---|
committer | James Moger <james.moger@gmail.com> | 2011-08-16 15:32:56 -0400 |
commit | d95e16170d063c0b74d04e6636e8fddbfa120689 (patch) | |
tree | a8157992ef14cb8f4392b847fbc8892cb30245d5 /src/com | |
parent | 8193609af00aa9529ed7b3090b5739c4e95b12c4 (diff) | |
download | iciql-d95e16170d063c0b74d04e6636e8fddbfa120689.tar.gz iciql-d95e16170d063c0b74d04e6636e8fddbfa120689.zip |
Finished MySQL dialect; v5.0.51b 100% tested. Added Db.dropTable(T)
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/iciql/Db.java | 42 | ||||
-rw-r--r-- | src/com/iciql/IciqlException.java | 18 | ||||
-rw-r--r-- | src/com/iciql/SQLDialect.java | 16 | ||||
-rw-r--r-- | src/com/iciql/SQLDialectDefault.java | 11 | ||||
-rw-r--r-- | src/com/iciql/SQLDialectDerby.java | 10 | ||||
-rw-r--r-- | src/com/iciql/SQLDialectMySQL.java | 41 | ||||
-rw-r--r-- | src/com/iciql/TableDefinition.java | 3 | ||||
-rw-r--r-- | src/com/iciql/TableInspector.java | 6 | ||||
-rw-r--r-- | src/com/iciql/build/Build.java | 10 | ||||
-rw-r--r-- | src/com/iciql/util/StatementLogger.java | 25 |
10 files changed, 147 insertions, 35 deletions
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()); } |