aboutsummaryrefslogtreecommitdiffstats
path: root/src/com
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 /src/com
parent8193609af00aa9529ed7b3090b5739c4e95b12c4 (diff)
downloadiciql-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.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
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());
}