]> source.dussan.org Git - iciql.git/commitdiff
Reformat project with default IntelliJ settings
authorJames Moger <james.moger@gitblit.com>
Tue, 5 Apr 2016 16:27:55 +0000 (12:27 -0400)
committerJames Moger <james.moger@gitblit.com>
Tue, 5 Apr 2016 16:27:55 +0000 (12:27 -0400)
132 files changed:
pom.xml
src/main/java/com/iciql/CompareType.java
src/main/java/com/iciql/Condition.java
src/main/java/com/iciql/ConditionAndOr.java
src/main/java/com/iciql/ConditionOpenClose.java
src/main/java/com/iciql/Constants.java
src/main/java/com/iciql/Dao.java
src/main/java/com/iciql/DaoClasspathStatementProvider.java
src/main/java/com/iciql/DaoProxy.java
src/main/java/com/iciql/DaoStatementProvider.java
src/main/java/com/iciql/Db.java
src/main/java/com/iciql/DbInspector.java
src/main/java/com/iciql/DbUpgrader.java
src/main/java/com/iciql/DbVersion.java
src/main/java/com/iciql/Define.java
src/main/java/com/iciql/Filter.java
src/main/java/com/iciql/Function.java
src/main/java/com/iciql/Iciql.java
src/main/java/com/iciql/IciqlException.java
src/main/java/com/iciql/ModelUtils.java
src/main/java/com/iciql/NestedConditions.java
src/main/java/com/iciql/OrderExpression.java
src/main/java/com/iciql/Query.java
src/main/java/com/iciql/QueryBetween.java
src/main/java/com/iciql/QueryCondition.java
src/main/java/com/iciql/QueryJoin.java
src/main/java/com/iciql/QueryJoinCondition.java
src/main/java/com/iciql/QueryWhere.java
src/main/java/com/iciql/RuntimeParameter.java
src/main/java/com/iciql/RuntimeToken.java
src/main/java/com/iciql/SQLDialect.java
src/main/java/com/iciql/SQLDialectDefault.java
src/main/java/com/iciql/SQLDialectDerby.java
src/main/java/com/iciql/SQLDialectH2.java
src/main/java/com/iciql/SQLDialectHSQL.java
src/main/java/com/iciql/SQLDialectMSSQL.java
src/main/java/com/iciql/SQLDialectMySQL.java
src/main/java/com/iciql/SQLDialectPostgreSQL.java
src/main/java/com/iciql/SQLDialectSQLite.java
src/main/java/com/iciql/SQLStatement.java
src/main/java/com/iciql/SelectColumn.java
src/main/java/com/iciql/SelectTable.java
src/main/java/com/iciql/SubQuery.java
src/main/java/com/iciql/SubQueryCondition.java
src/main/java/com/iciql/TableDefinition.java
src/main/java/com/iciql/TableInspector.java
src/main/java/com/iciql/TestCondition.java
src/main/java/com/iciql/Token.java
src/main/java/com/iciql/UpdateColumn.java
src/main/java/com/iciql/UpdateColumnIncrement.java
src/main/java/com/iciql/UpdateColumnSet.java
src/main/java/com/iciql/ValidationRemark.java
src/main/java/com/iciql/adapter/GsonTypeAdapter.java
src/main/java/com/iciql/adapter/JavaSerializationTypeAdapter.java
src/main/java/com/iciql/adapter/SnakeYamlTypeAdapter.java
src/main/java/com/iciql/adapter/XStreamTypeAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonObjectAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonStringAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonbObjectAdapter.java
src/main/java/com/iciql/adapter/postgresql/JsonbStringAdapter.java
src/main/java/com/iciql/adapter/postgresql/XmlObjectAdapter.java
src/main/java/com/iciql/adapter/postgresql/XmlStringAdapter.java
src/main/java/com/iciql/bytecode/And.java
src/main/java/com/iciql/bytecode/ArrayGet.java
src/main/java/com/iciql/bytecode/CaseWhen.java
src/main/java/com/iciql/bytecode/ClassReader.java
src/main/java/com/iciql/bytecode/Constant.java
src/main/java/com/iciql/bytecode/ConstantNumber.java
src/main/java/com/iciql/bytecode/ConstantString.java
src/main/java/com/iciql/bytecode/Function.java
src/main/java/com/iciql/bytecode/Not.java
src/main/java/com/iciql/bytecode/Null.java
src/main/java/com/iciql/bytecode/Operation.java
src/main/java/com/iciql/bytecode/Or.java
src/main/java/com/iciql/bytecode/Variable.java
src/main/java/com/iciql/bytecode/package.html
src/main/java/com/iciql/package.html
src/main/java/com/iciql/util/GenerateModels.java
src/main/java/com/iciql/util/IciqlLogger.java
src/main/java/com/iciql/util/JdbcUtils.java
src/main/java/com/iciql/util/Slf4jIciqlListener.java
src/main/java/com/iciql/util/StatementBuilder.java
src/main/java/com/iciql/util/StringUtils.java
src/main/java/com/iciql/util/Utils.java
src/main/java/com/iciql/util/WeakIdentityHashMap.java
src/main/java/com/iciql/util/package.html
src/main/java/java/lang/AutoCloseable.java
src/test/java/com/iciql/test/AliasMapTest.java
src/test/java/com/iciql/test/AnnotationsTest.java
src/test/java/com/iciql/test/BooleanModelTest.java
src/test/java/com/iciql/test/ClobTest.java
src/test/java/com/iciql/test/ConcurrencyTest.java
src/test/java/com/iciql/test/DataTypeAdapterTest.java
src/test/java/com/iciql/test/DefaultValuesTest.java
src/test/java/com/iciql/test/EnumsTest.java
src/test/java/com/iciql/test/ForeignKeyTest.java
src/test/java/com/iciql/test/IciqlSuite.java
src/test/java/com/iciql/test/JoinTest.java
src/test/java/com/iciql/test/ModelsTest.java
src/test/java/com/iciql/test/NestedConditionsTest.java
src/test/java/com/iciql/test/OneOfTest.java
src/test/java/com/iciql/test/PrimitivesTest.java
src/test/java/com/iciql/test/ProductDaoTest.java
src/test/java/com/iciql/test/RuntimeQueryTest.java
src/test/java/com/iciql/test/SamplesTest.java
src/test/java/com/iciql/test/TransactionTest.java
src/test/java/com/iciql/test/UUIDTest.java
src/test/java/com/iciql/test/UpdateTest.java
src/test/java/com/iciql/test/UpgradesTest.java
src/test/java/com/iciql/test/ViewsTest.java
src/test/java/com/iciql/test/models/BooleanModel.java
src/test/java/com/iciql/test/models/CategoryAnnotationOnly.java
src/test/java/com/iciql/test/models/ComplexObject.java
src/test/java/com/iciql/test/models/Customer.java
src/test/java/com/iciql/test/models/DefaultValuesModel.java
src/test/java/com/iciql/test/models/EnumModels.java
src/test/java/com/iciql/test/models/MultipleBoolsModel.java
src/test/java/com/iciql/test/models/Order.java
src/test/java/com/iciql/test/models/PrimitivesModel.java
src/test/java/com/iciql/test/models/Product.java
src/test/java/com/iciql/test/models/ProductAnnotationOnly.java
src/test/java/com/iciql/test/models/ProductAnnotationOnlyWithForeignKey.java
src/test/java/com/iciql/test/models/ProductInheritedAnnotation.java
src/test/java/com/iciql/test/models/ProductMixedAnnotation.java
src/test/java/com/iciql/test/models/ProductNoCreateTable.java
src/test/java/com/iciql/test/models/ProductView.java
src/test/java/com/iciql/test/models/ProductViewFromQuery.java
src/test/java/com/iciql/test/models/ProductViewInherited.java
src/test/java/com/iciql/test/models/ProductViewInheritedComplex.java
src/test/java/com/iciql/test/models/StaticQueries.java
src/test/java/com/iciql/test/models/SupportedTypes.java
src/test/resources/iciql.properties

diff --git a/pom.xml b/pom.xml
index 8a584e171ef27eef229bb8017db978ccf91ec660..ec378fbbcb080d8a4871ceb631bde75da48d9ddb 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
     <modelVersion>4.0.0</modelVersion>
 
index 87ce77e1bc91bbfc847f2b1a5156ad7ff24589fa..c97c0c8daae55ed9f8b19e0501f0d99ebb9b2975 100644 (file)
@@ -22,24 +22,24 @@ package com.iciql;
  */\r
 \r
 enum CompareType {\r
-       EQUAL("=", true), EXCEEDS(">", true), AT_LEAST(">=", true), LESS_THAN("<", true), AT_MOST("<=", true), NOT_EQUAL(\r
-                       "<>", true), IS_NOT_NULL("IS NOT NULL", false), IS_NULL("IS NULL", false), LIKE("LIKE", true), BETWEEN(\r
-                       "BETWEEN", true), IN("IN", true), NOT_IN("NOT IN", true);\r
+    EQUAL("=", true), EXCEEDS(">", true), AT_LEAST(">=", true), LESS_THAN("<", true), AT_MOST("<=", true), NOT_EQUAL(\r
+            "<>", true), IS_NOT_NULL("IS NOT NULL", false), IS_NULL("IS NULL", false), LIKE("LIKE", true), BETWEEN(\r
+            "BETWEEN", true), IN("IN", true), NOT_IN("NOT IN", true);\r
 \r
-       private String text;\r
-       private boolean hasRightExpression;\r
+    private String text;\r
+    private boolean hasRightExpression;\r
 \r
-       CompareType(String text, boolean hasRightExpression) {\r
-               this.text = text;\r
-               this.hasRightExpression = hasRightExpression;\r
-       }\r
+    CompareType(String text, boolean hasRightExpression) {\r
+        this.text = text;\r
+        this.hasRightExpression = hasRightExpression;\r
+    }\r
 \r
-       String getString() {\r
-               return text;\r
-       }\r
+    String getString() {\r
+        return text;\r
+    }\r
 \r
-       boolean hasRightExpression() {\r
-               return hasRightExpression;\r
-       }\r
+    boolean hasRightExpression() {\r
+        return hasRightExpression;\r
+    }\r
 \r
 }\r
index 0ed1d06e4ec3ace00eb4a39e63b65a0609a7d991..ab5a5e34e41bc583bb7e07fc3300e61fa3d43043 100644 (file)
@@ -19,56 +19,55 @@ package com.iciql;
 \r
 /**\r
  * A condition contains one or two operands and a compare operation.\r
- * \r
- * @param <A>\r
- *            the operand type\r
+ *\r
+ * @param <A> the operand type\r
  */\r
 \r
 class Condition<A> implements Token {\r
-       CompareType compareType;\r
-       A x, y, z;\r
-       Iterable<A> i;\r
+    CompareType compareType;\r
+    A x, y, z;\r
+    Iterable<A> i;\r
 \r
-       Condition(A x, CompareType compareType) {\r
-               this(x, null, null, null, compareType);\r
-       }\r
+    Condition(A x, CompareType compareType) {\r
+        this(x, null, null, null, compareType);\r
+    }\r
 \r
-       Condition(A x, A y, CompareType compareType) {\r
-               this(x, y, null, null, compareType);\r
-       }\r
+    Condition(A x, A y, CompareType compareType) {\r
+        this(x, y, null, null, compareType);\r
+    }\r
 \r
-       Condition(A x, A y, A z, CompareType compareType) {\r
-               this(x, y, z, null, compareType);\r
-       }\r
+    Condition(A x, A y, A z, CompareType compareType) {\r
+        this(x, y, z, null, compareType);\r
+    }\r
 \r
-       Condition(A x, Iterable<A> i, CompareType compareType) {\r
-               this(x,  null, null, i, compareType);\r
-       }\r
+    Condition(A x, Iterable<A> i, CompareType compareType) {\r
+        this(x, null, null, i, compareType);\r
+    }\r
 \r
-       Condition(A x, A y, A z, Iterable<A> i, CompareType compareType) {\r
-               this.compareType = compareType;\r
-               this.x = x;\r
-               this.y = y;\r
-               this.z = z;\r
-               this.i = i;\r
-       }\r
+    Condition(A x, A y, A z, Iterable<A> i, CompareType compareType) {\r
+        this.compareType = compareType;\r
+        this.x = x;\r
+        this.y = y;\r
+        this.z = z;\r
+        this.i = i;\r
+    }\r
 \r
-       @SuppressWarnings("unchecked")\r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               query.appendSQL(stat, null, x);\r
-               stat.appendSQL(" ");\r
-               stat.appendSQL(compareType.getString());\r
-               if (compareType.hasRightExpression()) {\r
-                       if (i == null) {\r
-                               stat.appendSQL(" ");\r
-                               if (z == null) {\r
-                                       query.appendSQL(stat, x, y);\r
-                               } else {\r
-                                       query.appendSQL(stat, x, y, z, compareType);\r
-                               }\r
-                       } else {\r
-                               query.appendSQL(stat, x, (Iterable<Object>)i, compareType);\r
-                       }\r
-               }\r
-       }\r
+    @SuppressWarnings("unchecked")\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        query.appendSQL(stat, null, x);\r
+        stat.appendSQL(" ");\r
+        stat.appendSQL(compareType.getString());\r
+        if (compareType.hasRightExpression()) {\r
+            if (i == null) {\r
+                stat.appendSQL(" ");\r
+                if (z == null) {\r
+                    query.appendSQL(stat, x, y);\r
+                } else {\r
+                    query.appendSQL(stat, x, y, z, compareType);\r
+                }\r
+            } else {\r
+                query.appendSQL(stat, x, (Iterable<Object>) i, compareType);\r
+            }\r
+        }\r
+    }\r
 }\r
index 4d1cd0e2e86f875df327fff81c89665563c5b804..228fa9a21c117ce560624e1c1b57531636134728 100644 (file)
@@ -22,16 +22,16 @@ package com.iciql;
  */\r
 \r
 enum ConditionAndOr implements Token {\r
-       AND("AND"), OR("OR");\r
+    AND("AND"), OR("OR");\r
 \r
-       private String text;\r
+    private String text;\r
 \r
-       ConditionAndOr(String text) {\r
-               this.text = text;\r
-       }\r
+    ConditionAndOr(String text) {\r
+        this.text = text;\r
+    }\r
 \r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               stat.appendSQL(text);\r
-       }\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        stat.appendSQL(text);\r
+    }\r
 \r
 }\r
index 5284abd489a6a3327d2dd44383c8e88ee38a6560..c0d6ea4ef30dc3fc313fb732c429cd1b0ae11f38 100644 (file)
 package com.iciql;
 
 enum ConditionOpenClose implements Token {
-       OPEN("("), CLOSE(")");
+    OPEN("("), CLOSE(")");
 
-       private String text;
+    private String text;
 
-       ConditionOpenClose(String text) {
-               this.text = text;
-       }
+    ConditionOpenClose(String text) {
+        this.text = text;
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               stat.appendSQL(text);
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        stat.appendSQL(text);
+    }
 
 }
index e27e24a7f0da2950cbb655c05c3a5cfa97eb1239..8c8b8986634cde4c0bf871c72d569d339ae3dc11 100644 (file)
@@ -25,38 +25,38 @@ import java.util.jar.Manifest;
  */\r
 public class Constants {\r
 \r
-       public static final String NAME = "iciql";\r
-\r
-       // The build script extracts this exact line so be careful editing it\r
-       // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String API_CURRENT = "15";\r
-\r
-       public static String getVersion() {\r
-               return getManifestValue("implementation-version", "0.0.0-SNAPSHOT");\r
-       }\r
-\r
-       public static String getBuildDate() {\r
-               return getManifestValue("build-date", "PENDING");\r
-       }\r
-\r
-       private static String getManifestValue(String attrib, String defaultValue) {\r
-               Class<?> clazz = Constants.class;\r
-               String className = clazz.getSimpleName() + ".class";\r
-               String classPath = clazz.getResource(className).toString();\r
-               try {\r
-                       String manifestPath;\r
-                       if (classPath.indexOf('!') > -1) {\r
-                               manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";\r
-                       } else {\r
-                               String pkgPath = "/" + clazz.getPackage().getName().replace('.', '/');\r
-                               manifestPath = classPath.substring(0, classPath.indexOf(pkgPath))  + "/META-INF/MANIFEST.MF";\r
-                       }\r
-                       Manifest manifest = new Manifest(new URL(manifestPath).openStream());\r
-                       Attributes attr = manifest.getMainAttributes();\r
-                       String value = attr.getValue(attrib);\r
-                       return value;\r
-               } catch (Exception e) {\r
-               }\r
-               return defaultValue;\r
-       }\r
+    public static final String NAME = "iciql";\r
+\r
+    // The build script extracts this exact line so be careful editing it\r
+    // and only use A-Z a-z 0-9 .-_ in the string.\r
+    public static final String API_CURRENT = "15";\r
+\r
+    public static String getVersion() {\r
+        return getManifestValue("implementation-version", "0.0.0-SNAPSHOT");\r
+    }\r
+\r
+    public static String getBuildDate() {\r
+        return getManifestValue("build-date", "PENDING");\r
+    }\r
+\r
+    private static String getManifestValue(String attrib, String defaultValue) {\r
+        Class<?> clazz = Constants.class;\r
+        String className = clazz.getSimpleName() + ".class";\r
+        String classPath = clazz.getResource(className).toString();\r
+        try {\r
+            String manifestPath;\r
+            if (classPath.indexOf('!') > -1) {\r
+                manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";\r
+            } else {\r
+                String pkgPath = "/" + clazz.getPackage().getName().replace('.', '/');\r
+                manifestPath = classPath.substring(0, classPath.indexOf(pkgPath)) + "/META-INF/MANIFEST.MF";\r
+            }\r
+            Manifest manifest = new Manifest(new URL(manifestPath).openStream());\r
+            Attributes attr = manifest.getMainAttributes();\r
+            String value = attr.getValue(attrib);\r
+            return value;\r
+        } catch (Exception e) {\r
+        }\r
+        return defaultValue;\r
+    }\r
 }\r
index 29b42f05e621b96def975bf2e3b370b39f241558..8cb16ee173f048304c99c6c1554d518f264f4d5f 100644 (file)
@@ -25,138 +25,137 @@ import java.util.List;
  * The Dao interface defines all CRUD methods for handling SQL object operations.
  *
  * @author James Moger
- *
  */
 public interface Dao extends AutoCloseable {
 
-       /**
-        * Insert an object into the database.
-        *
-        * @param t
-        * @return true if successful
-        */
-       <T> boolean insert(T t);
-
-       /**
-        * Insert an object into the database and return it's primary key.
-        *
-        * @param t
-        * @return
-        */
-       <T> long insertAndGetKey(T t);
-
-       /**
-        * Insert all objects into the database.
-        *
-        * @param list
-        */
-       <T> void insertAll(List<T> list);
-
-       /**
-        * Insert all objects into the database and return the list of primary keys.
-        *
-        * @param t
-        * @return a list of primary keys
-        */
-       <T> List<Long> insertAllAndGetKeys(List<T> t);
-
-       /**
-        * Updates an object in the database.
-        *
-        * @param t
-        * @return true if successful
-        */
-       <T> boolean update(T t);
-
-       /**
-        * Updates all objects in the database.
-        *
-        * @param list
-        */
-       <T> void updateAll(List<T> list);
-
-       /**
-        * Inserts or updates an object in the database.
-        *
-        * @param t
-        */
-       <T> void merge(T t);
-
-       /**
-        * Deletes an object from the database.
-        *
-        * @param t
-        * @return true if successful
-        */
-       <T> boolean delete(T t);
-
-       /**
-        * Deletes all objects from the database.
-        *
-        * @param list
-        */
-       <T> void deleteAll(List<T> list);
-
-       /**
-        * Returns the underlying Db instance for lower-level access to database methods
-        * or direct JDBC access.
-        *
-        * @return the db instance
-        */
-       Db db();
-
-       /**
-        * Close the underlying Db instance.
-        */
-       @Override
-       void close();
-
-       /**
-        * Used to specify custom names for method parameters to be used
-        * for the SqlQuery or SqlUpdate annotations.
-        *
-        * You don't need to explicitly bind the parameters as each parameter
-        * is accessible by the standard "argN" syntax (0-indexed).
-        *
-        * Additionally, if you are compiling with Java 8 AND specifying the
-        * -parameters flag for javac, then you may use the parameter's name.
-        */
-       @Retention(RetentionPolicy.RUNTIME)
-       @Target({ ElementType.PARAMETER })
-       public @interface Bind {
-               String value();
-       }
-
-       /**
-        *
-        */
-       @Retention(RetentionPolicy.RUNTIME)
-       @Target({ ElementType.PARAMETER })
-       public @interface BindBean {
-               String value() default "";
-       }
-
-       /**
-        * Used to indicate that a method should execute a query.
-        */
-       @Retention(RetentionPolicy.RUNTIME)
-       @Target({ ElementType.METHOD })
-       public @interface SqlQuery {
-               String value();
-       }
-
-       /**
-        * Used to indicate that a method should execute a statement.
-        */
-       @Retention(RetentionPolicy.RUNTIME)
-       @Target({ ElementType.METHOD })
-       public @interface SqlStatement {
-               String value();
-       }
-
-       public class BeanBinder {
-               public void bind(BindBean bind, Object obj) {
-
-               }
-       }
+    /**
+     * Insert an object into the database.
+     *
+     * @param t
+     * @return true if successful
+     */
+    <T> boolean insert(T t);
+
+    /**
+     * Insert an object into the database and return it's primary key.
+     *
+     * @param t
+     * @return
+     */
+    <T> long insertAndGetKey(T t);
+
+    /**
+     * Insert all objects into the database.
+     *
+     * @param list
+     */
+    <T> void insertAll(List<T> list);
+
+    /**
+     * Insert all objects into the database and return the list of primary keys.
+     *
+     * @param t
+     * @return a list of primary keys
+     */
+    <T> List<Long> insertAllAndGetKeys(List<T> t);
+
+    /**
+     * Updates an object in the database.
+     *
+     * @param t
+     * @return true if successful
+     */
+    <T> boolean update(T t);
+
+    /**
+     * Updates all objects in the database.
+     *
+     * @param list
+     */
+    <T> void updateAll(List<T> list);
+
+    /**
+     * Inserts or updates an object in the database.
+     *
+     * @param t
+     */
+    <T> void merge(T t);
+
+    /**
+     * Deletes an object from the database.
+     *
+     * @param t
+     * @return true if successful
+     */
+    <T> boolean delete(T t);
+
+    /**
+     * Deletes all objects from the database.
+     *
+     * @param list
+     */
+    <T> void deleteAll(List<T> list);
+
+    /**
+     * Returns the underlying Db instance for lower-level access to database methods
+     * or direct JDBC access.
+     *
+     * @return the db instance
+     */
+    Db db();
+
+    /**
+     * Close the underlying Db instance.
+     */
+    @Override
+    void close();
+
+    /**
+     * Used to specify custom names for method parameters to be used
+     * for the SqlQuery or SqlUpdate annotations.
+     * <p>
+     * You don't need to explicitly bind the parameters as each parameter
+     * is accessible by the standard "argN" syntax (0-indexed).
+     * <p>
+     * Additionally, if you are compiling with Java 8 AND specifying the
+     * -parameters flag for javac, then you may use the parameter's name.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface Bind {
+        String value();
+    }
+
+    /**
+     *
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.PARAMETER})
+    public @interface BindBean {
+        String value() default "";
+    }
+
+    /**
+     * Used to indicate that a method should execute a query.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.METHOD})
+    public @interface SqlQuery {
+        String value();
+    }
+
+    /**
+     * Used to indicate that a method should execute a statement.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.METHOD})
+    public @interface SqlStatement {
+        String value();
+    }
+
+    public class BeanBinder {
+        public void bind(BindBean bind, Object obj) {
+
+        }
+    }
 }
index b1bbe144ca60955241838172589e0727fe19a397..3bb0b9e15bfae9ae8481efe77a3cf65408e7f9eb 100644 (file)
  */
 package com.iciql;
 
+import com.iciql.Iciql.Mode;
+
 import java.io.InputStream;
 import java.util.Properties;
 
-import com.iciql.Iciql.Mode;
-
 /**
  * Loads DAO statements from Properties resource files the classpath.
  *
  * @author James Moger
- *
  */
 public class DaoClasspathStatementProvider implements DaoStatementProvider {
 
-       private final Properties externalStatements;
-
-       public DaoClasspathStatementProvider() {
-               externalStatements = load();
-       }
-
-       /**
-        * Returns the list of statement resources to try locating.
-        *
-        * @return
-        */
-       protected String[] getStatementResources() {
-               return new String[] { "/iciql.properties", "/iciql.xml", "/conf/iciql.properties", "/conf/iciql.xml" };
-       }
-
-       /**
-        * Loads the first statement resource found on the classpath.
-        *
-        * @return the loaded statements
-        */
-       private Properties load() {
-
-               Properties props = new Properties();
-               for (String resource : getStatementResources()) {
-
-                       InputStream is = null;
-
-                       try {
-                               is = DaoProxy.class.getResourceAsStream(resource);
-
-                               if (is != null) {
-
-                                       if (resource.toLowerCase().endsWith(".xml")) {
-                                               // load an .XML statements file
-                                               props.loadFromXML(is);
-                                       } else {
-                                               // load a .Properties statements file
-                                               props.load(is);
-                                       }
-
-                                       break;
-                               }
-
-                       } catch (Exception e) {
-                               throw new IciqlException(e, "Failed to parse {0}", resource);
-                       } finally {
-                               try {
-                                       is.close();
-                               } catch (Exception e) {
-                               }
-                       }
-
-               }
-               return props;
-       }
-
-       @Override
-       public String getStatement(String idOrStatement, Mode mode) {
-               final String modePrefix = "%" + mode.name().toLowerCase() + ".";
-               String value = externalStatements.getProperty(idOrStatement, idOrStatement);
-               value = externalStatements.getProperty(modePrefix + idOrStatement, value);
-               return value;
-       }
+    private final Properties externalStatements;
+
+    public DaoClasspathStatementProvider() {
+        externalStatements = load();
+    }
+
+    /**
+     * Returns the list of statement resources to try locating.
+     *
+     * @return
+     */
+    protected String[] getStatementResources() {
+        return new String[]{"/iciql.properties", "/iciql.xml", "/conf/iciql.properties", "/conf/iciql.xml"};
+    }
+
+    /**
+     * Loads the first statement resource found on the classpath.
+     *
+     * @return the loaded statements
+     */
+    private Properties load() {
+
+        Properties props = new Properties();
+        for (String resource : getStatementResources()) {
+
+            InputStream is = null;
+
+            try {
+                is = DaoProxy.class.getResourceAsStream(resource);
+
+                if (is != null) {
+
+                    if (resource.toLowerCase().endsWith(".xml")) {
+                        // load an .XML statements file
+                        props.loadFromXML(is);
+                    } else {
+                        // load a .Properties statements file
+                        props.load(is);
+                    }
+
+                    break;
+                }
+
+            } catch (Exception e) {
+                throw new IciqlException(e, "Failed to parse {0}", resource);
+            } finally {
+                try {
+                    is.close();
+                } catch (Exception e) {
+                }
+            }
+
+        }
+        return props;
+    }
+
+    @Override
+    public String getStatement(String idOrStatement, Mode mode) {
+        final String modePrefix = "%" + mode.name().toLowerCase() + ".";
+        String value = externalStatements.getProperty(idOrStatement, idOrStatement);
+        value = externalStatements.getProperty(modePrefix + idOrStatement, value);
+        return value;
+    }
 
 }
index 34187c4388c28744713f72a9185b366d1bd0eaa0..8851a0c6158df7633382c7f8372da3f1105b3026 100644 (file)
  */
 package com.iciql;
 
+import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.util.JdbcUtils;
+import com.iciql.util.StringUtils;
+import com.iciql.util.Utils;
+
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
@@ -37,503 +42,497 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import com.iciql.Iciql.DataTypeAdapter;
-import com.iciql.util.JdbcUtils;
-import com.iciql.util.StringUtils;
-import com.iciql.util.Utils;
-
 /**
  * DaoProxy creates a dynamic instance of the provided Dao interface.
  *
- * @author James Moger
- *
  * @param <X>
+ * @author James Moger
  */
 final class DaoProxy<X extends Dao> implements InvocationHandler, Dao {
 
-       private final Db db;
+    private final Db db;
 
-       private final Class<X> daoInterface;
+    private final Class<X> daoInterface;
 
-       private final char bindingDelimiter = ':';
+    private final char bindingDelimiter = ':';
 
-       private final Map<Method, IndexedSql> indexedSqlCache;
+    private final Map<Method, IndexedSql> indexedSqlCache;
 
-       DaoProxy(Db db, Class<X> daoInterface) {
-               this.db = db;
-               this.daoInterface = daoInterface;
-               this.indexedSqlCache = new ConcurrentHashMap<Method, IndexedSql>();
-       }
+    DaoProxy(Db db, Class<X> daoInterface) {
+        this.db = db;
+        this.daoInterface = daoInterface;
+        this.indexedSqlCache = new ConcurrentHashMap<Method, IndexedSql>();
+    }
 
-       /**
-        * Builds a proxy object for the DAO interface.
-        *
-        * @return a proxy object
-        */
-       @SuppressWarnings("unchecked")
-       X build() {
+    /**
+     * Builds a proxy object for the DAO interface.
+     *
+     * @return a proxy object
+     */
+    @SuppressWarnings("unchecked")
+    X build() {
 
-               if (!daoInterface.isInterface()) {
-                       throw new IciqlException("Dao {0} must be an interface!", daoInterface.getName());
-               }
+        if (!daoInterface.isInterface()) {
+            throw new IciqlException("Dao {0} must be an interface!", daoInterface.getName());
+        }
 
-               ClassLoader classLoader = daoInterface.getClassLoader();
+        ClassLoader classLoader = daoInterface.getClassLoader();
 
-               Set<Class<?>> interfaces = new HashSet<Class<?>>();
-               interfaces.add(Dao.class);
-               interfaces.add(daoInterface);
-               for (Class<?> clazz : daoInterface.getInterfaces()) {
-                       interfaces.add(clazz);
-               }
+        Set<Class<?>> interfaces = new HashSet<Class<?>>();
+        interfaces.add(Dao.class);
+        interfaces.add(daoInterface);
+        for (Class<?> clazz : daoInterface.getInterfaces()) {
+            interfaces.add(clazz);
+        }
 
-               Class<?>[] constructorParams = { InvocationHandler.class };
-               Class<?>[] allInterfaces = interfaces.toArray(new Class<?>[interfaces.size()]);
+        Class<?>[] constructorParams = {InvocationHandler.class};
+        Class<?>[] allInterfaces = interfaces.toArray(new Class<?>[interfaces.size()]);
 
-               try {
+        try {
 
-                       Class<?> proxyClass = Proxy.getProxyClass(classLoader, allInterfaces);
-                       Constructor<?> proxyConstructor = proxyClass.getConstructor(constructorParams);
-                       return (X) proxyConstructor.newInstance(new Object[] { this });
+            Class<?> proxyClass = Proxy.getProxyClass(classLoader, allInterfaces);
+            Constructor<?> proxyConstructor = proxyClass.getConstructor(constructorParams);
+            return (X) proxyConstructor.newInstance(new Object[]{this});
 
-               } catch (Exception e) {
-                       throw new IciqlException(e);
-               }
-       }
+        } catch (Exception e) {
+            throw new IciqlException(e);
+        }
+    }
 
-       /**
-        * Invoke intercepts method calls and delegates execution to the appropriate object.
-        */
-       @Override
-       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-               try {
+    /**
+     * Invoke intercepts method calls and delegates execution to the appropriate object.
+     */
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        try {
 
-                       if (method.getDeclaringClass() == Dao.class) {
+            if (method.getDeclaringClass() == Dao.class) {
 
-                               return method.invoke(this, args);
+                return method.invoke(this, args);
 
-                       } else if (method.isAnnotationPresent(SqlQuery.class)) {
+            } else if (method.isAnnotationPresent(SqlQuery.class)) {
 
-                               String sql = method.getAnnotation(SqlQuery.class).value();
-                               String statement = db.getDaoStatementProvider().getStatement(sql, db.getMode());
-                               return executeQuery(method, args, statement);
+                String sql = method.getAnnotation(SqlQuery.class).value();
+                String statement = db.getDaoStatementProvider().getStatement(sql, db.getMode());
+                return executeQuery(method, args, statement);
 
-                       } else if (method.isAnnotationPresent(SqlStatement.class)) {
+            } else if (method.isAnnotationPresent(SqlStatement.class)) {
 
-                               String sql = method.getAnnotation(SqlStatement.class).value();
-                               String statement = db.getDaoStatementProvider().getStatement(sql, db.getMode());
-                               return executeStatement(method, args, statement);
+                String sql = method.getAnnotation(SqlStatement.class).value();
+                String statement = db.getDaoStatementProvider().getStatement(sql, db.getMode());
+                return executeStatement(method, args, statement);
 
-                       } else {
+            } else {
 
-                               throw new IciqlException("Can not invoke non-dao method {0}.{1}",
-                                               method.getDeclaringClass().getSimpleName(), method.getName());
+                throw new IciqlException("Can not invoke non-dao method {0}.{1}",
+                        method.getDeclaringClass().getSimpleName(), method.getName());
 
-                       }
+            }
 
-               } catch (InvocationTargetException te) {
-                       throw te.getCause();
-               }
-       }
+        } catch (InvocationTargetException te) {
+            throw te.getCause();
+        }
+    }
 
-       /**
-        * Execute a query.
-        *
-        * @param method
-        * @param methodArgs
-        * @param sql
-        * @return the result
-        */
-       private Object executeQuery(Method method, Object[] methodArgs, String sql) {
+    /**
+     * Execute a query.
+     *
+     * @param method
+     * @param methodArgs
+     * @param sql
+     * @return the result
+     */
+    private Object executeQuery(Method method, Object[] methodArgs, String sql) {
 
                /*
-                * Determine and validate the return type
+         * Determine and validate the return type
                 */
-               Class<?> returnType = method.getReturnType();
-
-               if (void.class == returnType) {
-                       throw new IciqlException("You must specify a return type for @{0} {1}.{2}!",
-                                       SqlQuery.class.getSimpleName(), method.getDeclaringClass().getSimpleName(), method.getName());
-               }
-
-               if (Collection.class.isAssignableFrom(returnType)) {
-                       throw new IciqlException("You may not return a collection for an @{0} method, please change the return type of {1}.{2} to YourClass[]!",
-                                       SqlQuery.class.getSimpleName(), method.getDeclaringClass().getSimpleName(), method.getName());
-               }
-
-               boolean isArray = false;
-               if (returnType.isArray()) {
-                       isArray = true;
-                       returnType = returnType.getComponentType();
-               }
-
-               boolean isJavaType = returnType.isEnum()
-                               || returnType.isPrimitive()
-                               || java.lang.Boolean.class.isAssignableFrom(returnType)
-                               || java.lang.Number.class.isAssignableFrom(returnType)
-                               || java.lang.String.class.isAssignableFrom(returnType)
-                               || java.util.Date.class.isAssignableFrom(returnType)
-                               || byte[].class.isAssignableFrom(returnType);
-
-               Class<? extends DataTypeAdapter<?>> adapter = Utils.getDataTypeAdapter(method.getAnnotations());
-               if (adapter == null) {
-                       adapter = Utils.getDataTypeAdapter(returnType.getAnnotations());
-               }
+        Class<?> returnType = method.getReturnType();
+
+        if (void.class == returnType) {
+            throw new IciqlException("You must specify a return type for @{0} {1}.{2}!",
+                    SqlQuery.class.getSimpleName(), method.getDeclaringClass().getSimpleName(), method.getName());
+        }
+
+        if (Collection.class.isAssignableFrom(returnType)) {
+            throw new IciqlException("You may not return a collection for an @{0} method, please change the return type of {1}.{2} to YourClass[]!",
+                    SqlQuery.class.getSimpleName(), method.getDeclaringClass().getSimpleName(), method.getName());
+        }
+
+        boolean isArray = false;
+        if (returnType.isArray()) {
+            isArray = true;
+            returnType = returnType.getComponentType();
+        }
+
+        boolean isJavaType = returnType.isEnum()
+                || returnType.isPrimitive()
+                || java.lang.Boolean.class.isAssignableFrom(returnType)
+                || java.lang.Number.class.isAssignableFrom(returnType)
+                || java.lang.String.class.isAssignableFrom(returnType)
+                || java.util.Date.class.isAssignableFrom(returnType)
+                || byte[].class.isAssignableFrom(returnType);
+
+        Class<? extends DataTypeAdapter<?>> adapter = Utils.getDataTypeAdapter(method.getAnnotations());
+        if (adapter == null) {
+            adapter = Utils.getDataTypeAdapter(returnType.getAnnotations());
+        }
 
                /*
                 * Prepare & execute sql
                 */
-               PreparedSql preparedSql = prepareSql(method, methodArgs, sql);
+        PreparedSql preparedSql = prepareSql(method, methodArgs, sql);
 
-               List<Object> objects;
-               if (!isJavaType && adapter == null) {
+        List<Object> objects;
+        if (!isJavaType && adapter == null) {
 
-                       // query of an Iciql model
-                       objects = db.executeQuery(returnType, preparedSql.sql, preparedSql.parameters);
+            // query of an Iciql model
+            objects = db.executeQuery(returnType, preparedSql.sql, preparedSql.parameters);
 
-               } else {
+        } else {
 
-                       // query of (array of) standard Java type or a DataTypeAdapter type
-                       objects = Utils.newArrayList();
-                       ResultSet rs = db.executeQuery(preparedSql.sql, preparedSql.parameters);
-                       try {
+            // query of (array of) standard Java type or a DataTypeAdapter type
+            objects = Utils.newArrayList();
+            ResultSet rs = db.executeQuery(preparedSql.sql, preparedSql.parameters);
+            try {
 
-                               while (rs.next()) {
+                while (rs.next()) {
 
-                                       Object value = db.getDialect().deserialize(rs, 1, returnType, adapter);
-                                       objects.add(value);
+                    Object value = db.getDialect().deserialize(rs, 1, returnType, adapter);
+                    objects.add(value);
 
-                                       if (!isArray) {
-                                               // we are not returning an array so we break
-                                               // the loop and return the first result
-                                               break;
-                                       }
-                               }
+                    if (!isArray) {
+                        // we are not returning an array so we break
+                        // the loop and return the first result
+                        break;
+                    }
+                }
 
-                       } catch (SQLException e) {
-                               throw new IciqlException(e);
-                       } finally {
-                               JdbcUtils.closeSilently(rs);
-                       }
+            } catch (SQLException e) {
+                throw new IciqlException(e);
+            } finally {
+                JdbcUtils.closeSilently(rs);
+            }
 
-               }
+        }
 
                /*
                 * Return the results
                 */
-               if (objects == null || objects.isEmpty()) {
+        if (objects == null || objects.isEmpty()) {
 
-                       // no results
-                       if (isArray) {
-                               // return an empty array
-                               return Array.newInstance(returnType, 0);
-                       }
+            // no results
+            if (isArray) {
+                // return an empty array
+                return Array.newInstance(returnType, 0);
+            }
 
-                       // nothing to return!
-                       return null;
+            // nothing to return!
+            return null;
 
-               } else if (isArray) {
+        } else if (isArray) {
 
-                       // return an array of object results
-                       Object array = Array.newInstance(returnType, objects.size());
-                       for (int i = 0; i < objects.size(); i++) {
-                               Array.set(array, i, objects.get(i));
-                       }
-                       return array;
+            // return an array of object results
+            Object array = Array.newInstance(returnType, objects.size());
+            for (int i = 0; i < objects.size(); i++) {
+                Array.set(array, i, objects.get(i));
+            }
+            return array;
 
-               }
+        }
 
-               // return first element
-               return objects.get(0);
-       }
+        // return first element
+        return objects.get(0);
+    }
 
 
-       /**
-        * Execute a statement.
-        *
-        * @param method
-        * @param methodArgs
-        * @param sql
-        * @return the result
-        */
-       private Object executeStatement(Method method, Object[] methodArgs, String sql) {
+    /**
+     * Execute a statement.
+     *
+     * @param method
+     * @param methodArgs
+     * @param sql
+     * @return the result
+     */
+    private Object executeStatement(Method method, Object[] methodArgs, String sql) {
 
                /*
                 * Determine and validate the return type
                 */
-               Class<?> returnType = method.getReturnType();
+        Class<?> returnType = method.getReturnType();
 
-               if (void.class != returnType && boolean.class != returnType && int.class != returnType) {
+        if (void.class != returnType && boolean.class != returnType && int.class != returnType) {
 
-                       throw new IciqlException("Invalid return type '{0}' for @{1} {2}.{3}!",
-                                       returnType.getSimpleName(), SqlQuery.class.getSimpleName(),
-                                       method.getDeclaringClass().getSimpleName(), method.getName());
-               }
+            throw new IciqlException("Invalid return type '{0}' for @{1} {2}.{3}!",
+                    returnType.getSimpleName(), SqlQuery.class.getSimpleName(),
+                    method.getDeclaringClass().getSimpleName(), method.getName());
+        }
 
                /*
                 * Prepare & execute sql
                 */
-               PreparedSql preparedSql = prepareSql(method, methodArgs, sql);
-               int rows = db.executeUpdate(preparedSql.sql, preparedSql.parameters);
+        PreparedSql preparedSql = prepareSql(method, methodArgs, sql);
+        int rows = db.executeUpdate(preparedSql.sql, preparedSql.parameters);
 
                /*
                 * Return the results
                 */
-               if (void.class == returnType) {
-
-                       // return nothing
-                       return null;
-
-               } else if (boolean.class == returnType) {
-
-                       // return true if any rows were affected
-                       return rows > 0;
-
-               } else {
-
-                       // return number of rows
-                       return rows;
-
-               }
-       }
-
-       /**
-        * Prepares an sql statement and execution parameters based on the supplied
-        * method and it's arguments.
-        *
-        * @param method
-        * @param methodArgs
-        * @param sql
-        * @return a prepared sql statement and arguments
-        */
-       private PreparedSql prepareSql(Method method, Object[] methodArgs, String sql) {
-
-               if (methodArgs == null || methodArgs.length == 0) {
-                       // no method arguments
-                       return new PreparedSql(sql, null);
-               }
-
-               IndexedSql indexedSql = indexedSqlCache.get(method);
-
-               if (indexedSql == null) {
-
-                       // index the sql and method args
-                       indexedSql = indexSql(method, sql);
-
-                       // cache the indexed sql for re-use
-                       indexedSqlCache.put(method, indexedSql);
-               }
-
-               final PreparedSql preparedSql = indexedSql.prepareSql(db, methodArgs);
-               return preparedSql;
-       }
-
-       /**
-        * Indexes an sql statement and method args based on the supplied
-        * method and it's arguments.
-        *
-        * @param method
-        * @param sql
-        * @return an indexed sql statement and arguments
-        */
-       private IndexedSql indexSql(Method method, String sql) {
-
-               Map<String, IndexedArgument> parameterIndex = buildParameterIndex(method);
-
-               // build a regex to extract parameter names from the sql statement
-               StringBuilder sb = new StringBuilder();
-               sb.append(bindingDelimiter);
-               sb.append("{1}(\\?");
-               for (String name : parameterIndex.keySet()) {
-                       sb.append("|");
-                       // strip binding delimeter from name
-                       sb.append(name);
-               }
-               sb.append(')');
-
-               // identify parameters, replace with the '?' PreparedStatement
-               // delimiter and build the PreparedStatement parameters array
-               final String regex = sb.toString();
-               final Pattern p = Pattern.compile(regex);
-               final Matcher m = p.matcher(sql);
-               final StringBuffer buffer = new StringBuffer();
-
-               List<IndexedArgument> indexedArgs = Utils.newArrayList();
-               int count = 0;
-               while (m.find()) {
-                       String binding = m.group(1);
-                       m.appendReplacement(buffer, "?");
-
-                       IndexedArgument indexedArg;
-                       if ("?".equals(binding)) {
-                               // standard ? JDBC placeholder
-                               indexedArg = parameterIndex.get("arg" + count);
-                       } else {
-                               // named placeholder
-                               indexedArg = parameterIndex.get(binding);
-                       }
-
-                       if (indexedArg == null) {
-                               throw new IciqlException("Unbound SQL parameter '{0}' in {1}.{2}",
-                                               binding, method.getDeclaringClass().getSimpleName(), method.getName());
-                       }
-                       indexedArgs.add(indexedArg);
-
-                       count++;
-               }
-               m.appendTail(buffer);
-
-               final String statement = buffer.toString();
-
-               // create an IndexedSql container for the statement and indexes
-               return new IndexedSql(statement, Collections.unmodifiableList(indexedArgs));
-
-       }
-
-       /**
-        * Builds an index of parameter name->(position,typeAdapter) from the method arguments
-        * array. This index is calculated once per method.
-        *
-        * @param method
-        * @return a bindings map of ("name", IndexedArgument) pairs
-        */
-       private Map<String, IndexedArgument> buildParameterIndex(Method method) {
-
-               Map<String, IndexedArgument> index = new TreeMap<String, IndexedArgument>();
-
-               Annotation [][] annotationsMatrix = method.getParameterAnnotations();
-               for (int i = 0; i < annotationsMatrix.length; i++) {
-
-                       Annotation [] annotations = annotationsMatrix[i];
+        if (void.class == returnType) {
+
+            // return nothing
+            return null;
+
+        } else if (boolean.class == returnType) {
+
+            // return true if any rows were affected
+            return rows > 0;
+
+        } else {
+
+            // return number of rows
+            return rows;
+
+        }
+    }
+
+    /**
+     * Prepares an sql statement and execution parameters based on the supplied
+     * method and it's arguments.
+     *
+     * @param method
+     * @param methodArgs
+     * @param sql
+     * @return a prepared sql statement and arguments
+     */
+    private PreparedSql prepareSql(Method method, Object[] methodArgs, String sql) {
+
+        if (methodArgs == null || methodArgs.length == 0) {
+            // no method arguments
+            return new PreparedSql(sql, null);
+        }
+
+        IndexedSql indexedSql = indexedSqlCache.get(method);
+
+        if (indexedSql == null) {
+
+            // index the sql and method args
+            indexedSql = indexSql(method, sql);
+
+            // cache the indexed sql for re-use
+            indexedSqlCache.put(method, indexedSql);
+        }
+
+        final PreparedSql preparedSql = indexedSql.prepareSql(db, methodArgs);
+        return preparedSql;
+    }
+
+    /**
+     * Indexes an sql statement and method args based on the supplied
+     * method and it's arguments.
+     *
+     * @param method
+     * @param sql
+     * @return an indexed sql statement and arguments
+     */
+    private IndexedSql indexSql(Method method, String sql) {
+
+        Map<String, IndexedArgument> parameterIndex = buildParameterIndex(method);
+
+        // build a regex to extract parameter names from the sql statement
+        StringBuilder sb = new StringBuilder();
+        sb.append(bindingDelimiter);
+        sb.append("{1}(\\?");
+        for (String name : parameterIndex.keySet()) {
+            sb.append("|");
+            // strip binding delimeter from name
+            sb.append(name);
+        }
+        sb.append(')');
+
+        // identify parameters, replace with the '?' PreparedStatement
+        // delimiter and build the PreparedStatement parameters array
+        final String regex = sb.toString();
+        final Pattern p = Pattern.compile(regex);
+        final Matcher m = p.matcher(sql);
+        final StringBuffer buffer = new StringBuffer();
+
+        List<IndexedArgument> indexedArgs = Utils.newArrayList();
+        int count = 0;
+        while (m.find()) {
+            String binding = m.group(1);
+            m.appendReplacement(buffer, "?");
+
+            IndexedArgument indexedArg;
+            if ("?".equals(binding)) {
+                // standard ? JDBC placeholder
+                indexedArg = parameterIndex.get("arg" + count);
+            } else {
+                // named placeholder
+                indexedArg = parameterIndex.get(binding);
+            }
+
+            if (indexedArg == null) {
+                throw new IciqlException("Unbound SQL parameter '{0}' in {1}.{2}",
+                        binding, method.getDeclaringClass().getSimpleName(), method.getName());
+            }
+            indexedArgs.add(indexedArg);
+
+            count++;
+        }
+        m.appendTail(buffer);
+
+        final String statement = buffer.toString();
+
+        // create an IndexedSql container for the statement and indexes
+        return new IndexedSql(statement, Collections.unmodifiableList(indexedArgs));
+
+    }
+
+    /**
+     * Builds an index of parameter name->(position,typeAdapter) from the method arguments
+     * array. This index is calculated once per method.
+     *
+     * @param method
+     * @return a bindings map of ("name", IndexedArgument) pairs
+     */
+    private Map<String, IndexedArgument> buildParameterIndex(Method method) {
+
+        Map<String, IndexedArgument> index = new TreeMap<String, IndexedArgument>();
+
+        Annotation[][] annotationsMatrix = method.getParameterAnnotations();
+        for (int i = 0; i < annotationsMatrix.length; i++) {
+
+            Annotation[] annotations = annotationsMatrix[i];
 
                        /*
                         * Conditionally map the bean properties of the method argument
                         * class to Method and Field instances.
                         */
-                       BindBean bean = getAnnotation(BindBean.class, annotations);
-                       if (bean != null) {
-                               final String prefix = bean.value();
-                               final Class<?> argumentClass = method.getParameterTypes()[i];
-                               Map<String, IndexedArgument> beanIndex = buildBeanIndex(i, prefix, argumentClass);
-                               index.putAll(beanIndex);
-                       }
-
-                       Class<? extends DataTypeAdapter<?>> typeAdapter = Utils.getDataTypeAdapter(annotations);
-                       final IndexedArgument indexedArgument = new IndexedArgument(i, typeAdapter);
-
-                       // :N - 1-indexed, like JDBC ResultSet
-                       index.put("" + (i + 1), indexedArgument);
-
-                       // argN - 0-indexed, like Reflection
-                       index.put("arg" + i, indexedArgument);
-
-                       // Bound name
-                       Bind binding = getAnnotation(Bind.class, annotations);
-                       if (binding!= null && !binding.value().isEmpty()) {
-                               index.put(binding.value(), indexedArgument);
-                       }
-
-                       // try mapping Java 8 argument names, may overwrite argN
-                       try {
-                               Class<?> nullArgs = null;
-                               Method getParameters = method.getClass().getMethod("getParameters", nullArgs);
-                               if (getParameters != null) {
-                                       Object [] parameters = (Object []) getParameters.invoke(method, nullArgs);
-                                       if (parameters != null) {
-                                               Object o = parameters[i];
-                                               Method getName = o.getClass().getMethod("getName", nullArgs);
-                                               String j8name = getName.invoke(o, nullArgs).toString();
-                                               if (!j8name.isEmpty()) {
-                                                       index.put(j8name, indexedArgument);
-                                               }
-                                       }
-                               }
-                       } catch (Throwable t) {
-                       }
-               }
-
-               return index;
-       }
-
-       /**
-        * Builds an index of parameter name->(position,method) from the method arguments
-        * array. This index is calculated once per method.
-        *
-        * @param argumentIndex
-        * @param prefix
-        * @param beanClass
-        * @return a bindings map of ("prefix.property", IndexedArgument) pairs
-        */
-       private Map<String, IndexedArgument> buildBeanIndex(int argumentIndex, String prefix, Class<?> beanClass) {
-
-               final String beanPrefix = StringUtils.isNullOrEmpty(prefix) ? "" : (prefix + ".");
-               final Map<String, IndexedArgument> index = new TreeMap<String, IndexedArgument>();
-
-               // map JavaBean property getters
-               for (Method method : beanClass.getMethods()) {
-
-                       if (Modifier.isStatic(method.getModifiers())
-                               || method.getReturnType() == void.class
-                               || method.getParameterTypes().length > 0
-                               || method.getDeclaringClass() == Object.class) {
-
-                               // not a JavaBean property
-                               continue;
-                       }
-
-                       final String propertyName;
-                       final String name = method.getName();
-                       if (name.startsWith("get")) {
-                               propertyName = method.getName().substring(3);
-                       } else if (name.startsWith("is")) {
-                               propertyName = method.getName().substring(2);
-                       } else {
-                               propertyName = null;
-                       }
-
-                       if (propertyName == null) {
-                               // not a conventional JavaBean property
-                               continue;
-                       }
-
-                       final String binding = beanPrefix + preparePropertyName(propertyName);
-                       final IndexedArgument indexedArg = new IndexedArgument(argumentIndex, method);
-
-                       index.put(binding, indexedArg);
-               }
-
-               // map public instance fields
-               for (Field field : beanClass.getFields()) {
-
-                       if (Modifier.isStatic(field.getModifiers())) {
-                               // not a JavaBean property
-                               continue;
-                       }
-
-                       final String binding = beanPrefix + preparePropertyName(field.getName());
-                       final IndexedArgument indexedArg = new IndexedArgument(argumentIndex, field);
-
-                       index.put(binding, indexedArg);
-
-               }
-
-               return index;
-       }
-
-       @SuppressWarnings("unchecked")
-       private <T> T getAnnotation(Class<T> annotationClass, Annotation [] annotations) {
-               if (annotations != null) {
-                       for (Annotation annotation : annotations) {
-                               if (annotation.annotationType() == annotationClass) {
-                                       return (T) annotation;
-                               }
-                       }
-               }
-               return null;
-       }
-
-       private String preparePropertyName(String value) {
-               return Character.toLowerCase(value.charAt(0)) + value.substring(1);
-       }
+            BindBean bean = getAnnotation(BindBean.class, annotations);
+            if (bean != null) {
+                final String prefix = bean.value();
+                final Class<?> argumentClass = method.getParameterTypes()[i];
+                Map<String, IndexedArgument> beanIndex = buildBeanIndex(i, prefix, argumentClass);
+                index.putAll(beanIndex);
+            }
+
+            Class<? extends DataTypeAdapter<?>> typeAdapter = Utils.getDataTypeAdapter(annotations);
+            final IndexedArgument indexedArgument = new IndexedArgument(i, typeAdapter);
+
+            // :N - 1-indexed, like JDBC ResultSet
+            index.put("" + (i + 1), indexedArgument);
+
+            // argN - 0-indexed, like Reflection
+            index.put("arg" + i, indexedArgument);
+
+            // Bound name
+            Bind binding = getAnnotation(Bind.class, annotations);
+            if (binding != null && !binding.value().isEmpty()) {
+                index.put(binding.value(), indexedArgument);
+            }
+
+            // try mapping Java 8 argument names, may overwrite argN
+            try {
+                Class<?> nullArgs = null;
+                Method getParameters = method.getClass().getMethod("getParameters", nullArgs);
+                if (getParameters != null) {
+                    Object[] parameters = (Object[]) getParameters.invoke(method, nullArgs);
+                    if (parameters != null) {
+                        Object o = parameters[i];
+                        Method getName = o.getClass().getMethod("getName", nullArgs);
+                        String j8name = getName.invoke(o, nullArgs).toString();
+                        if (!j8name.isEmpty()) {
+                            index.put(j8name, indexedArgument);
+                        }
+                    }
+                }
+            } catch (Throwable t) {
+            }
+        }
+
+        return index;
+    }
+
+    /**
+     * Builds an index of parameter name->(position,method) from the method arguments
+     * array. This index is calculated once per method.
+     *
+     * @param argumentIndex
+     * @param prefix
+     * @param beanClass
+     * @return a bindings map of ("prefix.property", IndexedArgument) pairs
+     */
+    private Map<String, IndexedArgument> buildBeanIndex(int argumentIndex, String prefix, Class<?> beanClass) {
+
+        final String beanPrefix = StringUtils.isNullOrEmpty(prefix) ? "" : (prefix + ".");
+        final Map<String, IndexedArgument> index = new TreeMap<String, IndexedArgument>();
+
+        // map JavaBean property getters
+        for (Method method : beanClass.getMethods()) {
+
+            if (Modifier.isStatic(method.getModifiers())
+                    || method.getReturnType() == void.class
+                    || method.getParameterTypes().length > 0
+                    || method.getDeclaringClass() == Object.class) {
+
+                // not a JavaBean property
+                continue;
+            }
+
+            final String propertyName;
+            final String name = method.getName();
+            if (name.startsWith("get")) {
+                propertyName = method.getName().substring(3);
+            } else if (name.startsWith("is")) {
+                propertyName = method.getName().substring(2);
+            } else {
+                propertyName = null;
+            }
+
+            if (propertyName == null) {
+                // not a conventional JavaBean property
+                continue;
+            }
+
+            final String binding = beanPrefix + preparePropertyName(propertyName);
+            final IndexedArgument indexedArg = new IndexedArgument(argumentIndex, method);
+
+            index.put(binding, indexedArg);
+        }
+
+        // map public instance fields
+        for (Field field : beanClass.getFields()) {
+
+            if (Modifier.isStatic(field.getModifiers())) {
+                // not a JavaBean property
+                continue;
+            }
+
+            final String binding = beanPrefix + preparePropertyName(field.getName());
+            final IndexedArgument indexedArg = new IndexedArgument(argumentIndex, field);
+
+            index.put(binding, indexedArg);
+
+        }
+
+        return index;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T getAnnotation(Class<T> annotationClass, Annotation[] annotations) {
+        if (annotations != null) {
+            for (Annotation annotation : annotations) {
+                if (annotation.annotationType() == annotationClass) {
+                    return (T) annotation;
+                }
+            }
+        }
+        return null;
+    }
+
+    private String preparePropertyName(String value) {
+        return Character.toLowerCase(value.charAt(0)) + value.substring(1);
+    }
 
        /*
         *
@@ -541,213 +540,213 @@ final class DaoProxy<X extends Dao> implements InvocationHandler, Dao {
         *
         */
 
-       @Override
-       public final Db db() {
-               return db;
-       }
-
-       @Override
-       public final <T> boolean insert(T t) {
-               return db.insert(t);
-       }
-
-       @Override
-       public final <T> void insertAll(List<T> t) {
-               db.insertAll(t);
-       }
-
-       @Override
-       public final <T> long insertAndGetKey(T t) {
-               return db.insertAndGetKey(t);
-       }
-
-       @Override
-       public final <T> List<Long> insertAllAndGetKeys(List<T> t) {
-               return db.insertAllAndGetKeys(t);
-       }
-
-       @Override
-       public final <T> boolean update(T t) {
-               return db.update(t);
-       }
-
-       @Override
-       public final <T> void updateAll(List<T> t) {
-               db.updateAll(t);
-       }
-
-       @Override
-       public final <T> void merge(T t) {
-               db.merge(t);
-       }
-
-       @Override
-       public final <T> boolean delete(T t) {
-               return db.delete(t);
-       }
-
-       @Override
-       public final <T> void deleteAll(List<T> t) {
-               db.deleteAll(t);
-       }
-
-       @Override
-       public final void close() {
-               db.close();
-       }
-
-       /**
-        * Container class to hold the prepared JDBC SQL statement and execution
-        * parameters.
-        */
-       private class PreparedSql {
-               final String sql;
-               final Object [] parameters;
-
-               PreparedSql(String sql, Object [] parameters) {
-                       this.sql = sql;
-                       this.parameters = parameters;
-               }
-
-               @Override
-               public String toString() {
-                       return sql;
-               }
-
-       }
-
-       /**
-        * Container class to hold a parsed JDBC SQL statement and
-        * IndexedParameters.
-        * <p>
-        * Instances of this class are cached because they are functional processing
-        * containers as they contain Method and Field references for binding beans
-        * and matching to method arguments.
-        * </p>
-        */
-       private class IndexedSql {
-               final String sql;
-               final List<IndexedArgument> indexedArgs;
-
-               IndexedSql(String sql, List<IndexedArgument> indexedArgs) {
-                       this.sql = sql;
-                       this.indexedArgs = indexedArgs;
-               }
-
-               /**
-                * Prepares the method arguments for statement execution.
-                *
-                * @param db
-                * @param methodArgs
-                * @return the prepared sql statement and parameters
-                */
-               PreparedSql prepareSql(Db db, Object [] methodArgs) {
-
-                       Object [] parameters = new Object[indexedArgs.size()];
-
-                       for (int i = 0; i < indexedArgs.size(); i++) {
-
-                               IndexedArgument indexedArg = indexedArgs.get(i);
-                               Object methodArg = methodArgs[indexedArg.index];
+    @Override
+    public final Db db() {
+        return db;
+    }
+
+    @Override
+    public final <T> boolean insert(T t) {
+        return db.insert(t);
+    }
+
+    @Override
+    public final <T> void insertAll(List<T> t) {
+        db.insertAll(t);
+    }
+
+    @Override
+    public final <T> long insertAndGetKey(T t) {
+        return db.insertAndGetKey(t);
+    }
+
+    @Override
+    public final <T> List<Long> insertAllAndGetKeys(List<T> t) {
+        return db.insertAllAndGetKeys(t);
+    }
+
+    @Override
+    public final <T> boolean update(T t) {
+        return db.update(t);
+    }
+
+    @Override
+    public final <T> void updateAll(List<T> t) {
+        db.updateAll(t);
+    }
+
+    @Override
+    public final <T> void merge(T t) {
+        db.merge(t);
+    }
+
+    @Override
+    public final <T> boolean delete(T t) {
+        return db.delete(t);
+    }
+
+    @Override
+    public final <T> void deleteAll(List<T> t) {
+        db.deleteAll(t);
+    }
+
+    @Override
+    public final void close() {
+        db.close();
+    }
+
+    /**
+     * Container class to hold the prepared JDBC SQL statement and execution
+     * parameters.
+     */
+    private class PreparedSql {
+        final String sql;
+        final Object[] parameters;
+
+        PreparedSql(String sql, Object[] parameters) {
+            this.sql = sql;
+            this.parameters = parameters;
+        }
+
+        @Override
+        public String toString() {
+            return sql;
+        }
+
+    }
+
+    /**
+     * Container class to hold a parsed JDBC SQL statement and
+     * IndexedParameters.
+     * <p>
+     * Instances of this class are cached because they are functional processing
+     * containers as they contain Method and Field references for binding beans
+     * and matching to method arguments.
+     * </p>
+     */
+    private class IndexedSql {
+        final String sql;
+        final List<IndexedArgument> indexedArgs;
+
+        IndexedSql(String sql, List<IndexedArgument> indexedArgs) {
+            this.sql = sql;
+            this.indexedArgs = indexedArgs;
+        }
+
+        /**
+         * Prepares the method arguments for statement execution.
+         *
+         * @param db
+         * @param methodArgs
+         * @return the prepared sql statement and parameters
+         */
+        PreparedSql prepareSql(Db db, Object[] methodArgs) {
+
+            Object[] parameters = new Object[indexedArgs.size()];
+
+            for (int i = 0; i < indexedArgs.size(); i++) {
+
+                IndexedArgument indexedArg = indexedArgs.get(i);
+                Object methodArg = methodArgs[indexedArg.index];
+
+                Object value = methodArg;
+                Class<? extends DataTypeAdapter<?>> typeAdapter = indexedArg.typeAdapter;
+
+                if (indexedArg.method != null) {
+
+                    // execute the bean method
+                    try {
+
+                        value = indexedArg.method.invoke(methodArg);
+                        typeAdapter = Utils.getDataTypeAdapter(indexedArg.method.getAnnotations());
+
+                    } catch (Exception e) {
+                        throw new IciqlException(e);
+                    }
+
+                } else if (indexedArg.field != null) {
+
+                    // extract the field value
+                    try {
+
+                        value = indexedArg.field.get(methodArg);
+                        typeAdapter = Utils.getDataTypeAdapter(indexedArg.field.getAnnotations());
+
+                    } catch (Exception e) {
+                        throw new IciqlException(e);
+                    }
+
+                } else if (typeAdapter == null) {
+
+                    // identify the type adapter for the argument class
+                    typeAdapter = Utils.getDataTypeAdapter(methodArg.getClass().getAnnotations());
+                }
+
+                // prepare the parameter
+                parameters[i] = db.getDialect().serialize(value, typeAdapter);
+
+            }
+
+            return new PreparedSql(sql, parameters);
+
+        }
+
+        @Override
+        public String toString() {
+            return sql;
+        }
+    }
+
+    /**
+     * IndexedArgument holds cached information about how to process an method
+     * argument by it's index in the method arguments array.
+     * <p>
+     * An argument may be passed-through, might be bound to a bean property,
+     * might be transformed with a type adapter, or a combination of these.
+     * </p>
+     */
+    private class IndexedArgument {
+        final int index;
+        final Class<? extends DataTypeAdapter<?>> typeAdapter;
+        final Method method;
+        final Field field;
+
+        IndexedArgument(int index, Class<? extends DataTypeAdapter<?>> typeAdapter) {
+            this.index = index;
+            this.typeAdapter = typeAdapter;
+            this.method = null;
+            this.field = null;
+        }
+
+        IndexedArgument(int methodArgIndex, Method method) {
+            this.index = methodArgIndex;
+            this.typeAdapter = null;
+            this.method = method;
+            this.field = null;
+        }
+
+        IndexedArgument(int methodArgIndex, Field field) {
+            this.index = methodArgIndex;
+            this.typeAdapter = null;
+            this.method = null;
+            this.field = field;
+        }
+
+        @Override
+        public String toString() {
+
+            String accessor;
+            if (method != null) {
+                accessor = "M:" + method.getDeclaringClass().getSimpleName() + "." + method.getName();
+            } else if (field != null) {
+                accessor = "F:" + field.getDeclaringClass().getSimpleName() + "." + field.getName();
+            } else {
+                accessor = "A:arg";
+            }
 
-                               Object value = methodArg;
-                               Class<? extends DataTypeAdapter<?>> typeAdapter = indexedArg.typeAdapter;
-
-                               if (indexedArg.method != null) {
-
-                                       // execute the bean method
-                                       try {
-
-                                               value = indexedArg.method.invoke(methodArg);
-                                               typeAdapter = Utils.getDataTypeAdapter(indexedArg.method.getAnnotations());
-
-                                       } catch (Exception e) {
-                                               throw new IciqlException(e);
-                                       }
-
-                               } else if (indexedArg.field != null) {
-
-                                       // extract the field value
-                                       try {
-
-                                               value = indexedArg.field.get(methodArg);
-                                               typeAdapter = Utils.getDataTypeAdapter(indexedArg.field.getAnnotations());
-
-                                       } catch (Exception e) {
-                                               throw new IciqlException(e);
-                                       }
-
-                               } else if (typeAdapter == null) {
-
-                                       // identify the type adapter for the argument class
-                                       typeAdapter = Utils.getDataTypeAdapter(methodArg.getClass().getAnnotations());
-                               }
-
-                               // prepare the parameter
-                               parameters[i] = db.getDialect().serialize(value, typeAdapter);
-
-                       }
-
-                       return new PreparedSql(sql, parameters);
-
-               }
-
-               @Override
-               public String toString() {
-                       return sql;
-               }
-       }
-
-       /**
-        * IndexedArgument holds cached information about how to process an method
-        * argument by it's index in the method arguments array.
-        * <p>
-        * An argument may be passed-through, might be bound to a bean property,
-        * might be transformed with a type adapter, or a combination of these.
-        * </p>
-        */
-       private class IndexedArgument {
-               final int index;
-               final Class<? extends DataTypeAdapter<?>> typeAdapter;
-               final Method method;
-               final Field field;
-
-               IndexedArgument(int index, Class<? extends DataTypeAdapter<?>> typeAdapter) {
-                       this.index = index;
-                       this.typeAdapter = typeAdapter;
-                       this.method = null;
-                       this.field = null;
-               }
-
-               IndexedArgument(int methodArgIndex, Method method) {
-                       this.index = methodArgIndex;
-                       this.typeAdapter = null;
-                       this.method = method;
-                       this.field = null;
-               }
-
-               IndexedArgument(int methodArgIndex, Field field) {
-                       this.index = methodArgIndex;
-                       this.typeAdapter = null;
-                       this.method = null;
-                       this.field = field;
-               }
-
-               @Override
-               public String toString() {
-
-                       String accessor;
-                       if (method != null) {
-                               accessor = "M:" + method.getDeclaringClass().getSimpleName() + "." + method.getName();
-                       } else if (field != null) {
-                               accessor = "F:" + field.getDeclaringClass().getSimpleName() + "." + field.getName();
-                       } else {
-                               accessor = "A:arg";
-                       }
-
-                       return index + ":" + accessor + (typeAdapter == null ? "" : (":" + typeAdapter.getSimpleName()));
-               }
-
-       }
+            return index + ":" + accessor + (typeAdapter == null ? "" : (":" + typeAdapter.getSimpleName()));
+        }
+
+    }
 
 }
index 7e7522a39ec014a816bdcb821dfc3b9f985d2be2..673638c449711796c2904b4cf646e4a0983f272b 100644 (file)
@@ -21,16 +21,15 @@ import com.iciql.Iciql.Mode;
  * Defines the interface for retrieving externalized DAO statements.
  *
  * @author James Moger
- *
  */
 public interface DaoStatementProvider {
 
-       /**
-        * Returns the statement associated with the id.
-        *
-        * @param idOrStatement
-        * @param mode
-        * @return the statement
-        */
-       String getStatement(String idOrStatement, Mode mode);
+    /**
+     * Returns the statement associated with the id.
+     *
+     * @param idOrStatement
+     * @param mode
+     * @return the statement
+     */
+    String getStatement(String idOrStatement, Mode mode);
 }
index d0756bcbceb9a610d2614219bfcec98e9807d54c..24396a4aac7e55b2fdce954097ba37e6c9a879aa 100644 (file)
 
 package com.iciql;
 
+import com.iciql.DbUpgrader.DefaultDbUpgrader;
+import com.iciql.Iciql.IQTable;
+import com.iciql.Iciql.IQVersion;
+import com.iciql.Iciql.IQView;
+import com.iciql.Iciql.Mode;
+import com.iciql.util.IciqlLogger;
+import com.iciql.util.JdbcUtils;
+import com.iciql.util.StringUtils;
+import com.iciql.util.Utils;
+import com.iciql.util.WeakIdentityHashMap;
+
+import javax.sql.DataSource;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
@@ -35,851 +47,827 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.sql.DataSource;
-
-import com.iciql.DbUpgrader.DefaultDbUpgrader;
-import com.iciql.Iciql.IQTable;
-import com.iciql.Iciql.IQVersion;
-import com.iciql.Iciql.IQView;
-import com.iciql.Iciql.Mode;
-import com.iciql.util.IciqlLogger;
-import com.iciql.util.JdbcUtils;
-import com.iciql.util.StringUtils;
-import com.iciql.util.Utils;
-import com.iciql.util.WeakIdentityHashMap;
-
 /**
  * This class represents a connection to a database.
  */
 
 public class Db implements AutoCloseable {
 
-       /**
-        * This map It holds unique tokens that are generated by functions such as
-        * Function.sum(..) in "db.from(p).select(Function.sum(p.unitPrice))". It
-        * doesn't actually hold column tokens, as those are bound to the query
-        * itself.
-        */
-       private static final Map<Object, Token> TOKENS;
-
-       private static final Map<String, Class<? extends SQLDialect>> DIALECTS;
-
-       private final Connection conn;
-       private final Mode mode;
-       private final Map<Class<?>, TableDefinition<?>> classMap = Collections
-                       .synchronizedMap(new HashMap<Class<?>, TableDefinition<?>>());
-       private final SQLDialect dialect;
-       private DbUpgrader dbUpgrader = new DefaultDbUpgrader();
-       private final Set<Class<?>> upgradeChecked = Collections.synchronizedSet(new HashSet<Class<?>>());
-
-       private boolean skipCreate;
-       private boolean autoSavePoint = true;
-       private DaoStatementProvider daoStatementProvider;
-
-       static {
-               TOKENS = Collections.synchronizedMap(new WeakIdentityHashMap<Object, Token>());
-               DIALECTS = Collections.synchronizedMap(new HashMap<String, Class<? extends SQLDialect>>());
-               // can register by...
-               // 1. Connection class name
-               // 2. DatabaseMetaData.getDatabaseProductName()
-               DIALECTS.put("Apache Derby", SQLDialectDerby.class);
-               DIALECTS.put("H2", SQLDialectH2.class);
-               DIALECTS.put("HSQL Database Engine", SQLDialectHSQL.class);
-               DIALECTS.put("MySQL", SQLDialectMySQL.class);
-               DIALECTS.put("PostgreSQL", SQLDialectPostgreSQL.class);
-           DIALECTS.put("Microsoft SQL Server", SQLDialectMSSQL.class);
-           DIALECTS.put("SQLite", SQLDialectSQLite.class);
-       }
-
-       private Db(Connection conn, Mode mode) {
-               this.conn = conn;
-               this.mode = mode;
-               String databaseName = null;
-               try {
-                       DatabaseMetaData data = conn.getMetaData();
-                       databaseName = data.getDatabaseProductName();
-               } catch (SQLException s) {
-                       throw new IciqlException(s, "failed to retrieve database metadata!");
-               }
-               dialect = getDialect(databaseName, conn.getClass().getName());
-               dialect.configureDialect(this);
-               daoStatementProvider = new NoExternalDaoStatements();
-       }
-
-       /**
-        * Register a new/custom dialect class. You can use this method to replace
-        * any existing dialect or to add a new one.
-        *
-        * @param token
-        *            the fully qualified name of the connection class or the
-        *            expected result of DatabaseMetaData.getDatabaseProductName()
-        * @param dialectClass
-        *            the dialect class to register
-        */
-       public static void registerDialect(String token, Class<? extends SQLDialect> dialectClass) {
-               DIALECTS.put(token, dialectClass);
-       }
-
-       SQLDialect getDialect(String databaseName, String className) {
-               Class<? extends SQLDialect> dialectClass = null;
-               if (DIALECTS.containsKey(className)) {
-                       // dialect registered by connection class name
-                       dialectClass = DIALECTS.get(className);
-               } else if (DIALECTS.containsKey(databaseName)) {
-                       // dialect registered by database name
-                       dialectClass = DIALECTS.get(databaseName);
-               } else {
-                       // did not find a match, use default
-                       dialectClass = SQLDialectDefault.class;
-               }
-               return instance(dialectClass);
-       }
-
-       static <X> X registerToken(X x, Token token) {
-               TOKENS.put(x, token);
-               return x;
-       }
-
-       static <X> boolean isToken(X x) {
-               return TOKENS.containsKey(x);
-       }
-
-       static Token getToken(Object x) {
-               return TOKENS.get(x);
-       }
-
-       static <T> T instance(Class<T> clazz) {
-               try {
-                       return clazz.newInstance();
-               } catch (Exception e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public static Db open(String url) {
-               return open(url, Mode.PROD);
-       }
-
-       public static Db open(String url, Mode mode) {
-               try {
-                       Connection conn = JdbcUtils.getConnection(null, url, null, null);
-                       return new Db(conn, mode);
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public static Db open(String url, String user, String password) {
-               return open(url, user, password, Mode.PROD);
-       }
-
-       public static Db open(String url, String user, String password, Mode mode) {
-               try {
-                       Connection conn = JdbcUtils.getConnection(null, url, user, password);
-                       return new Db(conn, mode);
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public static Db open(String url, String user, char[] password) {
-               return open(url, user, password, Mode.PROD);
-       }
-
-       public static Db open(String url, String user, char[] password, Mode mode) {
-               try {
-                       Connection conn = JdbcUtils.getConnection(null, url, user, password == null ? null : new String(password));
-                       return new Db(conn, mode);
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public static Db open(DataSource ds) {
-               return open(ds, Mode.PROD);
-       }
-
-       /**
-        * Create a new database instance using a data source. This method is fast,
-        * so that you can always call open() / close() on usage.
-        *
-        * @param ds
-        *            the data source
-        * @param mode
-        *            the runtime mode
-        * @return the database instance.
-        */
-       public static Db open(DataSource ds, Mode mode) {
-               try {
-                       return new Db(ds.getConnection(), mode);
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public static Db open(Connection conn) {
-               return open(conn, Mode.PROD);
-       }
-
-       public static Db open(Connection conn, Mode mode) {
-               return new Db(conn, mode);
-       }
-
-       /**
-        * Returns the Iciql runtime mode.
-        *
-        * @return the runtime mode
-        */
-       public Mode getMode() {
-               return mode;
-       }
-
-       /**
-        * Returns a new DAO instance for the specified class.
-        *
-        * @param daoClass
-        * @return
-        * @throws Exception
-        */
-       @SuppressWarnings("resource")
-       public <X extends Dao> X open(Class<X> daoClass) {
-               return new DaoProxy<X>(this, daoClass).build();
-       }
-
-       /**
-        * Returns the DAO statement provider.
-        *
-        * @return the DAO statement provider
-        */
-       public DaoStatementProvider getDaoStatementProvider() {
-               return daoStatementProvider;
-       }
-
-       /**
-        * Sets the DAO statement provider.
-        *
-        * @param statementProvider
-        */
-       public void setDaoStatementProvider(DaoStatementProvider statementProvider) {
-               if (statementProvider == null) {
-                       throw new IciqlException("You must provide a valid {0} instance!",
-                                       DaoStatementProvider.class.getSimpleName());
-               }
-
-               this.daoStatementProvider = statementProvider;
-       }
-
-       /**
-        * Convenience function to avoid import statements in application code.
-        */
-       public void activateConsoleLogger() {
-               IciqlLogger.activateConsoleLogger();
-       }
-
-       /**
-        * Convenience function to avoid import statements in application code.
-        */
-       public void deactivateConsoleLogger() {
-               IciqlLogger.deactivateConsoleLogger();
-       }
-
-       public <T> boolean insert(T t) {
-               Class<?> clazz = t.getClass();
-               long rc = define(clazz).createIfRequired(this).insert(this, t, false);
-               if (rc == 0) {
-                       throw new IciqlException("Failed to insert {0}.  Affected rowcount == 0.", t);
-               }
-               return rc == 1;
-       }
-
-       public <T> long insertAndGetKey(T t) {
-               Class<?> clazz = t.getClass();
-               return define(clazz).createIfRequired(this).insert(this, t, true);
-       }
-
-       /**
-        * Upsert INSERTS if the record does not exist or UPDATES the record if it
-        * does exist. Not all databases support MERGE and the syntax varies with
-        * the database.
-        *
-        * If the database does not support a MERGE or INSERT OR REPLACE INTO syntax
-        * the dialect can try to simulate a merge by implementing:
-        * <p>
-        * INSERT INTO foo... (SELECT ?,... FROM foo WHERE pk=? HAVING count(*)=0)
-        * <p>
-        * iciql will check the affected row count returned by the internal merge
-        * method and if the affected row count = 0, it will issue an update.
-        * <p>
-        * See the Derby dialect for an implementation of this technique.
-        * <p>
-        * If the dialect does not support merge an IciqlException will be thrown.
-        *
-        * @param t
-        */
-       public <T> void upsert(T t) {
-               Class<?> clazz = t.getClass();
-               TableDefinition<?> def = define(clazz).createIfRequired(this);
-               int rc = def.merge(this, t);
-               if (rc == 0) {
-                       rc = def.update(this, t);
-               }
-               if (rc == 0) {
-                       throw new IciqlException("upsert failed");
-               }
-       }
-
-       /**
-        * Merge INSERTS if the record does not exist or UPDATES the record if it
-        * does exist. Not all databases support MERGE and the syntax varies with
-        * the database.
-        *
-        * If the database does not support a MERGE or INSERT OR REPLACE INTO syntax
-        * the dialect can try to simulate a merge by implementing:
-        * <p>
-        * INSERT INTO foo... (SELECT ?,... FROM foo WHERE pk=? HAVING count(*)=0)
-        * <p>
-        * iciql will check the affected row count returned by the internal merge
-        * method and if the affected row count = 0, it will issue an update.
-        * <p>
-        * See the Derby dialect for an implementation of this technique.
-        * <p>
-        * If the dialect does not support merge an IciqlException will be thrown.
-        *
-        * @param t
-        */
-       public <T> void merge(T t) {
-               upsert(t);
-       }
-
-       public <T> boolean update(T t) {
-               Class<?> clazz = t.getClass();
-               return define(clazz).createIfRequired(this).update(this, t) == 1;
-       }
-
-       public <T> boolean delete(T t) {
-               Class<?> clazz = t.getClass();
-               return define(clazz).createIfRequired(this).delete(this, t) == 1;
-       }
-
-       public <T extends Object> Query<T> from(T alias) {
-               Class<?> clazz = alias.getClass();
-               define(clazz).createIfRequired(this);
-               return Query.from(this, alias);
-       }
-
-       @SuppressWarnings("unchecked")
-       public <T> boolean dropTable(Class<? extends T> modelClass) {
-               TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
-               SQLStatement stat = new SQLStatement(this);
-               getDialect().prepareDropTable(stat, def);
-               IciqlLogger.drop(stat.getSQL());
-               int rc = 0;
-               try {
-                       rc = stat.executeUpdate();
-               } catch (IciqlException e) {
-                       if (e.getIciqlCode() != IciqlException.CODE_OBJECT_NOT_FOUND) {
-                               throw e;
-                       }
-               }
-               // remove this model class from the table definition cache
-               classMap.remove(modelClass);
-               // remove this model class from the upgrade checked cache
-               upgradeChecked.remove(modelClass);
-               return rc == 1;
-       }
-
-       @SuppressWarnings("unchecked")
-       public <T> boolean dropView(Class<? extends T> modelClass) {
-               TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
-               SQLStatement stat = new SQLStatement(this);
-               getDialect().prepareDropView(stat, def);
-               IciqlLogger.drop(stat.getSQL());
-               int rc = 0;
-               try {
-                       rc = stat.executeUpdate();
-               } catch (IciqlException e) {
-                       if (e.getIciqlCode() != IciqlException.CODE_OBJECT_NOT_FOUND) {
-                               throw e;
-                       }
-               }
-               // remove this model class from the table definition cache
-               classMap.remove(modelClass);
-               // remove this model class from the upgrade checked cache
-               upgradeChecked.remove(modelClass);
-               return rc == 1;
-       }
-
-       public <T> List<T> buildObjects(Class<? extends T> modelClass, ResultSet rs) {
-               return buildObjects(modelClass, false, rs);
-       }
-
-       @SuppressWarnings("unchecked")
-       public <T> List<T> buildObjects(Class<? extends T> modelClass, boolean wildcardSelect, ResultSet rs) {
-               List<T> result = new ArrayList<T>();
-               TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
-               try {
-                       // SQLite returns pre-closed ResultSets for query results with 0 rows
-                       if (!rs.isClosed()) {
-                               int[] columns = def.mapColumns(dialect, wildcardSelect, rs);
-                               while (rs.next()) {
-                                       T item = Utils.newObject(modelClass);
-                                       def.readRow(dialect, item, rs, columns);
-                                       result.add(item);
-                               }
-                       }
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-               return result;
-       }
-
-       Db upgradeDb() {
-               if (!upgradeChecked.contains(dbUpgrader.getClass())) {
-                       // flag as checked immediately because calls are nested.
-                       upgradeChecked.add(dbUpgrader.getClass());
-
-                       IQVersion model = dbUpgrader.getClass().getAnnotation(IQVersion.class);
-                       if (model.value() == 0) {
-                               // try superclass
-                               Class<?> superClass = dbUpgrader.getClass().getSuperclass();
-                               if (superClass.isAnnotationPresent(IQVersion.class)) {
-                                       model = superClass.getAnnotation(IQVersion.class);
-                               }
-                       }
-                       if (model.value() > 0) {
-                               DbVersion v = new DbVersion();
-                               // (SCHEMA="" && TABLE="") == DATABASE
-                               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());
-                                       // 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.
-                                       if ((model.value() > dbVersion.version) && (dbUpgrader != null)) {
-                                               // database is an older version than the model
-                                               boolean success = dbUpgrader.upgradeDatabase(this, dbVersion.version, model.value());
-                                               if (success) {
-                                                       dbVersion.version = model.value();
-                                                       update(dbVersion);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               return this;
-       }
-
-       <T> void upgradeTable(TableDefinition<T> model) {
-               if (!upgradeChecked.contains(model.getModelClass())) {
-                       // flag is checked immediately because calls are nested
-                       upgradeChecked.add(model.getModelClass());
-
-                       if (model.tableVersion > 0) {
-                               // 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).is(schema).and(v.tableName)
-                                               .is(model.tableName).selectFirst();
-                               if (dbVersion == null) {
-                                       // table has no version registration, but model specifies
-                                       // version: insert DbVersion entry
-                                       DbVersion newTable = new DbVersion(model.tableVersion);
-                                       newTable.schemaName = schema;
-                                       newTable.tableName = model.tableName;
-                                       insert(newTable);
-                               } else {
-                                       // table has a version registration:
-                                       // check if upgrade is required
-                                       if ((model.tableVersion > dbVersion.version) && (dbUpgrader != null)) {
-                                               // table is an older version than model
-                                               boolean success = dbUpgrader.upgradeTable(this, schema, model.tableName,
-                                                               dbVersion.version, model.tableVersion);
-                                               if (success) {
-                                                       dbVersion.version = model.tableVersion;
-                                                       update(dbVersion);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       <T> TableDefinition<T> define(Class<T> clazz) {
-               TableDefinition<T> def = getTableDefinition(clazz);
-               if (def == null) {
-                       upgradeDb();
-                       def = new TableDefinition<T>(clazz);
-                       def.mapFields(this);
-                       classMap.put(clazz, def);
-                       if (Iciql.class.isAssignableFrom(clazz)) {
-                               T t = instance(clazz);
-                               Iciql table = (Iciql) t;
-                               Define.define(def, table);
-                       } else if (clazz.isAnnotationPresent(IQTable.class)) {
-                               // annotated classes skip the Define().define() static
-                               // initializer
-                               T t = instance(clazz);
-                               def.mapObject(t);
-                       } else if (clazz.isAnnotationPresent(IQView.class)) {
-                               // annotated classes skip the Define().define() static
-                               // initializer
-                               T t = instance(clazz);
-                               def.mapObject(t);
-                       }
-               }
-               return def;
-       }
-
-       <T> boolean hasCreated(Class<T> clazz) {
-               return upgradeChecked.contains(clazz);
-       }
-
-       public synchronized void setDbUpgrader(DbUpgrader upgrader) {
-               if (!upgrader.getClass().isAnnotationPresent(IQVersion.class)) {
-                       throw new IciqlException("DbUpgrader must be annotated with " + IQVersion.class.getSimpleName());
-               }
-               this.dbUpgrader = upgrader;
-               upgradeChecked.clear();
-       }
-
-       public SQLDialect getDialect() {
-               return dialect;
-       }
-
-       public Connection getConnection() {
-               return conn;
-       }
-
-       @Override
-       public void close() {
-               try {
-                       conn.close();
-               } catch (Exception e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       public <A> TestCondition<A> test(A x) {
-               return new TestCondition<A>(x);
-       }
-
-       public <T> void insertAll(List<T> list) {
-               if (list.size() == 0) {
-                       return;
-               }
-               Savepoint savepoint = null;
-               try {
-                       Class<?> clazz = list.get(0).getClass();
-                       TableDefinition<?> def = define(clazz).createIfRequired(this);
-                       savepoint = prepareSavepoint();
-                       for (T t : list) {
-                               PreparedStatement ps = def.createInsertStatement(this, t, false);
-                               int rc = ps.executeUpdate();
-                               if (rc == 0) {
-                                       throw new IciqlException("Failed to insert {0}.  Affected rowcount == 0.", t);
-                               }
-                       }
-                       commit(savepoint);
-               } catch (SQLException e) {
-                       rollback(savepoint);
-                       throw new IciqlException(e);
-               } catch (IciqlException e) {
-                       rollback(savepoint);
-                       throw e;
-               }
-       }
-
-       public <T> List<Long> insertAllAndGetKeys(List<T> list) {
-               List<Long> identities = new ArrayList<Long>();
-               if (list.size() == 0) {
-                       return identities;
-               }
-               Savepoint savepoint = null;
-               try {
-                       Class<?> clazz = list.get(0).getClass();
-                       TableDefinition<?> def = define(clazz).createIfRequired(this);
-                       savepoint = prepareSavepoint();
-                       for (T t : list) {
-                               long key = def.insert(this,  t, true);
-                               identities.add(key);
-                       }
-                       commit(savepoint);
-               } catch (IciqlException e) {
-                       rollback(savepoint);
-                       throw e;
-               }
-               return identities;
-       }
-
-       public <T> void updateAll(List<T> list) {
-               if (list.size() == 0) {
-                       return;
-               }
-               Savepoint savepoint = null;
-               try {
-                       Class<?> clazz = list.get(0).getClass();
-                       TableDefinition<?> def = define(clazz).createIfRequired(this);
-                       savepoint = prepareSavepoint();
-                       for (T t : list) {
-                               def.update(this, t);
-                       }
-                       commit(savepoint);
-               } catch (IciqlException e) {
-                       rollback(savepoint);
-                       throw e;
-               }
-       }
-
-       public <T> void deleteAll(List<T> list) {
-               if (list.size() == 0) {
-                       return;
-               }
-               Savepoint savepoint = null;
-               try {
-                       Class<?> clazz = list.get(0).getClass();
-                       TableDefinition<?> def = define(clazz).createIfRequired(this);
-                       savepoint = prepareSavepoint();
-                       for (T t : list) {
-                               def.delete(this,  t);
-                       }
-                       commit(savepoint);
-               } catch (IciqlException e) {
-                       rollback(savepoint);
-                       throw e;
-               }
-       }
-
-       PreparedStatement prepare(String sql, boolean returnGeneratedKeys) {
-               IciqlException.checkUnmappedField(sql);
-               try {
-                       if (returnGeneratedKeys) {
-                               return conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
-                       }
-                       return conn.prepareStatement(sql);
-               } catch (SQLException e) {
-                       throw IciqlException.fromSQL(sql, e);
-               }
-       }
-
-       Savepoint prepareSavepoint() {
-               // don't change auto-commit mode.
-               // don't create save point.
-               if (!autoSavePoint || !dialect.supportsSavePoints()) {
-                       return null;
-               }
-               // create a savepoint
-               Savepoint savepoint = null;
-               try {
-                       conn.setAutoCommit(false);
-                       savepoint = conn.setSavepoint();
-               } catch (SQLFeatureNotSupportedException e) {
-                       // jdbc driver does not support save points
-               } catch (SQLException e) {
-                       throw new IciqlException(e, "Could not create save point");
-               }
-               return savepoint;
-       }
-
-       void commit(Savepoint savepoint) {
-               if (savepoint != null) {
-                       try {
-                               conn.commit();
-                               conn.setAutoCommit(true);
-                       } catch (SQLException e) {
-                               throw new IciqlException(e, "Failed to commit pending transactions");
-                       }
-               }
-       }
-
-       void rollback(Savepoint savepoint) {
-               if (savepoint != null) {
-                       try {
-                               conn.rollback(savepoint);
-                               conn.setAutoCommit(true);
-                       } catch (SQLException s) {
-                               throw new IciqlException(s, "Failed to rollback transactions");
-                       }
-               }
-       }
-
-       @SuppressWarnings("unchecked")
-       <T> TableDefinition<T> getTableDefinition(Class<T> clazz) {
-               return (TableDefinition<T>) classMap.get(clazz);
-       }
-
-       /**
-        * Run a SQL query directly against the database.
-        *
-        * Be sure to close the ResultSet with
-        *
-        * <pre>
-        * JdbcUtils.closeSilently(rs, true);
-        * </pre>
-        *
-        * @param sql
-        *            the SQL statement
-        * @param args
-        *            optional object arguments for x=? tokens in query
-        * @return the result set
-        */
-       public ResultSet executeQuery(String sql, List<?> args) {
-               return executeQuery(sql, args.toArray());
-       }
-
-       /**
-        * Run a SQL query directly against the database.
-        *
-        * Be sure to close the ResultSet with
-        *
-        * <pre>
-        * JdbcUtils.closeSilently(rs, true);
-        * </pre>
-        *
-        * @param sql
-        *            the SQL statement
-        * @param args
-        *            optional object arguments for x=? tokens in query
-        * @return the result set
-        */
-       public ResultSet executeQuery(String sql, Object... args) {
-               try {
-                       if (args == null || args.length == 0) {
-                               return conn.createStatement().executeQuery(sql);
-                       } else {
-                               PreparedStatement stat = conn.prepareStatement(sql);
-                               int i = 1;
-                               for (Object arg : args) {
-                                       stat.setObject(i++, arg);
-                               }
-                               return stat.executeQuery();
-                       }
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               }
-       }
-
-       /**
-        * Run a SQL query directly against the database and map the results to the
-        * model class.
-        *
-        * @param modelClass
-        *            the model class to bind the query ResultSet rows into.
-        * @param sql
-        *            the SQL statement
-        * @return the result set
-        */
-       public <T> List<T> executeQuery(Class<? extends T> modelClass, String sql, List<?> args) {
-               return executeQuery(modelClass, sql, args.toArray());
-       }
-
-       /**
-        * Run a SQL query directly against the database and map the results to the
-        * model class.
-        *
-        * @param modelClass
-        *            the model class to bind the query ResultSet rows into.
-        * @param sql
-        *            the SQL statement
-        * @return the result set
-        */
-       public <T> List<T> executeQuery(Class<? extends T> modelClass, String sql, Object... args) {
-               ResultSet rs = null;
-               try {
-                       if (args == null || args.length == 0) {
-                               rs = conn.createStatement().executeQuery(sql);
-                       } else {
-                               PreparedStatement stat = conn.prepareStatement(sql);
-                               int i = 1;
-                               for (Object arg : args) {
-                                       stat.setObject(i++, arg);
-                               }
-                               rs = stat.executeQuery();
-                       }
-                       boolean wildcardSelect = sql.toLowerCase().matches("select .*\\*.+");
-                       return buildObjects(modelClass, wildcardSelect, rs);
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-       }
-
-       /**
-        * Run a SQL statement directly against the database.
-        *
-        * @param sql
-        *            the SQL statement
-        * @return the update count
-        */
-       public int executeUpdate(String sql, Object... args) {
-               Statement stat = null;
-               try {
-                       int updateCount;
-                       if (args == null || args.length == 0) {
-                               stat = conn.createStatement();
-                               updateCount = stat.executeUpdate(sql);
-                       } else {
-                               PreparedStatement ps = conn.prepareStatement(sql);
-                               int i = 1;
-                               for (Object arg : args) {
-                                       ps.setObject(i++, arg);
-                               }
-                               updateCount = ps.executeUpdate();
-                               stat = ps;
-                       }
-                       return updateCount;
-               } catch (SQLException e) {
-                       throw new IciqlException(e);
-               } finally {
-                       JdbcUtils.closeSilently(stat);
-               }
-       }
-
-       /**
-        * Allow to enable/disable globally createIfRequired in TableDefinition.
-        * For advanced user wanting to gain full control of transactions.
-        * Default value is false.
-        * @param skipCreate
-        */
-       public void setSkipCreate(boolean skipCreate) {
-               this.skipCreate = skipCreate;
-       }
-
-       public boolean getSkipCreate() {
-               return this.skipCreate;
-       }
-
-       /**
-        * Allow to enable/disable usage of save point.
-        * For advanced user wanting to gain full control of transactions.
-        * Default value is false.
-        * @param autoSavePoint
-        */
-       public void setAutoSavePoint(boolean autoSavePoint) {
-               this.autoSavePoint = autoSavePoint;
-       }
-
-       public boolean getAutoSavePoint() {
-               return this.autoSavePoint;
-       }
-
-       /**
-        * Default DAO statement provider.
-        */
-       class NoExternalDaoStatements implements DaoStatementProvider {
-
-               @Override
-               public String getStatement(String idOrStatement, Mode mode) {
-                       return idOrStatement;
-               }
-
-       }
+    /**
+     * This map It holds unique tokens that are generated by functions such as
+     * Function.sum(..) in "db.from(p).select(Function.sum(p.unitPrice))". It
+     * doesn't actually hold column tokens, as those are bound to the query
+     * itself.
+     */
+    private static final Map<Object, Token> TOKENS;
+
+    private static final Map<String, Class<? extends SQLDialect>> DIALECTS;
+
+    private final Connection conn;
+    private final Mode mode;
+    private final Map<Class<?>, TableDefinition<?>> classMap = Collections
+            .synchronizedMap(new HashMap<Class<?>, TableDefinition<?>>());
+    private final SQLDialect dialect;
+    private DbUpgrader dbUpgrader = new DefaultDbUpgrader();
+    private final Set<Class<?>> upgradeChecked = Collections.synchronizedSet(new HashSet<Class<?>>());
+
+    private boolean skipCreate;
+    private boolean autoSavePoint = true;
+    private DaoStatementProvider daoStatementProvider;
+
+    static {
+        TOKENS = Collections.synchronizedMap(new WeakIdentityHashMap<Object, Token>());
+        DIALECTS = Collections.synchronizedMap(new HashMap<String, Class<? extends SQLDialect>>());
+        // can register by...
+        // 1. Connection class name
+        // 2. DatabaseMetaData.getDatabaseProductName()
+        DIALECTS.put("Apache Derby", SQLDialectDerby.class);
+        DIALECTS.put("H2", SQLDialectH2.class);
+        DIALECTS.put("HSQL Database Engine", SQLDialectHSQL.class);
+        DIALECTS.put("MySQL", SQLDialectMySQL.class);
+        DIALECTS.put("PostgreSQL", SQLDialectPostgreSQL.class);
+        DIALECTS.put("Microsoft SQL Server", SQLDialectMSSQL.class);
+        DIALECTS.put("SQLite", SQLDialectSQLite.class);
+    }
+
+    private Db(Connection conn, Mode mode) {
+        this.conn = conn;
+        this.mode = mode;
+        String databaseName = null;
+        try {
+            DatabaseMetaData data = conn.getMetaData();
+            databaseName = data.getDatabaseProductName();
+        } catch (SQLException s) {
+            throw new IciqlException(s, "failed to retrieve database metadata!");
+        }
+        dialect = getDialect(databaseName, conn.getClass().getName());
+        dialect.configureDialect(this);
+        daoStatementProvider = new NoExternalDaoStatements();
+    }
+
+    /**
+     * Register a new/custom dialect class. You can use this method to replace
+     * any existing dialect or to add a new one.
+     *
+     * @param token        the fully qualified name of the connection class or the
+     *                     expected result of DatabaseMetaData.getDatabaseProductName()
+     * @param dialectClass the dialect class to register
+     */
+    public static void registerDialect(String token, Class<? extends SQLDialect> dialectClass) {
+        DIALECTS.put(token, dialectClass);
+    }
+
+    SQLDialect getDialect(String databaseName, String className) {
+        Class<? extends SQLDialect> dialectClass = null;
+        if (DIALECTS.containsKey(className)) {
+            // dialect registered by connection class name
+            dialectClass = DIALECTS.get(className);
+        } else if (DIALECTS.containsKey(databaseName)) {
+            // dialect registered by database name
+            dialectClass = DIALECTS.get(databaseName);
+        } else {
+            // did not find a match, use default
+            dialectClass = SQLDialectDefault.class;
+        }
+        return instance(dialectClass);
+    }
+
+    static <X> X registerToken(X x, Token token) {
+        TOKENS.put(x, token);
+        return x;
+    }
+
+    static <X> boolean isToken(X x) {
+        return TOKENS.containsKey(x);
+    }
+
+    static Token getToken(Object x) {
+        return TOKENS.get(x);
+    }
+
+    static <T> T instance(Class<T> clazz) {
+        try {
+            return clazz.newInstance();
+        } catch (Exception e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public static Db open(String url) {
+        return open(url, Mode.PROD);
+    }
+
+    public static Db open(String url, Mode mode) {
+        try {
+            Connection conn = JdbcUtils.getConnection(null, url, null, null);
+            return new Db(conn, mode);
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public static Db open(String url, String user, String password) {
+        return open(url, user, password, Mode.PROD);
+    }
+
+    public static Db open(String url, String user, String password, Mode mode) {
+        try {
+            Connection conn = JdbcUtils.getConnection(null, url, user, password);
+            return new Db(conn, mode);
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public static Db open(String url, String user, char[] password) {
+        return open(url, user, password, Mode.PROD);
+    }
+
+    public static Db open(String url, String user, char[] password, Mode mode) {
+        try {
+            Connection conn = JdbcUtils.getConnection(null, url, user, password == null ? null : new String(password));
+            return new Db(conn, mode);
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public static Db open(DataSource ds) {
+        return open(ds, Mode.PROD);
+    }
+
+    /**
+     * Create a new database instance using a data source. This method is fast,
+     * so that you can always call open() / close() on usage.
+     *
+     * @param ds   the data source
+     * @param mode the runtime mode
+     * @return the database instance.
+     */
+    public static Db open(DataSource ds, Mode mode) {
+        try {
+            return new Db(ds.getConnection(), mode);
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public static Db open(Connection conn) {
+        return open(conn, Mode.PROD);
+    }
+
+    public static Db open(Connection conn, Mode mode) {
+        return new Db(conn, mode);
+    }
+
+    /**
+     * Returns the Iciql runtime mode.
+     *
+     * @return the runtime mode
+     */
+    public Mode getMode() {
+        return mode;
+    }
+
+    /**
+     * Returns a new DAO instance for the specified class.
+     *
+     * @param daoClass
+     * @return
+     * @throws Exception
+     */
+    @SuppressWarnings("resource")
+    public <X extends Dao> X open(Class<X> daoClass) {
+        return new DaoProxy<X>(this, daoClass).build();
+    }
+
+    /**
+     * Returns the DAO statement provider.
+     *
+     * @return the DAO statement provider
+     */
+    public DaoStatementProvider getDaoStatementProvider() {
+        return daoStatementProvider;
+    }
+
+    /**
+     * Sets the DAO statement provider.
+     *
+     * @param statementProvider
+     */
+    public void setDaoStatementProvider(DaoStatementProvider statementProvider) {
+        if (statementProvider == null) {
+            throw new IciqlException("You must provide a valid {0} instance!",
+                    DaoStatementProvider.class.getSimpleName());
+        }
+
+        this.daoStatementProvider = statementProvider;
+    }
+
+    /**
+     * Convenience function to avoid import statements in application code.
+     */
+    public void activateConsoleLogger() {
+        IciqlLogger.activateConsoleLogger();
+    }
+
+    /**
+     * Convenience function to avoid import statements in application code.
+     */
+    public void deactivateConsoleLogger() {
+        IciqlLogger.deactivateConsoleLogger();
+    }
+
+    public <T> boolean insert(T t) {
+        Class<?> clazz = t.getClass();
+        long rc = define(clazz).createIfRequired(this).insert(this, t, false);
+        if (rc == 0) {
+            throw new IciqlException("Failed to insert {0}.  Affected rowcount == 0.", t);
+        }
+        return rc == 1;
+    }
+
+    public <T> long insertAndGetKey(T t) {
+        Class<?> clazz = t.getClass();
+        return define(clazz).createIfRequired(this).insert(this, t, true);
+    }
+
+    /**
+     * Upsert INSERTS if the record does not exist or UPDATES the record if it
+     * does exist. Not all databases support MERGE and the syntax varies with
+     * the database.
+     * <p>
+     * If the database does not support a MERGE or INSERT OR REPLACE INTO syntax
+     * the dialect can try to simulate a merge by implementing:
+     * <p>
+     * INSERT INTO foo... (SELECT ?,... FROM foo WHERE pk=? HAVING count(*)=0)
+     * <p>
+     * iciql will check the affected row count returned by the internal merge
+     * method and if the affected row count = 0, it will issue an update.
+     * <p>
+     * See the Derby dialect for an implementation of this technique.
+     * <p>
+     * If the dialect does not support merge an IciqlException will be thrown.
+     *
+     * @param t
+     */
+    public <T> void upsert(T t) {
+        Class<?> clazz = t.getClass();
+        TableDefinition<?> def = define(clazz).createIfRequired(this);
+        int rc = def.merge(this, t);
+        if (rc == 0) {
+            rc = def.update(this, t);
+        }
+        if (rc == 0) {
+            throw new IciqlException("upsert failed");
+        }
+    }
+
+    /**
+     * Merge INSERTS if the record does not exist or UPDATES the record if it
+     * does exist. Not all databases support MERGE and the syntax varies with
+     * the database.
+     * <p>
+     * If the database does not support a MERGE or INSERT OR REPLACE INTO syntax
+     * the dialect can try to simulate a merge by implementing:
+     * <p>
+     * INSERT INTO foo... (SELECT ?,... FROM foo WHERE pk=? HAVING count(*)=0)
+     * <p>
+     * iciql will check the affected row count returned by the internal merge
+     * method and if the affected row count = 0, it will issue an update.
+     * <p>
+     * See the Derby dialect for an implementation of this technique.
+     * <p>
+     * If the dialect does not support merge an IciqlException will be thrown.
+     *
+     * @param t
+     */
+    public <T> void merge(T t) {
+        upsert(t);
+    }
+
+    public <T> boolean update(T t) {
+        Class<?> clazz = t.getClass();
+        return define(clazz).createIfRequired(this).update(this, t) == 1;
+    }
+
+    public <T> boolean delete(T t) {
+        Class<?> clazz = t.getClass();
+        return define(clazz).createIfRequired(this).delete(this, t) == 1;
+    }
+
+    public <T extends Object> Query<T> from(T alias) {
+        Class<?> clazz = alias.getClass();
+        define(clazz).createIfRequired(this);
+        return Query.from(this, alias);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> boolean dropTable(Class<? extends T> modelClass) {
+        TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
+        SQLStatement stat = new SQLStatement(this);
+        getDialect().prepareDropTable(stat, def);
+        IciqlLogger.drop(stat.getSQL());
+        int rc = 0;
+        try {
+            rc = stat.executeUpdate();
+        } catch (IciqlException e) {
+            if (e.getIciqlCode() != IciqlException.CODE_OBJECT_NOT_FOUND) {
+                throw e;
+            }
+        }
+        // remove this model class from the table definition cache
+        classMap.remove(modelClass);
+        // remove this model class from the upgrade checked cache
+        upgradeChecked.remove(modelClass);
+        return rc == 1;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> boolean dropView(Class<? extends T> modelClass) {
+        TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
+        SQLStatement stat = new SQLStatement(this);
+        getDialect().prepareDropView(stat, def);
+        IciqlLogger.drop(stat.getSQL());
+        int rc = 0;
+        try {
+            rc = stat.executeUpdate();
+        } catch (IciqlException e) {
+            if (e.getIciqlCode() != IciqlException.CODE_OBJECT_NOT_FOUND) {
+                throw e;
+            }
+        }
+        // remove this model class from the table definition cache
+        classMap.remove(modelClass);
+        // remove this model class from the upgrade checked cache
+        upgradeChecked.remove(modelClass);
+        return rc == 1;
+    }
+
+    public <T> List<T> buildObjects(Class<? extends T> modelClass, ResultSet rs) {
+        return buildObjects(modelClass, false, rs);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> List<T> buildObjects(Class<? extends T> modelClass, boolean wildcardSelect, ResultSet rs) {
+        List<T> result = new ArrayList<T>();
+        TableDefinition<T> def = (TableDefinition<T>) define(modelClass);
+        try {
+            // SQLite returns pre-closed ResultSets for query results with 0 rows
+            if (!rs.isClosed()) {
+                int[] columns = def.mapColumns(dialect, wildcardSelect, rs);
+                while (rs.next()) {
+                    T item = Utils.newObject(modelClass);
+                    def.readRow(dialect, item, rs, columns);
+                    result.add(item);
+                }
+            }
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+        return result;
+    }
+
+    Db upgradeDb() {
+        if (!upgradeChecked.contains(dbUpgrader.getClass())) {
+            // flag as checked immediately because calls are nested.
+            upgradeChecked.add(dbUpgrader.getClass());
+
+            IQVersion model = dbUpgrader.getClass().getAnnotation(IQVersion.class);
+            if (model.value() == 0) {
+                // try superclass
+                Class<?> superClass = dbUpgrader.getClass().getSuperclass();
+                if (superClass.isAnnotationPresent(IQVersion.class)) {
+                    model = superClass.getAnnotation(IQVersion.class);
+                }
+            }
+            if (model.value() > 0) {
+                DbVersion v = new DbVersion();
+                // (SCHEMA="" && TABLE="") == DATABASE
+                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());
+                    // 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.
+                    if ((model.value() > dbVersion.version) && (dbUpgrader != null)) {
+                        // database is an older version than the model
+                        boolean success = dbUpgrader.upgradeDatabase(this, dbVersion.version, model.value());
+                        if (success) {
+                            dbVersion.version = model.value();
+                            update(dbVersion);
+                        }
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
+    <T> void upgradeTable(TableDefinition<T> model) {
+        if (!upgradeChecked.contains(model.getModelClass())) {
+            // flag is checked immediately because calls are nested
+            upgradeChecked.add(model.getModelClass());
+
+            if (model.tableVersion > 0) {
+                // 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).is(schema).and(v.tableName)
+                        .is(model.tableName).selectFirst();
+                if (dbVersion == null) {
+                    // table has no version registration, but model specifies
+                    // version: insert DbVersion entry
+                    DbVersion newTable = new DbVersion(model.tableVersion);
+                    newTable.schemaName = schema;
+                    newTable.tableName = model.tableName;
+                    insert(newTable);
+                } else {
+                    // table has a version registration:
+                    // check if upgrade is required
+                    if ((model.tableVersion > dbVersion.version) && (dbUpgrader != null)) {
+                        // table is an older version than model
+                        boolean success = dbUpgrader.upgradeTable(this, schema, model.tableName,
+                                dbVersion.version, model.tableVersion);
+                        if (success) {
+                            dbVersion.version = model.tableVersion;
+                            update(dbVersion);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    <T> TableDefinition<T> define(Class<T> clazz) {
+        TableDefinition<T> def = getTableDefinition(clazz);
+        if (def == null) {
+            upgradeDb();
+            def = new TableDefinition<T>(clazz);
+            def.mapFields(this);
+            classMap.put(clazz, def);
+            if (Iciql.class.isAssignableFrom(clazz)) {
+                T t = instance(clazz);
+                Iciql table = (Iciql) t;
+                Define.define(def, table);
+            } else if (clazz.isAnnotationPresent(IQTable.class)) {
+                // annotated classes skip the Define().define() static
+                // initializer
+                T t = instance(clazz);
+                def.mapObject(t);
+            } else if (clazz.isAnnotationPresent(IQView.class)) {
+                // annotated classes skip the Define().define() static
+                // initializer
+                T t = instance(clazz);
+                def.mapObject(t);
+            }
+        }
+        return def;
+    }
+
+    <T> boolean hasCreated(Class<T> clazz) {
+        return upgradeChecked.contains(clazz);
+    }
+
+    public synchronized void setDbUpgrader(DbUpgrader upgrader) {
+        if (!upgrader.getClass().isAnnotationPresent(IQVersion.class)) {
+            throw new IciqlException("DbUpgrader must be annotated with " + IQVersion.class.getSimpleName());
+        }
+        this.dbUpgrader = upgrader;
+        upgradeChecked.clear();
+    }
+
+    public SQLDialect getDialect() {
+        return dialect;
+    }
+
+    public Connection getConnection() {
+        return conn;
+    }
+
+    @Override
+    public void close() {
+        try {
+            conn.close();
+        } catch (Exception e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    public <A> TestCondition<A> test(A x) {
+        return new TestCondition<A>(x);
+    }
+
+    public <T> void insertAll(List<T> list) {
+        if (list.size() == 0) {
+            return;
+        }
+        Savepoint savepoint = null;
+        try {
+            Class<?> clazz = list.get(0).getClass();
+            TableDefinition<?> def = define(clazz).createIfRequired(this);
+            savepoint = prepareSavepoint();
+            for (T t : list) {
+                PreparedStatement ps = def.createInsertStatement(this, t, false);
+                int rc = ps.executeUpdate();
+                if (rc == 0) {
+                    throw new IciqlException("Failed to insert {0}.  Affected rowcount == 0.", t);
+                }
+            }
+            commit(savepoint);
+        } catch (SQLException e) {
+            rollback(savepoint);
+            throw new IciqlException(e);
+        } catch (IciqlException e) {
+            rollback(savepoint);
+            throw e;
+        }
+    }
+
+    public <T> List<Long> insertAllAndGetKeys(List<T> list) {
+        List<Long> identities = new ArrayList<Long>();
+        if (list.size() == 0) {
+            return identities;
+        }
+        Savepoint savepoint = null;
+        try {
+            Class<?> clazz = list.get(0).getClass();
+            TableDefinition<?> def = define(clazz).createIfRequired(this);
+            savepoint = prepareSavepoint();
+            for (T t : list) {
+                long key = def.insert(this, t, true);
+                identities.add(key);
+            }
+            commit(savepoint);
+        } catch (IciqlException e) {
+            rollback(savepoint);
+            throw e;
+        }
+        return identities;
+    }
+
+    public <T> void updateAll(List<T> list) {
+        if (list.size() == 0) {
+            return;
+        }
+        Savepoint savepoint = null;
+        try {
+            Class<?> clazz = list.get(0).getClass();
+            TableDefinition<?> def = define(clazz).createIfRequired(this);
+            savepoint = prepareSavepoint();
+            for (T t : list) {
+                def.update(this, t);
+            }
+            commit(savepoint);
+        } catch (IciqlException e) {
+            rollback(savepoint);
+            throw e;
+        }
+    }
+
+    public <T> void deleteAll(List<T> list) {
+        if (list.size() == 0) {
+            return;
+        }
+        Savepoint savepoint = null;
+        try {
+            Class<?> clazz = list.get(0).getClass();
+            TableDefinition<?> def = define(clazz).createIfRequired(this);
+            savepoint = prepareSavepoint();
+            for (T t : list) {
+                def.delete(this, t);
+            }
+            commit(savepoint);
+        } catch (IciqlException e) {
+            rollback(savepoint);
+            throw e;
+        }
+    }
+
+    PreparedStatement prepare(String sql, boolean returnGeneratedKeys) {
+        IciqlException.checkUnmappedField(sql);
+        try {
+            if (returnGeneratedKeys) {
+                return conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+            }
+            return conn.prepareStatement(sql);
+        } catch (SQLException e) {
+            throw IciqlException.fromSQL(sql, e);
+        }
+    }
+
+    Savepoint prepareSavepoint() {
+        // don't change auto-commit mode.
+        // don't create save point.
+        if (!autoSavePoint || !dialect.supportsSavePoints()) {
+            return null;
+        }
+        // create a savepoint
+        Savepoint savepoint = null;
+        try {
+            conn.setAutoCommit(false);
+            savepoint = conn.setSavepoint();
+        } catch (SQLFeatureNotSupportedException e) {
+            // jdbc driver does not support save points
+        } catch (SQLException e) {
+            throw new IciqlException(e, "Could not create save point");
+        }
+        return savepoint;
+    }
+
+    void commit(Savepoint savepoint) {
+        if (savepoint != null) {
+            try {
+                conn.commit();
+                conn.setAutoCommit(true);
+            } catch (SQLException e) {
+                throw new IciqlException(e, "Failed to commit pending transactions");
+            }
+        }
+    }
+
+    void rollback(Savepoint savepoint) {
+        if (savepoint != null) {
+            try {
+                conn.rollback(savepoint);
+                conn.setAutoCommit(true);
+            } catch (SQLException s) {
+                throw new IciqlException(s, "Failed to rollback transactions");
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    <T> TableDefinition<T> getTableDefinition(Class<T> clazz) {
+        return (TableDefinition<T>) classMap.get(clazz);
+    }
+
+    /**
+     * Run a SQL query directly against the database.
+     * <p>
+     * Be sure to close the ResultSet with
+     * <p>
+     * <pre>
+     * JdbcUtils.closeSilently(rs, true);
+     * </pre>
+     *
+     * @param sql  the SQL statement
+     * @param args optional object arguments for x=? tokens in query
+     * @return the result set
+     */
+    public ResultSet executeQuery(String sql, List<?> args) {
+        return executeQuery(sql, args.toArray());
+    }
+
+    /**
+     * Run a SQL query directly against the database.
+     * <p>
+     * Be sure to close the ResultSet with
+     * <p>
+     * <pre>
+     * JdbcUtils.closeSilently(rs, true);
+     * </pre>
+     *
+     * @param sql  the SQL statement
+     * @param args optional object arguments for x=? tokens in query
+     * @return the result set
+     */
+    public ResultSet executeQuery(String sql, Object... args) {
+        try {
+            if (args == null || args.length == 0) {
+                return conn.createStatement().executeQuery(sql);
+            } else {
+                PreparedStatement stat = conn.prepareStatement(sql);
+                int i = 1;
+                for (Object arg : args) {
+                    stat.setObject(i++, arg);
+                }
+                return stat.executeQuery();
+            }
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        }
+    }
+
+    /**
+     * Run a SQL query directly against the database and map the results to the
+     * model class.
+     *
+     * @param modelClass the model class to bind the query ResultSet rows into.
+     * @param sql        the SQL statement
+     * @return the result set
+     */
+    public <T> List<T> executeQuery(Class<? extends T> modelClass, String sql, List<?> args) {
+        return executeQuery(modelClass, sql, args.toArray());
+    }
+
+    /**
+     * Run a SQL query directly against the database and map the results to the
+     * model class.
+     *
+     * @param modelClass the model class to bind the query ResultSet rows into.
+     * @param sql        the SQL statement
+     * @return the result set
+     */
+    public <T> List<T> executeQuery(Class<? extends T> modelClass, String sql, Object... args) {
+        ResultSet rs = null;
+        try {
+            if (args == null || args.length == 0) {
+                rs = conn.createStatement().executeQuery(sql);
+            } else {
+                PreparedStatement stat = conn.prepareStatement(sql);
+                int i = 1;
+                for (Object arg : args) {
+                    stat.setObject(i++, arg);
+                }
+                rs = stat.executeQuery();
+            }
+            boolean wildcardSelect = sql.toLowerCase().matches("select .*\\*.+");
+            return buildObjects(modelClass, wildcardSelect, rs);
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+    }
+
+    /**
+     * Run a SQL statement directly against the database.
+     *
+     * @param sql the SQL statement
+     * @return the update count
+     */
+    public int executeUpdate(String sql, Object... args) {
+        Statement stat = null;
+        try {
+            int updateCount;
+            if (args == null || args.length == 0) {
+                stat = conn.createStatement();
+                updateCount = stat.executeUpdate(sql);
+            } else {
+                PreparedStatement ps = conn.prepareStatement(sql);
+                int i = 1;
+                for (Object arg : args) {
+                    ps.setObject(i++, arg);
+                }
+                updateCount = ps.executeUpdate();
+                stat = ps;
+            }
+            return updateCount;
+        } catch (SQLException e) {
+            throw new IciqlException(e);
+        } finally {
+            JdbcUtils.closeSilently(stat);
+        }
+    }
+
+    /**
+     * Allow to enable/disable globally createIfRequired in TableDefinition.
+     * For advanced user wanting to gain full control of transactions.
+     * Default value is false.
+     *
+     * @param skipCreate
+     */
+    public void setSkipCreate(boolean skipCreate) {
+        this.skipCreate = skipCreate;
+    }
+
+    public boolean getSkipCreate() {
+        return this.skipCreate;
+    }
+
+    /**
+     * Allow to enable/disable usage of save point.
+     * For advanced user wanting to gain full control of transactions.
+     * Default value is false.
+     *
+     * @param autoSavePoint
+     */
+    public void setAutoSavePoint(boolean autoSavePoint) {
+        this.autoSavePoint = autoSavePoint;
+    }
+
+    public boolean getAutoSavePoint() {
+        return this.autoSavePoint;
+    }
+
+    /**
+     * Default DAO statement provider.
+     */
+    class NoExternalDaoStatements implements DaoStatementProvider {
+
+        @Override
+        public String getStatement(String idOrStatement, Mode mode) {
+            return idOrStatement;
+        }
+
+    }
 }
index acaceeac3bf65b595e2921ae706c32c512b04a82..62576e39eb9c0914e0ec6fea085d45f5162eaa22 100644 (file)
 
 package com.iciql;
 
+import com.iciql.Iciql.IQTable;
+import com.iciql.util.JdbcUtils;
+import com.iciql.util.StringUtils;
+import com.iciql.util.Utils;
+
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -24,11 +29,6 @@ import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.iciql.Iciql.IQTable;
-import com.iciql.util.JdbcUtils;
-import com.iciql.util.StringUtils;
-import com.iciql.util.Utils;
-
 /**
  * Class to inspect a model and a database for the purposes of model validation
  * and automatic model generation. This class finds the available schemas and
@@ -36,169 +36,158 @@ import com.iciql.util.Utils;
  */
 public class DbInspector {
 
-       private Db db;
-       private DatabaseMetaData metaData;
-       private Class<? extends java.util.Date> dateTimeClass = java.util.Date.class;
-
-       public DbInspector(Db db) {
-               this.db = db;
-               setPreferredDateTimeClass(db.getDialect().getDateTimeClass());
-       }
-
-       /**
-        * Set the preferred class to store date and time. Possible values are:
-        * java.util.Date (default) and java.sql.Timestamp.
-        * 
-        * @param dateTimeClass
-        *            the new class
-        */
-       public void setPreferredDateTimeClass(Class<? extends java.util.Date> dateTimeClass) {
-               this.dateTimeClass = dateTimeClass;
-       }
-
-       /**
-        * Generates models class skeletons for schemas and tables. If the table
-        * name is undefined, models will be generated for every table within the
-        * specified schema. Additionally, if no schema is defined, models will be
-        * generated for all schemas and all tables.
-        * 
-        * @param schema
-        *            the schema name (optional)
-        * @param table
-        *            the table name (optional)
-        * @param packageName
-        *            the package name (optional)
-        * @param annotateSchema
-        *            (includes schema name in annotation)
-        * @param trimStrings
-        *            (trims strings to maxLength of column)
-        * @return a list of complete model classes as strings, each element a class
-        */
-       public List<String> generateModel(String schema, String table, String packageName,
-                       boolean annotateSchema, boolean trimStrings) {
-               try {
-                       List<String> models = Utils.newArrayList();
-                       List<TableInspector> tables = getTables(schema, table);
-                       for (TableInspector t : tables) {
-                               t.read(metaData);
-                               String model = t.generateModel(packageName, annotateSchema, trimStrings);
-                               models.add(model);
-                       }
-                       return models;
-               } catch (SQLException s) {
-                       throw new IciqlException(s);
-               }
-       }
-
-       /**
-        * Validates a model.
-        * 
-        * @param model
-        *            an instance of the model class
-        * @param throwOnError
-        *            if errors should cause validation to fail
-        * @return a list of validation remarks
-        */
-       public <T> List<ValidationRemark> validateModel(T model, boolean throwOnError) {
-               try {
-                       TableInspector inspector = getTable(model);
-                       inspector.read(metaData);
-                       @SuppressWarnings("unchecked")
-                       Class<T> clazz = (Class<T>) model.getClass();
-                       TableDefinition<T> def = db.define(clazz);
-                       return inspector.validate(def, throwOnError);
-               } catch (SQLException s) {
-                       throw new IciqlException(s);
-               }
-       }
-
-       private DatabaseMetaData getMetaData() throws SQLException {
-               if (metaData == null) {
-                       metaData = db.getConnection().getMetaData();
-               }
-               return metaData;
-       }
-
-       /**
-        * Get the table in the database based on the model definition.
-        * 
-        * @param model
-        *            an instance of the model class
-        * @return the table inspector
-        */
-       private <T> TableInspector getTable(T model) throws SQLException {
-               @SuppressWarnings("unchecked")
-               Class<T> clazz = (Class<T>) model.getClass();
-               TableDefinition<T> def = db.define(clazz);
-               boolean forceUpperCase = getMetaData().storesUpperCaseIdentifiers();
-               String schema = (forceUpperCase && def.schemaName != null) ? def.schemaName.toUpperCase()
-                               : def.schemaName;
-               String table = forceUpperCase ? def.tableName.toUpperCase() : def.tableName;
-               List<TableInspector> tables = getTables(schema, table);
-               return tables.get(0);
-       }
-
-       /**
-        * Returns a list of tables. This method always returns at least one
-        * element. If no table is found, an exception is thrown.
-        * 
-        * @param schema
-        *            the schema name
-        * @param table
-        *            the table name
-        * @return a list of table inspectors (always contains at least one element)
-        */
-       private List<TableInspector> getTables(String schema, String table) throws SQLException {
-               ResultSet rs = null;
-               try {
-                       rs = getMetaData().getSchemas();
-                       ArrayList<String> schemaList = Utils.newArrayList();
-                       while (rs.next()) {
-                               schemaList.add(rs.getString("TABLE_SCHEM"));
-                       }
-                       JdbcUtils.closeSilently(rs);
-
-                       String iciqlTables = DbVersion.class.getAnnotation(IQTable.class).name();
-
-                       List<TableInspector> tables = Utils.newArrayList();
-                       if (schemaList.size() == 0) {
-                               schemaList.add(null);
-                       }
-                       for (String s : schemaList) {
-                               rs = getMetaData().getTables(null, s, null, new String[] { "TABLE" });
-                               while (rs.next()) {
-                                       String t = rs.getString("TABLE_NAME");
-                                       if (t.charAt(0) == '"') {
-                                               t = t.substring(1);
-                                       }
-                                       if (t.charAt(t.length() - 1) == '"') {
-                                               t = t.substring(0, t.length() - 1);
-                                       }
-                                       if (!t.equalsIgnoreCase(iciqlTables)) {
-                                               tables.add(new TableInspector(s, t, dateTimeClass));
-                                       }
-                               }
-                       }
-
-                       if (StringUtils.isNullOrEmpty(schema) && StringUtils.isNullOrEmpty(table)) {
-                               // all schemas and tables
-                               return tables;
-                       }
-                       // schema subset OR table subset OR exact match
-                       List<TableInspector> matches = Utils.newArrayList();
-                       for (TableInspector t : tables) {
-                               if (t.matches(schema, table)) {
-                                       matches.add(t);
-                               }
-                       }
-                       if (matches.size() == 0) {
-                               throw new IciqlException(MessageFormat.format("Failed to find schema={0} table={1}",
-                                               schema == null ? "" : schema, table == null ? "" : table));
-                       }
-                       return matches;
-               } finally {
-                       JdbcUtils.closeSilently(rs);
-               }
-       }
+    private Db db;
+    private DatabaseMetaData metaData;
+    private Class<? extends java.util.Date> dateTimeClass = java.util.Date.class;
+
+    public DbInspector(Db db) {
+        this.db = db;
+        setPreferredDateTimeClass(db.getDialect().getDateTimeClass());
+    }
+
+    /**
+     * Set the preferred class to store date and time. Possible values are:
+     * java.util.Date (default) and java.sql.Timestamp.
+     *
+     * @param dateTimeClass the new class
+     */
+    public void setPreferredDateTimeClass(Class<? extends java.util.Date> dateTimeClass) {
+        this.dateTimeClass = dateTimeClass;
+    }
+
+    /**
+     * Generates models class skeletons for schemas and tables. If the table
+     * name is undefined, models will be generated for every table within the
+     * specified schema. Additionally, if no schema is defined, models will be
+     * generated for all schemas and all tables.
+     *
+     * @param schema         the schema name (optional)
+     * @param table          the table name (optional)
+     * @param packageName    the package name (optional)
+     * @param annotateSchema (includes schema name in annotation)
+     * @param trimStrings    (trims strings to maxLength of column)
+     * @return a list of complete model classes as strings, each element a class
+     */
+    public List<String> generateModel(String schema, String table, String packageName,
+                                      boolean annotateSchema, boolean trimStrings) {
+        try {
+            List<String> models = Utils.newArrayList();
+            List<TableInspector> tables = getTables(schema, table);
+            for (TableInspector t : tables) {
+                t.read(metaData);
+                String model = t.generateModel(packageName, annotateSchema, trimStrings);
+                models.add(model);
+            }
+            return models;
+        } catch (SQLException s) {
+            throw new IciqlException(s);
+        }
+    }
+
+    /**
+     * Validates a model.
+     *
+     * @param model        an instance of the model class
+     * @param throwOnError if errors should cause validation to fail
+     * @return a list of validation remarks
+     */
+    public <T> List<ValidationRemark> validateModel(T model, boolean throwOnError) {
+        try {
+            TableInspector inspector = getTable(model);
+            inspector.read(metaData);
+            @SuppressWarnings("unchecked")
+            Class<T> clazz = (Class<T>) model.getClass();
+            TableDefinition<T> def = db.define(clazz);
+            return inspector.validate(def, throwOnError);
+        } catch (SQLException s) {
+            throw new IciqlException(s);
+        }
+    }
+
+    private DatabaseMetaData getMetaData() throws SQLException {
+        if (metaData == null) {
+            metaData = db.getConnection().getMetaData();
+        }
+        return metaData;
+    }
+
+    /**
+     * Get the table in the database based on the model definition.
+     *
+     * @param model an instance of the model class
+     * @return the table inspector
+     */
+    private <T> TableInspector getTable(T model) throws SQLException {
+        @SuppressWarnings("unchecked")
+        Class<T> clazz = (Class<T>) model.getClass();
+        TableDefinition<T> def = db.define(clazz);
+        boolean forceUpperCase = getMetaData().storesUpperCaseIdentifiers();
+        String schema = (forceUpperCase && def.schemaName != null) ? def.schemaName.toUpperCase()
+                : def.schemaName;
+        String table = forceUpperCase ? def.tableName.toUpperCase() : def.tableName;
+        List<TableInspector> tables = getTables(schema, table);
+        return tables.get(0);
+    }
+
+    /**
+     * Returns a list of tables. This method always returns at least one
+     * element. If no table is found, an exception is thrown.
+     *
+     * @param schema the schema name
+     * @param table  the table name
+     * @return a list of table inspectors (always contains at least one element)
+     */
+    private List<TableInspector> getTables(String schema, String table) throws SQLException {
+        ResultSet rs = null;
+        try {
+            rs = getMetaData().getSchemas();
+            ArrayList<String> schemaList = Utils.newArrayList();
+            while (rs.next()) {
+                schemaList.add(rs.getString("TABLE_SCHEM"));
+            }
+            JdbcUtils.closeSilently(rs);
+
+            String iciqlTables = DbVersion.class.getAnnotation(IQTable.class).name();
+
+            List<TableInspector> tables = Utils.newArrayList();
+            if (schemaList.size() == 0) {
+                schemaList.add(null);
+            }
+            for (String s : schemaList) {
+                rs = getMetaData().getTables(null, s, null, new String[]{"TABLE"});
+                while (rs.next()) {
+                    String t = rs.getString("TABLE_NAME");
+                    if (t.charAt(0) == '"') {
+                        t = t.substring(1);
+                    }
+                    if (t.charAt(t.length() - 1) == '"') {
+                        t = t.substring(0, t.length() - 1);
+                    }
+                    if (!t.equalsIgnoreCase(iciqlTables)) {
+                        tables.add(new TableInspector(s, t, dateTimeClass));
+                    }
+                }
+            }
+
+            if (StringUtils.isNullOrEmpty(schema) && StringUtils.isNullOrEmpty(table)) {
+                // all schemas and tables
+                return tables;
+            }
+            // schema subset OR table subset OR exact match
+            List<TableInspector> matches = Utils.newArrayList();
+            for (TableInspector t : tables) {
+                if (t.matches(schema, table)) {
+                    matches.add(t);
+                }
+            }
+            if (matches.size() == 0) {
+                throw new IciqlException(MessageFormat.format("Failed to find schema={0} table={1}",
+                        schema == null ? "" : schema, table == null ? "" : table));
+            }
+            return matches;
+        } finally {
+            JdbcUtils.closeSilently(rs);
+        }
+    }
 
 }
index 1303f4e5bc9ce3f4083fa34394d1bb5c9d7e9c89..1fd92843e0f655b9d9e3af4ca75775287876818b 100644 (file)
@@ -27,55 +27,47 @@ import com.iciql.Iciql.IQVersion;
  */
 public interface DbUpgrader {
 
-       /**
-        * Defines method interface to handle database upgrades. This method is only
-        * called if your <i>DbUpgrader</i> implementation is annotated with
-        * IQDatabase.
-        * 
-        * @param db
-        *            the database
-        * @param fromVersion
-        *            the old version
-        * @param toVersion
-        *            the new version
-        * @return true for successful upgrade. If the upgrade is successful, the
-        *         version registry is automatically updated.
-        */
-       boolean upgradeDatabase(Db db, int fromVersion, int toVersion);
+    /**
+     * Defines method interface to handle database upgrades. This method is only
+     * called if your <i>DbUpgrader</i> implementation is annotated with
+     * IQDatabase.
+     *
+     * @param db          the database
+     * @param fromVersion the old version
+     * @param toVersion   the new version
+     * @return true for successful upgrade. If the upgrade is successful, the
+     * version registry is automatically updated.
+     */
+    boolean upgradeDatabase(Db db, int fromVersion, int toVersion);
 
-       /**
-        * Defines method interface to handle table upgrades.
-        * 
-        * @param db
-        *            the database
-        * @param schema
-        *            the schema
-        * @param table
-        *            the table
-        * @param fromVersion
-        *            the old version
-        * @param toVersion
-        *            the new version
-        * @return true for successful upgrade. If the upgrade is successful, the
-        *         version registry is automatically updated.
-        */
-       boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion);
+    /**
+     * Defines method interface to handle table upgrades.
+     *
+     * @param db          the database
+     * @param schema      the schema
+     * @param table       the table
+     * @param fromVersion the old version
+     * @param toVersion   the new version
+     * @return true for successful upgrade. If the upgrade is successful, the
+     * version registry is automatically updated.
+     */
+    boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion);
 
-       /**
-        * The default database upgrader. It throws runtime exception instead of
-        * handling upgrade requests.
-        */
-       @IQVersion(0)
-       public static class DefaultDbUpgrader implements DbUpgrader {
+    /**
+     * The default database upgrader. It throws runtime exception instead of
+     * handling upgrade requests.
+     */
+    @IQVersion(0)
+    public static class DefaultDbUpgrader implements DbUpgrader {
 
-               public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
-                       throw new IciqlException("Please provide your own DbUpgrader implementation.");
-               }
+        public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
+            throw new IciqlException("Please provide your own DbUpgrader implementation.");
+        }
 
-               public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) {
-                       throw new IciqlException("Please provide your own DbUpgrader implementation.");
-               }
+        public boolean upgradeTable(Db db, String schema, String table, int fromVersion, int toVersion) {
+            throw new IciqlException("Please provide your own DbUpgrader implementation.");
+        }
 
-       }
+    }
 
 }
index 6270e1437456f3173e029cde1ca24311cb1274fa..26f1dd7eb4410540d2f4228ac2f924fa0fbc0a21 100644 (file)
@@ -23,33 +23,32 @@ import com.iciql.Iciql.IQTable;
 /**
  * A system table to track database and table versions.
  */
-@IQTable(name = "iq_versions", primaryKey = { "schemaName", "tableName" }, memoryTable = true)
+@IQTable(name = "iq_versions", primaryKey = {"schemaName", "tableName"}, memoryTable = true)
 public class DbVersion {
 
-       @IQColumn(length = 255)
-       String schemaName = "";
-
-       @IQColumn(length = 255)
-       String tableName = "";
-
-       @IQColumn
-       Integer version;
-
-       public DbVersion() {
-               // nothing to do
-       }
-
-       /**
-        * Constructor for defining a version entry. Both the schema and the table
-        * are empty strings, which means this is the row for the 'database'.
-        * 
-        * @param version
-        *            the database version
-        */
-       public DbVersion(int version) {
-               this.schemaName = "";
-               this.tableName = "";
-               this.version = version;
-       }
+    @IQColumn(length = 255)
+    String schemaName = "";
+
+    @IQColumn(length = 255)
+    String tableName = "";
+
+    @IQColumn
+    Integer version;
+
+    public DbVersion() {
+        // nothing to do
+    }
+
+    /**
+     * Constructor for defining a version entry. Both the schema and the table
+     * are empty strings, which means this is the row for the 'database'.
+     *
+     * @param version the database version
+     */
+    public DbVersion(int version) {
+        this.schemaName = "";
+        this.tableName = "";
+        this.version = version;
+    }
 
 }
index b16ee6ec9a596afe363bd73711fa359f20b382b3..54c9857560daee9b58c2ff7ae183365b915dec68 100644 (file)
@@ -28,31 +28,31 @@ import com.iciql.Iciql.IndexType;
 \r
 public class Define {\r
 \r
-       private static TableDefinition<?> currentTableDefinition;\r
-       private static Iciql currentTable;\r
+    private static TableDefinition<?> currentTableDefinition;\r
+    private static Iciql currentTable;\r
 \r
-       public static void skipCreate() {\r
-               checkInDefine();\r
-               currentTableDefinition.defineSkipCreate();\r
-       }\r
+    public static void skipCreate() {\r
+        checkInDefine();\r
+        currentTableDefinition.defineSkipCreate();\r
+    }\r
 \r
-       public static void index(IndexType type, Object... columns) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineIndex(null, type, columns);\r
-       }\r
+    public static void index(IndexType type, Object... columns) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineIndex(null, type, columns);\r
+    }\r
 \r
-       public static void index(String name, IndexType type, Object... columns) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineIndex(name, type, columns);\r
-       }\r
+    public static void index(String name, IndexType type, Object... columns) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineIndex(name, type, columns);\r
+    }\r
 \r
-       public static void constraintUnique(String name, Object... columns) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineConstraintUnique(name, columns);\r
-       }\r
+    public static void constraintUnique(String name, Object... columns) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineConstraintUnique(name, columns);\r
+    }\r
 \r
        /*\r
-        * The variable argument type Object can't be used twice :-)\r
+     * The variable argument type Object can't be used twice :-)\r
         */\r
 //     public static void constraintForeignKey(String name, String refTableName,\r
 //                     ConstraintDeleteType deleteType, ConstraintUpdateType updateType,\r
@@ -61,91 +61,91 @@ public class Define {
 //             currentTableDefinition.defineForeignKey(name, columns, refTableName, Columns, deleteType, updateType, deferrabilityType);\r
 //     }\r
 \r
-       public static void primaryKey(Object... columns) {\r
-               checkInDefine();\r
-               currentTableDefinition.definePrimaryKey(columns);\r
-       }\r
-\r
-       public static void schemaName(String schemaName) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineSchemaName(schemaName);\r
-       }\r
-\r
-       public static void tableName(String tableName) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineTableName(tableName);\r
-       }\r
-\r
-       public static void viewTableName(String viewTableName) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineViewTableName(viewTableName);\r
-       }\r
-\r
-       public static void memoryTable() {\r
-               checkInDefine();\r
-               currentTableDefinition.defineMemoryTable();\r
-       }\r
-\r
-       public static void columnName(Object column, String columnName) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineColumnName(column, columnName);\r
-       }\r
-\r
-       public static void autoIncrement(Object column) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineAutoIncrement(column);\r
-       }\r
-\r
-       public static void length(Object column, int length) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineLength(column, length);\r
-       }\r
-\r
-       public static void scale(Object column, int scale) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineScale(column, scale);\r
-       }\r
-\r
-       public static void trim(Object column) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineTrim(column);\r
-       }\r
-\r
-       public static void nullable(Object column, boolean isNullable) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineNullable(column, isNullable);\r
-       }\r
-\r
-       public static void defaultValue(Object column, String defaultValue) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineDefaultValue(column, defaultValue);\r
-       }\r
-\r
-       public static void constraint(Object column, String constraint) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineConstraint(column, constraint);\r
-       }\r
-\r
-       public static void typeAdapter(Object column, Class<? extends DataTypeAdapter<?>> typeAdapter) {\r
-               checkInDefine();\r
-               currentTableDefinition.defineTypeAdapter(column, typeAdapter);\r
-       }\r
-\r
-       static synchronized <T> void define(TableDefinition<T> tableDefinition, Iciql table) {\r
-               currentTableDefinition = tableDefinition;\r
-               currentTable = table;\r
-               tableDefinition.mapObject(table);\r
-               table.defineIQ();\r
-               currentTable = null;\r
-               currentTableDefinition = null;\r
-       }\r
-\r
-       private static void checkInDefine() {\r
-               if (currentTable == null) {\r
-                       throw new IciqlException("This method may only be called "\r
-                                       + "from within the define() method, and the define() method "\r
-                                       + "is called by the framework.");\r
-               }\r
-       }\r
+    public static void primaryKey(Object... columns) {\r
+        checkInDefine();\r
+        currentTableDefinition.definePrimaryKey(columns);\r
+    }\r
+\r
+    public static void schemaName(String schemaName) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineSchemaName(schemaName);\r
+    }\r
+\r
+    public static void tableName(String tableName) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineTableName(tableName);\r
+    }\r
+\r
+    public static void viewTableName(String viewTableName) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineViewTableName(viewTableName);\r
+    }\r
+\r
+    public static void memoryTable() {\r
+        checkInDefine();\r
+        currentTableDefinition.defineMemoryTable();\r
+    }\r
+\r
+    public static void columnName(Object column, String columnName) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineColumnName(column, columnName);\r
+    }\r
+\r
+    public static void autoIncrement(Object column) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineAutoIncrement(column);\r
+    }\r
+\r
+    public static void length(Object column, int length) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineLength(column, length);\r
+    }\r
+\r
+    public static void scale(Object column, int scale) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineScale(column, scale);\r
+    }\r
+\r
+    public static void trim(Object column) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineTrim(column);\r
+    }\r
+\r
+    public static void nullable(Object column, boolean isNullable) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineNullable(column, isNullable);\r
+    }\r
+\r
+    public static void defaultValue(Object column, String defaultValue) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineDefaultValue(column, defaultValue);\r
+    }\r
+\r
+    public static void constraint(Object column, String constraint) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineConstraint(column, constraint);\r
+    }\r
+\r
+    public static void typeAdapter(Object column, Class<? extends DataTypeAdapter<?>> typeAdapter) {\r
+        checkInDefine();\r
+        currentTableDefinition.defineTypeAdapter(column, typeAdapter);\r
+    }\r
+\r
+    static synchronized <T> void define(TableDefinition<T> tableDefinition, Iciql table) {\r
+        currentTableDefinition = tableDefinition;\r
+        currentTable = table;\r
+        tableDefinition.mapObject(table);\r
+        table.defineIQ();\r
+        currentTable = null;\r
+        currentTableDefinition = null;\r
+    }\r
+\r
+    private static void checkInDefine() {\r
+        if (currentTable == null) {\r
+            throw new IciqlException("This method may only be called "\r
+                    + "from within the define() method, and the define() method "\r
+                    + "is called by the framework.");\r
+        }\r
+    }\r
 \r
 }\r
index 99dbdc319abc68211a80a21067e811f8dce8950e..b4d4e2d3c20cee1eab57f3fb1dfa78c5156be79a 100644 (file)
@@ -21,5 +21,5 @@ package com.iciql;
  * Represents the WHERE clause of a query.
  */
 public interface Filter {
-       boolean where();
+    boolean where();
 }
index 3faddb709da83e3fec5b8ebfa003c3f58188c3ca..d0d3d2e0afbfe13858f70537b9467c0375ffa641 100644 (file)
@@ -24,126 +24,126 @@ import com.iciql.util.Utils;
  */\r
 public class Function implements Token {\r
 \r
-       // must be a new instance\r
-       private static final Long COUNT_STAR = new Long(0);\r
-\r
-       protected Object[] x;\r
-       private String name;\r
-\r
-       protected Function(String name, Object... x) {\r
-               this.name = name;\r
-               this.x = x;\r
-       }\r
-\r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               stat.appendSQL(name).appendSQL("(");\r
-               int i = 0;\r
-               for (Object o : x) {\r
-                       if (i++ > 0) {\r
-                               stat.appendSQL(",");\r
-                       }\r
-                       query.appendSQL(stat, null, o);\r
-               }\r
-               stat.appendSQL(")");\r
-       }\r
-\r
-       public static Long count() {\r
-               return COUNT_STAR;\r
-       }\r
-\r
-       public static Integer length(Object x) {\r
-               return Db.registerToken(Utils.newObject(Integer.class), new Function("LENGTH", x));\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       public static <T extends Number> T sum(T x) {\r
-               return (T) Db.registerToken(Utils.newObject(x.getClass()), new Function("SUM", x));\r
-       }\r
-\r
-       public static Long count(Object x) {\r
-               return Db.registerToken(Utils.newObject(Long.class), new Function("COUNT", x));\r
-       }\r
-\r
-       public static Boolean isNull(Object x) {\r
-               return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" IS NULL");\r
-                       }\r
-               });\r
-       }\r
-\r
-       public static Boolean isNotNull(Object x) {\r
-               return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" IS NOT NULL");\r
-                       }\r
-               });\r
-       }\r
-\r
-       public static Boolean not(Boolean x) {\r
-               return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("NOT ");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                       }\r
-               });\r
-       }\r
-\r
-       public static Boolean or(Boolean... x) {\r
-               return Db.registerToken(Utils.newObject(Boolean.class), new Function("", (Object[]) x) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               int i = 0;\r
-                               for (Object o : x) {\r
-                                       if (i++ > 0) {\r
-                                               stat.appendSQL(" OR ");\r
-                                       }\r
-                                       query.appendSQL(stat, null, o);\r
-                               }\r
-                       }\r
-               });\r
-       }\r
-\r
-       public static Boolean and(Boolean... x) {\r
-               return Db.registerToken(Utils.newObject(Boolean.class), new Function("", (Object[]) x) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               int i = 0;\r
-                               for (Object o : x) {\r
-                                       if (i++ > 0) {\r
-                                               stat.appendSQL(" AND ");\r
-                                       }\r
-                                       query.appendSQL(stat, null, o);\r
-                               }\r
-                       }\r
-               });\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       public static <X> X min(X x) {\r
-               Class<X> clazz = (Class<X>) x.getClass();\r
-               X o = Utils.newObject(clazz);\r
-               return Db.registerToken(o, new Function("MIN", x));\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       public static <X> X max(X x) {\r
-               Class<X> clazz = (Class<X>) x.getClass();\r
-               X o = Utils.newObject(clazz);\r
-               return Db.registerToken(o, new Function("MAX", x));\r
-       }\r
-\r
-       public static Boolean like(String x, String pattern) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function("LIKE", x, pattern) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" LIKE ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    // must be a new instance\r
+    private static final Long COUNT_STAR = new Long(0);\r
+\r
+    protected Object[] x;\r
+    private String name;\r
+\r
+    protected Function(String name, Object... x) {\r
+        this.name = name;\r
+        this.x = x;\r
+    }\r
+\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        stat.appendSQL(name).appendSQL("(");\r
+        int i = 0;\r
+        for (Object o : x) {\r
+            if (i++ > 0) {\r
+                stat.appendSQL(",");\r
+            }\r
+            query.appendSQL(stat, null, o);\r
+        }\r
+        stat.appendSQL(")");\r
+    }\r
+\r
+    public static Long count() {\r
+        return COUNT_STAR;\r
+    }\r
+\r
+    public static Integer length(Object x) {\r
+        return Db.registerToken(Utils.newObject(Integer.class), new Function("LENGTH", x));\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <T extends Number> T sum(T x) {\r
+        return (T) Db.registerToken(Utils.newObject(x.getClass()), new Function("SUM", x));\r
+    }\r
+\r
+    public static Long count(Object x) {\r
+        return Db.registerToken(Utils.newObject(Long.class), new Function("COUNT", x));\r
+    }\r
+\r
+    public static Boolean isNull(Object x) {\r
+        return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" IS NULL");\r
+            }\r
+        });\r
+    }\r
+\r
+    public static Boolean isNotNull(Object x) {\r
+        return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" IS NOT NULL");\r
+            }\r
+        });\r
+    }\r
+\r
+    public static Boolean not(Boolean x) {\r
+        return Db.registerToken(Utils.newObject(Boolean.class), new Function("", x) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("NOT ");\r
+                query.appendSQL(stat, null, x[0]);\r
+            }\r
+        });\r
+    }\r
+\r
+    public static Boolean or(Boolean... x) {\r
+        return Db.registerToken(Utils.newObject(Boolean.class), new Function("", (Object[]) x) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                int i = 0;\r
+                for (Object o : x) {\r
+                    if (i++ > 0) {\r
+                        stat.appendSQL(" OR ");\r
+                    }\r
+                    query.appendSQL(stat, null, o);\r
+                }\r
+            }\r
+        });\r
+    }\r
+\r
+    public static Boolean and(Boolean... x) {\r
+        return Db.registerToken(Utils.newObject(Boolean.class), new Function("", (Object[]) x) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                int i = 0;\r
+                for (Object o : x) {\r
+                    if (i++ > 0) {\r
+                        stat.appendSQL(" AND ");\r
+                    }\r
+                    query.appendSQL(stat, null, o);\r
+                }\r
+            }\r
+        });\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <X> X min(X x) {\r
+        Class<X> clazz = (Class<X>) x.getClass();\r
+        X o = Utils.newObject(clazz);\r
+        return Db.registerToken(o, new Function("MIN", x));\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <X> X max(X x) {\r
+        Class<X> clazz = (Class<X>) x.getClass();\r
+        X o = Utils.newObject(clazz);\r
+        return Db.registerToken(o, new Function("MAX", x));\r
+    }\r
+\r
+    public static Boolean like(String x, String pattern) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function("LIKE", x, pattern) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" LIKE ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
 }\r
index 302b34d3ba574d55ff5723b91e17e5ce0cf77c70..14d3ab6323fb3bf9ff481feeb34cea767f2803ff 100644 (file)
@@ -171,7 +171,7 @@ import java.lang.annotation.Target;
  * <p>\r
  * Automatic model generation: you may automatically generate model classes as\r
  * strings with the Db and DbInspector objects:\r
- *\r
+ * <p>\r
  * <pre>\r
  * Db db = Db.open(&quot;jdbc:h2:mem:&quot;, &quot;sa&quot;, &quot;sa&quot;);\r
  * DbInspector inspector = new DbInspector(db);\r
@@ -179,10 +179,10 @@ import java.lang.annotation.Target;
  *         inspector.generateModel(schema, table, packageName,\r
  *         annotateSchema, trimStrings)\r
  * </pre>\r
- *\r
+ * <p>\r
  * Or you may use the GenerateModels tool to generate and save your classes to\r
  * the file system:\r
- *\r
+ * <p>\r
  * <pre>\r
  * java -jar iciql.jar\r
  *      -url &quot;jdbc:h2:mem:&quot;\r
@@ -190,10 +190,10 @@ import java.lang.annotation.Target;
  *      -package packageName -folder destination\r
  *      -annotateSchema false -trimStrings true\r
  * </pre>\r
- *\r
+ * <p>\r
  * Model validation: you may validate your model class with DbInspector object.\r
  * The DbInspector will report errors, warnings, and suggestions:\r
- *\r
+ * <p>\r
  * <pre>\r
  * Db db = Db.open(&quot;jdbc:h2:mem:&quot;, &quot;sa&quot;, &quot;sa&quot;);\r
  * DbInspector inspector = new DbInspector(db);\r
@@ -205,615 +205,613 @@ import java.lang.annotation.Target;
  */\r
 public interface Iciql {\r
 \r
-       /**\r
-        * An annotation for an iciql version.\r
-        * <p>\r
-        *\r
-        * @IQVersion(1)\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQVersion {\r
-\r
-               /**\r
-                * If set to a non-zero value, iciql maintains a "iq_versions" table\r
-                * within your database. The version number is used to call to a\r
-                * registered DbUpgrader implementation to perform relevant ALTER\r
-                * statements. Default: 0. You must specify a DbUpgrader on your Db\r
-                * object to use this parameter.\r
-                */\r
-               int value() default 0;\r
-\r
-       }\r
-\r
-       /**\r
-        * An annotation for a schema.\r
-        * <p>\r
-        *\r
-        * @IQSchema("PUBLIC")\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQSchema {\r
-\r
-               /**\r
-                * The schema may be optionally specified. Default: unspecified.\r
-                */\r
-               String value() default "";\r
-\r
-       }\r
-\r
-       /**\r
-        * Enumeration defining the four index types.\r
-        */\r
-       public static enum IndexType {\r
-               STANDARD, UNIQUE, HASH, UNIQUE_HASH;\r
-       }\r
-\r
-       /**\r
-        * An index annotation.\r
-        * <p>\r
-        * <ul>\r
-        * <li>@IQIndex("name")\r
-        * <li>@IQIndex({"street", "city"})\r
-        * <li>@IQIndex(name="streetidx", value={"street", "city"})\r
-        * <li>@IQIndex(name="addressidx", type=IndexType.UNIQUE,\r
-        * value={"house_number", "street", "city"})\r
-        * </ul>\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQIndex {\r
-\r
-               /**\r
-                * Index name. If null or empty, iciql will generate one.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * Type of the index.\r
-                * <ul>\r
-                * <li>com.iciql.iciql.IndexType.STANDARD\r
-                * <li>com.iciql.iciql.IndexType.UNIQUE\r
-                * <li>com.iciql.iciql.IndexType.HASH\r
-                * <li>com.iciql.iciql.IndexType.UNIQUE_HASH\r
-                * </ul>\r
-                *\r
-                * HASH indexes may only be valid for single column indexes.\r
-                *\r
-                */\r
-               IndexType type() default IndexType.STANDARD;\r
-\r
-               /**\r
-                * Columns to include in index.\r
-                * <ul>\r
-                * <li>single column index: value = "id"\r
-                * <li>multiple column index: value = { "id", "name", "date" }\r
-                * </ul>\r
-                */\r
-               String[] value() default {};\r
-       }\r
-\r
-       /**\r
-        * Enumeration defining the ON DELETE actions.\r
-        */\r
-       public static enum ConstraintDeleteType {\r
-               UNSET, CASCADE, RESTRICT, SET_NULL, NO_ACTION, SET_DEFAULT;\r
-       }\r
-\r
-       /**\r
-        * Enumeration defining the ON UPDATE actions.\r
-        */\r
-       public static enum ConstraintUpdateType {\r
-               UNSET, CASCADE, RESTRICT, SET_NULL, NO_ACTION, SET_DEFAULT;\r
-       }\r
-\r
-       /**\r
-        * Enumeration defining the deferrability.\r
-        */\r
-       public static enum ConstraintDeferrabilityType {\r
-               UNSET, DEFERRABLE_INITIALLY_DEFERRED, DEFERRABLE_INITIALLY_IMMEDIATE, NOT_DEFERRABLE;\r
-       }\r
-\r
-       /**\r
-        * A foreign key constraint annotation.\r
-        * <p>\r
-        * <ul>\r
-        * <li>@IQContraintForeignKey(\r
-        *    foreignColumns = { "idaccount"},\r
-        *    referenceName = "account",\r
-        *    referenceColumns = { "id" },\r
-        *    deleteType = ConstrainDeleteType.CASCADE,\r
-        *    updateType = ConstraintUpdateType.NO_ACTION )\r
-        * </ul>\r
-        * Note : reference columns should have a unique constraint defined in referenceName table,\r
-        * some database used to define a unique index instead of a unique constraint\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQContraintForeignKey {\r
-\r
-               /**\r
-                * Constraint name. If null or empty, iciql will generate one.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * Type of the action on delete, default to unspecified.\r
-                * <ul>\r
-                * <li>com.iciql.iciql.ConstrainDeleteType.CASCADE\r
-                * <li>com.iciql.iciql.ConstrainDeleteType.RESTRICT\r
-                * <li>com.iciql.iciql.ConstrainDeleteType.SET_NULL\r
-                * <li>com.iciql.iciql.ConstrainDeleteType.NO_ACTION\r
-                * <li>com.iciql.iciql.ConstrainDeleteType.SET_DEFAULT\r
-                * </ul>\r
-                */\r
-               ConstraintDeleteType deleteType() default ConstraintDeleteType.UNSET;\r
-\r
-               /**\r
-                * Type of the action on update, default to unspecified.\r
-                * <ul>\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.CASCADE\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.RESTRICT\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.SET_NULL\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.NO_ACTION\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.SET_DEFAULT\r
-                * </ul>\r
-                */\r
-               ConstraintUpdateType updateType() default ConstraintUpdateType.UNSET;\r
-\r
-               /**\r
-                * Type of the deferrability mode, default to unspecified\r
-                * <ul>\r
-                * <li>com.iciql.iciql.ConstrainUpdateType.CASCADE\r
-                * <li>ConstraintDeferrabilityType.DEFERRABLE_INITIALLY_DEFERRED\r
-                * <li>ConstraintDeferrabilityType.DEFERRABLE_INITIALLY_IMMEDIATE\r
-                * <li>ConstraintDeferrabilityType.NOT_DEFERRABLE\r
-                * </ul>\r
-                */\r
-               ConstraintDeferrabilityType deferrabilityType() default ConstraintDeferrabilityType.UNSET;\r
-\r
-               /**\r
-                * The source table for the columns defined as foreign.\r
-                */\r
-               String tableName() default "";\r
-\r
-               /**\r
-                * Columns defined as 'foreign'.\r
-                * <ul>\r
-                * <li>single column : foreignColumns = "id"\r
-                * <li>multiple column : foreignColumns = { "id", "name", "date" }\r
-                * </ul>\r
-                */\r
-               String[] foreignColumns() default {};\r
-\r
-               /**\r
-                * The reference table for the columns defined as references.\r
-                */\r
-               String referenceName() default "";\r
-\r
-               /**\r
-                * Columns defined as 'references'.\r
-                * <ul>\r
-                * <li>single column : referenceColumns = "id"\r
-                * <li>multiple column : referenceColumns = { "id", "name", "date" }\r
-                * </ul>\r
-                */\r
-               String[] referenceColumns() default {};\r
-       }\r
-\r
-       /**\r
-        * Annotation to specify multiple foreign keys constraints.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQContraintsForeignKey {\r
-               IQContraintForeignKey[] value() default {};\r
-       }\r
-\r
-       /**\r
-        * A unique constraint annotation.\r
-        * <p>\r
-        * <ul>\r
-        * <li>@IQContraintUnique(uniqueColumns = { "street", "city" })\r
-        * <li>@IQContraintUnique(name="streetconstraint", uniqueColumns = { "street", "city" })\r
-        * </ul>\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQContraintUnique {\r
-\r
-               /**\r
-                * Constraint name. If null or empty, iciql will generate one.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * Columns defined as 'unique'.\r
-                * <ul>\r
-                * <li>single column : uniqueColumns = "id"\r
-                * <li>multiple column : uniqueColumns = { "id", "name", "date" }\r
-                * </ul>\r
-                */\r
-               String[] uniqueColumns() default {};\r
-\r
-       }\r
-\r
-       /**\r
-        * Annotation to specify multiple unique constraints.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQContraintsUnique {\r
-               IQContraintUnique[] value() default {};\r
-       }\r
-\r
-       /**\r
-        * Annotation to define a view.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQView {\r
-\r
-               /**\r
-                * The view name. If not specified the class name is used as the view\r
-                * name.\r
-                * <p>\r
-                * The view name may still be overridden in the define() method if the\r
-                * model class is not annotated with IQView. Default: unspecified.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * The source table for the view.\r
-                * <p>\r
-                * The view name may still be overridden in the define() method if the\r
-                * model class is not annotated with IQView. Default: unspecified.\r
-                */\r
-               String tableName() default "";\r
-\r
-               /**\r
-                * The inherit columns allows this model class to inherit columns from\r
-                * its super class. IQTable and IQView annotations present on the super\r
-                * class or above are honored. Default: false.\r
-                */\r
-               boolean inheritColumns() default false;\r
-\r
-               /**\r
-                * Whether or not iciql tries to create the view. Default:\r
-                * true.\r
-                */\r
-               boolean create() default true;\r
-\r
-               /**\r
-                * If true, only fields that are explicitly annotated as IQColumn are\r
-                * mapped. Default: true.\r
-                */\r
-               boolean annotationsOnly() default true;\r
-       }\r
-\r
-       /**\r
-        * String snippet defining SQL constraints for a field. Use "this" as\r
-        * a placeholder for the column name.  "this" will be substituted at\r
-        * runtime.\r
-        * <p>\r
-        * IQConstraint("this > 2 AND this <= 7")\r
-        * <p>\r
-        * This snippet may still be overridden in the define() method if the\r
-        * model class is not annotated with IQTable or IQView. Default: unspecified.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.FIELD)\r
-       public @interface IQConstraint {\r
-\r
-               String value() default "";\r
-       }\r
-\r
-       /**\r
-        * Annotation to specify multiple indexes.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQIndexes {\r
-               IQIndex[] value() default {};\r
-       }\r
-\r
-       /**\r
-        * Annotation to define a table.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.TYPE)\r
-       public @interface IQTable {\r
-\r
-               /**\r
-                * The table name. If not specified the class name is used as the table\r
-                * name.\r
-                * <p>\r
-                * The table name may still be overridden in the define() method if the\r
-                * model class is not annotated with IQTable. Default: unspecified.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * The primary key may be optionally specified. If it is not specified,\r
-                * then no primary key is set by the IQTable annotation. You may specify\r
-                * a composite primary key.\r
-                * <ul>\r
-                * <li>single column primaryKey: value = "id"\r
-                * <li>compound primary key: value = { "id", "name" }\r
-                * </ul>\r
-                * The primary key may still be overridden in the define() method if the\r
-                * model class is not annotated with IQTable. Default: unspecified.\r
-                */\r
-               String[] primaryKey() default {};\r
-\r
-               /**\r
-                * The inherit columns allows this model class to inherit columns from\r
-                * its super class. IQTable and IQView annotations present on the super\r
-                * class or above are honored. Default: false.\r
-                */\r
-               boolean inheritColumns() default false;\r
-\r
-               /**\r
-                * Whether or not iciql tries to create the table and indexes. Default:\r
-                * true.\r
-                */\r
-               boolean create() default true;\r
-\r
-               /**\r
-                * If true, only fields that are explicitly annotated as IQColumn are\r
-                * mapped. Default: true.\r
-                */\r
-               boolean annotationsOnly() default true;\r
-\r
-               /**\r
-                * If true, this table is created as a memory table where data is\r
-                * persistent, but index data is kept in main memory. Valid only for H2\r
-                * and HSQL databases. Default: false.\r
-                */\r
-               boolean memoryTable() default false;\r
-       }\r
-\r
-       /**\r
-        * Annotation to define a column. Annotated fields may have any scope\r
-        * (however, the JVM may raise a SecurityException if the SecurityManager\r
-        * doesn't allow iciql to access the field.)\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.FIELD)\r
-       public @interface IQColumn {\r
-\r
-               /**\r
-                * If not specified, the field name is used as the column name. Default:\r
-                * the field name.\r
-                */\r
-               String name() default "";\r
-\r
-               /**\r
-                * This column is the primary key. Default: false.\r
-                */\r
-               boolean primaryKey() default false;\r
-\r
-               /**\r
-                * The column is created with a sequence as the default value. Default:\r
-                * false.\r
-                */\r
-               boolean autoIncrement() default false;\r
-\r
-               /**\r
-                * Length is used to define the length of a VARCHAR column or to define\r
-                * the precision of a DECIMAL(precision, scale) expression.\r
-                * <p>\r
-                * If larger than zero, it is used during the CREATE TABLE phase. For\r
-                * string values it may also be used to prevent database exceptions on\r
-                * INSERT and UPDATE statements (see trim).\r
-                * <p>\r
-                * Any length set in define() may override this annotation setting if\r
-                * the model class is not annotated with IQTable. Default: 0.\r
-                */\r
-               int length() default 0;\r
-\r
-               /**\r
-                * Scale is used during the CREATE TABLE phase to define the scale of a\r
-                * DECIMAL(precision, scale) expression.\r
-                * <p>\r
-                * Any scale set in define() may override this annotation setting if the\r
-                * model class is not annotated with IQTable. Default: 0.\r
-                */\r
-               int scale() default 0;\r
-\r
-               /**\r
-                * If true, iciql will automatically trim the string if it exceeds\r
-                * length (value.substring(0, length)). Default: false.\r
-                */\r
-               boolean trim() default false;\r
-\r
-               /**\r
-                * If false, iciql will set the column NOT NULL during the CREATE TABLE\r
-                * phase. Default: true.\r
-                */\r
-               boolean nullable() default true;\r
-\r
-               /**\r
-                * The default value assigned to the column during the CREATE TABLE\r
-                * phase. This field could contain a literal single-quoted value, or a\r
-                * function call. Empty strings are considered NULL. Examples:\r
-                * <ul>\r
-                * <li>defaultValue="" (null)\r
-                * <li>defaultValue="CURRENT_TIMESTAMP"\r
-                * <li>defaultValue="''" (empty string)\r
-                * <li>defaultValue="'0'"\r
-                * <li>defaultValue="'1970-01-01 00:00:01'"\r
-                * </ul>\r
-                * if the default value is specified, and auto increment is disabled,\r
-                * and primary key is disabled, then this value is included in the\r
-                * "DEFAULT ..." phrase of a column during the CREATE TABLE process.\r
-                * <p>\r
-                * Alternatively, you may specify a default object value on the field\r
-                * and this will be converted to a properly formatted DEFAULT expression\r
-                * during the CREATE TABLE process.\r
-                * <p>\r
-                * Default: unspecified (null).\r
-                */\r
-               String defaultValue() default "";\r
-\r
-       }\r
-\r
-       /**\r
-        * Interface for using the EnumType.ENUMID enumeration mapping strategy.\r
-        * <p>\r
-        * Enumerations wishing to use EnumType.ENUMID must implement this\r
-        * interface.\r
-        */\r
-       public interface EnumId<X> {\r
-               X enumId();\r
-               Class<X> enumIdClass();\r
-       }\r
-\r
-\r
-\r
-       /**\r
-        * Enumeration representing how to map a java.lang.Enum to a column.\r
-        * <p>\r
-        * <ul>\r
-        * <li>NAME - name() : string\r
-        * <li>ORDINAL - ordinal() : int\r
-        * <li>ENUMID - enumId() : X\r
-        * </ul>\r
-        *\r
-        * @see com.iciql.Iciql.EnumId interface\r
-        */\r
-       public enum EnumType {\r
-               NAME, ORDINAL, ENUMID;\r
-\r
-               public static final EnumType DEFAULT_TYPE = NAME;\r
-       }\r
-\r
-       /**\r
-        * Annotation to define how a java.lang.Enum is mapped to a column.\r
-        * <p>\r
-        * This annotation can be used on:\r
-        * <ul>\r
-        * <li>a field instance of an enumeration type\r
-        * <li>on the enumeration class declaration\r
-        * </ul>\r
-        * If you choose to annotate the class declaration, that will be the default\r
-        * mapping strategy for all @IQColumn instances of the enum. This can still\r
-        * be overridden for an individual field by specifying the IQEnum\r
-        * annotation.\r
-        * <p>\r
-        * The default mapping is by NAME.\r
-        *\r
-        * <pre>\r
-        * IQEnum(EnumType.NAME)\r
-        * </pre>\r
-        *\r
-        * A string mapping will generate either a VARCHAR, if IQColumn.length > 0\r
-        * or a TEXT column if IQColumn.length == 0\r
-        *\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target({ ElementType.FIELD, ElementType.TYPE })\r
-       public @interface IQEnum {\r
-               EnumType value() default EnumType.NAME;\r
-       }\r
-\r
-       /**\r
-        * Annotation to define an ignored field.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target(ElementType.FIELD)\r
-       public @interface IQIgnore{\r
-       }\r
-\r
-       /**\r
-        * The runtime mode for Iciql.\r
-        */\r
-       public static enum Mode {\r
-\r
-               DEV, TEST, PROD;\r
-\r
-               public static Mode fromValue(String value) {\r
-\r
-                       for (Mode mode : values()) {\r
-                               if (mode.name().equalsIgnoreCase(value)) {\r
-                                       return mode;\r
-                               }\r
-                       }\r
-\r
-                       return PROD;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * This method is called to let the table define the primary key, indexes,\r
-        * and the table name.\r
-        */\r
-       void defineIQ();\r
-\r
-       /**\r
-        * Specify a custom type adapter for a method return type, a class field, or a method\r
-        * parameter.  Type adapters allow you to transform content received from or inserted into\r
-        * a database field.\r
-        */\r
-       @Retention(RetentionPolicy.RUNTIME)\r
-       @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })\r
-       public @interface TypeAdapter {\r
-               Class<? extends DataTypeAdapter<?>> value();\r
-       }\r
-\r
-       /**\r
-        * Interface to allow implementations of custom data type adapters for supporting\r
-        * database-specific data types, like the Postgres 'json' or 'xml' types,\r
-        * or for supporting other object serialization schemes.\r
-        * <p><b>NOTE:</b> Data type adapters are not thread-safe!</p>\r
-        *\r
-        * @param <T>\r
-        */\r
-       public interface DataTypeAdapter<T> {\r
-\r
-               /**\r
-                * The SQL data type for this adapter.\r
-                *\r
-                * @return the SQL data type\r
-                */\r
-               String getDataType();\r
-\r
-               /**\r
-                * The Java domain type for this adapter.\r
-                *\r
-                * @return the Java domain type\r
-                */\r
-               Class<T> getJavaType();\r
-\r
-\r
-               /**\r
-                * Set the runtime mode.\r
-                * <p>\r
-                * Allows type adapters to adapt type mappings based on the runtime\r
-                * mode.\r
-                * </p>\r
-                *\r
-                * @param mode\r
-                */\r
-               void setMode(Mode mode);\r
-\r
-               /**\r
-                * Serializes your Java object into a JDBC object.\r
-                *\r
-                * @param value\r
-                * @return a JDBC object\r
-                */\r
-               Object serialize(T value);\r
-\r
-               /**\r
-                * Deserializes a JDBC object into your Java object.\r
-                *\r
-                * @param value\r
-                * @return the Java object\r
-                */\r
-               T deserialize(Object value);\r
-\r
-       }\r
+    /**\r
+     * An annotation for an iciql version.\r
+     * <p>\r
+     *\r
+     * @IQVersion(1)\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQVersion {\r
+\r
+        /**\r
+         * If set to a non-zero value, iciql maintains a "iq_versions" table\r
+         * within your database. The version number is used to call to a\r
+         * registered DbUpgrader implementation to perform relevant ALTER\r
+         * statements. Default: 0. You must specify a DbUpgrader on your Db\r
+         * object to use this parameter.\r
+         */\r
+        int value() default 0;\r
+\r
+    }\r
+\r
+    /**\r
+     * An annotation for a schema.\r
+     * <p>\r
+     *\r
+     * @IQSchema("PUBLIC")\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQSchema {\r
+\r
+        /**\r
+         * The schema may be optionally specified. Default: unspecified.\r
+         */\r
+        String value() default "";\r
+\r
+    }\r
+\r
+    /**\r
+     * Enumeration defining the four index types.\r
+     */\r
+    public static enum IndexType {\r
+        STANDARD, UNIQUE, HASH, UNIQUE_HASH;\r
+    }\r
+\r
+    /**\r
+     * An index annotation.\r
+     * <p>\r
+     * <ul>\r
+     * <li>@IQIndex("name")\r
+     * <li>@IQIndex({"street", "city"})\r
+     * <li>@IQIndex(name="streetidx", value={"street", "city"})\r
+     * <li>@IQIndex(name="addressidx", type=IndexType.UNIQUE,\r
+     * value={"house_number", "street", "city"})\r
+     * </ul>\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQIndex {\r
+\r
+        /**\r
+         * Index name. If null or empty, iciql will generate one.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * Type of the index.\r
+         * <ul>\r
+         * <li>com.iciql.iciql.IndexType.STANDARD\r
+         * <li>com.iciql.iciql.IndexType.UNIQUE\r
+         * <li>com.iciql.iciql.IndexType.HASH\r
+         * <li>com.iciql.iciql.IndexType.UNIQUE_HASH\r
+         * </ul>\r
+         * <p>\r
+         * HASH indexes may only be valid for single column indexes.\r
+         */\r
+        IndexType type() default IndexType.STANDARD;\r
+\r
+        /**\r
+         * Columns to include in index.\r
+         * <ul>\r
+         * <li>single column index: value = "id"\r
+         * <li>multiple column index: value = { "id", "name", "date" }\r
+         * </ul>\r
+         */\r
+        String[] value() default {};\r
+    }\r
+\r
+    /**\r
+     * Enumeration defining the ON DELETE actions.\r
+     */\r
+    public static enum ConstraintDeleteType {\r
+        UNSET, CASCADE, RESTRICT, SET_NULL, NO_ACTION, SET_DEFAULT;\r
+    }\r
+\r
+    /**\r
+     * Enumeration defining the ON UPDATE actions.\r
+     */\r
+    public static enum ConstraintUpdateType {\r
+        UNSET, CASCADE, RESTRICT, SET_NULL, NO_ACTION, SET_DEFAULT;\r
+    }\r
+\r
+    /**\r
+     * Enumeration defining the deferrability.\r
+     */\r
+    public static enum ConstraintDeferrabilityType {\r
+        UNSET, DEFERRABLE_INITIALLY_DEFERRED, DEFERRABLE_INITIALLY_IMMEDIATE, NOT_DEFERRABLE;\r
+    }\r
+\r
+    /**\r
+     * A foreign key constraint annotation.\r
+     * <p>\r
+     * <ul>\r
+     * <li>@IQContraintForeignKey(\r
+     * foreignColumns = { "idaccount"},\r
+     * referenceName = "account",\r
+     * referenceColumns = { "id" },\r
+     * deleteType = ConstrainDeleteType.CASCADE,\r
+     * updateType = ConstraintUpdateType.NO_ACTION )\r
+     * </ul>\r
+     * Note : reference columns should have a unique constraint defined in referenceName table,\r
+     * some database used to define a unique index instead of a unique constraint\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQContraintForeignKey {\r
+\r
+        /**\r
+         * Constraint name. If null or empty, iciql will generate one.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * Type of the action on delete, default to unspecified.\r
+         * <ul>\r
+         * <li>com.iciql.iciql.ConstrainDeleteType.CASCADE\r
+         * <li>com.iciql.iciql.ConstrainDeleteType.RESTRICT\r
+         * <li>com.iciql.iciql.ConstrainDeleteType.SET_NULL\r
+         * <li>com.iciql.iciql.ConstrainDeleteType.NO_ACTION\r
+         * <li>com.iciql.iciql.ConstrainDeleteType.SET_DEFAULT\r
+         * </ul>\r
+         */\r
+        ConstraintDeleteType deleteType() default ConstraintDeleteType.UNSET;\r
+\r
+        /**\r
+         * Type of the action on update, default to unspecified.\r
+         * <ul>\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.CASCADE\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.RESTRICT\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.SET_NULL\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.NO_ACTION\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.SET_DEFAULT\r
+         * </ul>\r
+         */\r
+        ConstraintUpdateType updateType() default ConstraintUpdateType.UNSET;\r
+\r
+        /**\r
+         * Type of the deferrability mode, default to unspecified\r
+         * <ul>\r
+         * <li>com.iciql.iciql.ConstrainUpdateType.CASCADE\r
+         * <li>ConstraintDeferrabilityType.DEFERRABLE_INITIALLY_DEFERRED\r
+         * <li>ConstraintDeferrabilityType.DEFERRABLE_INITIALLY_IMMEDIATE\r
+         * <li>ConstraintDeferrabilityType.NOT_DEFERRABLE\r
+         * </ul>\r
+         */\r
+        ConstraintDeferrabilityType deferrabilityType() default ConstraintDeferrabilityType.UNSET;\r
+\r
+        /**\r
+         * The source table for the columns defined as foreign.\r
+         */\r
+        String tableName() default "";\r
+\r
+        /**\r
+         * Columns defined as 'foreign'.\r
+         * <ul>\r
+         * <li>single column : foreignColumns = "id"\r
+         * <li>multiple column : foreignColumns = { "id", "name", "date" }\r
+         * </ul>\r
+         */\r
+        String[] foreignColumns() default {};\r
+\r
+        /**\r
+         * The reference table for the columns defined as references.\r
+         */\r
+        String referenceName() default "";\r
+\r
+        /**\r
+         * Columns defined as 'references'.\r
+         * <ul>\r
+         * <li>single column : referenceColumns = "id"\r
+         * <li>multiple column : referenceColumns = { "id", "name", "date" }\r
+         * </ul>\r
+         */\r
+        String[] referenceColumns() default {};\r
+    }\r
+\r
+    /**\r
+     * Annotation to specify multiple foreign keys constraints.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQContraintsForeignKey {\r
+        IQContraintForeignKey[] value() default {};\r
+    }\r
+\r
+    /**\r
+     * A unique constraint annotation.\r
+     * <p>\r
+     * <ul>\r
+     * <li>@IQContraintUnique(uniqueColumns = { "street", "city" })\r
+     * <li>@IQContraintUnique(name="streetconstraint", uniqueColumns = { "street", "city" })\r
+     * </ul>\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQContraintUnique {\r
+\r
+        /**\r
+         * Constraint name. If null or empty, iciql will generate one.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * Columns defined as 'unique'.\r
+         * <ul>\r
+         * <li>single column : uniqueColumns = "id"\r
+         * <li>multiple column : uniqueColumns = { "id", "name", "date" }\r
+         * </ul>\r
+         */\r
+        String[] uniqueColumns() default {};\r
+\r
+    }\r
+\r
+    /**\r
+     * Annotation to specify multiple unique constraints.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQContraintsUnique {\r
+        IQContraintUnique[] value() default {};\r
+    }\r
+\r
+    /**\r
+     * Annotation to define a view.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQView {\r
+\r
+        /**\r
+         * The view name. If not specified the class name is used as the view\r
+         * name.\r
+         * <p>\r
+         * The view name may still be overridden in the define() method if the\r
+         * model class is not annotated with IQView. Default: unspecified.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * The source table for the view.\r
+         * <p>\r
+         * The view name may still be overridden in the define() method if the\r
+         * model class is not annotated with IQView. Default: unspecified.\r
+         */\r
+        String tableName() default "";\r
+\r
+        /**\r
+         * The inherit columns allows this model class to inherit columns from\r
+         * its super class. IQTable and IQView annotations present on the super\r
+         * class or above are honored. Default: false.\r
+         */\r
+        boolean inheritColumns() default false;\r
+\r
+        /**\r
+         * Whether or not iciql tries to create the view. Default:\r
+         * true.\r
+         */\r
+        boolean create() default true;\r
+\r
+        /**\r
+         * If true, only fields that are explicitly annotated as IQColumn are\r
+         * mapped. Default: true.\r
+         */\r
+        boolean annotationsOnly() default true;\r
+    }\r
+\r
+    /**\r
+     * String snippet defining SQL constraints for a field. Use "this" as\r
+     * a placeholder for the column name.  "this" will be substituted at\r
+     * runtime.\r
+     * <p>\r
+     * IQConstraint("this > 2 AND this <= 7")\r
+     * <p>\r
+     * This snippet may still be overridden in the define() method if the\r
+     * model class is not annotated with IQTable or IQView. Default: unspecified.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.FIELD)\r
+    public @interface IQConstraint {\r
+\r
+        String value() default "";\r
+    }\r
+\r
+    /**\r
+     * Annotation to specify multiple indexes.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQIndexes {\r
+        IQIndex[] value() default {};\r
+    }\r
+\r
+    /**\r
+     * Annotation to define a table.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.TYPE)\r
+    public @interface IQTable {\r
+\r
+        /**\r
+         * The table name. If not specified the class name is used as the table\r
+         * name.\r
+         * <p>\r
+         * The table name may still be overridden in the define() method if the\r
+         * model class is not annotated with IQTable. Default: unspecified.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * The primary key may be optionally specified. If it is not specified,\r
+         * then no primary key is set by the IQTable annotation. You may specify\r
+         * a composite primary key.\r
+         * <ul>\r
+         * <li>single column primaryKey: value = "id"\r
+         * <li>compound primary key: value = { "id", "name" }\r
+         * </ul>\r
+         * The primary key may still be overridden in the define() method if the\r
+         * model class is not annotated with IQTable. Default: unspecified.\r
+         */\r
+        String[] primaryKey() default {};\r
+\r
+        /**\r
+         * The inherit columns allows this model class to inherit columns from\r
+         * its super class. IQTable and IQView annotations present on the super\r
+         * class or above are honored. Default: false.\r
+         */\r
+        boolean inheritColumns() default false;\r
+\r
+        /**\r
+         * Whether or not iciql tries to create the table and indexes. Default:\r
+         * true.\r
+         */\r
+        boolean create() default true;\r
+\r
+        /**\r
+         * If true, only fields that are explicitly annotated as IQColumn are\r
+         * mapped. Default: true.\r
+         */\r
+        boolean annotationsOnly() default true;\r
+\r
+        /**\r
+         * If true, this table is created as a memory table where data is\r
+         * persistent, but index data is kept in main memory. Valid only for H2\r
+         * and HSQL databases. Default: false.\r
+         */\r
+        boolean memoryTable() default false;\r
+    }\r
+\r
+    /**\r
+     * Annotation to define a column. Annotated fields may have any scope\r
+     * (however, the JVM may raise a SecurityException if the SecurityManager\r
+     * doesn't allow iciql to access the field.)\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.FIELD)\r
+    public @interface IQColumn {\r
+\r
+        /**\r
+         * If not specified, the field name is used as the column name. Default:\r
+         * the field name.\r
+         */\r
+        String name() default "";\r
+\r
+        /**\r
+         * This column is the primary key. Default: false.\r
+         */\r
+        boolean primaryKey() default false;\r
+\r
+        /**\r
+         * The column is created with a sequence as the default value. Default:\r
+         * false.\r
+         */\r
+        boolean autoIncrement() default false;\r
+\r
+        /**\r
+         * Length is used to define the length of a VARCHAR column or to define\r
+         * the precision of a DECIMAL(precision, scale) expression.\r
+         * <p>\r
+         * If larger than zero, it is used during the CREATE TABLE phase. For\r
+         * string values it may also be used to prevent database exceptions on\r
+         * INSERT and UPDATE statements (see trim).\r
+         * <p>\r
+         * Any length set in define() may override this annotation setting if\r
+         * the model class is not annotated with IQTable. Default: 0.\r
+         */\r
+        int length() default 0;\r
+\r
+        /**\r
+         * Scale is used during the CREATE TABLE phase to define the scale of a\r
+         * DECIMAL(precision, scale) expression.\r
+         * <p>\r
+         * Any scale set in define() may override this annotation setting if the\r
+         * model class is not annotated with IQTable. Default: 0.\r
+         */\r
+        int scale() default 0;\r
+\r
+        /**\r
+         * If true, iciql will automatically trim the string if it exceeds\r
+         * length (value.substring(0, length)). Default: false.\r
+         */\r
+        boolean trim() default false;\r
+\r
+        /**\r
+         * If false, iciql will set the column NOT NULL during the CREATE TABLE\r
+         * phase. Default: true.\r
+         */\r
+        boolean nullable() default true;\r
+\r
+        /**\r
+         * The default value assigned to the column during the CREATE TABLE\r
+         * phase. This field could contain a literal single-quoted value, or a\r
+         * function call. Empty strings are considered NULL. Examples:\r
+         * <ul>\r
+         * <li>defaultValue="" (null)\r
+         * <li>defaultValue="CURRENT_TIMESTAMP"\r
+         * <li>defaultValue="''" (empty string)\r
+         * <li>defaultValue="'0'"\r
+         * <li>defaultValue="'1970-01-01 00:00:01'"\r
+         * </ul>\r
+         * if the default value is specified, and auto increment is disabled,\r
+         * and primary key is disabled, then this value is included in the\r
+         * "DEFAULT ..." phrase of a column during the CREATE TABLE process.\r
+         * <p>\r
+         * Alternatively, you may specify a default object value on the field\r
+         * and this will be converted to a properly formatted DEFAULT expression\r
+         * during the CREATE TABLE process.\r
+         * <p>\r
+         * Default: unspecified (null).\r
+         */\r
+        String defaultValue() default "";\r
+\r
+    }\r
+\r
+    /**\r
+     * Interface for using the EnumType.ENUMID enumeration mapping strategy.\r
+     * <p>\r
+     * Enumerations wishing to use EnumType.ENUMID must implement this\r
+     * interface.\r
+     */\r
+    public interface EnumId<X> {\r
+        X enumId();\r
+\r
+        Class<X> enumIdClass();\r
+    }\r
+\r
+\r
+    /**\r
+     * Enumeration representing how to map a java.lang.Enum to a column.\r
+     * <p>\r
+     * <ul>\r
+     * <li>NAME - name() : string\r
+     * <li>ORDINAL - ordinal() : int\r
+     * <li>ENUMID - enumId() : X\r
+     * </ul>\r
+     *\r
+     * @see com.iciql.Iciql.EnumId interface\r
+     */\r
+    public enum EnumType {\r
+        NAME, ORDINAL, ENUMID;\r
+\r
+        public static final EnumType DEFAULT_TYPE = NAME;\r
+    }\r
+\r
+    /**\r
+     * Annotation to define how a java.lang.Enum is mapped to a column.\r
+     * <p>\r
+     * This annotation can be used on:\r
+     * <ul>\r
+     * <li>a field instance of an enumeration type\r
+     * <li>on the enumeration class declaration\r
+     * </ul>\r
+     * If you choose to annotate the class declaration, that will be the default\r
+     * mapping strategy for all @IQColumn instances of the enum. This can still\r
+     * be overridden for an individual field by specifying the IQEnum\r
+     * annotation.\r
+     * <p>\r
+     * The default mapping is by NAME.\r
+     * <p>\r
+     * <pre>\r
+     * IQEnum(EnumType.NAME)\r
+     * </pre>\r
+     * <p>\r
+     * A string mapping will generate either a VARCHAR, if IQColumn.length > 0\r
+     * or a TEXT column if IQColumn.length == 0\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target({ElementType.FIELD, ElementType.TYPE})\r
+    public @interface IQEnum {\r
+        EnumType value() default EnumType.NAME;\r
+    }\r
+\r
+    /**\r
+     * Annotation to define an ignored field.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target(ElementType.FIELD)\r
+    public @interface IQIgnore {\r
+    }\r
+\r
+    /**\r
+     * The runtime mode for Iciql.\r
+     */\r
+    public static enum Mode {\r
+\r
+        DEV, TEST, PROD;\r
+\r
+        public static Mode fromValue(String value) {\r
+\r
+            for (Mode mode : values()) {\r
+                if (mode.name().equalsIgnoreCase(value)) {\r
+                    return mode;\r
+                }\r
+            }\r
+\r
+            return PROD;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * This method is called to let the table define the primary key, indexes,\r
+     * and the table name.\r
+     */\r
+    void defineIQ();\r
+\r
+    /**\r
+     * Specify a custom type adapter for a method return type, a class field, or a method\r
+     * parameter.  Type adapters allow you to transform content received from or inserted into\r
+     * a database field.\r
+     */\r
+    @Retention(RetentionPolicy.RUNTIME)\r
+    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})\r
+    public @interface TypeAdapter {\r
+        Class<? extends DataTypeAdapter<?>> value();\r
+    }\r
+\r
+    /**\r
+     * Interface to allow implementations of custom data type adapters for supporting\r
+     * database-specific data types, like the Postgres 'json' or 'xml' types,\r
+     * or for supporting other object serialization schemes.\r
+     * <p><b>NOTE:</b> Data type adapters are not thread-safe!</p>\r
+     *\r
+     * @param <T>\r
+     */\r
+    public interface DataTypeAdapter<T> {\r
+\r
+        /**\r
+         * The SQL data type for this adapter.\r
+         *\r
+         * @return the SQL data type\r
+         */\r
+        String getDataType();\r
+\r
+        /**\r
+         * The Java domain type for this adapter.\r
+         *\r
+         * @return the Java domain type\r
+         */\r
+        Class<T> getJavaType();\r
+\r
+\r
+        /**\r
+         * Set the runtime mode.\r
+         * <p>\r
+         * Allows type adapters to adapt type mappings based on the runtime\r
+         * mode.\r
+         * </p>\r
+         *\r
+         * @param mode\r
+         */\r
+        void setMode(Mode mode);\r
+\r
+        /**\r
+         * Serializes your Java object into a JDBC object.\r
+         *\r
+         * @param value\r
+         * @return a JDBC object\r
+         */\r
+        Object serialize(T value);\r
+\r
+        /**\r
+         * Deserializes a JDBC object into your Java object.\r
+         *\r
+         * @param value\r
+         * @return the Java object\r
+         */\r
+        T deserialize(Object value);\r
+\r
+    }\r
 \r
 }\r
index 3db62cfbc27bb35244a581ea6905dab21454dab1..b5e1ca6d120f3a47acc53bf510690a998350857a 100644 (file)
@@ -26,170 +26,170 @@ import java.util.regex.Pattern;
  */\r
 public class IciqlException extends RuntimeException {\r
 \r
-       public static final int CODE_UNMAPPED_FIELD = 1;\r
-       public static final int CODE_DUPLICATE_KEY = 2;\r
-       public static final int CODE_OBJECT_NOT_FOUND = 3;\r
-       public static final int CODE_OBJECT_ALREADY_EXISTS = 4;\r
-       public static final int CODE_CONSTRAINT_VIOLATION = 5;\r
-       public static final int CODE_UNCHARACTERIZED = 6;\r
-\r
-       private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";\r
-\r
-       private static final long serialVersionUID = 1L;\r
-\r
-       private String sql;\r
-\r
-       private int iciqlCode;\r
-\r
-       public IciqlException(Throwable t) {\r
-               super(t.getMessage(), t);\r
-               configureCode(t);\r
-       }\r
-\r
-       public IciqlException(String message, Object... parameters) {\r
-               super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);\r
-       }\r
-\r
-       public IciqlException(Throwable t, String message, Object... parameters) {\r
-               super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message, t);\r
-               configureCode(t);\r
-       }\r
-\r
-       public static void checkUnmappedField(String sql) {\r
-               if (Pattern.compile(IciqlException.TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {\r
-                       IciqlException e = new IciqlException("unmapped field in statement!");\r
-                       e.sql = sql;\r
-                       e.iciqlCode = CODE_UNMAPPED_FIELD;\r
-                       throw e;\r
-               }\r
-       }\r
-\r
-       public static IciqlException fromSQL(String sql, Throwable t) {\r
-               if (Pattern.compile(TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {\r
-                       IciqlException e = new IciqlException(t, "unmapped field in statement!");\r
-                       e.sql = sql;\r
-                       e.iciqlCode = CODE_UNMAPPED_FIELD;\r
-                       return e;\r
-               } else {\r
-                       IciqlException e = new IciqlException(t, t.getMessage());\r
-                       e.sql = sql;\r
-                       return e;\r
-               }\r
-       }\r
-\r
-       public void setSQL(String sql) {\r
-               this.sql = sql;\r
-       }\r
-\r
-       public String getSQL() {\r
-               return sql;\r
-       }\r
-\r
-       public int getIciqlCode() {\r
-               return iciqlCode;\r
-       }\r
-\r
-       private void configureCode(Throwable t) {\r
-               if (t == null) {\r
-                       return;\r
-               }\r
-               if (t instanceof SQLException) {\r
-                       // http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html\r
-                       SQLException s = (SQLException) t;\r
-                       String state = s.getSQLState();\r
-                       if ("23000".equals(state)) {\r
-                               // MySQL duplicate primary key on insert\r
-                               iciqlCode = CODE_DUPLICATE_KEY;\r
-                               if (s.getErrorCode() == 1217) {\r
-                                       iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
-                               }\r
-                       } else if ("23505".equals(state)) {\r
-                               // Derby duplicate primary key on insert\r
-                               iciqlCode = CODE_DUPLICATE_KEY;\r
-                       } else if ("42000".equals(state)) {\r
-                               // MySQL duplicate unique index value on insert\r
-                               iciqlCode = CODE_DUPLICATE_KEY;\r
-                       } else if ("42Y07".equals(state)) {\r
-                               // Derby schema not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("42X05".equals(state)) {\r
-                               // Derby table not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("42Y55".equals(state)) {\r
-                               // Derby table not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("42S02".equals(state)) {\r
-                               // H2 table not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("42501".equals(state)) {\r
-                               // HSQL table not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("42P01".equals(state)) {\r
-                               // PostgreSQL table not found\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("X0X05".equals(state)) {\r
-                               // Derby view/table not found exists\r
-                               iciqlCode = CODE_OBJECT_NOT_FOUND;\r
-                       } else if ("X0Y32".equals(state)) {\r
-                               // Derby table already exists\r
-                               iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
-                       } else if ("42P07".equals(state)) {\r
-                               // PostgreSQL table or index already exists\r
-                               iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
-                       } else if ("42S01".equals(state)) {\r
-                               // MySQL view already exists\r
-                               iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
-                       } else if ("42S11".equals(state)) {\r
-                               // H2 index already exists\r
-                               iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
-                       } else if ("42504".equals(state)) {\r
-                               // HSQL index already exists\r
-                               iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
-                       } else if ("2BP01".equals(state)) {\r
-                               // PostgreSQL constraint violation\r
-                               iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
-                       } else if ("42533".equals(state)) {\r
-                               // HSQL constraint violation\r
-                               iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
-                       } 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
-                       }\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public String toString() {\r
-               StringBuilder sb = new StringBuilder();\r
-               sb.append(getClass().getName());\r
-               String message = getLocalizedMessage();\r
-               if (message != null) {\r
-                       sb.append(": ").append(message);\r
-               }\r
-               if (sql != null) {\r
-                       sb.append('\n').append(sql);\r
-               }\r
-               return sb.toString();\r
-       }\r
+    public static final int CODE_UNMAPPED_FIELD = 1;\r
+    public static final int CODE_DUPLICATE_KEY = 2;\r
+    public static final int CODE_OBJECT_NOT_FOUND = 3;\r
+    public static final int CODE_OBJECT_ALREADY_EXISTS = 4;\r
+    public static final int CODE_CONSTRAINT_VIOLATION = 5;\r
+    public static final int CODE_UNCHARACTERIZED = 6;\r
+\r
+    private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";\r
+\r
+    private static final long serialVersionUID = 1L;\r
+\r
+    private String sql;\r
+\r
+    private int iciqlCode;\r
+\r
+    public IciqlException(Throwable t) {\r
+        super(t.getMessage(), t);\r
+        configureCode(t);\r
+    }\r
+\r
+    public IciqlException(String message, Object... parameters) {\r
+        super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);\r
+    }\r
+\r
+    public IciqlException(Throwable t, String message, Object... parameters) {\r
+        super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message, t);\r
+        configureCode(t);\r
+    }\r
+\r
+    public static void checkUnmappedField(String sql) {\r
+        if (Pattern.compile(IciqlException.TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {\r
+            IciqlException e = new IciqlException("unmapped field in statement!");\r
+            e.sql = sql;\r
+            e.iciqlCode = CODE_UNMAPPED_FIELD;\r
+            throw e;\r
+        }\r
+    }\r
+\r
+    public static IciqlException fromSQL(String sql, Throwable t) {\r
+        if (Pattern.compile(TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {\r
+            IciqlException e = new IciqlException(t, "unmapped field in statement!");\r
+            e.sql = sql;\r
+            e.iciqlCode = CODE_UNMAPPED_FIELD;\r
+            return e;\r
+        } else {\r
+            IciqlException e = new IciqlException(t, t.getMessage());\r
+            e.sql = sql;\r
+            return e;\r
+        }\r
+    }\r
+\r
+    public void setSQL(String sql) {\r
+        this.sql = sql;\r
+    }\r
+\r
+    public String getSQL() {\r
+        return sql;\r
+    }\r
+\r
+    public int getIciqlCode() {\r
+        return iciqlCode;\r
+    }\r
+\r
+    private void configureCode(Throwable t) {\r
+        if (t == null) {\r
+            return;\r
+        }\r
+        if (t instanceof SQLException) {\r
+            // http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html\r
+            SQLException s = (SQLException) t;\r
+            String state = s.getSQLState();\r
+            if ("23000".equals(state)) {\r
+                // MySQL duplicate primary key on insert\r
+                iciqlCode = CODE_DUPLICATE_KEY;\r
+                if (s.getErrorCode() == 1217) {\r
+                    iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
+                }\r
+            } else if ("23505".equals(state)) {\r
+                // Derby duplicate primary key on insert\r
+                iciqlCode = CODE_DUPLICATE_KEY;\r
+            } else if ("42000".equals(state)) {\r
+                // MySQL duplicate unique index value on insert\r
+                iciqlCode = CODE_DUPLICATE_KEY;\r
+            } else if ("42Y07".equals(state)) {\r
+                // Derby schema not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("42X05".equals(state)) {\r
+                // Derby table not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("42Y55".equals(state)) {\r
+                // Derby table not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("42S02".equals(state)) {\r
+                // H2 table not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("42501".equals(state)) {\r
+                // HSQL table not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("42P01".equals(state)) {\r
+                // PostgreSQL table not found\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("X0X05".equals(state)) {\r
+                // Derby view/table not found exists\r
+                iciqlCode = CODE_OBJECT_NOT_FOUND;\r
+            } else if ("X0Y32".equals(state)) {\r
+                // Derby table already exists\r
+                iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
+            } else if ("42P07".equals(state)) {\r
+                // PostgreSQL table or index already exists\r
+                iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
+            } else if ("42S01".equals(state)) {\r
+                // MySQL view already exists\r
+                iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
+            } else if ("42S11".equals(state)) {\r
+                // H2 index already exists\r
+                iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
+            } else if ("42504".equals(state)) {\r
+                // HSQL index already exists\r
+                iciqlCode = CODE_OBJECT_ALREADY_EXISTS;\r
+            } else if ("2BP01".equals(state)) {\r
+                // PostgreSQL constraint violation\r
+                iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
+            } else if ("42533".equals(state)) {\r
+                // HSQL constraint violation\r
+                iciqlCode = CODE_CONSTRAINT_VIOLATION;\r
+            } 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
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append(getClass().getName());\r
+        String message = getLocalizedMessage();\r
+        if (message != null) {\r
+            sb.append(": ").append(message);\r
+        }\r
+        if (sql != null) {\r
+            sb.append('\n').append(sql);\r
+        }\r
+        return sb.toString();\r
+    }\r
 }\r
index 7fa1de6b688585126840445517f5c0cc54d2a544..14dc615850e56e510046f7dc53c269a7c19029b3 100644 (file)
@@ -17,7 +17,8 @@
 
 package com.iciql;
 
-import static com.iciql.util.StringUtils.isNullOrEmpty;
+import com.iciql.TableDefinition.FieldDefinition;
+import com.iciql.util.StringUtils;
 
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
@@ -32,8 +33,7 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.regex.Pattern;
 
-import com.iciql.TableDefinition.FieldDefinition;
-import com.iciql.util.StringUtils;
+import static com.iciql.util.StringUtils.isNullOrEmpty;
 
 /**
  * Utility methods for models related to type mapping, default value validation,
@@ -41,469 +41,460 @@ import com.iciql.util.StringUtils;
  */
 class ModelUtils {
 
-       /**
-        * The list of supported data types. It is used by the runtime mapping for
-        * CREATE statements.
-        */
-       private static final Map<Class<?>, String> SUPPORTED_TYPES = new HashMap<Class<?>, String>();
-
-       static {
-               Map<Class<?>, String> m = SUPPORTED_TYPES;
-               m.put(String.class, "VARCHAR");
-               m.put(Boolean.class, "BOOLEAN");
-               m.put(Byte.class, "TINYINT");
-               m.put(Short.class, "SMALLINT");
-               m.put(Integer.class, "INT");
-               m.put(Long.class, "BIGINT");
-               m.put(Float.class, "REAL");
-               m.put(Double.class, "DOUBLE");
-               m.put(BigDecimal.class, "DECIMAL");
-               m.put(java.sql.Timestamp.class, "TIMESTAMP");
-               m.put(java.util.Date.class, "TIMESTAMP");
-               m.put(java.sql.Date.class, "DATE");
-               m.put(java.sql.Time.class, "TIME");
-               m.put(byte[].class, "BLOB");
-               m.put(UUID.class, "UUID");
-
-               // map primitives
-               m.put(boolean.class, m.get(Boolean.class));
-               m.put(byte.class, m.get(Byte.class));
-               m.put(short.class, m.get(Short.class));
-               m.put(int.class, m.get(Integer.class));
-               m.put(long.class, m.get(Long.class));
-               m.put(float.class, m.get(Float.class));
-               m.put(double.class, m.get(Double.class));
-       }
-
-       /**
-        * Convert SQL type aliases to the list of supported types. This map is used
-        * by generation and validation.
-        */
-       private static final Map<String, String> SQL_TYPES = new HashMap<String, String>();
-
-       static {
-               Map<String, String> m = SQL_TYPES;
-               m.put("CHAR", "VARCHAR");
-               m.put("CHARACTER", "VARCHAR");
-               m.put("NCHAR", "VARCHAR");
-               m.put("VARCHAR_CASESENSITIVE", "VARCHAR");
-               m.put("VARCHAR_IGNORECASE", "VARCHAR");
-               m.put("LONGVARCHAR", "VARCHAR");
-               m.put("VARCHAR2", "VARCHAR");
-               m.put("NVARCHAR", "VARCHAR");
-               m.put("NVARCHAR2", "VARCHAR");
-               m.put("TEXT", "VARCHAR");
-               m.put("NTEXT", "VARCHAR");
-               m.put("TINYTEXT", "VARCHAR");
-               m.put("MEDIUMTEXT", "VARCHAR");
-               m.put("LONGTEXT", "VARCHAR");
-               m.put("CLOB", "VARCHAR");
-               m.put("NCLOB", "VARCHAR");
-
-               // logic
-               m.put("BIT", "BOOLEAN");
-               m.put("BOOL", "BOOLEAN");
-
-               // numeric
-               m.put("BYTE", "TINYINT");
-               m.put("INT2", "SMALLINT");
-               m.put("YEAR", "SMALLINT");
-               m.put("INTEGER", "INT");
-               m.put("MEDIUMINT", "INT");
-               m.put("INT4", "INT");
-               m.put("SIGNED", "INT");
-               m.put("INT8", "BIGINT");
-               m.put("IDENTITY", "BIGINT");
-               m.put("SERIAL", "INT");
-               m.put("BIGSERIAL", "BIGINT");
-
-               // decimal
-               m.put("NUMBER", "DECIMAL");
-               m.put("DEC", "DECIMAL");
-               m.put("NUMERIC", "DECIMAL");
-               m.put("FLOAT", "DOUBLE");
-               m.put("FLOAT4", "DOUBLE");
-               m.put("FLOAT8", "DOUBLE");
-               m.put("DOUBLE PRECISION", "DOUBLE");
-
-               // date
-               m.put("DATETIME", "TIMESTAMP");
-               m.put("SMALLDATETIME", "TIMESTAMP");
-
-               // binary types
-               m.put("TINYBLOB", "BLOB");
-               m.put("MEDIUMBLOB", "BLOB");
-               m.put("LONGBLOB", "BLOB");
-               m.put("IMAGE", "BLOB");
-               m.put("OID", "BLOB");
-       }
-
-       private static final List<String> KEYWORDS = Arrays.asList("abstract", "assert", "boolean", "break",
-                       "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else",
-                       "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import",
-                       "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected",
-                       "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this",
-                       "throw", "throws", "transient", "try", "void", "volatile", "while", "false", "null", "true");
-
-       /**
-        * Returns a SQL type mapping for a Java class.
-        *
-        * @param fieldDef
-        *            the field to map
-        * @return
-        */
-       static String getDataType(FieldDefinition fieldDef) {
-               Class<?> fieldClass = fieldDef.field.getType();
-               if (fieldClass.isEnum()) {
-                       switch (fieldDef.enumType) {
-                       case ORDINAL:
-                               return "INT";
-                       case ENUMID:
-                               String sqlType = SUPPORTED_TYPES.get(fieldDef.enumTypeClass);
-                               if (sqlType == null) {
-                                       throw new IciqlException("Unsupported enum mapping type {0} for {1}",
-                                                       fieldDef.enumTypeClass, fieldDef.columnName);
-                               }
-                               return sqlType;
-                       case NAME:
-                       default:
-                               return "VARCHAR";
-                       }
-               }
-               if (SUPPORTED_TYPES.containsKey(fieldClass)) {
-                       return SUPPORTED_TYPES.get(fieldClass);
-               }
-               throw new IciqlException("Unsupported type " + fieldClass.getName());
-       }
-
-       /**
-        * Returns the Java class for a given SQL type.
-        *
-        * @param sqlType
-        * @param dateTimeClass
-        *            the preferred date class (java.util.Date or
-        *            java.sql.Timestamp)
-        * @return
-        */
-       static Class<?> getClassForSqlType(String sqlType, Class<? extends java.util.Date> dateTimeClass) {
-               sqlType = sqlType.toUpperCase();
-               // XXX dropping "UNSIGNED" or parts like that could be trouble
-               sqlType = sqlType.split(" ")[0].trim();
-               if (sqlType.indexOf('(') > -1) {
-                       // strip out length or precision
-                       sqlType = sqlType.substring(0, sqlType.indexOf('('));
-               }
-
-               if (SQL_TYPES.containsKey(sqlType)) {
-                       // convert the sqlType to a standard type
-                       sqlType = SQL_TYPES.get(sqlType);
-               }
-               Class<?> mappedClass = null;
-               for (Class<?> clazz : SUPPORTED_TYPES.keySet()) {
-                       if (clazz.isPrimitive()) {
-                               // do not map from SQL TYPE to primitive type
-                               continue;
-                       }
-                       if (SUPPORTED_TYPES.get(clazz).equalsIgnoreCase(sqlType)) {
-                               mappedClass = clazz;
-
-                               break;
-                       }
-               }
-               if (mappedClass != null) {
-                       if (mappedClass.equals(java.util.Date.class) || mappedClass.equals(java.sql.Timestamp.class)) {
-                               return dateTimeClass;
-                       }
-                       return mappedClass;
-               }
-               return null;
-       }
-
-       /**
-        * Tries to create a convert a SQL table name to a camel case class name.
-        *
-        * @param tableName
-        *            the SQL table name
-        * @return the class name
-        */
-       static String convertTableToClassName(String tableName) {
-               String[] chunks = StringUtils.arraySplit(tableName, '_', false);
-               StringBuilder className = new StringBuilder();
-               for (String chunk : chunks) {
-                       if (chunk.length() == 0) {
-                               // leading or trailing _
-                               continue;
-                       }
-                       String[] subchunks = StringUtils.arraySplit(chunk, ' ', false);
-                       for (String subchunk : subchunks) {
-                               if (subchunk.length() == 0) {
-                                       // leading or trailing space
-                                       continue;
-                               }
-                               className.append(Character.toUpperCase(subchunk.charAt(0)));
-                               className.append(subchunk.substring(1).toLowerCase());
-                       }
-               }
-               return className.toString();
-       }
-
-       /**
-        * Ensures that SQL column names don't collide with Java keywords.
-        *
-        * @param columnName
-        *            the column name
-        * @return the Java field name
-        */
-       static String convertColumnToFieldName(String columnName) {
-               String lower = columnName.toLowerCase();
-               if (KEYWORDS.contains(lower)) {
-                       lower += "Value";
-               }
-               return lower;
-       }
-
-       /**
-        * Converts a DEFAULT clause value into an object.
-        *
-        * @param field
-        *            definition
-        * @return object
-        */
-       static Object getDefaultValue(FieldDefinition def, Class<? extends Date> dateTimeClass) {
-               Class<?> valueType = getClassForSqlType(def.dataType, dateTimeClass);
-               if (String.class.isAssignableFrom(valueType)) {
-                       if (StringUtils.isNullOrEmpty(def.defaultValue)) {
-                               // literal default must be specified within single quotes
-                               return null;
-                       }
-                       if (def.defaultValue.charAt(0) == '\''
-                                       && def.defaultValue.charAt(def.defaultValue.length() - 1) == '\'') {
-                               // strip leading and trailing single quotes
-                               return def.defaultValue.substring(1, def.defaultValue.length() - 1).trim();
-                       }
-                       return def.defaultValue;
-               }
-
-               if (StringUtils.isNullOrEmpty(def.defaultValue)) {
-                       // can not create object from empty string
-                       return null;
-               }
-
-               // strip leading and trailing single quotes
-               String content = def.defaultValue;
-               if (content.charAt(0) == '\'') {
-                       content = content.substring(1);
-               }
-               if (content.charAt(content.length() - 1) == '\'') {
-                       content = content.substring(0, content.length() - 2);
-               }
-
-               if (StringUtils.isNullOrEmpty(content)) {
-                       // can not create object from empty string
-                       return null;
-               }
-
-               if (Boolean.class.isAssignableFrom(valueType) || boolean.class.isAssignableFrom(valueType)) {
-                       return Boolean.parseBoolean(content);
-               }
-
-               if (Number.class.isAssignableFrom(valueType)) {
-                       try {
-                               // delegate to static valueOf() method to parse string
-                               Method m = valueType.getMethod("valueOf", String.class);
-                               return m.invoke(null, content);
-                       } catch (NumberFormatException e) {
-                               throw new IciqlException(e, "Failed to parse {0} as a number!", def.defaultValue);
-                       } catch (Throwable t) {
-                       }
-               }
-
-               String dateRegex = "[0-9]{1,4}[-/\\.][0-9]{1,2}[-/\\.][0-9]{1,2}";
-               String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
-
-               if (java.sql.Date.class.isAssignableFrom(valueType)) {
-                       // this may be a little loose....
-                       // 00-00-00
-                       // 00/00/00
-                       // 00.00.00
-                       Pattern pattern = Pattern.compile(dateRegex);
-                       if (pattern.matcher(content).matches()) {
-                               DateFormat df = DateFormat.getDateInstance();
-                               try {
-                                       return df.parse(content);
-                               } catch (Exception e) {
-                                       throw new IciqlException(e, "Failed to parse {0} as a date!", def.defaultValue);
-                               }
-                       }
-               }
-
-               if (java.sql.Time.class.isAssignableFrom(valueType)) {
-                       // 00:00:00
-                       Pattern pattern = Pattern.compile(timeRegex);
-                       if (pattern.matcher(content).matches()) {
-                               DateFormat df = DateFormat.getTimeInstance();
-                               try {
-                                       return df.parse(content);
-                               } catch (Exception e) {
-                                       throw new IciqlException(e, "Failed to parse {0} as a time!", def.defaultValue);
-                               }
-                       }
-               }
-
-               if (java.util.Date.class.isAssignableFrom(valueType)) {
-                       // this may be a little loose....
-                       // 00-00-00 00:00:00
-                       // 00/00/00T00:00:00
-                       // 00.00.00T00:00:00
-                       Pattern pattern = Pattern.compile(dateRegex + "." + timeRegex);
-                       if (pattern.matcher(content).matches()) {
-                               DateFormat df = DateFormat.getDateTimeInstance();
-                               try {
-                                       return df.parse(content);
-                               } catch (Exception e) {
-                                       throw new IciqlException(e, "Failed to parse {0} as a datetimestamp!", def.defaultValue);
-                               }
-                       }
-               }
-               return content;
-       }
-
-       /**
-        * Converts the object into a DEFAULT clause value.
-        *
-        * @param o
-        *            the default object
-        * @return the value formatted for a DEFAULT clause
-        */
-       static String formatDefaultValue(Object o) {
-               Class<?> objectClass = o.getClass();
-               String value = null;
-               if (Number.class.isAssignableFrom(objectClass)) {
-                       // NUMBER
-                       return ((Number) o).toString();
-               } else if (Boolean.class.isAssignableFrom(objectClass)) {
-                       // BOOLEAN
-                       return o.toString();
-               } else if (java.sql.Date.class.isAssignableFrom(objectClass)) {
-                       // DATE
-                       value = new SimpleDateFormat("yyyy-MM-dd").format((Date) o);
-               } else if (java.sql.Time.class.isAssignableFrom(objectClass)) {
-                       // TIME
-                       value = new SimpleDateFormat("HH:mm:ss").format((Date) o);
-               } else if (Date.class.isAssignableFrom(objectClass)) {
-                       // DATETIME
-                       value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) o);
-               } else if (String.class.isAssignableFrom(objectClass)) {
-                       // STRING
-                       value = o.toString();
-               }
-               if (value == null) {
-                       return "''";
-               }
-               return MessageFormat.format("''{0}''", value);
-       }
-
-       /**
-        * Checks the formatting of IQColumn.defaultValue().
-        *
-        * @param defaultValue
-        *            the default value
-        * @return true if it is
-        */
-       static boolean isProperlyFormattedDefaultValue(String defaultValue) {
-               if (isNullOrEmpty(defaultValue)) {
-                       return true;
-               }
-               Pattern literalDefault = Pattern.compile("'.*'");
-               Pattern functionDefault = Pattern.compile("[^'].*[^']");
-               return literalDefault.matcher(defaultValue).matches()
-                               || functionDefault.matcher(defaultValue).matches();
-       }
-
-       /**
-        * Checks to see if the default value matches the class.
-        *
-        * @param modelClass
-        *            the class
-        * @param defaultValue
-        *            the value
-        * @return true if it does
-        */
-       static boolean isValidDefaultValue(Class<?> modelClass, String defaultValue) {
-
-               if (defaultValue == null) {
-                       // NULL
-                       return true;
-               }
-               if (defaultValue.trim().length() == 0) {
-                       // NULL (effectively)
-                       return true;
-               }
-
-               // function / variable
-               Pattern functionDefault = Pattern.compile("[^'].*[^']");
-               if (functionDefault.matcher(defaultValue).matches()) {
-                       // hard to validate this since its in the database
-                       // assume it is good
-                       return true;
-               }
-
-               // STRING
-               if (modelClass == String.class) {
-                       Pattern stringDefault = Pattern.compile("'(.|\\n)*'");
-                       return stringDefault.matcher(defaultValue).matches();
-               }
-
-               String dateRegex = "[0-9]{1,4}[-/\\.][0-9]{1,2}[-/\\.][0-9]{1,2}";
-               String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
-
-               // TIMESTAMP
-               if (modelClass == java.util.Date.class || modelClass == java.sql.Timestamp.class) {
-                       // this may be a little loose....
-                       // 00-00-00 00:00:00
-                       // 00/00/00T00:00:00
-                       // 00.00.00T00:00:00
-                       Pattern pattern = Pattern.compile("'" + dateRegex + "." + timeRegex + "'");
-                       return pattern.matcher(defaultValue).matches();
-               }
-
-               // DATE
-               if (modelClass == java.sql.Date.class) {
-                       // this may be a little loose....
-                       // 00-00-00
-                       // 00/00/00
-                       // 00.00.00
-                       Pattern pattern = Pattern.compile("'" + dateRegex + "'");
-                       return pattern.matcher(defaultValue).matches();
-               }
-
-               // TIME
-               if (modelClass == java.sql.Time.class) {
-                       // 00:00:00
-                       Pattern pattern = Pattern.compile("'" + timeRegex + "'");
-                       return pattern.matcher(defaultValue).matches();
-               }
-
-               // NUMBER
-               if (Number.class.isAssignableFrom(modelClass)) {
-                       // strip single quotes
-                       String unquoted = defaultValue;
-                       if (unquoted.charAt(0) == '\'') {
-                               unquoted = unquoted.substring(1);
-                       }
-                       if (unquoted.charAt(unquoted.length() - 1) == '\'') {
-                               unquoted = unquoted.substring(0, unquoted.length() - 1);
-                       }
-
-                       try {
-                               // delegate to static valueOf() method to parse string
-                               Method m = modelClass.getMethod("valueOf", String.class);
-                               m.invoke(null, unquoted);
-                       } catch (NumberFormatException ex) {
-                               return false;
-                       } catch (Throwable t) {
-                       }
-               }
-               return true;
-       }
+    /**
+     * The list of supported data types. It is used by the runtime mapping for
+     * CREATE statements.
+     */
+    private static final Map<Class<?>, String> SUPPORTED_TYPES = new HashMap<Class<?>, String>();
+
+    static {
+        Map<Class<?>, String> m = SUPPORTED_TYPES;
+        m.put(String.class, "VARCHAR");
+        m.put(Boolean.class, "BOOLEAN");
+        m.put(Byte.class, "TINYINT");
+        m.put(Short.class, "SMALLINT");
+        m.put(Integer.class, "INT");
+        m.put(Long.class, "BIGINT");
+        m.put(Float.class, "REAL");
+        m.put(Double.class, "DOUBLE");
+        m.put(BigDecimal.class, "DECIMAL");
+        m.put(java.sql.Timestamp.class, "TIMESTAMP");
+        m.put(java.util.Date.class, "TIMESTAMP");
+        m.put(java.sql.Date.class, "DATE");
+        m.put(java.sql.Time.class, "TIME");
+        m.put(byte[].class, "BLOB");
+        m.put(UUID.class, "UUID");
+
+        // map primitives
+        m.put(boolean.class, m.get(Boolean.class));
+        m.put(byte.class, m.get(Byte.class));
+        m.put(short.class, m.get(Short.class));
+        m.put(int.class, m.get(Integer.class));
+        m.put(long.class, m.get(Long.class));
+        m.put(float.class, m.get(Float.class));
+        m.put(double.class, m.get(Double.class));
+    }
+
+    /**
+     * Convert SQL type aliases to the list of supported types. This map is used
+     * by generation and validation.
+     */
+    private static final Map<String, String> SQL_TYPES = new HashMap<String, String>();
+
+    static {
+        Map<String, String> m = SQL_TYPES;
+        m.put("CHAR", "VARCHAR");
+        m.put("CHARACTER", "VARCHAR");
+        m.put("NCHAR", "VARCHAR");
+        m.put("VARCHAR_CASESENSITIVE", "VARCHAR");
+        m.put("VARCHAR_IGNORECASE", "VARCHAR");
+        m.put("LONGVARCHAR", "VARCHAR");
+        m.put("VARCHAR2", "VARCHAR");
+        m.put("NVARCHAR", "VARCHAR");
+        m.put("NVARCHAR2", "VARCHAR");
+        m.put("TEXT", "VARCHAR");
+        m.put("NTEXT", "VARCHAR");
+        m.put("TINYTEXT", "VARCHAR");
+        m.put("MEDIUMTEXT", "VARCHAR");
+        m.put("LONGTEXT", "VARCHAR");
+        m.put("CLOB", "VARCHAR");
+        m.put("NCLOB", "VARCHAR");
+
+        // logic
+        m.put("BIT", "BOOLEAN");
+        m.put("BOOL", "BOOLEAN");
+
+        // numeric
+        m.put("BYTE", "TINYINT");
+        m.put("INT2", "SMALLINT");
+        m.put("YEAR", "SMALLINT");
+        m.put("INTEGER", "INT");
+        m.put("MEDIUMINT", "INT");
+        m.put("INT4", "INT");
+        m.put("SIGNED", "INT");
+        m.put("INT8", "BIGINT");
+        m.put("IDENTITY", "BIGINT");
+        m.put("SERIAL", "INT");
+        m.put("BIGSERIAL", "BIGINT");
+
+        // decimal
+        m.put("NUMBER", "DECIMAL");
+        m.put("DEC", "DECIMAL");
+        m.put("NUMERIC", "DECIMAL");
+        m.put("FLOAT", "DOUBLE");
+        m.put("FLOAT4", "DOUBLE");
+        m.put("FLOAT8", "DOUBLE");
+        m.put("DOUBLE PRECISION", "DOUBLE");
+
+        // date
+        m.put("DATETIME", "TIMESTAMP");
+        m.put("SMALLDATETIME", "TIMESTAMP");
+
+        // binary types
+        m.put("TINYBLOB", "BLOB");
+        m.put("MEDIUMBLOB", "BLOB");
+        m.put("LONGBLOB", "BLOB");
+        m.put("IMAGE", "BLOB");
+        m.put("OID", "BLOB");
+    }
+
+    private static final List<String> KEYWORDS = Arrays.asList("abstract", "assert", "boolean", "break",
+            "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else",
+            "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import",
+            "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected",
+            "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this",
+            "throw", "throws", "transient", "try", "void", "volatile", "while", "false", "null", "true");
+
+    /**
+     * Returns a SQL type mapping for a Java class.
+     *
+     * @param fieldDef the field to map
+     * @return
+     */
+    static String getDataType(FieldDefinition fieldDef) {
+        Class<?> fieldClass = fieldDef.field.getType();
+        if (fieldClass.isEnum()) {
+            switch (fieldDef.enumType) {
+                case ORDINAL:
+                    return "INT";
+                case ENUMID:
+                    String sqlType = SUPPORTED_TYPES.get(fieldDef.enumTypeClass);
+                    if (sqlType == null) {
+                        throw new IciqlException("Unsupported enum mapping type {0} for {1}",
+                                fieldDef.enumTypeClass, fieldDef.columnName);
+                    }
+                    return sqlType;
+                case NAME:
+                default:
+                    return "VARCHAR";
+            }
+        }
+        if (SUPPORTED_TYPES.containsKey(fieldClass)) {
+            return SUPPORTED_TYPES.get(fieldClass);
+        }
+        throw new IciqlException("Unsupported type " + fieldClass.getName());
+    }
+
+    /**
+     * Returns the Java class for a given SQL type.
+     *
+     * @param sqlType
+     * @param dateTimeClass the preferred date class (java.util.Date or
+     *                      java.sql.Timestamp)
+     * @return
+     */
+    static Class<?> getClassForSqlType(String sqlType, Class<? extends java.util.Date> dateTimeClass) {
+        sqlType = sqlType.toUpperCase();
+        // XXX dropping "UNSIGNED" or parts like that could be trouble
+        sqlType = sqlType.split(" ")[0].trim();
+        if (sqlType.indexOf('(') > -1) {
+            // strip out length or precision
+            sqlType = sqlType.substring(0, sqlType.indexOf('('));
+        }
+
+        if (SQL_TYPES.containsKey(sqlType)) {
+            // convert the sqlType to a standard type
+            sqlType = SQL_TYPES.get(sqlType);
+        }
+        Class<?> mappedClass = null;
+        for (Class<?> clazz : SUPPORTED_TYPES.keySet()) {
+            if (clazz.isPrimitive()) {
+                // do not map from SQL TYPE to primitive type
+                continue;
+            }
+            if (SUPPORTED_TYPES.get(clazz).equalsIgnoreCase(sqlType)) {
+                mappedClass = clazz;
+
+                break;
+            }
+        }
+        if (mappedClass != null) {
+            if (mappedClass.equals(java.util.Date.class) || mappedClass.equals(java.sql.Timestamp.class)) {
+                return dateTimeClass;
+            }
+            return mappedClass;
+        }
+        return null;
+    }
+
+    /**
+     * Tries to create a convert a SQL table name to a camel case class name.
+     *
+     * @param tableName the SQL table name
+     * @return the class name
+     */
+    static String convertTableToClassName(String tableName) {
+        String[] chunks = StringUtils.arraySplit(tableName, '_', false);
+        StringBuilder className = new StringBuilder();
+        for (String chunk : chunks) {
+            if (chunk.length() == 0) {
+                // leading or trailing _
+                continue;
+            }
+            String[] subchunks = StringUtils.arraySplit(chunk, ' ', false);
+            for (String subchunk : subchunks) {
+                if (subchunk.length() == 0) {
+                    // leading or trailing space
+                    continue;
+                }
+                className.append(Character.toUpperCase(subchunk.charAt(0)));
+                className.append(subchunk.substring(1).toLowerCase());
+            }
+        }
+        return className.toString();
+    }
+
+    /**
+     * Ensures that SQL column names don't collide with Java keywords.
+     *
+     * @param columnName the column name
+     * @return the Java field name
+     */
+    static String convertColumnToFieldName(String columnName) {
+        String lower = columnName.toLowerCase();
+        if (KEYWORDS.contains(lower)) {
+            lower += "Value";
+        }
+        return lower;
+    }
+
+    /**
+     * Converts a DEFAULT clause value into an object.
+     *
+     * @param field definition
+     * @return object
+     */
+    static Object getDefaultValue(FieldDefinition def, Class<? extends Date> dateTimeClass) {
+        Class<?> valueType = getClassForSqlType(def.dataType, dateTimeClass);
+        if (String.class.isAssignableFrom(valueType)) {
+            if (StringUtils.isNullOrEmpty(def.defaultValue)) {
+                // literal default must be specified within single quotes
+                return null;
+            }
+            if (def.defaultValue.charAt(0) == '\''
+                    && def.defaultValue.charAt(def.defaultValue.length() - 1) == '\'') {
+                // strip leading and trailing single quotes
+                return def.defaultValue.substring(1, def.defaultValue.length() - 1).trim();
+            }
+            return def.defaultValue;
+        }
+
+        if (StringUtils.isNullOrEmpty(def.defaultValue)) {
+            // can not create object from empty string
+            return null;
+        }
+
+        // strip leading and trailing single quotes
+        String content = def.defaultValue;
+        if (content.charAt(0) == '\'') {
+            content = content.substring(1);
+        }
+        if (content.charAt(content.length() - 1) == '\'') {
+            content = content.substring(0, content.length() - 2);
+        }
+
+        if (StringUtils.isNullOrEmpty(content)) {
+            // can not create object from empty string
+            return null;
+        }
+
+        if (Boolean.class.isAssignableFrom(valueType) || boolean.class.isAssignableFrom(valueType)) {
+            return Boolean.parseBoolean(content);
+        }
+
+        if (Number.class.isAssignableFrom(valueType)) {
+            try {
+                // delegate to static valueOf() method to parse string
+                Method m = valueType.getMethod("valueOf", String.class);
+                return m.invoke(null, content);
+            } catch (NumberFormatException e) {
+                throw new IciqlException(e, "Failed to parse {0} as a number!", def.defaultValue);
+            } catch (Throwable t) {
+            }
+        }
+
+        String dateRegex = "[0-9]{1,4}[-/\\.][0-9]{1,2}[-/\\.][0-9]{1,2}";
+        String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
+
+        if (java.sql.Date.class.isAssignableFrom(valueType)) {
+            // this may be a little loose....
+            // 00-00-00
+            // 00/00/00
+            // 00.00.00
+            Pattern pattern = Pattern.compile(dateRegex);
+            if (pattern.matcher(content).matches()) {
+                DateFormat df = DateFormat.getDateInstance();
+                try {
+                    return df.parse(content);
+                } catch (Exception e) {
+                    throw new IciqlException(e, "Failed to parse {0} as a date!", def.defaultValue);
+                }
+            }
+        }
+
+        if (java.sql.Time.class.isAssignableFrom(valueType)) {
+            // 00:00:00
+            Pattern pattern = Pattern.compile(timeRegex);
+            if (pattern.matcher(content).matches()) {
+                DateFormat df = DateFormat.getTimeInstance();
+                try {
+                    return df.parse(content);
+                } catch (Exception e) {
+                    throw new IciqlException(e, "Failed to parse {0} as a time!", def.defaultValue);
+                }
+            }
+        }
+
+        if (java.util.Date.class.isAssignableFrom(valueType)) {
+            // this may be a little loose....
+            // 00-00-00 00:00:00
+            // 00/00/00T00:00:00
+            // 00.00.00T00:00:00
+            Pattern pattern = Pattern.compile(dateRegex + "." + timeRegex);
+            if (pattern.matcher(content).matches()) {
+                DateFormat df = DateFormat.getDateTimeInstance();
+                try {
+                    return df.parse(content);
+                } catch (Exception e) {
+                    throw new IciqlException(e, "Failed to parse {0} as a datetimestamp!", def.defaultValue);
+                }
+            }
+        }
+        return content;
+    }
+
+    /**
+     * Converts the object into a DEFAULT clause value.
+     *
+     * @param o the default object
+     * @return the value formatted for a DEFAULT clause
+     */
+    static String formatDefaultValue(Object o) {
+        Class<?> objectClass = o.getClass();
+        String value = null;
+        if (Number.class.isAssignableFrom(objectClass)) {
+            // NUMBER
+            return ((Number) o).toString();
+        } else if (Boolean.class.isAssignableFrom(objectClass)) {
+            // BOOLEAN
+            return o.toString();
+        } else if (java.sql.Date.class.isAssignableFrom(objectClass)) {
+            // DATE
+            value = new SimpleDateFormat("yyyy-MM-dd").format((Date) o);
+        } else if (java.sql.Time.class.isAssignableFrom(objectClass)) {
+            // TIME
+            value = new SimpleDateFormat("HH:mm:ss").format((Date) o);
+        } else if (Date.class.isAssignableFrom(objectClass)) {
+            // DATETIME
+            value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) o);
+        } else if (String.class.isAssignableFrom(objectClass)) {
+            // STRING
+            value = o.toString();
+        }
+        if (value == null) {
+            return "''";
+        }
+        return MessageFormat.format("''{0}''", value);
+    }
+
+    /**
+     * Checks the formatting of IQColumn.defaultValue().
+     *
+     * @param defaultValue the default value
+     * @return true if it is
+     */
+    static boolean isProperlyFormattedDefaultValue(String defaultValue) {
+        if (isNullOrEmpty(defaultValue)) {
+            return true;
+        }
+        Pattern literalDefault = Pattern.compile("'.*'");
+        Pattern functionDefault = Pattern.compile("[^'].*[^']");
+        return literalDefault.matcher(defaultValue).matches()
+                || functionDefault.matcher(defaultValue).matches();
+    }
+
+    /**
+     * Checks to see if the default value matches the class.
+     *
+     * @param modelClass   the class
+     * @param defaultValue the value
+     * @return true if it does
+     */
+    static boolean isValidDefaultValue(Class<?> modelClass, String defaultValue) {
+
+        if (defaultValue == null) {
+            // NULL
+            return true;
+        }
+        if (defaultValue.trim().length() == 0) {
+            // NULL (effectively)
+            return true;
+        }
+
+        // function / variable
+        Pattern functionDefault = Pattern.compile("[^'].*[^']");
+        if (functionDefault.matcher(defaultValue).matches()) {
+            // hard to validate this since its in the database
+            // assume it is good
+            return true;
+        }
+
+        // STRING
+        if (modelClass == String.class) {
+            Pattern stringDefault = Pattern.compile("'(.|\\n)*'");
+            return stringDefault.matcher(defaultValue).matches();
+        }
+
+        String dateRegex = "[0-9]{1,4}[-/\\.][0-9]{1,2}[-/\\.][0-9]{1,2}";
+        String timeRegex = "[0-2]{1}[0-9]{1}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}";
+
+        // TIMESTAMP
+        if (modelClass == java.util.Date.class || modelClass == java.sql.Timestamp.class) {
+            // this may be a little loose....
+            // 00-00-00 00:00:00
+            // 00/00/00T00:00:00
+            // 00.00.00T00:00:00
+            Pattern pattern = Pattern.compile("'" + dateRegex + "." + timeRegex + "'");
+            return pattern.matcher(defaultValue).matches();
+        }
+
+        // DATE
+        if (modelClass == java.sql.Date.class) {
+            // this may be a little loose....
+            // 00-00-00
+            // 00/00/00
+            // 00.00.00
+            Pattern pattern = Pattern.compile("'" + dateRegex + "'");
+            return pattern.matcher(defaultValue).matches();
+        }
+
+        // TIME
+        if (modelClass == java.sql.Time.class) {
+            // 00:00:00
+            Pattern pattern = Pattern.compile("'" + timeRegex + "'");
+            return pattern.matcher(defaultValue).matches();
+        }
+
+        // NUMBER
+        if (Number.class.isAssignableFrom(modelClass)) {
+            // strip single quotes
+            String unquoted = defaultValue;
+            if (unquoted.charAt(0) == '\'') {
+                unquoted = unquoted.substring(1);
+            }
+            if (unquoted.charAt(unquoted.length() - 1) == '\'') {
+                unquoted = unquoted.substring(0, unquoted.length() - 1);
+            }
+
+            try {
+                // delegate to static valueOf() method to parse string
+                Method m = modelClass.getMethod("valueOf", String.class);
+                m.invoke(null, unquoted);
+            } catch (NumberFormatException ex) {
+                return false;
+            } catch (Throwable t) {
+            }
+        }
+        return true;
+    }
 }
index 5c92a8662a6b8d2ea8e63360f5ec2bfbd4058726..c60645c79f850b49c1b5f570949026c12c680302 100644 (file)
@@ -19,114 +19,114 @@ package com.iciql;
 
 public abstract class NestedConditions<T> {
 
-       public static class And<T> extends NestedConditions<T> {
+    public static class And<T> extends NestedConditions<T> {
 
-               public And(Db db, T alias) {
-                       super(db, alias);
-               }
+        public And(Db db, T alias) {
+            super(db, alias);
+        }
 
-               protected QueryCondition<T, Boolean> and(boolean x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Boolean> and(boolean x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Byte> and(byte x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Byte> and(byte x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Short> and(short x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Short> and(short x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Integer> and(int x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Integer> and(int x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Long> and(long x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Long> and(long x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Float> and(float x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Float> and(float x) {
+            return where.and(x);
+        }
 
-               protected QueryCondition<T, Double> and(double x) {
-                       return where.and(x);
-               }
+        protected QueryCondition<T, Double> and(double x) {
+            return where.and(x);
+        }
 
-               protected <A> QueryCondition<T, A> and(A x) {
-                       return where.and(x);
-               }
+        protected <A> QueryCondition<T, A> and(A x) {
+            return where.and(x);
+        }
 
-               protected QueryWhere<T> and(And<T> conditions) {
-                       where.andOpen();
-                       where.query.addConditionToken(conditions.where.query);
-                       return where.close();
-               }
+        protected QueryWhere<T> and(And<T> conditions) {
+            where.andOpen();
+            where.query.addConditionToken(conditions.where.query);
+            return where.close();
+        }
 
-               protected QueryWhere<T> and(Or<T> conditions) {
-                       where.andOpen();
-                       where.query.addConditionToken(conditions.where.query);
-                       return where.close();
-               }
+        protected QueryWhere<T> and(Or<T> conditions) {
+            where.andOpen();
+            where.query.addConditionToken(conditions.where.query);
+            return where.close();
+        }
 
-       }
+    }
 
-       public static class Or<T> extends NestedConditions<T> {
+    public static class Or<T> extends NestedConditions<T> {
 
-               public Or(Db db, T alias) {
-                       super(db, alias);
-               }
+        public Or(Db db, T alias) {
+            super(db, alias);
+        }
 
-               protected QueryCondition<T, Boolean> or(boolean x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Boolean> or(boolean x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Byte> or(byte x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Byte> or(byte x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Short> or(short x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Short> or(short x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Integer> or(int x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Integer> or(int x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Long> or(long x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Long> or(long x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Float> or(float x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Float> or(float x) {
+            return where.or(x);
+        }
 
-               protected QueryCondition<T, Double> or(double x) {
-                       return where.or(x);
-               }
+        protected QueryCondition<T, Double> or(double x) {
+            return where.or(x);
+        }
 
-               protected <A> QueryCondition<T, A> or(A x) {
-                       return where.or(x);
-               }
+        protected <A> QueryCondition<T, A> or(A x) {
+            return where.or(x);
+        }
 
-               protected QueryWhere<T> or(And<T> conditions) {
-                       where.orOpen();
-                       where.query.addConditionToken(conditions.where.query);
-                       return where.close();
-               }
+        protected QueryWhere<T> or(And<T> conditions) {
+            where.orOpen();
+            where.query.addConditionToken(conditions.where.query);
+            return where.close();
+        }
 
-               protected QueryWhere<T> or(Or<T> conditions) {
-                       where.orOpen();
-                       where.query.addConditionToken(conditions.where.query);
-                       return where.close();
-               }
+        protected QueryWhere<T> or(Or<T> conditions) {
+            where.orOpen();
+            where.query.addConditionToken(conditions.where.query);
+            return where.close();
+        }
 
-       }
+    }
 
-       QueryWhere<T> where;
+    QueryWhere<T> where;
 
-       private NestedConditions(Db db, T alias) {
-               where = new QueryWhere<T>(Query.rebuild(db, alias));
-       }
+    private NestedConditions(Db db, T alias) {
+        where = new QueryWhere<T>(Query.rebuild(db, alias));
+    }
 
 }
index f450bfba033c59d2ba06ad9e27ff8ed95efafd95..9694da118319fcca4f8d4ff4faa872f0e3dc14c5 100644 (file)
@@ -19,37 +19,36 @@ package com.iciql;
 \r
 /**\r
  * An expression to order by in a query.\r
- * \r
- * @param <T>\r
- *            the query data type\r
+ *\r
+ * @param <T> the query data type\r
  */\r
 \r
 class OrderExpression<T> {\r
-       private Query<T> query;\r
-       private Object expression;\r
-       private boolean desc;\r
-       private boolean nullsFirst;\r
-       private boolean nullsLast;\r
+    private Query<T> query;\r
+    private Object expression;\r
+    private boolean desc;\r
+    private boolean nullsFirst;\r
+    private boolean nullsLast;\r
 \r
-       OrderExpression(Query<T> query, Object expression, boolean desc, boolean nullsFirst, boolean nullsLast) {\r
-               this.query = query;\r
-               this.expression = expression;\r
-               this.desc = desc;\r
-               this.nullsFirst = nullsFirst;\r
-               this.nullsLast = nullsLast;\r
-       }\r
+    OrderExpression(Query<T> query, Object expression, boolean desc, boolean nullsFirst, boolean nullsLast) {\r
+        this.query = query;\r
+        this.expression = expression;\r
+        this.desc = desc;\r
+        this.nullsFirst = nullsFirst;\r
+        this.nullsLast = nullsLast;\r
+    }\r
 \r
-       void appendSQL(SQLStatement stat) {\r
-               query.appendSQL(stat, null, expression);\r
-               if (desc) {\r
-                       stat.appendSQL(" DESC");\r
-               }\r
-               if (nullsLast) {\r
-                       stat.appendSQL(" NULLS LAST");\r
-               }\r
-               if (nullsFirst) {\r
-                       stat.appendSQL(" NULLS FIRST");\r
-               }\r
-       }\r
+    void appendSQL(SQLStatement stat) {\r
+        query.appendSQL(stat, null, expression);\r
+        if (desc) {\r
+            stat.appendSQL(" DESC");\r
+        }\r
+        if (nullsLast) {\r
+            stat.appendSQL(" NULLS LAST");\r
+        }\r
+        if (nullsFirst) {\r
+            stat.appendSQL(" NULLS FIRST");\r
+        }\r
+    }\r
 \r
 }\r
index 7a8a1fffd68fa15737301cc20e9d2fa54c41550a..d26e7b7768097a51a722f4dfcc5617799345b23f 100644 (file)
 
 package com.iciql;
 
-import java.lang.reflect.Field;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.List;
-
 import com.iciql.Iciql.DataTypeAdapter;
 import com.iciql.Iciql.EnumType;
 import com.iciql.NestedConditions.And;
@@ -35,1015 +26,1002 @@ import com.iciql.util.IciqlLogger;
 import com.iciql.util.JdbcUtils;
 import com.iciql.util.Utils;
 
+import java.lang.reflect.Field;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+
 /**
  * This class represents a query.
  *
- * @param <T>
- *            the return type
+ * @param <T> the return type
  */
 
 public class Query<T> {
 
-       private Db db;
-       private SelectTable<T> from;
-       private ArrayList<Token> conditions = Utils.newArrayList();
-       private ArrayList<UpdateColumn> updateColumnDeclarations = Utils.newArrayList();
-       private int conditionDepth = 0;
-       private ArrayList<SelectTable<T>> joins = Utils.newArrayList();
-       private final IdentityHashMap<Object, SelectColumn<T>> aliasMap = Utils.newIdentityHashMap();
-       private ArrayList<OrderExpression<T>> orderByList = Utils.newArrayList();
-       private ArrayList<Object> groupByExpressions = Utils.newArrayList();
-       private long limit;
-       private long offset;
-
-       private Query(Db db) {
-               this.db = db;
-       }
-
-       /**
-        * from() is a static factory method to build a Query object.
-        *
-        * @param db
-        * @param alias
-        * @return a query object
-        */
-       @SuppressWarnings("unchecked")
-       static <T> Query<T> from(Db db, T alias) {
-               Query<T> query = new Query<T>(db);
-               TableDefinition<T> def = (TableDefinition<T>) db.define(alias.getClass());
-               query.from = new SelectTable<T>(db, query, alias, false);
-               def.initSelectObject(query.from, alias, query.aliasMap, false);
-               return query;
-       }
-
-       @SuppressWarnings("unchecked")
-       static <T> Query<T> rebuild(Db db, T alias) {
-               Query<T> query = new Query<T>(db);
-               TableDefinition<T> def = (TableDefinition<T>) db.define(alias.getClass());
-               query.from = new SelectTable<T>(db, query, alias, false);
-               def.initSelectObject(query.from, alias, query.aliasMap, true);
-               return query;
-       }
-
-       public long selectCount() {
-               SQLStatement stat = getSelectStatement(false);
-               stat.appendSQL("COUNT(*) ");
-               appendFromWhere(stat);
-               ResultSet rs = stat.executeQuery();
-               try {
-                       rs.next();
-                       long value = rs.getLong(1);
-                       return value;
-               } catch (SQLException e) {
-                       throw IciqlException.fromSQL(stat.getSQL(), e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-       }
-
-       public List<T> select() {
-               return select(false);
-       }
-
-       public T selectFirst() {
-               List<T> list = limit(1).select(false);
-               return list.isEmpty() ? null : list.get(0);
-       }
-
-       public List<T> selectDistinct() {
-               return select(true);
-       }
-
-       public <X, Z> X selectFirst(Z x) {
-               List<X> list = limit(1).select(x);
-               return list.isEmpty() ? null : list.get(0);
-       }
-
-       public <X> void createView(Class<X> viewClass) {
-               TableDefinition<X> viewDef = db.define(viewClass);
-
-               SQLStatement fromWhere = new SQLStatement(db);
-               appendFromWhere(fromWhere, false);
-
-               SQLStatement stat = new SQLStatement(db);
-               db.getDialect().prepareCreateView(stat, viewDef, fromWhere.toSQL());
-               IciqlLogger.create(stat.toSQL());
-               stat.execute();
-       }
-
-       public <X> void replaceView(Class<X> viewClass) {
-               db.dropView(viewClass);
-               createView(viewClass);
-       }
-
-       public String getSQL() {
-               SQLStatement stat = getSelectStatement(false);
-               stat.appendSQL("*");
-               appendFromWhere(stat);
-               return stat.getSQL().trim();
-       }
-
-       /**
-        * toSQL returns a static string version of the query with runtime variables
-        * properly encoded. This method is also useful when combined with the where
-        * clause methods like isParameter() or atLeastParameter() which allows
-        * iciql to generate re-usable parameterized string statements.
-        *
-        * @return the sql query as plain text
-        */
-       public String toSQL() {
-               return toSQL(false);
-       }
-
-       /**
-        * toSQL returns a static string version of the query with runtime variables
-        * properly encoded. This method is also useful when combined with the where
-        * clause methods like isParameter() or atLeastParameter() which allows
-        * iciql to generate re-usable parameterized string statements.
-        *
-        * @param distinct
-        *            if true SELECT DISTINCT is used for the query
-        * @return the sql query as plain text
-        */
-       public String toSQL(boolean distinct) {
-               return toSQL(distinct, null);
-       }
-
-       /**
-        * toSQL returns a static string version of the query with runtime variables
-        * properly encoded. This method is also useful when combined with the where
-        * clause methods like isParameter() or atLeastParameter() which allows
-        * iciql to generate re-usable parameterized string statements.
-        *
-        * @param distinct
-        *            if true SELECT DISTINCT is used for the query
-        * @param k
-        *            k is used to select only the columns of the specified alias
-        *            for an inner join statement. An example of a generated
-        *            statement is: SELECT DISTINCT t1.* FROM sometable AS t1 INNER
-        *            JOIN othertable AS t2 ON t1.id = t2.id WHERE t2.flag = true
-        *            without the alias parameter the statement would start with
-        *            SELECT DISTINCT * FROM...
-        * @return the sql query as plain text
-        */
-       public <K> String toSQL(boolean distinct, K k) {
-               SQLStatement stat = new SQLStatement(getDb());
-               if (updateColumnDeclarations.size() > 0) {
-                       stat.appendSQL("UPDATE ");
-                       from.appendSQL(stat);
-                       stat.appendSQL(" SET ");
-                       int i = 0;
-                       for (UpdateColumn declaration : updateColumnDeclarations) {
-                               if (i++ > 0) {
-                                       stat.appendSQL(", ");
-                               }
-                               declaration.appendSQL(stat);
-                       }
-                       appendWhere(stat);
-               } else {
-                       stat.appendSQL("SELECT ");
-                       if (distinct) {
-                               stat.appendSQL("DISTINCT ");
-                       }
-                       if (k != null) {
-                               SelectTable<?> sel = getSelectTable(k);
-                               if (sel == null) {
-                                       // unknown alias, use wildcard
-                                       IciqlLogger.warn("Alias {0} is not defined in the statement!", k.getClass());
-                                       stat.appendSQL("*");
-                               } else if (isJoin()) {
-                                       // join query, use AS alias
-                                       String as = sel.getAs();
-                                       stat.appendSQL(as + ".*");
-                               } else {
-                                       // schema.table.*
-                                       String schema = sel.getAliasDefinition().schemaName;
-                                       String table = sel.getAliasDefinition().tableName;
-                                       String as = getDb().getDialect().prepareTableName(schema, table);
-                                       stat.appendSQL(as + ".*");
-                               }
-                       } else {
-                               // alias unspecified, use wildcard
-                               stat.appendSQL("*");
-                       }
-                       appendFromWhere(stat);
-               }
-               return stat.toSQL().trim();
-       }
-
-       <Z> String toSubQuery(Z z) {
-               SQLStatement stat = getSelectStatement(false);
-               SelectColumn<T> col = aliasMap.get(z);
-               String columnName = col.getFieldDefinition().columnName;
-               stat.appendColumn(columnName);
-               appendFromWhere(stat);
-               return stat.toSQL();
-       }
-
-       private List<T> select(boolean distinct) {
-               List<T> result = Utils.newArrayList();
-               TableDefinition<T> def = from.getAliasDefinition();
-               SQLStatement stat = getSelectStatement(distinct);
-               def.appendSelectList(stat);
-               appendFromWhere(stat);
-               ResultSet rs = stat.executeQuery();
-               try {
-                       // SQLite returns pre-closed ResultSets for query results with 0 rows
-                       if (!rs.isClosed()) {
-                               int[] columns = def.mapColumns(db.getDialect(), false, rs);
-                               while (rs.next()) {
-                                       T item = from.newObject();
-                                       def.readRow(db.getDialect(), item, rs, columns);
-                                       result.add(item);
-                               }
-                       }
-               } catch (SQLException e) {
-                       throw IciqlException.fromSQL(stat.getSQL(), e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-               return result;
-       }
-
-       public int delete() {
-               SQLStatement stat = new SQLStatement(db);
-               stat.appendSQL("DELETE FROM ");
-               from.appendSQL(stat);
-               appendWhere(stat);
-               IciqlLogger.delete(stat.getSQL());
-               return stat.executeUpdate();
-       }
-
-       public <A> Query<T> setNull(A field) {
-               return set(field).to(null);
-       }
-
-       public <A> UpdateColumnSet<T, A> set(A field) {
-               from.getAliasDefinition().checkMultipleEnums(field);
-               return new UpdateColumnSet<T, A>(this, field);
-       }
-
-       public UpdateColumnSet<T, Boolean> set(boolean field) {
-               from.getAliasDefinition().checkMultipleBooleans();
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Byte> set(byte field) {
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Short> set(short field) {
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Integer> set(int field) {
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Long> set(long field) {
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Float> set(float field) {
-               return setPrimitive(field);
-       }
-
-       public UpdateColumnSet<T, Double> set(double field) {
-               return setPrimitive(field);
-       }
-
-       private <A> UpdateColumnSet<T, A> setPrimitive(A field) {
-               A alias = getPrimitiveAliasByValue(field);
-               if (alias == null) {
-                       // this will result in an unmapped field exception
-                       return set(field);
-               }
-               return set(alias);
-       }
-
-       public <A> UpdateColumnIncrement<T, A> increment(A field) {
-               return new UpdateColumnIncrement<T, A>(this, field);
-       }
-
-       public UpdateColumnIncrement<T, Byte> increment(byte field) {
-               return incrementPrimitive(field);
-       }
-
-       public UpdateColumnIncrement<T, Short> increment(short field) {
-               return incrementPrimitive(field);
-       }
-
-       public UpdateColumnIncrement<T, Integer> increment(int field) {
-               return incrementPrimitive(field);
-       }
-
-       public UpdateColumnIncrement<T, Long> increment(long field) {
-               return incrementPrimitive(field);
-       }
-
-       public UpdateColumnIncrement<T, Float> increment(float field) {
-               return incrementPrimitive(field);
-       }
-
-       public UpdateColumnIncrement<T, Double> increment(double field) {
-               return incrementPrimitive(field);
-       }
-
-       private <A> UpdateColumnIncrement<T, A> incrementPrimitive(A field) {
-               A alias = getPrimitiveAliasByValue(field);
-               if (alias == null) {
-                       // this will result in an unmapped field exception
-                       return increment(field);
-               }
-               return increment(alias);
-       }
-
-       public int update() {
-               if (updateColumnDeclarations.size() == 0) {
-                       throw new IciqlException("Missing set or increment call.");
-               }
-               SQLStatement stat = new SQLStatement(db);
-               stat.appendSQL("UPDATE ");
-               from.appendSQL(stat);
-               stat.appendSQL(" SET ");
-               int i = 0;
-               for (UpdateColumn declaration : updateColumnDeclarations) {
-                       if (i++ > 0) {
-                               stat.appendSQL(", ");
-                       }
-                       declaration.appendSQL(stat);
-               }
-               appendWhere(stat);
-               IciqlLogger.update(stat.getSQL());
-               return stat.executeUpdate();
-       }
-
-       public <X, Z> List<X> selectDistinct(Z x) {
-               return select(x, true);
-       }
-
-       public <X, Z> List<X> select(Z x) {
-               return select(x, false);
-       }
-
-       @SuppressWarnings("unchecked")
-       private <X, Z> List<X> select(Z x, boolean distinct) {
-               Class<?> clazz = x.getClass();
-               if (Db.isToken(x)) {
-                       // selecting a function
-                       return selectFunction((X) x, distinct);
-               } else {
-                       // selecting a column
-                       SelectColumn<T> col = getColumnByReference(x);
-                       if (col == null) {
-                               col = getColumnByReference(getPrimitiveAliasByValue(x));
-                       }
-                       if (col != null) {
-                               return (List<X>) selectColumn(col, clazz, distinct);
-                       }
-               }
-
-               // selecting into a new object type
-               Class<?> enclosingClass = clazz.getEnclosingClass();
-               if (enclosingClass != null) {
-                       // anonymous inner class
-                       clazz = clazz.getSuperclass();
-               }
-               return select((Class<X>) clazz, (X) x, distinct);
-       }
-
-       private <X> List<X> select(Class<X> clazz, X x, boolean distinct) {
-               List<X> result = Utils.newArrayList();
-               TableDefinition<X> def = db.define(clazz);
-               SQLStatement stat = getSelectStatement(distinct);
-               def.appendSelectList(stat, this, x);
-               appendFromWhere(stat);
-               ResultSet rs = stat.executeQuery();
-               try {
-                       // SQLite returns pre-closed ResultSets for query results with 0 rows
-                       if (!rs.isClosed()) {
-                               int[] columns = def.mapColumns(db.getDialect(), false, rs);
-                               while (rs.next()) {
-                                       X row = Utils.newObject(clazz);
-                                       def.readRow(db.getDialect(), row, rs, columns);
-                                       result.add(row);
-                               }
-                       }
-               } catch (SQLException e) {
-                       throw IciqlException.fromSQL(stat.getSQL(), e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-               return result;
-       }
-
-       @SuppressWarnings("unchecked")
-       private <X> List<X> selectFunction(X x, boolean distinct) {
-               SQLStatement stat = getSelectStatement(distinct);
-               appendSQL(stat, null, x);
-               appendFromWhere(stat);
-               ResultSet rs = stat.executeQuery();
-               List<X> result = Utils.newArrayList();
-               try {
-                       // SQLite returns pre-closed ResultSets for query results with 0 rows
-                       if (!rs.isClosed()) {
-                               while (rs.next()) {
-                                       X value = (X) rs.getObject(1);
-                                       result.add(value);
-                               }
-                       }
-               } catch (Exception e) {
-                       throw IciqlException.fromSQL(stat.getSQL(), e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-               return result;
-       }
-
-       @SuppressWarnings("unchecked")
-       private <X> List<X> selectColumn(SelectColumn<T> col, Class<X> clazz, boolean distinct) {
-               SQLStatement stat = getSelectStatement(distinct);
-               col.appendSQL(stat);
-               appendFromWhere(stat);
-               ResultSet rs = stat.executeQuery();
-               List<X> result = Utils.newArrayList();
-               Class<? extends DataTypeAdapter<?>> typeAdapter = col.getFieldDefinition().typeAdapter;
-               try {
-                       // SQLite returns pre-closed ResultSets for query results with 0 rows
-                       if (!rs.isClosed()) {
-                               while (rs.next()) {
-                                       X value = (X) db.getDialect().deserialize(rs, 1, clazz, typeAdapter);
-                                       result.add(value);
-                               }
-                       }
-               } catch (Exception e) {
-                       throw IciqlException.fromSQL(stat.getSQL(), e);
-               } finally {
-                       JdbcUtils.closeSilently(rs, true);
-               }
-               return result;
-       }
-
-       private SQLStatement getSelectStatement(boolean distinct) {
-               SQLStatement stat = new SQLStatement(db);
-               stat.appendSQL("SELECT ");
-               if (distinct) {
-                       stat.appendSQL("DISTINCT ");
-               }
-               return stat;
-       }
-
-       /**
-        * Begin a primitive boolean field condition clause.
-        *
-        * @param x
-        *            the primitive boolean field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Boolean> where(boolean x) {
-               from.getAliasDefinition().checkMultipleBooleans();
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive short field condition clause.
-        *
-        * @param x
-        *            the primitive short field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Byte> where(byte x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive short field condition clause.
-        *
-        * @param x
-        *            the primitive short field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Short> where(short x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive int field condition clause.
-        *
-        * @param x
-        *            the primitive int field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Integer> where(int x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive long field condition clause.
-        *
-        * @param x
-        *            the primitive long field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Long> where(long x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive float field condition clause.
-        *
-        * @param x
-        *            the primitive float field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Float> where(float x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begin a primitive double field condition clause.
-        *
-        * @param x
-        *            the primitive double field to query
-        * @return a query condition to continue building the condition
-        */
-       public QueryCondition<T, Double> where(double x) {
-               return wherePrimitive(x);
-       }
-
-       /**
-        * Begins a primitive field condition clause.
-        *
-        * @param value
-        * @return a query condition to continue building the condition
-        */
-       private <A> QueryCondition<T, A> wherePrimitive(A value) {
-               A alias = getPrimitiveAliasByValue(value);
-               if (alias == null) {
-                       // this will result in an unmapped field exception
-                       return where(value);
-               }
-               return where(alias);
-       }
-
-       /**
-        * Begin an Object field condition clause.
-        *
-        * @param x
-        *            the mapped object to query
-        * @return a query condition to continue building the condition
-        */
-       public <A> QueryCondition<T, A> where(A x) {
-               from.getAliasDefinition().checkMultipleEnums(x);
-               return new QueryCondition<T, A>(this, x);
-       }
-
-       public <A> QueryWhere<T> where(Filter filter) {
-               HashMap<String, Object> fieldMap = Utils.newHashMap();
-               for (Field f : filter.getClass().getDeclaredFields()) {
-                       f.setAccessible(true);
-                       try {
-                               Object obj = f.get(filter);
-                               if (obj == from.getAlias()) {
-                                       List<TableDefinition.FieldDefinition> fields = from.getAliasDefinition().getFields();
-                                       String name = f.getName();
-                                       for (TableDefinition.FieldDefinition field : fields) {
-                                               String n = name + "." + field.field.getName();
-                                               Object o = field.field.get(obj);
-                                               fieldMap.put(n, o);
-                                       }
-                               }
-                               fieldMap.put(f.getName(), f.get(filter));
-                       } catch (Exception e) {
-                               throw new IciqlException(e);
-                       }
-               }
-               Token filterCode = new ClassReader().decompile(filter, fieldMap, "where");
-               // String filterQuery = filterCode.toString();
-               conditions.add(filterCode);
-               return new QueryWhere<T>(this);
-       }
-
-       public QueryWhere<T> where(String fragment, List<?> args) {
-               return this.where(fragment, args.toArray());
-       }
-
-       public QueryWhere<T> where(String fragment, Object... args) {
-               conditions.add(new RuntimeToken(fragment, args));
-               return new QueryWhere<T>(this);
-       }
-
-       public Query<T> where(And<T> conditions) {
-               whereTrue();
-               addConditionToken(conditions.where.query);
-               return this;
-       }
-
-       public Query<T> where(Or<T> conditions) {
-               whereFalse();
-               addConditionToken(conditions.where.query);
-               return this;
-       }
-
-       public QueryWhere<T> whereTrue() {
-               return whereTrue(true);
-       }
-
-       public QueryWhere<T> whereFalse() {
-               return whereTrue(false);
-       }
-
-       public QueryWhere<T> whereTrue(Boolean condition) {
-               Token token = new Function("", condition);
-               addConditionToken(token);
-               return new QueryWhere<T>(this);
-       }
-
-       /**
-        * Sets the Limit and Offset of a query.
-        *
-        * @return the query
-        */
-
-       public Query<T> limit(long limit) {
-               this.limit = limit;
-               return this;
-       }
-
-       public Query<T> offset(long offset) {
-               this.offset = offset;
-               return this;
-       }
-
-       public Query<T> orderBy(boolean field) {
-               from.getAliasDefinition().checkMultipleBooleans();
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(byte field) {
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(short field) {
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(int field) {
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(long field) {
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(float field) {
-               return orderByPrimitive(field);
-       }
-
-       public Query<T> orderBy(double field) {
-               return orderByPrimitive(field);
-       }
-
-       Query<T> orderByPrimitive(Object field) {
-               Object alias = getPrimitiveAliasByValue(field);
-               if (alias == null) {
-                       return orderBy(field);
-               }
-               return orderBy(alias);
-       }
-
-       public Query<T> orderBy(Object expr) {
-               from.getAliasDefinition().checkMultipleEnums(expr);
-               OrderExpression<T> e = new OrderExpression<T>(this, expr, false, false, false);
-               addOrderBy(e);
-               return this;
-       }
-
-       /**
-        * Order by a number of columns.
-        *
-        * @param expressions
-        *            the columns
-        * @return the query
-        */
-
-       public Query<T> orderBy(Object... expressions) {
-               for (Object expr : expressions) {
-                       from.getAliasDefinition().checkMultipleEnums(expr);
-                       OrderExpression<T> e = new OrderExpression<T>(this, expr, false, false, false);
-                       addOrderBy(e);
-               }
-               return this;
-       }
-
-       public Query<T> orderByDesc(byte field) {
-               return orderByDescPrimitive(field);
-       }
-
-       public Query<T> orderByDesc(short field) {
-               return orderByDescPrimitive(field);
-       }
-
-       public Query<T> orderByDesc(int field) {
-               return orderByDescPrimitive(field);
-       }
-
-       public Query<T> orderByDesc(long field) {
-               return orderByDescPrimitive(field);
-       }
-
-       public Query<T> orderByDesc(float field) {
-               return orderByDescPrimitive(field);
-       }
-
-       public Query<T> orderByDesc(double field) {
-               return orderByDescPrimitive(field);
-       }
-
-       Query<T> orderByDescPrimitive(Object field) {
-               Object alias = getPrimitiveAliasByValue(field);
-               if (alias == null) {
-                       return orderByDesc(field);
-               }
-               return orderByDesc(alias);
-       }
-
-       public Query<T> orderByDesc(Object expr) {
-               OrderExpression<T> e = new OrderExpression<T>(this, expr, true, false, false);
-               addOrderBy(e);
-               return this;
-       }
-
-       public Query<T> groupBy(boolean field) {
-               from.getAliasDefinition().checkMultipleBooleans();
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(byte field) {
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(short field) {
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(int field) {
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(long field) {
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(float field) {
-               return groupByPrimitive(field);
-       }
-
-       public Query<T> groupBy(double field) {
-               return groupByPrimitive(field);
-       }
-
-       Query<T> groupByPrimitive(Object field) {
-               Object alias = getPrimitiveAliasByValue(field);
-               if (alias == null) {
-                       return groupBy(field);
-               }
-               return groupBy(alias);
-       }
-
-       public Query<T> groupBy(Object expr) {
-               from.getAliasDefinition().checkMultipleEnums(expr);
-               groupByExpressions.add(expr);
-               return this;
-       }
-
-       public Query<T> groupBy(Object... groupBy) {
-               this.groupByExpressions.addAll(Arrays.asList(groupBy));
-               return this;
-       }
-
-       /**
-        * INTERNAL
-        *
-        * @param stat
-        *            the statement
-        * @param alias
-        *            the alias object (can be null)
-        * @param value
-        *            the value
-        */
-       public void appendSQL(SQLStatement stat, Object alias, Object value) {
-               if (Function.count() == value) {
-                       stat.appendSQL("COUNT(*)");
-                       return;
-               }
-               if (RuntimeParameter.PARAMETER == value) {
-                       stat.appendSQL("?");
-                       addParameter(stat, alias, value);
-                       return;
-               }
-               Token token = Db.getToken(value);
-               if (token != null) {
-                       token.appendSQL(stat, this);
-                       return;
-               }
-               if (alias != null && value != null && value.getClass().isEnum()) {
-                       // special case:
-                       // value is first enum constant which is also the alias object.
-                       // the first enum constant is used as the alias because we can not
-                       // instantiate an enum reflectively.
-                       stat.appendSQL("?");
-                       addParameter(stat, alias, value);
-                       return;
-               }
-               SelectColumn<T> col = getColumnByReference(value);
-               if (col != null) {
-                       col.appendSQL(stat);
-                       return;
-               }
-               stat.appendSQL("?");
-               addParameter(stat, alias, value);
-       }
-
-       /**
-        * INTERNAL
-        *
-        * @param stat
-        *            the statement
-        * @param alias
-        *            the alias object (can be null)
-        * @param valueLeft
-        *            the value on the left of the compound clause
-        * @param valueRight
-        *            the value on the right of the compound clause
-        * @param compareType
-        *            the current compare type (e.g. BETWEEN)
-        */
-       public void appendSQL(SQLStatement stat, Object alias, Object valueLeft, Object valueRight,
-                       CompareType compareType) {
-               stat.appendSQL("?");
-               stat.appendSQL(" ");
-               switch (compareType) {
-               case BETWEEN:
-                       stat.appendSQL("AND");
-                       break;
-               }
-               stat.appendSQL(" ");
-               stat.appendSQL("?");
-               addParameter(stat, alias, valueLeft);
-               addParameter(stat, alias, valueRight);
-       }
-
-       public void appendSQL(SQLStatement stat, Object alias, Iterable<Object> values,
-                       CompareType compareType) {
-               boolean first = true;
-               stat.appendSQL("(");
-               for (Object value : values) {
-                       if (first) {
-                               first = false;
-                       } else {
-                               stat.appendSQL(", ");
-                       }
-                       stat.appendSQL("?");
-                       addParameter(stat, alias, value);
-               }
-               stat.appendSQL(")");
-       }
-
-       private void addParameter(SQLStatement stat, Object alias, Object value) {
-               SelectColumn<T> col = getColumnByReference(alias);
-               if (col != null && value != null && value.getClass().isEnum()) {
-                       // enum
-                       TableDefinition.FieldDefinition field = col.getFieldDefinition();
-                       EnumType type = field.enumType;
-                       Enum<?> anEnum = (Enum<?>) value;
-                       Object y = Utils.convertEnum(anEnum, type);
-                       stat.addParameter(y);
-               } else if (col != null) {
-                       // object
-                       TableDefinition.FieldDefinition field = col.getFieldDefinition();
-                       Class<? extends DataTypeAdapter<?>> typeAdapter = field.typeAdapter;
-                       if (value != null && value instanceof String) {
-                               if (field.trim && field.length > 0) {
-                                       // clip strings (issue-15)
-                                       String s = (String) value;
-                                       if (s.length() > field.length) {
-                                               value = s.substring(0, field.length);
-                                       }
-                               }
-                       }
-                       Object parameter = db.getDialect().serialize(value, typeAdapter);
-                       stat.addParameter(parameter);
-               } else {
-                       // primitive
-                       stat.addParameter(value);
-               }
-       }
-
-       void addConditionToken(Token condition) {
-               if (condition == ConditionOpenClose.OPEN) {
-                       conditionDepth ++;
-               } else if (condition == ConditionOpenClose.CLOSE) {
-                       conditionDepth --;
-                       if (conditionDepth < 0) {
-                               throw new IciqlException("unmatch condition open-close count");
-                       }
-               }
-               conditions.add(condition);
-       }
-
-       void addConditionToken(Query<T> other) {
-               for (Token condition : other.conditions) {
-                       addConditionToken(condition);
-               }
-       }
-
-       void addUpdateColumnDeclaration(UpdateColumn declaration) {
-               updateColumnDeclarations.add(declaration);
-       }
-
-       void appendWhere(SQLStatement stat) {
-               if (conditionDepth != 0) {
-                       throw new IciqlException("unmatch condition open-close count");
-               }
-               if (!conditions.isEmpty()) {
-                       stat.appendSQL(" WHERE ");
-
-                       boolean skipNextConjunction = false;
-
-                       for (Token token : conditions) {
-
-                               if (skipNextConjunction && token instanceof ConditionAndOr) {
-                                       skipNextConjunction = false;
-                                       continue;
-                               }
-
-                               token.appendSQL(stat, this);
-                               stat.appendSQL(" ");
-
-                               if (ConditionOpenClose.OPEN == token) {
-                                       skipNextConjunction = true;
-                               }
-                       }
-               }
-       }
-
-       void appendFromWhere(SQLStatement stat) {
-               appendFromWhere(stat, true);
-       }
-
-       void appendFromWhere(SQLStatement stat, boolean log) {
-               stat.appendSQL(" FROM ");
-               from.appendSQL(stat);
-               for (SelectTable<T> join : joins) {
-                       join.appendSQLAsJoin(stat, this);
-               }
-               appendWhere(stat);
-               if (!groupByExpressions.isEmpty()) {
-                       stat.appendSQL(" GROUP BY ");
-                       int i = 0;
-                       for (Object obj : groupByExpressions) {
-                               if (i++ > 0) {
-                                       stat.appendSQL(", ");
-                               }
-                               appendSQL(stat, null, obj);
-                               stat.appendSQL(" ");
-                       }
-               }
-               if (!orderByList.isEmpty()) {
-                       stat.appendSQL(" ORDER BY ");
-                       int i = 0;
-                       for (OrderExpression<T> o : orderByList) {
-                               if (i++ > 0) {
-                                       stat.appendSQL(", ");
-                               }
-                               o.appendSQL(stat);
-                               stat.appendSQL(" ");
-                       }
-               }
-               db.getDialect().appendLimitOffset(stat, limit, offset);
-               if (log) {
-                       IciqlLogger.select(stat.getSQL());
-               }
-       }
-
-       /**
-        * Join another table.
-        *
-        * @param alias
-        *            an alias for the table to join
-        * @return the joined query
-        */
-
-       public <A> QueryJoin<T> innerJoin(A alias) {
+    private Db db;
+    private SelectTable<T> from;
+    private ArrayList<Token> conditions = Utils.newArrayList();
+    private ArrayList<UpdateColumn> updateColumnDeclarations = Utils.newArrayList();
+    private int conditionDepth = 0;
+    private ArrayList<SelectTable<T>> joins = Utils.newArrayList();
+    private final IdentityHashMap<Object, SelectColumn<T>> aliasMap = Utils.newIdentityHashMap();
+    private ArrayList<OrderExpression<T>> orderByList = Utils.newArrayList();
+    private ArrayList<Object> groupByExpressions = Utils.newArrayList();
+    private long limit;
+    private long offset;
+
+    private Query(Db db) {
+        this.db = db;
+    }
+
+    /**
+     * from() is a static factory method to build a Query object.
+     *
+     * @param db
+     * @param alias
+     * @return a query object
+     */
+    @SuppressWarnings("unchecked")
+    static <T> Query<T> from(Db db, T alias) {
+        Query<T> query = new Query<T>(db);
+        TableDefinition<T> def = (TableDefinition<T>) db.define(alias.getClass());
+        query.from = new SelectTable<T>(db, query, alias, false);
+        def.initSelectObject(query.from, alias, query.aliasMap, false);
+        return query;
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> Query<T> rebuild(Db db, T alias) {
+        Query<T> query = new Query<T>(db);
+        TableDefinition<T> def = (TableDefinition<T>) db.define(alias.getClass());
+        query.from = new SelectTable<T>(db, query, alias, false);
+        def.initSelectObject(query.from, alias, query.aliasMap, true);
+        return query;
+    }
+
+    public long selectCount() {
+        SQLStatement stat = getSelectStatement(false);
+        stat.appendSQL("COUNT(*) ");
+        appendFromWhere(stat);
+        ResultSet rs = stat.executeQuery();
+        try {
+            rs.next();
+            long value = rs.getLong(1);
+            return value;
+        } catch (SQLException e) {
+            throw IciqlException.fromSQL(stat.getSQL(), e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+    }
+
+    public List<T> select() {
+        return select(false);
+    }
+
+    public T selectFirst() {
+        List<T> list = limit(1).select(false);
+        return list.isEmpty() ? null : list.get(0);
+    }
+
+    public List<T> selectDistinct() {
+        return select(true);
+    }
+
+    public <X, Z> X selectFirst(Z x) {
+        List<X> list = limit(1).select(x);
+        return list.isEmpty() ? null : list.get(0);
+    }
+
+    public <X> void createView(Class<X> viewClass) {
+        TableDefinition<X> viewDef = db.define(viewClass);
+
+        SQLStatement fromWhere = new SQLStatement(db);
+        appendFromWhere(fromWhere, false);
+
+        SQLStatement stat = new SQLStatement(db);
+        db.getDialect().prepareCreateView(stat, viewDef, fromWhere.toSQL());
+        IciqlLogger.create(stat.toSQL());
+        stat.execute();
+    }
+
+    public <X> void replaceView(Class<X> viewClass) {
+        db.dropView(viewClass);
+        createView(viewClass);
+    }
+
+    public String getSQL() {
+        SQLStatement stat = getSelectStatement(false);
+        stat.appendSQL("*");
+        appendFromWhere(stat);
+        return stat.getSQL().trim();
+    }
+
+    /**
+     * toSQL returns a static string version of the query with runtime variables
+     * properly encoded. This method is also useful when combined with the where
+     * clause methods like isParameter() or atLeastParameter() which allows
+     * iciql to generate re-usable parameterized string statements.
+     *
+     * @return the sql query as plain text
+     */
+    public String toSQL() {
+        return toSQL(false);
+    }
+
+    /**
+     * toSQL returns a static string version of the query with runtime variables
+     * properly encoded. This method is also useful when combined with the where
+     * clause methods like isParameter() or atLeastParameter() which allows
+     * iciql to generate re-usable parameterized string statements.
+     *
+     * @param distinct if true SELECT DISTINCT is used for the query
+     * @return the sql query as plain text
+     */
+    public String toSQL(boolean distinct) {
+        return toSQL(distinct, null);
+    }
+
+    /**
+     * toSQL returns a static string version of the query with runtime variables
+     * properly encoded. This method is also useful when combined with the where
+     * clause methods like isParameter() or atLeastParameter() which allows
+     * iciql to generate re-usable parameterized string statements.
+     *
+     * @param distinct if true SELECT DISTINCT is used for the query
+     * @param k        k is used to select only the columns of the specified alias
+     *                 for an inner join statement. An example of a generated
+     *                 statement is: SELECT DISTINCT t1.* FROM sometable AS t1 INNER
+     *                 JOIN othertable AS t2 ON t1.id = t2.id WHERE t2.flag = true
+     *                 without the alias parameter the statement would start with
+     *                 SELECT DISTINCT * FROM...
+     * @return the sql query as plain text
+     */
+    public <K> String toSQL(boolean distinct, K k) {
+        SQLStatement stat = new SQLStatement(getDb());
+        if (updateColumnDeclarations.size() > 0) {
+            stat.appendSQL("UPDATE ");
+            from.appendSQL(stat);
+            stat.appendSQL(" SET ");
+            int i = 0;
+            for (UpdateColumn declaration : updateColumnDeclarations) {
+                if (i++ > 0) {
+                    stat.appendSQL(", ");
+                }
+                declaration.appendSQL(stat);
+            }
+            appendWhere(stat);
+        } else {
+            stat.appendSQL("SELECT ");
+            if (distinct) {
+                stat.appendSQL("DISTINCT ");
+            }
+            if (k != null) {
+                SelectTable<?> sel = getSelectTable(k);
+                if (sel == null) {
+                    // unknown alias, use wildcard
+                    IciqlLogger.warn("Alias {0} is not defined in the statement!", k.getClass());
+                    stat.appendSQL("*");
+                } else if (isJoin()) {
+                    // join query, use AS alias
+                    String as = sel.getAs();
+                    stat.appendSQL(as + ".*");
+                } else {
+                    // schema.table.*
+                    String schema = sel.getAliasDefinition().schemaName;
+                    String table = sel.getAliasDefinition().tableName;
+                    String as = getDb().getDialect().prepareTableName(schema, table);
+                    stat.appendSQL(as + ".*");
+                }
+            } else {
+                // alias unspecified, use wildcard
+                stat.appendSQL("*");
+            }
+            appendFromWhere(stat);
+        }
+        return stat.toSQL().trim();
+    }
+
+    <Z> String toSubQuery(Z z) {
+        SQLStatement stat = getSelectStatement(false);
+        SelectColumn<T> col = aliasMap.get(z);
+        String columnName = col.getFieldDefinition().columnName;
+        stat.appendColumn(columnName);
+        appendFromWhere(stat);
+        return stat.toSQL();
+    }
+
+    private List<T> select(boolean distinct) {
+        List<T> result = Utils.newArrayList();
+        TableDefinition<T> def = from.getAliasDefinition();
+        SQLStatement stat = getSelectStatement(distinct);
+        def.appendSelectList(stat);
+        appendFromWhere(stat);
+        ResultSet rs = stat.executeQuery();
+        try {
+            // SQLite returns pre-closed ResultSets for query results with 0 rows
+            if (!rs.isClosed()) {
+                int[] columns = def.mapColumns(db.getDialect(), false, rs);
+                while (rs.next()) {
+                    T item = from.newObject();
+                    def.readRow(db.getDialect(), item, rs, columns);
+                    result.add(item);
+                }
+            }
+        } catch (SQLException e) {
+            throw IciqlException.fromSQL(stat.getSQL(), e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+        return result;
+    }
+
+    public int delete() {
+        SQLStatement stat = new SQLStatement(db);
+        stat.appendSQL("DELETE FROM ");
+        from.appendSQL(stat);
+        appendWhere(stat);
+        IciqlLogger.delete(stat.getSQL());
+        return stat.executeUpdate();
+    }
+
+    public <A> Query<T> setNull(A field) {
+        return set(field).to(null);
+    }
+
+    public <A> UpdateColumnSet<T, A> set(A field) {
+        from.getAliasDefinition().checkMultipleEnums(field);
+        return new UpdateColumnSet<T, A>(this, field);
+    }
+
+    public UpdateColumnSet<T, Boolean> set(boolean field) {
+        from.getAliasDefinition().checkMultipleBooleans();
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Byte> set(byte field) {
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Short> set(short field) {
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Integer> set(int field) {
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Long> set(long field) {
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Float> set(float field) {
+        return setPrimitive(field);
+    }
+
+    public UpdateColumnSet<T, Double> set(double field) {
+        return setPrimitive(field);
+    }
+
+    private <A> UpdateColumnSet<T, A> setPrimitive(A field) {
+        A alias = getPrimitiveAliasByValue(field);
+        if (alias == null) {
+            // this will result in an unmapped field exception
+            return set(field);
+        }
+        return set(alias);
+    }
+
+    public <A> UpdateColumnIncrement<T, A> increment(A field) {
+        return new UpdateColumnIncrement<T, A>(this, field);
+    }
+
+    public UpdateColumnIncrement<T, Byte> increment(byte field) {
+        return incrementPrimitive(field);
+    }
+
+    public UpdateColumnIncrement<T, Short> increment(short field) {
+        return incrementPrimitive(field);
+    }
+
+    public UpdateColumnIncrement<T, Integer> increment(int field) {
+        return incrementPrimitive(field);
+    }
+
+    public UpdateColumnIncrement<T, Long> increment(long field) {
+        return incrementPrimitive(field);
+    }
+
+    public UpdateColumnIncrement<T, Float> increment(float field) {
+        return incrementPrimitive(field);
+    }
+
+    public UpdateColumnIncrement<T, Double> increment(double field) {
+        return incrementPrimitive(field);
+    }
+
+    private <A> UpdateColumnIncrement<T, A> incrementPrimitive(A field) {
+        A alias = getPrimitiveAliasByValue(field);
+        if (alias == null) {
+            // this will result in an unmapped field exception
+            return increment(field);
+        }
+        return increment(alias);
+    }
+
+    public int update() {
+        if (updateColumnDeclarations.size() == 0) {
+            throw new IciqlException("Missing set or increment call.");
+        }
+        SQLStatement stat = new SQLStatement(db);
+        stat.appendSQL("UPDATE ");
+        from.appendSQL(stat);
+        stat.appendSQL(" SET ");
+        int i = 0;
+        for (UpdateColumn declaration : updateColumnDeclarations) {
+            if (i++ > 0) {
+                stat.appendSQL(", ");
+            }
+            declaration.appendSQL(stat);
+        }
+        appendWhere(stat);
+        IciqlLogger.update(stat.getSQL());
+        return stat.executeUpdate();
+    }
+
+    public <X, Z> List<X> selectDistinct(Z x) {
+        return select(x, true);
+    }
+
+    public <X, Z> List<X> select(Z x) {
+        return select(x, false);
+    }
+
+    @SuppressWarnings("unchecked")
+    private <X, Z> List<X> select(Z x, boolean distinct) {
+        Class<?> clazz = x.getClass();
+        if (Db.isToken(x)) {
+            // selecting a function
+            return selectFunction((X) x, distinct);
+        } else {
+            // selecting a column
+            SelectColumn<T> col = getColumnByReference(x);
+            if (col == null) {
+                col = getColumnByReference(getPrimitiveAliasByValue(x));
+            }
+            if (col != null) {
+                return (List<X>) selectColumn(col, clazz, distinct);
+            }
+        }
+
+        // selecting into a new object type
+        Class<?> enclosingClass = clazz.getEnclosingClass();
+        if (enclosingClass != null) {
+            // anonymous inner class
+            clazz = clazz.getSuperclass();
+        }
+        return select((Class<X>) clazz, (X) x, distinct);
+    }
+
+    private <X> List<X> select(Class<X> clazz, X x, boolean distinct) {
+        List<X> result = Utils.newArrayList();
+        TableDefinition<X> def = db.define(clazz);
+        SQLStatement stat = getSelectStatement(distinct);
+        def.appendSelectList(stat, this, x);
+        appendFromWhere(stat);
+        ResultSet rs = stat.executeQuery();
+        try {
+            // SQLite returns pre-closed ResultSets for query results with 0 rows
+            if (!rs.isClosed()) {
+                int[] columns = def.mapColumns(db.getDialect(), false, rs);
+                while (rs.next()) {
+                    X row = Utils.newObject(clazz);
+                    def.readRow(db.getDialect(), row, rs, columns);
+                    result.add(row);
+                }
+            }
+        } catch (SQLException e) {
+            throw IciqlException.fromSQL(stat.getSQL(), e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <X> List<X> selectFunction(X x, boolean distinct) {
+        SQLStatement stat = getSelectStatement(distinct);
+        appendSQL(stat, null, x);
+        appendFromWhere(stat);
+        ResultSet rs = stat.executeQuery();
+        List<X> result = Utils.newArrayList();
+        try {
+            // SQLite returns pre-closed ResultSets for query results with 0 rows
+            if (!rs.isClosed()) {
+                while (rs.next()) {
+                    X value = (X) rs.getObject(1);
+                    result.add(value);
+                }
+            }
+        } catch (Exception e) {
+            throw IciqlException.fromSQL(stat.getSQL(), e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <X> List<X> selectColumn(SelectColumn<T> col, Class<X> clazz, boolean distinct) {
+        SQLStatement stat = getSelectStatement(distinct);
+        col.appendSQL(stat);
+        appendFromWhere(stat);
+        ResultSet rs = stat.executeQuery();
+        List<X> result = Utils.newArrayList();
+        Class<? extends DataTypeAdapter<?>> typeAdapter = col.getFieldDefinition().typeAdapter;
+        try {
+            // SQLite returns pre-closed ResultSets for query results with 0 rows
+            if (!rs.isClosed()) {
+                while (rs.next()) {
+                    X value = (X) db.getDialect().deserialize(rs, 1, clazz, typeAdapter);
+                    result.add(value);
+                }
+            }
+        } catch (Exception e) {
+            throw IciqlException.fromSQL(stat.getSQL(), e);
+        } finally {
+            JdbcUtils.closeSilently(rs, true);
+        }
+        return result;
+    }
+
+    private SQLStatement getSelectStatement(boolean distinct) {
+        SQLStatement stat = new SQLStatement(db);
+        stat.appendSQL("SELECT ");
+        if (distinct) {
+            stat.appendSQL("DISTINCT ");
+        }
+        return stat;
+    }
+
+    /**
+     * Begin a primitive boolean field condition clause.
+     *
+     * @param x the primitive boolean field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Boolean> where(boolean x) {
+        from.getAliasDefinition().checkMultipleBooleans();
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive short field condition clause.
+     *
+     * @param x the primitive short field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Byte> where(byte x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive short field condition clause.
+     *
+     * @param x the primitive short field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Short> where(short x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive int field condition clause.
+     *
+     * @param x the primitive int field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Integer> where(int x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive long field condition clause.
+     *
+     * @param x the primitive long field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Long> where(long x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive float field condition clause.
+     *
+     * @param x the primitive float field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Float> where(float x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begin a primitive double field condition clause.
+     *
+     * @param x the primitive double field to query
+     * @return a query condition to continue building the condition
+     */
+    public QueryCondition<T, Double> where(double x) {
+        return wherePrimitive(x);
+    }
+
+    /**
+     * Begins a primitive field condition clause.
+     *
+     * @param value
+     * @return a query condition to continue building the condition
+     */
+    private <A> QueryCondition<T, A> wherePrimitive(A value) {
+        A alias = getPrimitiveAliasByValue(value);
+        if (alias == null) {
+            // this will result in an unmapped field exception
+            return where(value);
+        }
+        return where(alias);
+    }
+
+    /**
+     * Begin an Object field condition clause.
+     *
+     * @param x the mapped object to query
+     * @return a query condition to continue building the condition
+     */
+    public <A> QueryCondition<T, A> where(A x) {
+        from.getAliasDefinition().checkMultipleEnums(x);
+        return new QueryCondition<T, A>(this, x);
+    }
+
+    public <A> QueryWhere<T> where(Filter filter) {
+        HashMap<String, Object> fieldMap = Utils.newHashMap();
+        for (Field f : filter.getClass().getDeclaredFields()) {
+            f.setAccessible(true);
+            try {
+                Object obj = f.get(filter);
+                if (obj == from.getAlias()) {
+                    List<TableDefinition.FieldDefinition> fields = from.getAliasDefinition().getFields();
+                    String name = f.getName();
+                    for (TableDefinition.FieldDefinition field : fields) {
+                        String n = name + "." + field.field.getName();
+                        Object o = field.field.get(obj);
+                        fieldMap.put(n, o);
+                    }
+                }
+                fieldMap.put(f.getName(), f.get(filter));
+            } catch (Exception e) {
+                throw new IciqlException(e);
+            }
+        }
+        Token filterCode = new ClassReader().decompile(filter, fieldMap, "where");
+        // String filterQuery = filterCode.toString();
+        conditions.add(filterCode);
+        return new QueryWhere<T>(this);
+    }
+
+    public QueryWhere<T> where(String fragment, List<?> args) {
+        return this.where(fragment, args.toArray());
+    }
+
+    public QueryWhere<T> where(String fragment, Object... args) {
+        conditions.add(new RuntimeToken(fragment, args));
+        return new QueryWhere<T>(this);
+    }
+
+    public Query<T> where(And<T> conditions) {
+        whereTrue();
+        addConditionToken(conditions.where.query);
+        return this;
+    }
+
+    public Query<T> where(Or<T> conditions) {
+        whereFalse();
+        addConditionToken(conditions.where.query);
+        return this;
+    }
+
+    public QueryWhere<T> whereTrue() {
+        return whereTrue(true);
+    }
+
+    public QueryWhere<T> whereFalse() {
+        return whereTrue(false);
+    }
+
+    public QueryWhere<T> whereTrue(Boolean condition) {
+        Token token = new Function("", condition);
+        addConditionToken(token);
+        return new QueryWhere<T>(this);
+    }
+
+    /**
+     * Sets the Limit and Offset of a query.
+     *
+     * @return the query
+     */
+
+    public Query<T> limit(long limit) {
+        this.limit = limit;
+        return this;
+    }
+
+    public Query<T> offset(long offset) {
+        this.offset = offset;
+        return this;
+    }
+
+    public Query<T> orderBy(boolean field) {
+        from.getAliasDefinition().checkMultipleBooleans();
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(byte field) {
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(short field) {
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(int field) {
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(long field) {
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(float field) {
+        return orderByPrimitive(field);
+    }
+
+    public Query<T> orderBy(double field) {
+        return orderByPrimitive(field);
+    }
+
+    Query<T> orderByPrimitive(Object field) {
+        Object alias = getPrimitiveAliasByValue(field);
+        if (alias == null) {
+            return orderBy(field);
+        }
+        return orderBy(alias);
+    }
+
+    public Query<T> orderBy(Object expr) {
+        from.getAliasDefinition().checkMultipleEnums(expr);
+        OrderExpression<T> e = new OrderExpression<T>(this, expr, false, false, false);
+        addOrderBy(e);
+        return this;
+    }
+
+    /**
+     * Order by a number of columns.
+     *
+     * @param expressions the columns
+     * @return the query
+     */
+
+    public Query<T> orderBy(Object... expressions) {
+        for (Object expr : expressions) {
+            from.getAliasDefinition().checkMultipleEnums(expr);
+            OrderExpression<T> e = new OrderExpression<T>(this, expr, false, false, false);
+            addOrderBy(e);
+        }
+        return this;
+    }
+
+    public Query<T> orderByDesc(byte field) {
+        return orderByDescPrimitive(field);
+    }
+
+    public Query<T> orderByDesc(short field) {
+        return orderByDescPrimitive(field);
+    }
+
+    public Query<T> orderByDesc(int field) {
+        return orderByDescPrimitive(field);
+    }
+
+    public Query<T> orderByDesc(long field) {
+        return orderByDescPrimitive(field);
+    }
+
+    public Query<T> orderByDesc(float field) {
+        return orderByDescPrimitive(field);
+    }
+
+    public Query<T> orderByDesc(double field) {
+        return orderByDescPrimitive(field);
+    }
+
+    Query<T> orderByDescPrimitive(Object field) {
+        Object alias = getPrimitiveAliasByValue(field);
+        if (alias == null) {
+            return orderByDesc(field);
+        }
+        return orderByDesc(alias);
+    }
+
+    public Query<T> orderByDesc(Object expr) {
+        OrderExpression<T> e = new OrderExpression<T>(this, expr, true, false, false);
+        addOrderBy(e);
+        return this;
+    }
+
+    public Query<T> groupBy(boolean field) {
+        from.getAliasDefinition().checkMultipleBooleans();
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(byte field) {
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(short field) {
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(int field) {
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(long field) {
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(float field) {
+        return groupByPrimitive(field);
+    }
+
+    public Query<T> groupBy(double field) {
+        return groupByPrimitive(field);
+    }
+
+    Query<T> groupByPrimitive(Object field) {
+        Object alias = getPrimitiveAliasByValue(field);
+        if (alias == null) {
+            return groupBy(field);
+        }
+        return groupBy(alias);
+    }
+
+    public Query<T> groupBy(Object expr) {
+        from.getAliasDefinition().checkMultipleEnums(expr);
+        groupByExpressions.add(expr);
+        return this;
+    }
+
+    public Query<T> groupBy(Object... groupBy) {
+        this.groupByExpressions.addAll(Arrays.asList(groupBy));
+        return this;
+    }
+
+    /**
+     * INTERNAL
+     *
+     * @param stat  the statement
+     * @param alias the alias object (can be null)
+     * @param value the value
+     */
+    public void appendSQL(SQLStatement stat, Object alias, Object value) {
+        if (Function.count() == value) {
+            stat.appendSQL("COUNT(*)");
+            return;
+        }
+        if (RuntimeParameter.PARAMETER == value) {
+            stat.appendSQL("?");
+            addParameter(stat, alias, value);
+            return;
+        }
+        Token token = Db.getToken(value);
+        if (token != null) {
+            token.appendSQL(stat, this);
+            return;
+        }
+        if (alias != null && value != null && value.getClass().isEnum()) {
+            // special case:
+            // value is first enum constant which is also the alias object.
+            // the first enum constant is used as the alias because we can not
+            // instantiate an enum reflectively.
+            stat.appendSQL("?");
+            addParameter(stat, alias, value);
+            return;
+        }
+        SelectColumn<T> col = getColumnByReference(value);
+        if (col != null) {
+            col.appendSQL(stat);
+            return;
+        }
+        stat.appendSQL("?");
+        addParameter(stat, alias, value);
+    }
+
+    /**
+     * INTERNAL
+     *
+     * @param stat        the statement
+     * @param alias       the alias object (can be null)
+     * @param valueLeft   the value on the left of the compound clause
+     * @param valueRight  the value on the right of the compound clause
+     * @param compareType the current compare type (e.g. BETWEEN)
+     */
+    public void appendSQL(SQLStatement stat, Object alias, Object valueLeft, Object valueRight,
+                          CompareType compareType) {
+        stat.appendSQL("?");
+        stat.appendSQL(" ");
+        switch (compareType) {
+            case BETWEEN:
+                stat.appendSQL("AND");
+                break;
+        }
+        stat.appendSQL(" ");
+        stat.appendSQL("?");
+        addParameter(stat, alias, valueLeft);
+        addParameter(stat, alias, valueRight);
+    }
+
+    public void appendSQL(SQLStatement stat, Object alias, Iterable<Object> values,
+                          CompareType compareType) {
+        boolean first = true;
+        stat.appendSQL("(");
+        for (Object value : values) {
+            if (first) {
+                first = false;
+            } else {
+                stat.appendSQL(", ");
+            }
+            stat.appendSQL("?");
+            addParameter(stat, alias, value);
+        }
+        stat.appendSQL(")");
+    }
+
+    private void addParameter(SQLStatement stat, Object alias, Object value) {
+        SelectColumn<T> col = getColumnByReference(alias);
+        if (col != null && value != null && value.getClass().isEnum()) {
+            // enum
+            TableDefinition.FieldDefinition field = col.getFieldDefinition();
+            EnumType type = field.enumType;
+            Enum<?> anEnum = (Enum<?>) value;
+            Object y = Utils.convertEnum(anEnum, type);
+            stat.addParameter(y);
+        } else if (col != null) {
+            // object
+            TableDefinition.FieldDefinition field = col.getFieldDefinition();
+            Class<? extends DataTypeAdapter<?>> typeAdapter = field.typeAdapter;
+            if (value != null && value instanceof String) {
+                if (field.trim && field.length > 0) {
+                    // clip strings (issue-15)
+                    String s = (String) value;
+                    if (s.length() > field.length) {
+                        value = s.substring(0, field.length);
+                    }
+                }
+            }
+            Object parameter = db.getDialect().serialize(value, typeAdapter);
+            stat.addParameter(parameter);
+        } else {
+            // primitive
+            stat.addParameter(value);
+        }
+    }
+
+    void addConditionToken(Token condition) {
+        if (condition == ConditionOpenClose.OPEN) {
+            conditionDepth++;
+        } else if (condition == ConditionOpenClose.CLOSE) {
+            conditionDepth--;
+            if (conditionDepth < 0) {
+                throw new IciqlException("unmatch condition open-close count");
+            }
+        }
+        conditions.add(condition);
+    }
+
+    void addConditionToken(Query<T> other) {
+        for (Token condition : other.conditions) {
+            addConditionToken(condition);
+        }
+    }
+
+    void addUpdateColumnDeclaration(UpdateColumn declaration) {
+        updateColumnDeclarations.add(declaration);
+    }
+
+    void appendWhere(SQLStatement stat) {
+        if (conditionDepth != 0) {
+            throw new IciqlException("unmatch condition open-close count");
+        }
+        if (!conditions.isEmpty()) {
+            stat.appendSQL(" WHERE ");
+
+            boolean skipNextConjunction = false;
+
+            for (Token token : conditions) {
+
+                if (skipNextConjunction && token instanceof ConditionAndOr) {
+                    skipNextConjunction = false;
+                    continue;
+                }
+
+                token.appendSQL(stat, this);
+                stat.appendSQL(" ");
+
+                if (ConditionOpenClose.OPEN == token) {
+                    skipNextConjunction = true;
+                }
+            }
+        }
+    }
+
+    void appendFromWhere(SQLStatement stat) {
+        appendFromWhere(stat, true);
+    }
+
+    void appendFromWhere(SQLStatement stat, boolean log) {
+        stat.appendSQL(" FROM ");
+        from.appendSQL(stat);
+        for (SelectTable<T> join : joins) {
+            join.appendSQLAsJoin(stat, this);
+        }
+        appendWhere(stat);
+        if (!groupByExpressions.isEmpty()) {
+            stat.appendSQL(" GROUP BY ");
+            int i = 0;
+            for (Object obj : groupByExpressions) {
+                if (i++ > 0) {
+                    stat.appendSQL(", ");
+                }
+                appendSQL(stat, null, obj);
+                stat.appendSQL(" ");
+            }
+        }
+        if (!orderByList.isEmpty()) {
+            stat.appendSQL(" ORDER BY ");
+            int i = 0;
+            for (OrderExpression<T> o : orderByList) {
+                if (i++ > 0) {
+                    stat.appendSQL(", ");
+                }
+                o.appendSQL(stat);
+                stat.appendSQL(" ");
+            }
+        }
+        db.getDialect().appendLimitOffset(stat, limit, offset);
+        if (log) {
+            IciqlLogger.select(stat.getSQL());
+        }
+    }
+
+    /**
+     * Join another table.
+     *
+     * @param alias an alias for the table to join
+     * @return the joined query
+     */
+
+    public <A> QueryJoin<T> innerJoin(A alias) {
         return join(alias, false);
-       }
+    }
 
     public <A> QueryJoin<T> leftJoin(A alias) {
         return join(alias, true);
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings({"unchecked", "rawtypes"})
     private <A> QueryJoin<T> join(A alias, boolean outerJoin) {
         TableDefinition<T> def = (TableDefinition<T>) db.define(alias.getClass());
         SelectTable<T> join = new SelectTable(db, this, alias, outerJoin);
@@ -1052,63 +1030,63 @@ public class Query<T> {
         return new QueryJoin(this, join);
     }
 
-       Db getDb() {
-               return db;
-       }
-
-       SelectTable<T> getFrom() {
-               return from;
-       }
-
-       boolean isJoin() {
-               return !joins.isEmpty();
-       }
-
-       SelectTable<?> getSelectTable(Object alias) {
-               if (from.getAlias() == alias) {
-                       return from;
-               } else {
-                       for (SelectTable<?> join : joins) {
-                               if (join.getAlias() == alias) {
-                                       return join;
-                               }
-                       }
-               }
-               return null;
-       }
-
-       /**
-        * This method returns a mapped Object field by its reference.
-        *
-        * @param obj
-        * @return
-        */
-       private SelectColumn<T> getColumnByReference(Object obj) {
-               SelectColumn<T> col = aliasMap.get(obj);
-               return col;
-       }
-
-       /**
-        * This method returns the alias of a mapped primitive field by its value.
-        *
-        * @param obj
-        * @return
-        */
-       @SuppressWarnings("unchecked")
-       <A> A getPrimitiveAliasByValue(A obj) {
-               for (Object alias : aliasMap.keySet()) {
-                       if (alias.equals(obj)) {
-                               SelectColumn<T> match = aliasMap.get(alias);
-                               if (match.getFieldDefinition().isPrimitive) {
-                                       return (A) alias;
-                               }
-                       }
-               }
-               return null;
-       }
-
-       void addOrderBy(OrderExpression<T> expr) {
-               orderByList.add(expr);
-       }
+    Db getDb() {
+        return db;
+    }
+
+    SelectTable<T> getFrom() {
+        return from;
+    }
+
+    boolean isJoin() {
+        return !joins.isEmpty();
+    }
+
+    SelectTable<?> getSelectTable(Object alias) {
+        if (from.getAlias() == alias) {
+            return from;
+        } else {
+            for (SelectTable<?> join : joins) {
+                if (join.getAlias() == alias) {
+                    return join;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This method returns a mapped Object field by its reference.
+     *
+     * @param obj
+     * @return
+     */
+    private SelectColumn<T> getColumnByReference(Object obj) {
+        SelectColumn<T> col = aliasMap.get(obj);
+        return col;
+    }
+
+    /**
+     * This method returns the alias of a mapped primitive field by its value.
+     *
+     * @param obj
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    <A> A getPrimitiveAliasByValue(A obj) {
+        for (Object alias : aliasMap.keySet()) {
+            if (alias.equals(obj)) {
+                SelectColumn<T> match = aliasMap.get(alias);
+                if (match.getFieldDefinition().isPrimitive) {
+                    return (A) alias;
+                }
+            }
+        }
+        return null;
+    }
+
+    void addOrderBy(OrderExpression<T> expr) {
+        orderByList.add(expr);
+    }
 
 }
index 72d19dc425a5ee15da07187b4f51647ffb76cd3c..f3a556150a5f337faf8d35d352dca2ce84655edf 100644 (file)
@@ -18,43 +18,37 @@ package com.iciql;
 \r
 /**\r
  * This class represents a "between y and z" condition.\r
- * \r
- * @param <T>\r
- *            the return type of the query\r
- * @param <A>\r
- *            the incomplete condition data type\r
+ *\r
+ * @param <T> the return type of the query\r
+ * @param <A> the incomplete condition data type\r
  */\r
 public class QueryBetween<T, A> {\r
 \r
-       private Query<T> query;\r
-       private A x;\r
-       private A y;\r
+    private Query<T> query;\r
+    private A x;\r
+    private A y;\r
 \r
-       /**\r
-        * Construct a between condition.\r
-        * \r
-        * @param query\r
-        *            the query\r
-        * @param x\r
-        *            the alias\r
-        * @param y\r
-        *            the lower bound of the between condition\r
-        */\r
-       public QueryBetween(Query<T> query, A x, A y) {\r
-               this.query = query;\r
-               this.x = x;\r
-               this.y = y;\r
-       }\r
+    /**\r
+     * Construct a between condition.\r
+     *\r
+     * @param query the query\r
+     * @param x     the alias\r
+     * @param y     the lower bound of the between condition\r
+     */\r
+    public QueryBetween(Query<T> query, A x, A y) {\r
+        this.query = query;\r
+        this.x = x;\r
+        this.y = y;\r
+    }\r
 \r
-       /**\r
-        * Set the upper bound of the between condition.\r
-        * \r
-        * @param z\r
-        *            the upper bound of the between condition\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> and(A z) {\r
-               query.addConditionToken(new Condition<A>(x, y, z, CompareType.BETWEEN));\r
-               return new QueryWhere<T>(query);\r
-       }\r
+    /**\r
+     * Set the upper bound of the between condition.\r
+     *\r
+     * @param z the upper bound of the between condition\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> and(A z) {\r
+        query.addConditionToken(new Condition<A>(x, y, z, CompareType.BETWEEN));\r
+        return new QueryWhere<T>(query);\r
+    }\r
 }\r
index cef95c19f54be94f8135d1723ecb6937be0c2f92..fce66afc8334571e33d6399a817fa6bd58c6d19a 100644 (file)
@@ -21,128 +21,126 @@ import com.iciql.util.Utils;
 
 /**
  * This class represents a query with an incomplete condition.
- * 
- * @param <T>
- *            the return type of the query
- * @param <A>
- *            the incomplete condition data type
+ *
+ * @param <T> the return type of the query
+ * @param <A> the incomplete condition data type
  */
 
 public class QueryCondition<T, A> {
 
-       private Query<T> query;
-       private A x;
-
-       QueryCondition(Query<T> query, A x) {
-               this.query = query;
-               this.x = x;
-       }
-
-       public <Q, Z> QueryWhere<T> in(SubQuery<Q, Z> q) {
-               query.addConditionToken(new SubQueryCondition<A, Q, Z>(x, q));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> oneOf(A... a) {
-               return oneOf(Utils.newArrayIterable(a));
-       }
-
-       public QueryWhere<T> oneOf(Iterable<A> i) {
-               query.addConditionToken(new Condition<A>(x, i, CompareType.IN));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> noneOf(A... a) {
-               return noneOf(Utils.newArrayIterable(a));
-       }
-
-       public QueryWhere<T> noneOf(Iterable<A> i) {
-               query.addConditionToken(new Condition<A>(x, i, CompareType.NOT_IN));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> is(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.EQUAL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> isNot(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.NOT_EQUAL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> isNull() {
-               query.addConditionToken(new Condition<A>(x, CompareType.IS_NULL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> isNotNull() {
-               query.addConditionToken(new Condition<A>(x, CompareType.IS_NOT_NULL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> exceeds(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.EXCEEDS));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> atLeast(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.AT_LEAST));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> lessThan(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.LESS_THAN));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> atMost(A y) {
-               query.addConditionToken(new Condition<A>(x, y, CompareType.AT_MOST));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryBetween<T, A> between(A y) {
-               return new QueryBetween<T, A>(query, x, y);
-       }
-
-       public QueryWhere<T> like(A pattern) {
-               query.addConditionToken(new Condition<A>(x, pattern, CompareType.LIKE));
-               return new QueryWhere<T>(query);
-       }
-
-       /*
-        * These method allows you to generate "x=?", "x!=?", etc where conditions.
-        * Parameter substitution must be done manually later with db.executeQuery.
-        * This allows for building re-usable SQL string statements from your model
-        * classes.
-        */
-       public QueryWhere<T> isParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.EQUAL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> isNotParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.NOT_EQUAL));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> exceedsParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.EXCEEDS));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> lessThanParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.LESS_THAN));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> atMostParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.AT_MOST));
-               return new QueryWhere<T>(query);
-       }
-
-       public QueryWhere<T> likeParameter() {
-               query.addConditionToken(new RuntimeParameter<A>(x, CompareType.LIKE));
-               return new QueryWhere<T>(query);
-       }
+    private Query<T> query;
+    private A x;
+
+    QueryCondition(Query<T> query, A x) {
+        this.query = query;
+        this.x = x;
+    }
+
+    public <Q, Z> QueryWhere<T> in(SubQuery<Q, Z> q) {
+        query.addConditionToken(new SubQueryCondition<A, Q, Z>(x, q));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> oneOf(A... a) {
+        return oneOf(Utils.newArrayIterable(a));
+    }
+
+    public QueryWhere<T> oneOf(Iterable<A> i) {
+        query.addConditionToken(new Condition<A>(x, i, CompareType.IN));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> noneOf(A... a) {
+        return noneOf(Utils.newArrayIterable(a));
+    }
+
+    public QueryWhere<T> noneOf(Iterable<A> i) {
+        query.addConditionToken(new Condition<A>(x, i, CompareType.NOT_IN));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> is(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.EQUAL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> isNot(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.NOT_EQUAL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> isNull() {
+        query.addConditionToken(new Condition<A>(x, CompareType.IS_NULL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> isNotNull() {
+        query.addConditionToken(new Condition<A>(x, CompareType.IS_NOT_NULL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> exceeds(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.EXCEEDS));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> atLeast(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.AT_LEAST));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> lessThan(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.LESS_THAN));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> atMost(A y) {
+        query.addConditionToken(new Condition<A>(x, y, CompareType.AT_MOST));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryBetween<T, A> between(A y) {
+        return new QueryBetween<T, A>(query, x, y);
+    }
+
+    public QueryWhere<T> like(A pattern) {
+        query.addConditionToken(new Condition<A>(x, pattern, CompareType.LIKE));
+        return new QueryWhere<T>(query);
+    }
+
+    /*
+     * These method allows you to generate "x=?", "x!=?", etc where conditions.
+     * Parameter substitution must be done manually later with db.executeQuery.
+     * This allows for building re-usable SQL string statements from your model
+     * classes.
+     */
+    public QueryWhere<T> isParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.EQUAL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> isNotParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.NOT_EQUAL));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> exceedsParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.EXCEEDS));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> lessThanParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.LESS_THAN));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> atMostParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.AT_MOST));
+        return new QueryWhere<T>(query);
+    }
+
+    public QueryWhere<T> likeParameter() {
+        query.addConditionToken(new RuntimeParameter<A>(x, CompareType.LIKE));
+        return new QueryWhere<T>(query);
+    }
 }
index 6d0484edddc70c1239beb903ad636f26dd1a8e29..325ae5000e513b17ab9d36c205dee636ad324182 100644 (file)
@@ -23,53 +23,53 @@ package com.iciql;
 \r
 public class QueryJoin<T> {\r
 \r
-       private Query<T> query;\r
-       private SelectTable<T> join;\r
+    private Query<T> query;\r
+    private SelectTable<T> join;\r
 \r
-       QueryJoin(Query<T> query, SelectTable<T> join) {\r
-               this.query = query;\r
-               this.join = join;\r
-       }\r
+    QueryJoin(Query<T> query, SelectTable<T> join) {\r
+        this.query = query;\r
+        this.join = join;\r
+    }\r
 \r
-       public QueryJoinCondition<T, Boolean> on(boolean x) {\r
-               query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Boolean> on(boolean x) {\r
+        query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Byte> on(byte x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Byte> on(byte x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Short> on(short x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Short> on(short x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Integer> on(int x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Integer> on(int x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Long> on(long x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Long> on(long x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Float> on(float x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Float> on(float x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       public QueryJoinCondition<T, Double> on(double x) {\r
-               return addPrimitive(x);\r
-       }\r
+    public QueryJoinCondition<T, Double> on(double x) {\r
+        return addPrimitive(x);\r
+    }\r
 \r
-       private <A> QueryJoinCondition<T, A> addPrimitive(A x) {\r
-               A alias = query.getPrimitiveAliasByValue(x);\r
-               if (alias == null) {\r
-                       // this will result in an unmapped field exception\r
-                       return new QueryJoinCondition<T, A>(query, join, x);\r
-               }\r
-               return new QueryJoinCondition<T, A>(query, join, alias);\r
-       }\r
+    private <A> QueryJoinCondition<T, A> addPrimitive(A x) {\r
+        A alias = query.getPrimitiveAliasByValue(x);\r
+        if (alias == null) {\r
+            // this will result in an unmapped field exception\r
+            return new QueryJoinCondition<T, A>(query, join, x);\r
+        }\r
+        return new QueryJoinCondition<T, A>(query, join, alias);\r
+    }\r
 \r
-       public <A> QueryJoinCondition<T, A> on(A x) {\r
-               return new QueryJoinCondition<T, A>(query, join, x);\r
-       }\r
+    public <A> QueryJoinCondition<T, A> on(A x) {\r
+        return new QueryJoinCondition<T, A>(query, join, x);\r
+    }\r
 }\r
index 6dfd21880c2fbba5253d0514b0ca4808be334e49..d1a82d909ffc8fc7f922f6c795a19caaba6ec5ab 100644 (file)
@@ -20,64 +20,63 @@ package com.iciql;
 \r
 /**\r
  * This class represents a query with join and an incomplete condition.\r
- * \r
- * @param <A>\r
- *            the incomplete condition data type\r
+ *\r
+ * @param <A> the incomplete condition data type\r
  */\r
 \r
 public class QueryJoinCondition<T, A> {\r
 \r
-       private Query<T> query;\r
-       private SelectTable<T> join;\r
-       private A x;\r
+    private Query<T> query;\r
+    private SelectTable<T> join;\r
+    private A x;\r
+\r
+    QueryJoinCondition(Query<T> query, SelectTable<T> join, A x) {\r
+        this.query = query;\r
+        this.join = join;\r
+        this.x = x;\r
+    }\r
 \r
-       QueryJoinCondition(Query<T> query, SelectTable<T> join, A x) {\r
-               this.query = query;\r
-               this.join = join;\r
-               this.x = x;\r
-       }\r
+    public Query<T> is(boolean y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(boolean y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(byte y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(byte y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(short y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(short y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(int y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(int y) {\r
-               return addPrimitive(y);\r
-       }\r
-       \r
-       public Query<T> is(long y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(long y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(float y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(float y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       public Query<T> is(double y) {\r
-               return addPrimitive(y);\r
-       }       \r
+    public Query<T> is(double y) {\r
+        return addPrimitive(y);\r
+    }\r
 \r
-       @SuppressWarnings("unchecked")\r
-       private Query<T> addPrimitive(Object o) {               \r
-               A alias = query.getPrimitiveAliasByValue((A) o);\r
-               if (alias == null) {\r
-                       join.addConditionToken(new Condition<A>(x, (A) o, CompareType.EQUAL));\r
-               } else {\r
-                       join.addConditionToken(new Condition<A>(x, alias, CompareType.EQUAL));\r
-               }\r
-               return query;           \r
-       }\r
+    @SuppressWarnings("unchecked")\r
+    private Query<T> addPrimitive(Object o) {\r
+        A alias = query.getPrimitiveAliasByValue((A) o);\r
+        if (alias == null) {\r
+            join.addConditionToken(new Condition<A>(x, (A) o, CompareType.EQUAL));\r
+        } else {\r
+            join.addConditionToken(new Condition<A>(x, alias, CompareType.EQUAL));\r
+        }\r
+        return query;\r
+    }\r
 \r
-       public Query<T> is(A y) {\r
-               join.addConditionToken(new Condition<A>(x, y, CompareType.EQUAL));\r
-               return query;\r
-       }\r
+    public Query<T> is(A y) {\r
+        join.addConditionToken(new Condition<A>(x, y, CompareType.EQUAL));\r
+        return query;\r
+    }\r
 }\r
index fdce1cbab86f501d442d9b7a88a8c01315a2ad47..16f1397c0939673a7f03139204eb853149a3fadf 100644 (file)
 \r
 package com.iciql;\r
 \r
-import java.util.List;\r
-\r
 import com.iciql.NestedConditions.And;\r
 import com.iciql.NestedConditions.Or;\r
 \r
+import java.util.List;\r
+\r
 /**\r
  * This class represents a query with a condition.\r
  *\r
- * @param <T>\r
- *            the return type\r
+ * @param <T> the return type\r
  */\r
 \r
 public class QueryWhere<T> {\r
 \r
-       Query<T> query;\r
-\r
-       QueryWhere(Query<T> query) {\r
-               this.query = query;\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive boolean.\r
-        *\r
-        * @param x\r
-        *            the primitive boolean field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Boolean> and(boolean x) {\r
-               query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive byte.\r
-        *\r
-        * @param x\r
-        *            the primitive byte field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Byte> and(byte x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive short.\r
-        *\r
-        * @param x\r
-        *            the primitive short field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Short> and(short x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive int.\r
-        *\r
-        * @param x\r
-        *            the primitive int field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Integer> and(int x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive long.\r
-        *\r
-        * @param x\r
-        *            the primitive long field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Long> and(long x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive float.\r
-        *\r
-        * @param x\r
-        *            the primitive float field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Float> and(float x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped primitive double.\r
-        *\r
-        * @param x\r
-        *            the primitive double field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Double> and(double x) {\r
-               return addPrimitive(ConditionAndOr.AND, x);\r
-       }\r
-\r
-       private <A> QueryCondition<T, A> addPrimitive(ConditionAndOr condition, A x) {\r
-               query.addConditionToken(condition);\r
-               A alias = query.getPrimitiveAliasByValue(x);\r
-               if (alias == null) {\r
-                       // this will result in an unmapped field exception\r
-                       return new QueryCondition<T, A>(query, x);\r
-               }\r
-               return new QueryCondition<T, A>(query, alias);\r
-       }\r
-\r
-       /**\r
-        * Specify an AND condition with a mapped Object field.\r
-        *\r
-        * @param x\r
-        *            the Object field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public <A> QueryCondition<T, A> and(A x) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(x);\r
-               query.addConditionToken(ConditionAndOr.AND);\r
-               return new QueryCondition<T, A>(query, x);\r
-       }\r
-\r
-       public QueryWhere<T> and(And<T> conditions) {\r
-               andOpen();\r
-               query.addConditionToken(conditions.where.query);\r
-               return close();\r
-       }\r
-\r
-       public QueryWhere<T> and(Or<T> conditions) {\r
-               andOpen();\r
-               query.addConditionToken(conditions.where.query);\r
-               return close();\r
-       }\r
-\r
-       public QueryWhere<T> andOpen() {\r
-               return open(ConditionAndOr.AND);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive boolean.\r
-        *\r
-        * @param x\r
-        *            the primitive boolean field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Boolean> or(boolean x) {\r
-               query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive byte.\r
-        *\r
-        * @param x\r
-        *            the primitive byte field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Byte> or(byte x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive short.\r
-        *\r
-        * @param x\r
-        *            the primitive short field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Short> or(short x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive int.\r
-        *\r
-        * @param x\r
-        *            the primitive int field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Integer> or(int x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive long.\r
-        *\r
-        * @param x\r
-        *            the primitive long field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Long> or(long x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive float.\r
-        *\r
-        * @param x\r
-        *            the primitive float field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Float> or(float x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped primitive double.\r
-        *\r
-        * @param x\r
-        *            the primitive double field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public QueryCondition<T, Double> or(double x) {\r
-               return addPrimitive(ConditionAndOr.OR, x);\r
-       }\r
-\r
-       /**\r
-        * Specify an OR condition with a mapped Object field.\r
-        *\r
-        * @param x\r
-        *            the Object field to query\r
-        * @return a query condition to continue building the condition\r
-        */\r
-       public <A> QueryCondition<T, A> or(A x) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(x);\r
-               query.addConditionToken(ConditionAndOr.OR);\r
-               return new QueryCondition<T, A>(query, x);\r
-       }\r
-\r
-       public QueryWhere<T> or(And<T> conditions) {\r
-               orOpen();\r
-               query.addConditionToken(conditions.where.query);\r
-               return close();\r
-       }\r
-\r
-       public QueryWhere<T> or(Or<T> conditions) {\r
-               orOpen();\r
-               query.addConditionToken(conditions.where.query);\r
-               return close();\r
-       }\r
-\r
-       public QueryWhere<T> orOpen() {\r
-               return open(ConditionAndOr.OR);\r
-       }\r
-\r
-       private QueryWhere<T> open(ConditionAndOr andOr) {\r
-               query.addConditionToken(andOr);\r
-               query.addConditionToken(ConditionOpenClose.OPEN);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> close() {\r
-               query.addConditionToken(ConditionOpenClose.CLOSE);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> limit(long limit) {\r
-               query.limit(limit);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> offset(long offset) {\r
-               query.offset(offset);\r
-               return this;\r
-       }\r
-\r
-       public String getSQL() {\r
-               SQLStatement stat = new SQLStatement(query.getDb());\r
-               stat.appendSQL("SELECT *");\r
-               query.appendFromWhere(stat);\r
-               return stat.getSQL().trim();\r
-       }\r
-\r
-       /**\r
-        * toSQL returns a static string version of the query with runtime variables\r
-        * properly encoded. This method is also useful when combined with the where\r
-        * clause methods like isParameter() or atLeastParameter() which allows\r
-        * iciql to generate re-usable parameterized string statements.\r
-        *\r
-        * @return the sql query as plain text\r
-        */\r
-       public String toSQL() {\r
-               return query.toSQL(false);\r
-       }\r
-\r
-       /**\r
-        * toSQL returns a static string version of the query with runtime variables\r
-        * properly encoded. This method is also useful when combined with the where\r
-        * clause methods like isParameter() or atLeastParameter() which allows\r
-        * iciql to generate re-usable parameterized string statements.\r
-        *\r
-        * @param distinct\r
-        *            if true SELECT DISTINCT is used for the query\r
-        * @return the sql query as plain text\r
-        */\r
-       public String toSQL(boolean distinct) {\r
-               return query.toSQL(distinct);\r
-       }\r
-\r
-       /**\r
-        * toSQL returns a static string version of the query with runtime variables\r
-        * properly encoded. This method is also useful when combined with the where\r
-        * clause methods like isParameter() or atLeastParameter() which allows\r
-        * iciql to generate re-usable parameterized string statements.\r
-        *\r
-        * @param distinct\r
-        *            if true SELECT DISTINCT is used for the query\r
-        * @param k\r
-        *            k is used to select only the columns of the specified alias\r
-        *            for an inner join statement. An example of a generated\r
-        *            statement is: SELECT DISTINCT t1.* FROM sometable AS t1 INNER\r
-        *            JOIN othertable AS t2 ON t1.id = t2.id WHERE t2.flag = true\r
-        *            without the alias parameter the statement would start with\r
-        *            SELECT DISTINCT * FROM...\r
-        * @return the sql query as plain text\r
-        */\r
-       public <K> String toSQL(boolean distinct, K k) {\r
-               return query.toSQL(distinct, k);\r
-       }\r
-\r
-       public <Z> SubQuery<T, Z> subQuery(Z x) {\r
-               return new SubQuery<T, Z>(query, x);\r
-       }\r
-\r
-       public SubQuery<T, Boolean> subQuery(boolean x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Byte> subQuery(byte x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Short> subQuery(short x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Integer> subQuery(int x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Long> subQuery(long x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Float> subQuery(float x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public SubQuery<T, Double> subQuery(double x) {\r
-               return subQuery(query.getPrimitiveAliasByValue(x));\r
-       }\r
-\r
-       public <X, Z> List<X> select(Z x) {\r
-               return query.select(x);\r
-       }\r
-\r
-       public <X, Z> List<X> selectDistinct(Z x) {\r
-               return query.selectDistinct(x);\r
-       }\r
-\r
-       public <X, Z> X selectFirst(Z x) {\r
-               List<X> list = query.select(x);\r
-               return list.isEmpty() ? null : list.get(0);\r
-       }\r
-\r
-       public List<T> select() {\r
-               return query.select();\r
-       }\r
-\r
-       public T selectFirst() {\r
-               List<T> list = select();\r
-               return list.isEmpty() ? null : list.get(0);\r
-       }\r
-\r
-       public List<T> selectDistinct() {\r
-               return query.selectDistinct();\r
-       }\r
-\r
-       public void createView(Class<?> viewClass) {\r
-               query.createView(viewClass);\r
-       }\r
-\r
-       public void replaceView(Class<?> viewClass) {\r
-               query.replaceView(viewClass);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive boolean field\r
-        *\r
-        * @param field\r
-        *            a primitive boolean field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(boolean field) {\r
-               query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive byte field\r
-        *\r
-        * @param field\r
-        *            a primitive byte field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(byte field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive short field\r
-        *\r
-        * @param field\r
-        *            a primitive short field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(short field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       public QueryWhere<T> orderBy(int field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive long field\r
-        *\r
-        * @param field\r
-        *            a primitive long field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(long field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive float field\r
-        *\r
-        * @param field\r
-        *            a primitive float field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(float field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Order by primitive double field\r
-        *\r
-        * @param field\r
-        *            a primitive double field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> orderBy(double field) {\r
-               return orderByPrimitive(field);\r
-       }\r
-\r
-       private QueryWhere<T> orderByPrimitive(Object field) {\r
-               query.orderByPrimitive(field);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderBy(Object field) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(field);\r
-               query.orderBy(field);\r
-               return this;\r
-       }\r
-\r
-       /**\r
-        * Order by a number of Object columns.\r
-        *\r
-        * @param expressions\r
-        *            the order by expressions\r
-        * @return the query\r
-        */\r
-\r
-       public QueryWhere<T> orderBy(Object... expressions) {\r
-               query.orderBy(expressions);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderByNullsFirst(Object expr) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
-               OrderExpression<T> e = new OrderExpression<T>(query, expr, false, true, false);\r
-               query.addOrderBy(e);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderByNullsLast(Object expr) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
-               OrderExpression<T> e = new OrderExpression<T>(query, expr, false, false, true);\r
-               query.addOrderBy(e);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderByDesc(Object expr) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
-               OrderExpression<T> e = new OrderExpression<T>(query, expr, true, false, false);\r
-               query.addOrderBy(e);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderByDescNullsFirst(Object expr) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
-               OrderExpression<T> e = new OrderExpression<T>(query, expr, true, true, false);\r
-               query.addOrderBy(e);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> orderByDescNullsLast(Object expr) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
-               OrderExpression<T> e = new OrderExpression<T>(query, expr, true, false, true);\r
-               query.addOrderBy(e);\r
-               return this;\r
-       }\r
-\r
-       /**\r
-        * Group by primitive boolean field\r
-        *\r
-        * @param field\r
-        *            a primitive boolean field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(boolean field) {\r
-               query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Group by primitive byte field\r
-        *\r
-        * @param field\r
-        *            a primitive byte field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(byte field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Group by primitive short field\r
-        *\r
-        * @param field\r
-        *            a primitive short field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(short field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       public QueryWhere<T> groupBy(int field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Group by primitive long field\r
-        *\r
-        * @param field\r
-        *            a primitive long field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(long field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Group by primitive float field\r
-        *\r
-        * @param field\r
-        *            a primitive float field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(float field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       /**\r
-        * Group by primitive double field\r
-        *\r
-        * @param field\r
-        *            a primitive double field\r
-        * @return the query\r
-        */\r
-       public QueryWhere<T> groupBy(double field) {\r
-               return groupByPrimitive(field);\r
-       }\r
-\r
-       private QueryWhere<T> groupByPrimitive(Object field) {\r
-               query.groupByPrimitive(field);\r
-               return this;\r
-       }\r
-\r
-       public QueryWhere<T> groupBy(Object field) {\r
-               query.getFrom().getAliasDefinition().checkMultipleEnums(field);\r
-               query.groupBy(field);\r
-               return this;\r
-       }\r
-\r
-       /**\r
-        * Group by a number of Object columns.\r
-        *\r
-        * @param expressions\r
-        *            the group by expressions\r
-        * @return the query\r
-        */\r
-\r
-       public QueryWhere<T> groupBy(Object... expressions) {\r
-               query.groupBy(expressions);\r
-               return this;\r
-       }\r
-\r
-       public int delete() {\r
-               return query.delete();\r
-       }\r
-\r
-       public int update() {\r
-               return query.update();\r
-       }\r
-\r
-       public long selectCount() {\r
-               return query.selectCount();\r
-       }\r
+    Query<T> query;\r
+\r
+    QueryWhere(Query<T> query) {\r
+        this.query = query;\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive boolean.\r
+     *\r
+     * @param x the primitive boolean field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Boolean> and(boolean x) {\r
+        query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive byte.\r
+     *\r
+     * @param x the primitive byte field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Byte> and(byte x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive short.\r
+     *\r
+     * @param x the primitive short field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Short> and(short x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive int.\r
+     *\r
+     * @param x the primitive int field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Integer> and(int x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive long.\r
+     *\r
+     * @param x the primitive long field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Long> and(long x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive float.\r
+     *\r
+     * @param x the primitive float field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Float> and(float x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped primitive double.\r
+     *\r
+     * @param x the primitive double field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Double> and(double x) {\r
+        return addPrimitive(ConditionAndOr.AND, x);\r
+    }\r
+\r
+    private <A> QueryCondition<T, A> addPrimitive(ConditionAndOr condition, A x) {\r
+        query.addConditionToken(condition);\r
+        A alias = query.getPrimitiveAliasByValue(x);\r
+        if (alias == null) {\r
+            // this will result in an unmapped field exception\r
+            return new QueryCondition<T, A>(query, x);\r
+        }\r
+        return new QueryCondition<T, A>(query, alias);\r
+    }\r
+\r
+    /**\r
+     * Specify an AND condition with a mapped Object field.\r
+     *\r
+     * @param x the Object field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public <A> QueryCondition<T, A> and(A x) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(x);\r
+        query.addConditionToken(ConditionAndOr.AND);\r
+        return new QueryCondition<T, A>(query, x);\r
+    }\r
+\r
+    public QueryWhere<T> and(And<T> conditions) {\r
+        andOpen();\r
+        query.addConditionToken(conditions.where.query);\r
+        return close();\r
+    }\r
+\r
+    public QueryWhere<T> and(Or<T> conditions) {\r
+        andOpen();\r
+        query.addConditionToken(conditions.where.query);\r
+        return close();\r
+    }\r
+\r
+    public QueryWhere<T> andOpen() {\r
+        return open(ConditionAndOr.AND);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive boolean.\r
+     *\r
+     * @param x the primitive boolean field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Boolean> or(boolean x) {\r
+        query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive byte.\r
+     *\r
+     * @param x the primitive byte field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Byte> or(byte x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive short.\r
+     *\r
+     * @param x the primitive short field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Short> or(short x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive int.\r
+     *\r
+     * @param x the primitive int field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Integer> or(int x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive long.\r
+     *\r
+     * @param x the primitive long field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Long> or(long x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive float.\r
+     *\r
+     * @param x the primitive float field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Float> or(float x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped primitive double.\r
+     *\r
+     * @param x the primitive double field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public QueryCondition<T, Double> or(double x) {\r
+        return addPrimitive(ConditionAndOr.OR, x);\r
+    }\r
+\r
+    /**\r
+     * Specify an OR condition with a mapped Object field.\r
+     *\r
+     * @param x the Object field to query\r
+     * @return a query condition to continue building the condition\r
+     */\r
+    public <A> QueryCondition<T, A> or(A x) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(x);\r
+        query.addConditionToken(ConditionAndOr.OR);\r
+        return new QueryCondition<T, A>(query, x);\r
+    }\r
+\r
+    public QueryWhere<T> or(And<T> conditions) {\r
+        orOpen();\r
+        query.addConditionToken(conditions.where.query);\r
+        return close();\r
+    }\r
+\r
+    public QueryWhere<T> or(Or<T> conditions) {\r
+        orOpen();\r
+        query.addConditionToken(conditions.where.query);\r
+        return close();\r
+    }\r
+\r
+    public QueryWhere<T> orOpen() {\r
+        return open(ConditionAndOr.OR);\r
+    }\r
+\r
+    private QueryWhere<T> open(ConditionAndOr andOr) {\r
+        query.addConditionToken(andOr);\r
+        query.addConditionToken(ConditionOpenClose.OPEN);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> close() {\r
+        query.addConditionToken(ConditionOpenClose.CLOSE);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> limit(long limit) {\r
+        query.limit(limit);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> offset(long offset) {\r
+        query.offset(offset);\r
+        return this;\r
+    }\r
+\r
+    public String getSQL() {\r
+        SQLStatement stat = new SQLStatement(query.getDb());\r
+        stat.appendSQL("SELECT *");\r
+        query.appendFromWhere(stat);\r
+        return stat.getSQL().trim();\r
+    }\r
+\r
+    /**\r
+     * toSQL returns a static string version of the query with runtime variables\r
+     * properly encoded. This method is also useful when combined with the where\r
+     * clause methods like isParameter() or atLeastParameter() which allows\r
+     * iciql to generate re-usable parameterized string statements.\r
+     *\r
+     * @return the sql query as plain text\r
+     */\r
+    public String toSQL() {\r
+        return query.toSQL(false);\r
+    }\r
+\r
+    /**\r
+     * toSQL returns a static string version of the query with runtime variables\r
+     * properly encoded. This method is also useful when combined with the where\r
+     * clause methods like isParameter() or atLeastParameter() which allows\r
+     * iciql to generate re-usable parameterized string statements.\r
+     *\r
+     * @param distinct if true SELECT DISTINCT is used for the query\r
+     * @return the sql query as plain text\r
+     */\r
+    public String toSQL(boolean distinct) {\r
+        return query.toSQL(distinct);\r
+    }\r
+\r
+    /**\r
+     * toSQL returns a static string version of the query with runtime variables\r
+     * properly encoded. This method is also useful when combined with the where\r
+     * clause methods like isParameter() or atLeastParameter() which allows\r
+     * iciql to generate re-usable parameterized string statements.\r
+     *\r
+     * @param distinct if true SELECT DISTINCT is used for the query\r
+     * @param k        k is used to select only the columns of the specified alias\r
+     *                 for an inner join statement. An example of a generated\r
+     *                 statement is: SELECT DISTINCT t1.* FROM sometable AS t1 INNER\r
+     *                 JOIN othertable AS t2 ON t1.id = t2.id WHERE t2.flag = true\r
+     *                 without the alias parameter the statement would start with\r
+     *                 SELECT DISTINCT * FROM...\r
+     * @return the sql query as plain text\r
+     */\r
+    public <K> String toSQL(boolean distinct, K k) {\r
+        return query.toSQL(distinct, k);\r
+    }\r
+\r
+    public <Z> SubQuery<T, Z> subQuery(Z x) {\r
+        return new SubQuery<T, Z>(query, x);\r
+    }\r
+\r
+    public SubQuery<T, Boolean> subQuery(boolean x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Byte> subQuery(byte x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Short> subQuery(short x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Integer> subQuery(int x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Long> subQuery(long x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Float> subQuery(float x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public SubQuery<T, Double> subQuery(double x) {\r
+        return subQuery(query.getPrimitiveAliasByValue(x));\r
+    }\r
+\r
+    public <X, Z> List<X> select(Z x) {\r
+        return query.select(x);\r
+    }\r
+\r
+    public <X, Z> List<X> selectDistinct(Z x) {\r
+        return query.selectDistinct(x);\r
+    }\r
+\r
+    public <X, Z> X selectFirst(Z x) {\r
+        List<X> list = query.select(x);\r
+        return list.isEmpty() ? null : list.get(0);\r
+    }\r
+\r
+    public List<T> select() {\r
+        return query.select();\r
+    }\r
+\r
+    public T selectFirst() {\r
+        List<T> list = select();\r
+        return list.isEmpty() ? null : list.get(0);\r
+    }\r
+\r
+    public List<T> selectDistinct() {\r
+        return query.selectDistinct();\r
+    }\r
+\r
+    public void createView(Class<?> viewClass) {\r
+        query.createView(viewClass);\r
+    }\r
+\r
+    public void replaceView(Class<?> viewClass) {\r
+        query.replaceView(viewClass);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive boolean field\r
+     *\r
+     * @param field a primitive boolean field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(boolean field) {\r
+        query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive byte field\r
+     *\r
+     * @param field a primitive byte field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(byte field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive short field\r
+     *\r
+     * @param field a primitive short field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(short field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    public QueryWhere<T> orderBy(int field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive long field\r
+     *\r
+     * @param field a primitive long field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(long field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive float field\r
+     *\r
+     * @param field a primitive float field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(float field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Order by primitive double field\r
+     *\r
+     * @param field a primitive double field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> orderBy(double field) {\r
+        return orderByPrimitive(field);\r
+    }\r
+\r
+    private QueryWhere<T> orderByPrimitive(Object field) {\r
+        query.orderByPrimitive(field);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderBy(Object field) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(field);\r
+        query.orderBy(field);\r
+        return this;\r
+    }\r
+\r
+    /**\r
+     * Order by a number of Object columns.\r
+     *\r
+     * @param expressions the order by expressions\r
+     * @return the query\r
+     */\r
+\r
+    public QueryWhere<T> orderBy(Object... expressions) {\r
+        query.orderBy(expressions);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderByNullsFirst(Object expr) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
+        OrderExpression<T> e = new OrderExpression<T>(query, expr, false, true, false);\r
+        query.addOrderBy(e);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderByNullsLast(Object expr) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
+        OrderExpression<T> e = new OrderExpression<T>(query, expr, false, false, true);\r
+        query.addOrderBy(e);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderByDesc(Object expr) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
+        OrderExpression<T> e = new OrderExpression<T>(query, expr, true, false, false);\r
+        query.addOrderBy(e);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderByDescNullsFirst(Object expr) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
+        OrderExpression<T> e = new OrderExpression<T>(query, expr, true, true, false);\r
+        query.addOrderBy(e);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> orderByDescNullsLast(Object expr) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(expr);\r
+        OrderExpression<T> e = new OrderExpression<T>(query, expr, true, false, true);\r
+        query.addOrderBy(e);\r
+        return this;\r
+    }\r
+\r
+    /**\r
+     * Group by primitive boolean field\r
+     *\r
+     * @param field a primitive boolean field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(boolean field) {\r
+        query.getFrom().getAliasDefinition().checkMultipleBooleans();\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Group by primitive byte field\r
+     *\r
+     * @param field a primitive byte field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(byte field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Group by primitive short field\r
+     *\r
+     * @param field a primitive short field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(short field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    public QueryWhere<T> groupBy(int field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Group by primitive long field\r
+     *\r
+     * @param field a primitive long field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(long field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Group by primitive float field\r
+     *\r
+     * @param field a primitive float field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(float field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    /**\r
+     * Group by primitive double field\r
+     *\r
+     * @param field a primitive double field\r
+     * @return the query\r
+     */\r
+    public QueryWhere<T> groupBy(double field) {\r
+        return groupByPrimitive(field);\r
+    }\r
+\r
+    private QueryWhere<T> groupByPrimitive(Object field) {\r
+        query.groupByPrimitive(field);\r
+        return this;\r
+    }\r
+\r
+    public QueryWhere<T> groupBy(Object field) {\r
+        query.getFrom().getAliasDefinition().checkMultipleEnums(field);\r
+        query.groupBy(field);\r
+        return this;\r
+    }\r
+\r
+    /**\r
+     * Group by a number of Object columns.\r
+     *\r
+     * @param expressions the group by expressions\r
+     * @return the query\r
+     */\r
+\r
+    public QueryWhere<T> groupBy(Object... expressions) {\r
+        query.groupBy(expressions);\r
+        return this;\r
+    }\r
+\r
+    public int delete() {\r
+        return query.delete();\r
+    }\r
+\r
+    public int update() {\r
+        return query.update();\r
+    }\r
+\r
+    public long selectCount() {\r
+        return query.selectCount();\r
+    }\r
 \r
 }\r
index 0fbedba0f2efc5aa50cdf179c8e5e2098f21a8c7..f60007eddcfe8e078d4a20c8b08e064d99f4b48d 100644 (file)
@@ -20,30 +20,29 @@ package com.iciql;
  * A runtime parameter is used to generate x=? conditions so that iciql can\r
  * build re-usable dynamic queries with parameter substitution done manually at\r
  * runtime.\r
- * \r
- * @param <A>\r
- *            the operand type\r
+ *\r
+ * @param <A> the operand type\r
  */\r
 \r
 class RuntimeParameter<A> implements Token {\r
-       \r
-       public final static String PARAMETER = "";\r
-       \r
-       A x;\r
-       CompareType compareType;\r
 \r
-       RuntimeParameter(A x, CompareType type) {\r
-               this.x = x;\r
-               this.compareType = type;\r
-       }\r
+    public final static String PARAMETER = "";\r
+\r
+    A x;\r
+    CompareType compareType;\r
+\r
+    RuntimeParameter(A x, CompareType type) {\r
+        this.x = x;\r
+        this.compareType = type;\r
+    }\r
 \r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               query.appendSQL(stat, null, x);\r
-               stat.appendSQL(" ");\r
-               stat.appendSQL(compareType.getString());\r
-               if (compareType.hasRightExpression()) {\r
-                       stat.appendSQL(" ");\r
-                       query.appendSQL(stat, x, PARAMETER);\r
-               }\r
-       }\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        query.appendSQL(stat, null, x);\r
+        stat.appendSQL(" ");\r
+        stat.appendSQL(compareType.getString());\r
+        if (compareType.hasRightExpression()) {\r
+            stat.appendSQL(" ");\r
+            query.appendSQL(stat, x, PARAMETER);\r
+        }\r
+    }\r
 }\r
index cbfd882efd7a23a6ad7533821d20a39e2c03ca91..cc747a4c8a97bd54b2e33bb13883f8eecdd700de 100644 (file)
  */\r
 package com.iciql;\r
 \r
-import java.text.MessageFormat;\r
-\r
 import com.iciql.util.StringUtils;\r
 \r
+import java.text.MessageFormat;\r
+\r
 /**\r
  * Represents a traditional PreparedStatment fragment like "id=?, name=?".\r
- * \r
  */\r
 public class RuntimeToken implements Token {\r
 \r
-       final String fragment;\r
-       final Object[] args;\r
+    final String fragment;\r
+    final Object[] args;\r
 \r
-       public RuntimeToken(String fragment, Object... args) {\r
-               this.fragment = fragment;\r
-               this.args = args == null ? new Object[0] : args;\r
-       }\r
+    public RuntimeToken(String fragment, Object... args) {\r
+        this.fragment = fragment;\r
+        this.args = args == null ? new Object[0] : args;\r
+    }\r
 \r
-       /**\r
-        * Append the SQL to the given statement using the given query.\r
-        * \r
-        * @param stat\r
-        *            the statement to append the SQL to\r
-        * @param query\r
-        *            the query to use\r
-        */\r
-       @Override\r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               int tokenCount = StringUtils.count('?', fragment);\r
-               if (tokenCount != args.length) {\r
-                       throw new IciqlException(MessageFormat.format(\r
-                                       "Fragment \"{0}\" specifies {1} tokens but you supplied {2} args", fragment, tokenCount,\r
-                                       args.length));\r
-               }\r
-               stat.appendSQL(fragment);\r
-               for (Object arg : args) {\r
-                       stat.addParameter(arg);\r
-               }\r
-       }\r
+    /**\r
+     * Append the SQL to the given statement using the given query.\r
+     *\r
+     * @param stat  the statement to append the SQL to\r
+     * @param query the query to use\r
+     */\r
+    @Override\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        int tokenCount = StringUtils.count('?', fragment);\r
+        if (tokenCount != args.length) {\r
+            throw new IciqlException(MessageFormat.format(\r
+                    "Fragment \"{0}\" specifies {1} tokens but you supplied {2} args", fragment, tokenCount,\r
+                    args.length));\r
+        }\r
+        stat.appendSQL(fragment);\r
+        for (Object arg : args) {\r
+            stat.addParameter(arg);\r
+        }\r
+    }\r
 }\r
index 8e6361a2bb908be89a47ed1945cdd87ccfe2cc0b..1cb4931d9781f93f1dbbefe73a0f921b617e3909 100644 (file)
 
 package com.iciql;
 
-import java.sql.ResultSet;
-
 import com.iciql.Iciql.DataTypeAdapter;
 import com.iciql.TableDefinition.IndexDefinition;
 
+import java.sql.ResultSet;
+
 /**
  * This interface defines points where iciql can build different statements
  * depending on the database used.
  */
 public interface SQLDialect {
 
-       /**
-        * Registers the type adapter instance.
-        *
-        * @param typeAdapter
-        */
-       void registerAdapter(DataTypeAdapter<?> typeAdapter);
-
-       /**
-        * Returns the registered instance of the type adapter.
-        *
-        * @param typeAdapter
-        * @return the type adapter instance
-        */
-       DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter);
-
-       /**
-        * Serialize the Java object into a type or format that the database will accept.
-        *
-        * @param value
-        * @param typeAdapter
-        * @return the serialized object
-        */
-       <T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter);
-
-       /**
-        * Deserialize the object received from the database into a Java type.
-        *
-        * @param rs
-        * @param columnIndex
-        * @param targetType
-        * @param typeAdapter
-        * @return the deserialized object
-        */
-       Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter);
-
-       /**
-        * Configure the dialect.
-        *
-        * @param db
-        */
-       void configureDialect(Db db);
-
-       /**
-        * Returns true if savepoints are supported.
-        *
-        * @return true if savepoints may be used.
-        */
-       boolean supportsSavePoints();
-
-       /**
-        * 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
-        *            the schema name, or null for no schema
-        * @param tableName
-        *            the properly formatted table name
-        * @return the SQL snippet
-        */
-       String prepareTableName(String schemaName, String tableName);
-
-       /**
-        * Returns a properly formatted column name for the dialect.
-        *
-        * @param name
-        *            the column name
-        * @return the properly formatted column name
-        */
-       String prepareColumnName(String name);
-
-       /**
-        * Get the CREATE TABLE statement.
-        *
-        * @param stat
-        * @param def
-        */
-       <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 VIEW statement.
-        *
-        * @param stat
-        *            return the SQL statement
-        * @param def
-        *            table definition
-        */
-       <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def);
-
-       /**
-        * Get the CREATE VIEW statement.
-        *
-        * @param stat
-        *            return the SQL statement
-        * @param def
-        *            table definition
-        * @param fromWhere
-        */
-       <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def, String fromWhere);
-
-       /**
-        * Get the DROP VIEW statement.
-        *
-        * @param stat
-        *            return the SQL statement
-        * @param def
-        *            table definition
-        */
-       <T> void prepareDropView(SQLStatement stat, TableDefinition<T> def);
-
-       /**
-        * Get the CREATE INDEX statement.
-        *
-        * @param stat
-        *            return the SQL statement
-        * @param schemaName
-        *            the schema name
-        * @param tableName
-        *            the table name
-        * @param index
-        *            the index definition
-        */
-       void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName, IndexDefinition index);
-
-       /**
-        * Get a MERGE or REPLACE INTO statement.
-        *
-        * @param stat
-        *            return the SQL statement
-        * @param schemaName
-        *            the schema name
-        * @param tableName
-        *            the table name
-        * @param def
-        *            the table definition
-        * @param obj
-        *            values
-        */
-       <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName, TableDefinition<T> def,
-                       Object obj);
-
-       /**
-        * Append "LIMIT limit OFFSET offset" to the SQL statement.
-        *
-        * @param stat
-        *            the statement
-        * @param limit
-        *            the limit
-        * @param offset
-        *            the offset
-        */
-       void appendLimitOffset(SQLStatement stat, long limit, long offset);
-
-       /**
-        * Returns the preferred DATETIME class for the database.
-        * <p>
-        * Either java.util.Date or java.sql.Timestamp
-        *
-        * @return preferred DATETIME class
-        */
-       Class<? extends java.util.Date> getDateTimeClass();
-
-       /**
-        * When building static string statements this method flattens an object to
-        * a string representation suitable for a static string statement.
-        *
-        * @param o
-        * @return the string equivalent of this object
-        */
-       String prepareStringParameter(Object o);
-
-       /**
-        * Returns the name of a formatted column identifier for the dialect.
-        *
-        * @param name
-        *            the column name
-        * @return the column name without formatting syntax
-        */
-       String extractColumnName(String name);
+    /**
+     * Registers the type adapter instance.
+     *
+     * @param typeAdapter
+     */
+    void registerAdapter(DataTypeAdapter<?> typeAdapter);
+
+    /**
+     * Returns the registered instance of the type adapter.
+     *
+     * @param typeAdapter
+     * @return the type adapter instance
+     */
+    DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter);
+
+    /**
+     * Serialize the Java object into a type or format that the database will accept.
+     *
+     * @param value
+     * @param typeAdapter
+     * @return the serialized object
+     */
+    <T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter);
+
+    /**
+     * Deserialize the object received from the database into a Java type.
+     *
+     * @param rs
+     * @param columnIndex
+     * @param targetType
+     * @param typeAdapter
+     * @return the deserialized object
+     */
+    Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter);
+
+    /**
+     * Configure the dialect.
+     *
+     * @param db
+     */
+    void configureDialect(Db db);
+
+    /**
+     * Returns true if savepoints are supported.
+     *
+     * @return true if savepoints may be used.
+     */
+    boolean supportsSavePoints();
+
+    /**
+     * 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 the schema name, or null for no schema
+     * @param tableName  the properly formatted table name
+     * @return the SQL snippet
+     */
+    String prepareTableName(String schemaName, String tableName);
+
+    /**
+     * Returns a properly formatted column name for the dialect.
+     *
+     * @param name the column name
+     * @return the properly formatted column name
+     */
+    String prepareColumnName(String name);
+
+    /**
+     * Get the CREATE TABLE statement.
+     *
+     * @param stat
+     * @param def
+     */
+    <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 VIEW statement.
+     *
+     * @param stat return the SQL statement
+     * @param def  table definition
+     */
+    <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def);
+
+    /**
+     * Get the CREATE VIEW statement.
+     *
+     * @param stat      return the SQL statement
+     * @param def       table definition
+     * @param fromWhere
+     */
+    <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def, String fromWhere);
+
+    /**
+     * Get the DROP VIEW statement.
+     *
+     * @param stat return the SQL statement
+     * @param def  table definition
+     */
+    <T> void prepareDropView(SQLStatement stat, TableDefinition<T> def);
+
+    /**
+     * Get the CREATE INDEX statement.
+     *
+     * @param stat       return the SQL statement
+     * @param schemaName the schema name
+     * @param tableName  the table name
+     * @param index      the index definition
+     */
+    void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName, IndexDefinition index);
+
+    /**
+     * Get a MERGE or REPLACE INTO statement.
+     *
+     * @param stat       return the SQL statement
+     * @param schemaName the schema name
+     * @param tableName  the table name
+     * @param def        the table definition
+     * @param obj        values
+     */
+    <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName, TableDefinition<T> def,
+                          Object obj);
+
+    /**
+     * Append "LIMIT limit OFFSET offset" to the SQL statement.
+     *
+     * @param stat   the statement
+     * @param limit  the limit
+     * @param offset the offset
+     */
+    void appendLimitOffset(SQLStatement stat, long limit, long offset);
+
+    /**
+     * Returns the preferred DATETIME class for the database.
+     * <p>
+     * Either java.util.Date or java.sql.Timestamp
+     *
+     * @return preferred DATETIME class
+     */
+    Class<? extends java.util.Date> getDateTimeClass();
+
+    /**
+     * When building static string statements this method flattens an object to
+     * a string representation suitable for a static string statement.
+     *
+     * @param o
+     * @return the string equivalent of this object
+     */
+    String prepareStringParameter(Object o);
+
+    /**
+     * Returns the name of a formatted column identifier for the dialect.
+     *
+     * @param name the column name
+     * @return the column name without formatting syntax
+     */
+    String extractColumnName(String name);
 
 }
index ec3f605ba6f6da6a85a17153c1a79409ff9f0308..4f635a9965df28a5a5617b9a70dbb8a9807b48ba 100644 (file)
 
 package com.iciql;
 
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
 import com.iciql.Iciql.ConstraintDeleteType;
 import com.iciql.Iciql.ConstraintUpdateType;
 import com.iciql.Iciql.DataTypeAdapter;
@@ -42,491 +31,502 @@ import com.iciql.util.StatementBuilder;
 import com.iciql.util.StringUtils;
 import com.iciql.util.Utils;
 
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * Default implementation of an SQL dialect.
  */
 public class SQLDialectDefault implements SQLDialect {
 
-       final String LITERAL = "'";
-
-       protected float databaseVersion;
-       protected int databaseMajorVersion;
-       protected int databaseMinorVersion;
-       protected String databaseName;
-       protected String productVersion;
-       protected Mode mode;
-       protected Map<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>> typeAdapters;
-
-       public SQLDialectDefault() {
-               typeAdapters = new ConcurrentHashMap<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>>();
-       }
-
-       @Override
-       public String toString() {
-               return getClass().getName() + ": " + databaseName + " " + productVersion;
-       }
-
-       @Override
-       public void configureDialect(Db db) {
-               Connection conn = db.getConnection();
-               DatabaseMetaData data = null;
-               try {
-                       data = conn.getMetaData();
-                       databaseName = data.getDatabaseProductName();
-                       databaseMajorVersion = data.getDatabaseMajorVersion();
-                       databaseMinorVersion = data.getDatabaseMinorVersion();
-                       databaseVersion = Float.parseFloat(databaseMajorVersion + "."
-                                       + databaseMinorVersion);
-                       productVersion = data.getDatabaseProductVersion();
-               } catch (SQLException e) {
-                       throw new IciqlException(e, "failed to retrieve database metadata!");
-               }
-
-               mode = db.getMode();
-       }
-
-       @Override
-       public boolean supportsSavePoints() {
-               return true;
-       }
-
-       /**
-        * Allows subclasses to change the type of a column for a CREATE statement.
-        *
-        * @param sqlType
-        * @return the SQL type or a preferred alternative
-        */
-       @Override
-       public String convertSqlType(String sqlType) {
-               return sqlType;
-       }
-
-       @Override
-       public Class<? extends java.util.Date> getDateTimeClass() {
-               return java.util.Date.class;
-       }
-
-       @Override
-       public String prepareTableName(String schemaName, String tableName) {
-               if (StringUtils.isNullOrEmpty(schemaName)) {
-                       return tableName;
-               }
-               return schemaName + "." + tableName;
-       }
-
-       @Override
-       public String prepareColumnName(String name) {
-               return name;
-       }
-
-       @Override
-       public String extractColumnName(String name) {
-               return name.replace('\"', ' ').replace('\'', ' ').trim();
-       }
-
-       @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;
-       }
-
-       protected <T> String prepareCreateTable(TableDefinition<T> def) {
-               return "CREATE TABLE";
-       }
-
-       @Override
-       public <T> void prepareCreateTable(SQLStatement stat, TableDefinition<T> def) {
-               StatementBuilder buff = new StatementBuilder();
-               buff.append(prepareCreateTable(def));
-               buff.append(" ");
-               buff.append(prepareTableName(def.schemaName, def.tableName)).append('(');
-
-               boolean hasIdentityColumn = false;
-               for (FieldDefinition field : def.fields) {
-                       buff.appendExceptFirst(", ");
-                       buff.append(prepareColumnName(field.columnName)).append(' ');
-                       String dataType = field.dataType;
-                       if (dataType.equals("VARCHAR")) {
-                               // check to see if we should use VARCHAR or CLOB
-                               if (field.length <= 0) {
-                                       dataType = "CLOB";
-                               }
-                               buff.append(convertSqlType(dataType));
-                               if (field.length > 0) {
-                                       buff.append('(').append(field.length).append(')');
-                               }
-                       } else if (dataType.equals("DECIMAL")) {
-                               // DECIMAL(precision,scale)
-                               buff.append(convertSqlType(dataType));
-                               if (field.length > 0) {
-                                       buff.append('(').append(field.length);
-                                       if (field.scale > 0) {
-                                               buff.append(',').append(field.scale);
-                                       }
-                                       buff.append(')');
-                               }
-                       } else {
-                               // other
-                               hasIdentityColumn |= prepareColumnDefinition(buff, convertSqlType(dataType),
-                                               field.isAutoIncrement, field.isPrimaryKey);
-                       }
-
-                       // default values
-                       if (!field.isAutoIncrement && !field.isPrimaryKey) {
-                               String dv = field.defaultValue;
-                               if (!StringUtils.isNullOrEmpty(dv)) {
-                                       if (ModelUtils.isProperlyFormattedDefaultValue(dv)
-                                                       && ModelUtils.isValidDefaultValue(field.field.getType(), dv)) {
-                                               buff.append(" DEFAULT " + dv);
-                                       }
-                               }
-                       }
-
-                       if (!field.nullable) {
-                               buff.append(" NOT NULL");
-                       }
-               }
-
-               // if table does not have identity column then specify primary key
-               if (!hasIdentityColumn) {
-                       if (def.primaryKeyColumnNames != null && def.primaryKeyColumnNames.size() > 0) {
-                               buff.append(", PRIMARY KEY(");
-                               buff.resetCount();
-                               for (String n : def.primaryKeyColumnNames) {
-                                       buff.appendExceptFirst(", ");
-                                       buff.append(prepareColumnName(n));
-                               }
-                               buff.append(')');
-                       }
-               }
-
-               // create unique constraints
-               if (def.constraintsUnique.size() > 0) {
-                       buff.append(", ");
-                       buff.resetCount();
-                       for (ConstraintUniqueDefinition constraint : def.constraintsUnique) {
-                               buff.append("CONSTRAINT ");
-                               buff.append(constraint.constraintName);
-                               buff.append(" UNIQUE ");
-                               buff.append(" (");
-                               for (String col : constraint.uniqueColumns) {
-                                       buff.appendExceptFirst(", ");
-                                       buff.append(prepareColumnName(col));
-                               }
-                               buff.append(") ");
-                       }
-               }
-
-               // create foreign key constraints
-               if (def.constraintsForeignKey.size() > 0) {
-                       buff.append(", ");
-                       buff.resetCount();
-                       for (ConstraintForeignKeyDefinition constraint : def.constraintsForeignKey) {
-                               buff.appendExceptFirst(", ");
-                               buff.append(String.format("CONSTRAINT %s FOREIGN KEY(%s) REFERENCES %s(%s)",
-                                               constraint.constraintName,
-                                               constraint.foreignColumns.get(0),
-                                               constraint.referenceTable,
-                                               constraint.referenceColumns.get(0)));
-
-                               if (constraint.deleteType != ConstraintDeleteType.UNSET) {
-                                       buff.append(" ON DELETE ");
-                                       switch (constraint.deleteType) {
-                                       case CASCADE:
-                                               buff.append("CASCADE ");
-                                               break;
-                                       case RESTRICT:
-                                               buff.append("RESTRICT ");
-                                               break;
-                                       case SET_NULL:
-                                               buff.append("SET NULL ");
-                                               break;
-                                       case NO_ACTION:
-                                               buff.append("NO ACTION ");
-                                               break;
-                                       case SET_DEFAULT:
-                                               buff.append("SET DEFAULT ");
-                                               break;
-                                       }
-                               }
-                               if (constraint.updateType != ConstraintUpdateType.UNSET) {
-                                       buff.append(" ON UPDATE ");
-                                       switch (constraint.updateType) {
-                                       case CASCADE:
-                                               buff.append("CASCADE ");
-                                               break;
-                                       case RESTRICT:
-                                               buff.append("RESTRICT ");
-                                               break;
-                                       case SET_NULL:
-                                               buff.append("SET NULL ");
-                                               break;
-                                       case NO_ACTION:
-                                               buff.append("NO ACTION ");
-                                               break;
-                                       case SET_DEFAULT:
-                                               buff.append("SET DEFAULT ");
-                                               break;
-                                       }
-                               }
-                               switch (constraint.deferrabilityType) {
-                               case DEFERRABLE_INITIALLY_DEFERRED:
-                                       buff.append("DEFERRABLE INITIALLY DEFERRED ");
-                                       break;
-                               case DEFERRABLE_INITIALLY_IMMEDIATE:
-                                       buff.append("DEFERRABLE INITIALLY IMMEDIATE ");
-                                       break;
-                               case NOT_DEFERRABLE:
-                                       buff.append("NOT DEFERRABLE ");
-                                       break;
-                               case UNSET:
-                                       break;
-                               }
-                       }
-               }
-
-               buff.append(')');
-               stat.setSQL(buff.toString());
-       }
-
-       @Override
-       public <T> void prepareDropView(SQLStatement stat, TableDefinition<T> def) {
-               StatementBuilder buff = new StatementBuilder("DROP VIEW "
-                               + prepareTableName(def.schemaName, def.tableName));
-               stat.setSQL(buff.toString());
-               return;
-       }
-
-       protected <T> String prepareCreateView(TableDefinition<T> def) {
-               return "CREATE VIEW";
-       }
-
-       @Override
-       public <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def) {
-               StatementBuilder buff = new StatementBuilder();
-               buff.append(" FROM ");
-               buff.append(prepareTableName(def.schemaName, def.viewTableName));
-
-               StatementBuilder where = new StatementBuilder();
-               for (FieldDefinition field : def.fields) {
-                       if (!StringUtils.isNullOrEmpty(field.constraint)) {
-                               where.appendExceptFirst(", ");
-                               String col = prepareColumnName(field.columnName);
-                               String constraint = field.constraint.replace("{0}", col).replace("this", col);
-                               where.append(constraint);
-                       }
-               }
-               if (where.length() > 0) {
-                       buff.append(" WHERE ");
-                       buff.append(where.toString());
-               }
-
-               prepareCreateView(stat, def, buff.toString());
-       }
-
-       @Override
-       public <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def, String fromWhere) {
-               StatementBuilder buff = new StatementBuilder();
-               buff.append(prepareCreateView(def));
-               buff.append(" ");
-               buff.append(prepareTableName(def.schemaName, def.tableName));
-
-               buff.append(" AS SELECT ");
-               for (FieldDefinition field : def.fields) {
-                       buff.appendExceptFirst(", ");
-                       buff.append(prepareColumnName(field.columnName));
-               }
-               buff.append(fromWhere);
-               stat.setSQL(buff.toString());
-       }
-
-       protected boolean isIntegerType(String dataType) {
-               if ("INT".equals(dataType)) {
-                       return true;
-               } else if ("INTEGER".equals(dataType)) {
-                       return true;
-               } else if ("TINYINT".equals(dataType)) {
-                       return true;
-               } else if ("SMALLINT".equals(dataType)) {
-                       return true;
-               } else if ("MEDIUMINT".equals(dataType)) {
-                       return true;
-               } else if ("BIGINT".equals(dataType)) {
-                       return true;
-               }
-               return false;
-       }
-
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,
-                       boolean isAutoIncrement, boolean isPrimaryKey) {
-               buff.append(dataType);
-               if (isAutoIncrement) {
-                       buff.append(" AUTO_INCREMENT");
-               }
-               return false;
-       }
-
-       @Override
-       public void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName,
-                       IndexDefinition index) {
-               StatementBuilder buff = new StatementBuilder();
-               buff.append("CREATE ");
-               switch (index.type) {
-               case UNIQUE:
-                       buff.append("UNIQUE ");
-                       break;
-               case UNIQUE_HASH:
-                       buff.append("UNIQUE ");
-                       break;
-               default:
-                       IciqlLogger.warn("{0} does not support hash indexes", getClass().getSimpleName());
-               }
-               buff.append("INDEX ");
-               buff.append(index.indexName);
-               buff.append(" ON ");
-               // FIXME maybe we can use schemaName ?
-               // buff.append(prepareTableName(schemaName, tableName));
-               buff.append(tableName);
-               buff.append("(");
-               for (String col : index.columnNames) {
-                       buff.appendExceptFirst(", ");
-                       buff.append(prepareColumnName(col));
-               }
-               buff.append(") ");
-
-               stat.setSQL(buff.toString().trim());
-       }
-
-       /**
-        * PostgreSQL and Derby do not support the SQL2003 MERGE syntax, but we can
-        * use a trick to insert a row if it does not exist and call update() in
-        * Db.merge() if the affected row count is 0.
-        * <p>
-        * Databases that do support a MERGE syntax should override this method.
-        * <p>
-        * http://stackoverflow.com/questions/407688
-        */
-       @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));
-               buff.append(" (");
-               buff.resetCount();
-               for (FieldDefinition field : def.fields) {
-                       buff.appendExceptFirst(", ");
-                       buff.append(prepareColumnName(field.columnName));
-               }
-               buff.append(") (SELECT ");
-               buff.resetCount();
-               for (FieldDefinition field : def.fields) {
-                       buff.appendExceptFirst(", ");
-                       buff.append('?');
-                       Object value = def.getValue(obj, field);
-                       Object parameter = serialize(value, field.typeAdapter);
-                       stat.addParameter(parameter);
-               }
-               buff.append(" FROM ");
-               buff.append(prepareTableName(schemaName, tableName));
-               buff.append(" WHERE ");
-               buff.resetCount();
-               for (FieldDefinition field : def.fields) {
-                       if (field.isPrimaryKey) {
-                               buff.appendExceptFirst(" AND ");
-                               buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName)));
-                               Object value = def.getValue(obj, field);
-                               Object parameter = serialize(value, field.typeAdapter);
-                               stat.addParameter(parameter);
-                       }
-               }
-               buff.append(" HAVING count(*)=0)");
-               stat.setSQL(buff.toString());
-       }
-
-       @Override
-       public void appendLimitOffset(SQLStatement stat, long limit, long offset) {
-               if (limit > 0) {
-                       stat.appendSQL(" LIMIT " + limit);
-               }
-               if (offset > 0) {
-                       stat.appendSQL(" OFFSET " + offset);
-               }
-       }
-
-       @Override
-       public void registerAdapter(DataTypeAdapter<?> typeAdapter) {
-               typeAdapters.put((Class<? extends DataTypeAdapter<?>>) typeAdapter.getClass(), typeAdapter);
-       }
-
-       @Override
-       public DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               DataTypeAdapter<?> dta = typeAdapters.get(typeAdapter);
-               if (dta == null) {
-                       dta = Utils.newObject(typeAdapter);
-                       typeAdapters.put(typeAdapter, dta);
-               }
-               dta.setMode(mode);
-               return dta;
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public <T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               if (typeAdapter == null) {
-                       // pass-through
-                       return value;
-               }
-
-               DataTypeAdapter<T> dta = (DataTypeAdapter<T>) getAdapter(typeAdapter);
-               return dta.serialize(value);
-       }
-
-       @Override
-       public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               Object value = null;
-               try {
-                       if (typeAdapter == null) {
-                               // standard object deserialization
-                               Object o = rs.getObject(columnIndex);
-                               if (o == null) {
-                                       // no-op
-                                       value = null;
-                               } else if (Clob.class.isAssignableFrom(o.getClass())) {
-                                       value = Utils.convert(o, String.class);
-                               } else if (Blob.class.isAssignableFrom(o.getClass())) {
-                                       value = Utils.convert(o, byte[].class);
-                               } else {
-                                       value = Utils.convert(o, targetType);
-                               }
-                       } else {
-                               // custom object deserialization with a DataTypeAdapter
-                               DataTypeAdapter<?> dta = getAdapter(typeAdapter);
-                               Object object = rs.getObject(columnIndex);
-                               value = dta.deserialize(object);
-                       }
-               } catch (SQLException e) {
-                       throw new IciqlException(e, "Can not convert the value at column {0} to {1}",
-                                       columnIndex, targetType.getName());
-               }
-               return value;
-       }
-
-       @Override
-       public String prepareStringParameter(Object o) {
-               if (o instanceof String) {
-                       return LITERAL + o.toString().replace(LITERAL, "''") + LITERAL;
-               } else if (o instanceof Character) {
-                       return LITERAL + o.toString() + LITERAL;
-               } else if (o instanceof java.sql.Time) {
-                       return LITERAL + new SimpleDateFormat("HH:mm:ss").format(o) + LITERAL;
-               } else if (o instanceof java.sql.Date) {
-                       return LITERAL + new SimpleDateFormat("yyyy-MM-dd").format(o) + LITERAL;
-               } else if (o instanceof java.util.Date) {
-                       return LITERAL + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(o) + LITERAL;
-               }
-               return o.toString();
-       }
+    final String LITERAL = "'";
+
+    protected float databaseVersion;
+    protected int databaseMajorVersion;
+    protected int databaseMinorVersion;
+    protected String databaseName;
+    protected String productVersion;
+    protected Mode mode;
+    protected Map<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>> typeAdapters;
+
+    public SQLDialectDefault() {
+        typeAdapters = new ConcurrentHashMap<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>>();
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + ": " + databaseName + " " + productVersion;
+    }
+
+    @Override
+    public void configureDialect(Db db) {
+        Connection conn = db.getConnection();
+        DatabaseMetaData data = null;
+        try {
+            data = conn.getMetaData();
+            databaseName = data.getDatabaseProductName();
+            databaseMajorVersion = data.getDatabaseMajorVersion();
+            databaseMinorVersion = data.getDatabaseMinorVersion();
+            databaseVersion = Float.parseFloat(databaseMajorVersion + "."
+                    + databaseMinorVersion);
+            productVersion = data.getDatabaseProductVersion();
+        } catch (SQLException e) {
+            throw new IciqlException(e, "failed to retrieve database metadata!");
+        }
+
+        mode = db.getMode();
+    }
+
+    @Override
+    public boolean supportsSavePoints() {
+        return true;
+    }
+
+    /**
+     * Allows subclasses to change the type of a column for a CREATE statement.
+     *
+     * @param sqlType
+     * @return the SQL type or a preferred alternative
+     */
+    @Override
+    public String convertSqlType(String sqlType) {
+        return sqlType;
+    }
+
+    @Override
+    public Class<? extends java.util.Date> getDateTimeClass() {
+        return java.util.Date.class;
+    }
+
+    @Override
+    public String prepareTableName(String schemaName, String tableName) {
+        if (StringUtils.isNullOrEmpty(schemaName)) {
+            return tableName;
+        }
+        return schemaName + "." + tableName;
+    }
+
+    @Override
+    public String prepareColumnName(String name) {
+        return name;
+    }
+
+    @Override
+    public String extractColumnName(String name) {
+        return name.replace('\"', ' ').replace('\'', ' ').trim();
+    }
+
+    @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;
+    }
+
+    protected <T> String prepareCreateTable(TableDefinition<T> def) {
+        return "CREATE TABLE";
+    }
+
+    @Override
+    public <T> void prepareCreateTable(SQLStatement stat, TableDefinition<T> def) {
+        StatementBuilder buff = new StatementBuilder();
+        buff.append(prepareCreateTable(def));
+        buff.append(" ");
+        buff.append(prepareTableName(def.schemaName, def.tableName)).append('(');
+
+        boolean hasIdentityColumn = false;
+        for (FieldDefinition field : def.fields) {
+            buff.appendExceptFirst(", ");
+            buff.append(prepareColumnName(field.columnName)).append(' ');
+            String dataType = field.dataType;
+            if (dataType.equals("VARCHAR")) {
+                // check to see if we should use VARCHAR or CLOB
+                if (field.length <= 0) {
+                    dataType = "CLOB";
+                }
+                buff.append(convertSqlType(dataType));
+                if (field.length > 0) {
+                    buff.append('(').append(field.length).append(')');
+                }
+            } else if (dataType.equals("DECIMAL")) {
+                // DECIMAL(precision,scale)
+                buff.append(convertSqlType(dataType));
+                if (field.length > 0) {
+                    buff.append('(').append(field.length);
+                    if (field.scale > 0) {
+                        buff.append(',').append(field.scale);
+                    }
+                    buff.append(')');
+                }
+            } else {
+                // other
+                hasIdentityColumn |= prepareColumnDefinition(buff, convertSqlType(dataType),
+                        field.isAutoIncrement, field.isPrimaryKey);
+            }
+
+            // default values
+            if (!field.isAutoIncrement && !field.isPrimaryKey) {
+                String dv = field.defaultValue;
+                if (!StringUtils.isNullOrEmpty(dv)) {
+                    if (ModelUtils.isProperlyFormattedDefaultValue(dv)
+                            && ModelUtils.isValidDefaultValue(field.field.getType(), dv)) {
+                        buff.append(" DEFAULT " + dv);
+                    }
+                }
+            }
+
+            if (!field.nullable) {
+                buff.append(" NOT NULL");
+            }
+        }
+
+        // if table does not have identity column then specify primary key
+        if (!hasIdentityColumn) {
+            if (def.primaryKeyColumnNames != null && def.primaryKeyColumnNames.size() > 0) {
+                buff.append(", PRIMARY KEY(");
+                buff.resetCount();
+                for (String n : def.primaryKeyColumnNames) {
+                    buff.appendExceptFirst(", ");
+                    buff.append(prepareColumnName(n));
+                }
+                buff.append(')');
+            }
+        }
+
+        // create unique constraints
+        if (def.constraintsUnique.size() > 0) {
+            buff.append(", ");
+            buff.resetCount();
+            for (ConstraintUniqueDefinition constraint : def.constraintsUnique) {
+                buff.append("CONSTRAINT ");
+                buff.append(constraint.constraintName);
+                buff.append(" UNIQUE ");
+                buff.append(" (");
+                for (String col : constraint.uniqueColumns) {
+                    buff.appendExceptFirst(", ");
+                    buff.append(prepareColumnName(col));
+                }
+                buff.append(") ");
+            }
+        }
+
+        // create foreign key constraints
+        if (def.constraintsForeignKey.size() > 0) {
+            buff.append(", ");
+            buff.resetCount();
+            for (ConstraintForeignKeyDefinition constraint : def.constraintsForeignKey) {
+                buff.appendExceptFirst(", ");
+                buff.append(String.format("CONSTRAINT %s FOREIGN KEY(%s) REFERENCES %s(%s)",
+                        constraint.constraintName,
+                        constraint.foreignColumns.get(0),
+                        constraint.referenceTable,
+                        constraint.referenceColumns.get(0)));
+
+                if (constraint.deleteType != ConstraintDeleteType.UNSET) {
+                    buff.append(" ON DELETE ");
+                    switch (constraint.deleteType) {
+                        case CASCADE:
+                            buff.append("CASCADE ");
+                            break;
+                        case RESTRICT:
+                            buff.append("RESTRICT ");
+                            break;
+                        case SET_NULL:
+                            buff.append("SET NULL ");
+                            break;
+                        case NO_ACTION:
+                            buff.append("NO ACTION ");
+                            break;
+                        case SET_DEFAULT:
+                            buff.append("SET DEFAULT ");
+                            break;
+                    }
+                }
+                if (constraint.updateType != ConstraintUpdateType.UNSET) {
+                    buff.append(" ON UPDATE ");
+                    switch (constraint.updateType) {
+                        case CASCADE:
+                            buff.append("CASCADE ");
+                            break;
+                        case RESTRICT:
+                            buff.append("RESTRICT ");
+                            break;
+                        case SET_NULL:
+                            buff.append("SET NULL ");
+                            break;
+                        case NO_ACTION:
+                            buff.append("NO ACTION ");
+                            break;
+                        case SET_DEFAULT:
+                            buff.append("SET DEFAULT ");
+                            break;
+                    }
+                }
+                switch (constraint.deferrabilityType) {
+                    case DEFERRABLE_INITIALLY_DEFERRED:
+                        buff.append("DEFERRABLE INITIALLY DEFERRED ");
+                        break;
+                    case DEFERRABLE_INITIALLY_IMMEDIATE:
+                        buff.append("DEFERRABLE INITIALLY IMMEDIATE ");
+                        break;
+                    case NOT_DEFERRABLE:
+                        buff.append("NOT DEFERRABLE ");
+                        break;
+                    case UNSET:
+                        break;
+                }
+            }
+        }
+
+        buff.append(')');
+        stat.setSQL(buff.toString());
+    }
+
+    @Override
+    public <T> void prepareDropView(SQLStatement stat, TableDefinition<T> def) {
+        StatementBuilder buff = new StatementBuilder("DROP VIEW "
+                + prepareTableName(def.schemaName, def.tableName));
+        stat.setSQL(buff.toString());
+        return;
+    }
+
+    protected <T> String prepareCreateView(TableDefinition<T> def) {
+        return "CREATE VIEW";
+    }
+
+    @Override
+    public <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def) {
+        StatementBuilder buff = new StatementBuilder();
+        buff.append(" FROM ");
+        buff.append(prepareTableName(def.schemaName, def.viewTableName));
+
+        StatementBuilder where = new StatementBuilder();
+        for (FieldDefinition field : def.fields) {
+            if (!StringUtils.isNullOrEmpty(field.constraint)) {
+                where.appendExceptFirst(", ");
+                String col = prepareColumnName(field.columnName);
+                String constraint = field.constraint.replace("{0}", col).replace("this", col);
+                where.append(constraint);
+            }
+        }
+        if (where.length() > 0) {
+            buff.append(" WHERE ");
+            buff.append(where.toString());
+        }
+
+        prepareCreateView(stat, def, buff.toString());
+    }
+
+    @Override
+    public <T> void prepareCreateView(SQLStatement stat, TableDefinition<T> def, String fromWhere) {
+        StatementBuilder buff = new StatementBuilder();
+        buff.append(prepareCreateView(def));
+        buff.append(" ");
+        buff.append(prepareTableName(def.schemaName, def.tableName));
+
+        buff.append(" AS SELECT ");
+        for (FieldDefinition field : def.fields) {
+            buff.appendExceptFirst(", ");
+            buff.append(prepareColumnName(field.columnName));
+        }
+        buff.append(fromWhere);
+        stat.setSQL(buff.toString());
+    }
+
+    protected boolean isIntegerType(String dataType) {
+        if ("INT".equals(dataType)) {
+            return true;
+        } else if ("INTEGER".equals(dataType)) {
+            return true;
+        } else if ("TINYINT".equals(dataType)) {
+            return true;
+        } else if ("SMALLINT".equals(dataType)) {
+            return true;
+        } else if ("MEDIUMINT".equals(dataType)) {
+            return true;
+        } else if ("BIGINT".equals(dataType)) {
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {
+        buff.append(dataType);
+        if (isAutoIncrement) {
+            buff.append(" AUTO_INCREMENT");
+        }
+        return false;
+    }
+
+    @Override
+    public void prepareCreateIndex(SQLStatement stat, String schemaName, String tableName,
+                                   IndexDefinition index) {
+        StatementBuilder buff = new StatementBuilder();
+        buff.append("CREATE ");
+        switch (index.type) {
+            case UNIQUE:
+                buff.append("UNIQUE ");
+                break;
+            case UNIQUE_HASH:
+                buff.append("UNIQUE ");
+                break;
+            default:
+                IciqlLogger.warn("{0} does not support hash indexes", getClass().getSimpleName());
+        }
+        buff.append("INDEX ");
+        buff.append(index.indexName);
+        buff.append(" ON ");
+        // FIXME maybe we can use schemaName ?
+        // buff.append(prepareTableName(schemaName, tableName));
+        buff.append(tableName);
+        buff.append("(");
+        for (String col : index.columnNames) {
+            buff.appendExceptFirst(", ");
+            buff.append(prepareColumnName(col));
+        }
+        buff.append(") ");
+
+        stat.setSQL(buff.toString().trim());
+    }
+
+    /**
+     * PostgreSQL and Derby do not support the SQL2003 MERGE syntax, but we can
+     * use a trick to insert a row if it does not exist and call update() in
+     * Db.merge() if the affected row count is 0.
+     * <p>
+     * Databases that do support a MERGE syntax should override this method.
+     * <p>
+     * http://stackoverflow.com/questions/407688
+     */
+    @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));
+        buff.append(" (");
+        buff.resetCount();
+        for (FieldDefinition field : def.fields) {
+            buff.appendExceptFirst(", ");
+            buff.append(prepareColumnName(field.columnName));
+        }
+        buff.append(") (SELECT ");
+        buff.resetCount();
+        for (FieldDefinition field : def.fields) {
+            buff.appendExceptFirst(", ");
+            buff.append('?');
+            Object value = def.getValue(obj, field);
+            Object parameter = serialize(value, field.typeAdapter);
+            stat.addParameter(parameter);
+        }
+        buff.append(" FROM ");
+        buff.append(prepareTableName(schemaName, tableName));
+        buff.append(" WHERE ");
+        buff.resetCount();
+        for (FieldDefinition field : def.fields) {
+            if (field.isPrimaryKey) {
+                buff.appendExceptFirst(" AND ");
+                buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName)));
+                Object value = def.getValue(obj, field);
+                Object parameter = serialize(value, field.typeAdapter);
+                stat.addParameter(parameter);
+            }
+        }
+        buff.append(" HAVING count(*)=0)");
+        stat.setSQL(buff.toString());
+    }
+
+    @Override
+    public void appendLimitOffset(SQLStatement stat, long limit, long offset) {
+        if (limit > 0) {
+            stat.appendSQL(" LIMIT " + limit);
+        }
+        if (offset > 0) {
+            stat.appendSQL(" OFFSET " + offset);
+        }
+    }
+
+    @Override
+    public void registerAdapter(DataTypeAdapter<?> typeAdapter) {
+        typeAdapters.put((Class<? extends DataTypeAdapter<?>>) typeAdapter.getClass(), typeAdapter);
+    }
+
+    @Override
+    public DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter) {
+        DataTypeAdapter<?> dta = typeAdapters.get(typeAdapter);
+        if (dta == null) {
+            dta = Utils.newObject(typeAdapter);
+            typeAdapters.put(typeAdapter, dta);
+        }
+        dta.setMode(mode);
+        return dta;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter) {
+        if (typeAdapter == null) {
+            // pass-through
+            return value;
+        }
+
+        DataTypeAdapter<T> dta = (DataTypeAdapter<T>) getAdapter(typeAdapter);
+        return dta.serialize(value);
+    }
+
+    @Override
+    public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) {
+        Object value = null;
+        try {
+            if (typeAdapter == null) {
+                // standard object deserialization
+                Object o = rs.getObject(columnIndex);
+                if (o == null) {
+                    // no-op
+                    value = null;
+                } else if (Clob.class.isAssignableFrom(o.getClass())) {
+                    value = Utils.convert(o, String.class);
+                } else if (Blob.class.isAssignableFrom(o.getClass())) {
+                    value = Utils.convert(o, byte[].class);
+                } else {
+                    value = Utils.convert(o, targetType);
+                }
+            } else {
+                // custom object deserialization with a DataTypeAdapter
+                DataTypeAdapter<?> dta = getAdapter(typeAdapter);
+                Object object = rs.getObject(columnIndex);
+                value = dta.deserialize(object);
+            }
+        } catch (SQLException e) {
+            throw new IciqlException(e, "Can not convert the value at column {0} to {1}",
+                    columnIndex, targetType.getName());
+        }
+        return value;
+    }
+
+    @Override
+    public String prepareStringParameter(Object o) {
+        if (o instanceof String) {
+            return LITERAL + o.toString().replace(LITERAL, "''") + LITERAL;
+        } else if (o instanceof Character) {
+            return LITERAL + o.toString() + LITERAL;
+        } else if (o instanceof java.sql.Time) {
+            return LITERAL + new SimpleDateFormat("HH:mm:ss").format(o) + LITERAL;
+        } else if (o instanceof java.sql.Date) {
+            return LITERAL + new SimpleDateFormat("yyyy-MM-dd").format(o) + LITERAL;
+        } else if (o instanceof java.util.Date) {
+            return LITERAL + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(o) + LITERAL;
+        }
+        return o.toString();
+    }
 
 }
index 99405b742616d56b5557601744553bc4d71e808c..77fc73ee4591d2aa12aa839dfcd2e54a77e2df7a 100644 (file)
@@ -23,49 +23,49 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectDerby extends SQLDialectDefault {\r
 \r
-       @Override\r
-       public Class<? extends java.util.Date> getDateTimeClass() {\r
-               return java.sql.Timestamp.class;\r
-       }\r
+    @Override\r
+    public Class<? extends java.util.Date> getDateTimeClass() {\r
+        return java.sql.Timestamp.class;\r
+    }\r
 \r
-       @Override\r
-       public String convertSqlType(String sqlType) {\r
-               if ("TINYINT".equals(sqlType)) {\r
-                       // Derby does not have a TINYINT/BYTE type\r
-                       return "SMALLINT";\r
-               }\r
-               return sqlType;\r
-       }\r
+    @Override\r
+    public String convertSqlType(String sqlType) {\r
+        if ("TINYINT".equals(sqlType)) {\r
+            // Derby does not have a TINYINT/BYTE type\r
+            return "SMALLINT";\r
+        }\r
+        return sqlType;\r
+    }\r
 \r
-       @Override\r
-       public void appendLimitOffset(SQLStatement stat, long limit, long offset) {\r
-               // FETCH/OFFSET added in 10.5\r
-               if (databaseMajorVersion >= 10 && databaseMinorVersion >= 5) {\r
-                       if (offset > 0) {\r
-                               stat.appendSQL(" OFFSET " + offset + (offset == 1 ? " ROW" : " ROWS"));\r
-                       }\r
-                       if (limit > 0) {\r
-                               stat.appendSQL(" FETCH NEXT " + limit + (limit == 1 ? " ROW" : " ROWS") + " ONLY");\r
-                       }\r
-               }\r
-       }\r
+    @Override\r
+    public void appendLimitOffset(SQLStatement stat, long limit, long offset) {\r
+        // FETCH/OFFSET added in 10.5\r
+        if (databaseMajorVersion >= 10 && databaseMinorVersion >= 5) {\r
+            if (offset > 0) {\r
+                stat.appendSQL(" OFFSET " + offset + (offset == 1 ? " ROW" : " ROWS"));\r
+            }\r
+            if (limit > 0) {\r
+                stat.appendSQL(" FETCH NEXT " + limit + (limit == 1 ? " ROW" : " ROWS") + " ONLY");\r
+            }\r
+        }\r
+    }\r
 \r
-       @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
-                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
-               String convertedType = convertSqlType(dataType);\r
-               buff.append(convertedType);\r
-               if (isIntegerType(dataType) && isAutoIncrement) {\r
-                       buff.append(" GENERATED BY DEFAULT AS IDENTITY");\r
-               }\r
-               return false;\r
-       }\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {\r
+        String convertedType = convertSqlType(dataType);\r
+        buff.append(convertedType);\r
+        if (isIntegerType(dataType) && isAutoIncrement) {\r
+            buff.append(" GENERATED BY DEFAULT AS IDENTITY");\r
+        }\r
+        return false;\r
+    }\r
 \r
-       @Override\r
-       public <T> void prepareDropTable(SQLStatement stat, TableDefinition<T> def) {\r
-               StatementBuilder buff = new StatementBuilder("DROP TABLE "\r
-                               + prepareTableName(def.schemaName, def.tableName));\r
-               stat.setSQL(buff.toString());\r
-               return;\r
-       }\r
+    @Override\r
+    public <T> void prepareDropTable(SQLStatement stat, TableDefinition<T> def) {\r
+        StatementBuilder buff = new StatementBuilder("DROP TABLE "\r
+                + prepareTableName(def.schemaName, def.tableName));\r
+        stat.setSQL(buff.toString());\r
+        return;\r
+    }\r
 }
\ No newline at end of file
index 2d7d0fd7039518b72d0fa79c1644921a251d1d0f..12cc161d10dc42e470e68f5beced14b067f62292 100644 (file)
@@ -25,112 +25,112 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectH2 extends SQLDialectDefault {\r
 \r
-       /**\r
-        * CACHED tables are created by default. MEMORY tables are created upon\r
-        * request.\r
-        */\r
-       @Override\r
-       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
-               if (def.memoryTable) {\r
-                       return "CREATE MEMORY TABLE IF NOT EXISTS";\r
-               } else {\r
-                       return "CREATE CACHED TABLE IF NOT EXISTS";\r
-               }\r
-       }\r
+    /**\r
+     * CACHED tables are created by default. MEMORY tables are created upon\r
+     * request.\r
+     */\r
+    @Override\r
+    protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+        if (def.memoryTable) {\r
+            return "CREATE MEMORY TABLE IF NOT EXISTS";\r
+        } else {\r
+            return "CREATE CACHED TABLE IF NOT EXISTS";\r
+        }\r
+    }\r
 \r
-       @Override\r
-       protected <T> String prepareCreateView(TableDefinition<T> def) {\r
-               return "CREATE VIEW IF NOT EXISTS";\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
+    @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
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
-                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
-               String convertedType = convertSqlType(dataType);\r
-               boolean isIdentity = false;\r
-               if (isIntegerType(dataType)) {\r
-                       if (isAutoIncrement && isPrimaryKey) {\r
-                               buff.append("IDENTITY");\r
-                               isIdentity = true;\r
-                       } else if (isAutoIncrement) {\r
-                               buff.append(convertedType);\r
-                               buff.append(" AUTO_INCREMENT");\r
-                       } else {\r
-                               buff.append(convertedType);\r
-                       }\r
-               } else {\r
-                       buff.append(convertedType);\r
-               }\r
-               return isIdentity;\r
-       }\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {\r
+        String convertedType = convertSqlType(dataType);\r
+        boolean isIdentity = false;\r
+        if (isIntegerType(dataType)) {\r
+            if (isAutoIncrement && isPrimaryKey) {\r
+                buff.append("IDENTITY");\r
+                isIdentity = true;\r
+            } else if (isAutoIncrement) {\r
+                buff.append(convertedType);\r
+                buff.append(" AUTO_INCREMENT");\r
+            } else {\r
+                buff.append(convertedType);\r
+            }\r
+        } else {\r
+            buff.append(convertedType);\r
+        }\r
+        return isIdentity;\r
+    }\r
 \r
-       @Override\r
-       public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {\r
-               StatementBuilder buff = new StatementBuilder();\r
-               buff.append("CREATE ");\r
-               switch (index.type) {\r
-               case STANDARD:\r
-                       break;\r
-               case UNIQUE:\r
-                       buff.append("UNIQUE ");\r
-                       break;\r
-               case HASH:\r
-                       buff.append("HASH ");\r
-                       break;\r
-               case UNIQUE_HASH:\r
-                       buff.append("UNIQUE HASH ");\r
-                       break;\r
-               }\r
-               buff.append("INDEX IF NOT EXISTS ");\r
-               buff.append(index.indexName);\r
-               buff.append(" ON ");\r
-               buff.append(table);\r
-               buff.append("(");\r
-               for (String col : index.columnNames) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(col);\r
-               }\r
-               buff.append(")");\r
-               stat.setSQL(buff.toString());\r
-       }\r
+    @Override\r
+    public void prepareCreateIndex(SQLStatement stat, String schema, String table, IndexDefinition index) {\r
+        StatementBuilder buff = new StatementBuilder();\r
+        buff.append("CREATE ");\r
+        switch (index.type) {\r
+            case STANDARD:\r
+                break;\r
+            case UNIQUE:\r
+                buff.append("UNIQUE ");\r
+                break;\r
+            case HASH:\r
+                buff.append("HASH ");\r
+                break;\r
+            case UNIQUE_HASH:\r
+                buff.append("UNIQUE HASH ");\r
+                break;\r
+        }\r
+        buff.append("INDEX IF NOT EXISTS ");\r
+        buff.append(index.indexName);\r
+        buff.append(" ON ");\r
+        buff.append(table);\r
+        buff.append("(");\r
+        for (String col : index.columnNames) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(col);\r
+        }\r
+        buff.append(")");\r
+        stat.setSQL(buff.toString());\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("MERGE 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(") KEY(");\r
-               buff.resetCount();\r
-               for (FieldDefinition field : def.fields) {\r
-                       if (field.isPrimaryKey) {\r
-                               buff.appendExceptFirst(", ");\r
-                               buff.append(field.columnName);\r
-                       }\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
+    @Override\r
+    public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,\r
+                                 TableDefinition<T> def, Object obj) {\r
+        StatementBuilder buff = new StatementBuilder("MERGE 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(") KEY(");\r
+        buff.resetCount();\r
+        for (FieldDefinition field : def.fields) {\r
+            if (field.isPrimaryKey) {\r
+                buff.appendExceptFirst(", ");\r
+                buff.append(field.columnName);\r
+            }\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
 }
\ No newline at end of file
index 8b05ca4b7f6ae1eb6af0dcbf462b778a5675fb69..74a3dcc3e73d873b8450ce6c523b05c36df5e694 100644 (file)
 \r
 package com.iciql;\r
 \r
-import java.text.MessageFormat;\r
-\r
 import com.iciql.TableDefinition.FieldDefinition;\r
 import com.iciql.util.StatementBuilder;\r
 \r
+import java.text.MessageFormat;\r
+\r
 /**\r
  * HyperSQL database dialect.\r
  */\r
 public class SQLDialectHSQL extends SQLDialectDefault {\r
 \r
-       /**\r
-        * CACHED tables are created by default. MEMORY tables are created upon\r
-        * request.\r
-        */\r
-       @Override\r
-       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
-               if (def.memoryTable) {\r
-                       return "CREATE MEMORY TABLE IF NOT EXISTS";\r
-               } else {\r
-                       return "CREATE CACHED TABLE IF NOT EXISTS";\r
-               }\r
-       }\r
+    /**\r
+     * CACHED tables are created by default. MEMORY tables are created upon\r
+     * request.\r
+     */\r
+    @Override\r
+    protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+        if (def.memoryTable) {\r
+            return "CREATE MEMORY TABLE IF NOT EXISTS";\r
+        } else {\r
+            return "CREATE CACHED TABLE IF NOT EXISTS";\r
+        }\r
+    }\r
 \r
-       @Override\r
-       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
+    @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
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
-                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
-               boolean isIdentity = false;\r
-               String convertedType = convertSqlType(dataType);\r
-               buff.append(convertedType);\r
-               if (isIntegerType(dataType) && isAutoIncrement && isPrimaryKey) {\r
-                       buff.append(" IDENTITY");\r
-                       isIdentity = true;\r
-               }\r
-               return isIdentity;\r
-       }\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {\r
+        boolean isIdentity = false;\r
+        String convertedType = convertSqlType(dataType);\r
+        buff.append(convertedType);\r
+        if (isIntegerType(dataType) && isAutoIncrement && isPrimaryKey) {\r
+            buff.append(" IDENTITY");\r
+            isIdentity = true;\r
+        }\r
+        return isIdentity;\r
+    }\r
 \r
-       @Override\r
-       public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,\r
-                       TableDefinition<T> def, Object obj) {\r
-               final String valuePrefix = "v";\r
-               StatementBuilder buff = new StatementBuilder("MERGE INTO ");\r
-               buff.append(prepareTableName(schemaName, tableName));\r
-               // a, b, c....\r
-               buff.append(" USING (VALUES(");\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append("CAST(? AS ");\r
-                       String dataType = convertSqlType(field.dataType);\r
-                       buff.append(dataType);\r
-                       if ("VARCHAR".equals(dataType)) {\r
-                               if (field.length > 0) {\r
-                                       // VARCHAR(x)\r
-                                       buff.append(MessageFormat.format("({0})", field.length));\r
-                               }\r
-                       } else if ("DECIMAL".equals(dataType)) {\r
-                               if (field.length > 0) {\r
-                                       if (field.scale > 0) {\r
-                                               // DECIMAL(x,y)\r
-                                               buff.append(MessageFormat.format("({0},{1})", field.length, field.scale));\r
-                                       } else {\r
-                                               // DECIMAL(x)\r
-                                               buff.append(MessageFormat.format("({0})", field.length));\r
-                                       }\r
-                               }\r
-                       }\r
-                       buff.append(')');\r
-                       Object value = def.getValue(obj, field);\r
-                       Object parameter = serialize(value, field.typeAdapter);\r
-                       stat.addParameter(parameter);\r
-               }\r
+    @Override\r
+    public <T> void prepareMerge(SQLStatement stat, String schemaName, String tableName,\r
+                                 TableDefinition<T> def, Object obj) {\r
+        final String valuePrefix = "v";\r
+        StatementBuilder buff = new StatementBuilder("MERGE INTO ");\r
+        buff.append(prepareTableName(schemaName, tableName));\r
+        // a, b, c....\r
+        buff.append(" USING (VALUES(");\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append("CAST(? AS ");\r
+            String dataType = convertSqlType(field.dataType);\r
+            buff.append(dataType);\r
+            if ("VARCHAR".equals(dataType)) {\r
+                if (field.length > 0) {\r
+                    // VARCHAR(x)\r
+                    buff.append(MessageFormat.format("({0})", field.length));\r
+                }\r
+            } else if ("DECIMAL".equals(dataType)) {\r
+                if (field.length > 0) {\r
+                    if (field.scale > 0) {\r
+                        // DECIMAL(x,y)\r
+                        buff.append(MessageFormat.format("({0},{1})", field.length, field.scale));\r
+                    } else {\r
+                        // DECIMAL(x)\r
+                        buff.append(MessageFormat.format("({0})", field.length));\r
+                    }\r
+                }\r
+            }\r
+            buff.append(')');\r
+            Object value = def.getValue(obj, field);\r
+            Object parameter = serialize(value, field.typeAdapter);\r
+            stat.addParameter(parameter);\r
+        }\r
 \r
-               // map to temporary table\r
-               buff.resetCount();\r
-               buff.append(")) AS vals (");\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(prepareColumnName(valuePrefix + field.columnName));\r
-               }\r
+        // map to temporary table\r
+        buff.resetCount();\r
+        buff.append(")) AS vals (");\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(prepareColumnName(valuePrefix + field.columnName));\r
+        }\r
 \r
-               buff.append(") ON ");\r
+        buff.append(") ON ");\r
 \r
-               // create the ON condition\r
-               // (va, vb) = (va,vb)\r
-               String[] prefixes = { "", valuePrefix };\r
-               for (int i = 0; i < prefixes.length; i++) {\r
-                       String prefix = prefixes[i];\r
-                       buff.resetCount();\r
-                       buff.append('(');\r
-                       for (FieldDefinition field : def.fields) {\r
-                               if (field.isPrimaryKey) {\r
-                                       buff.appendExceptFirst(", ");\r
-                                       buff.append(prepareColumnName(prefix + field.columnName));\r
-                               }\r
-                       }\r
-                       buff.append(")");\r
-                       if (i == 0) {\r
-                               buff.append('=');\r
-                       }\r
-               }\r
+        // create the ON condition\r
+        // (va, vb) = (va,vb)\r
+        String[] prefixes = {"", valuePrefix};\r
+        for (int i = 0; i < prefixes.length; i++) {\r
+            String prefix = prefixes[i];\r
+            buff.resetCount();\r
+            buff.append('(');\r
+            for (FieldDefinition field : def.fields) {\r
+                if (field.isPrimaryKey) {\r
+                    buff.appendExceptFirst(", ");\r
+                    buff.append(prepareColumnName(prefix + field.columnName));\r
+                }\r
+            }\r
+            buff.append(")");\r
+            if (i == 0) {\r
+                buff.append('=');\r
+            }\r
+        }\r
 \r
-               // UPDATE\r
-               // set a=va\r
-               buff.append(" WHEN MATCHED THEN UPDATE SET ");\r
-               buff.resetCount();\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(prepareColumnName(field.columnName));\r
-                       buff.append('=');\r
-                       buff.append(prepareColumnName(valuePrefix + field.columnName));\r
-               }\r
+        // UPDATE\r
+        // set a=va\r
+        buff.append(" WHEN MATCHED THEN UPDATE SET ");\r
+        buff.resetCount();\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(prepareColumnName(field.columnName));\r
+            buff.append('=');\r
+            buff.append(prepareColumnName(valuePrefix + field.columnName));\r
+        }\r
 \r
-               // INSERT\r
-               // insert va, vb, vc....\r
-               buff.append(" WHEN NOT MATCHED THEN INSERT ");\r
-               buff.resetCount();\r
-               buff.append(" VALUES (");\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(prepareColumnName(valuePrefix + field.columnName));\r
-               }\r
-               buff.append(')');\r
-               stat.setSQL(buff.toString());\r
-       }\r
+        // INSERT\r
+        // insert va, vb, vc....\r
+        buff.append(" WHEN NOT MATCHED THEN INSERT ");\r
+        buff.resetCount();\r
+        buff.append(" VALUES (");\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(prepareColumnName(valuePrefix + field.columnName));\r
+        }\r
+        buff.append(')');\r
+        stat.setSQL(buff.toString());\r
+    }\r
 }
\ No newline at end of file
index e591d4a09e7314a527ce778f403436e78056e2d0..7f765fadfa61c45b1355b05bfb98bd2710c6fa0c 100644 (file)
@@ -22,37 +22,37 @@ package com.iciql;
  */
 public class SQLDialectMSSQL extends SQLDialectDefault {
 
-       @Override
-       public String extractColumnName(String name) {
-               return super.extractColumnName(name).replace('[', ' ').replace(']', ' ').trim();
-       }
-
-  /**
-   * Append limit and offset rows
-   *
-   * @param stat Statement
-   * @param limit Limit rows
-   * @param offset Offset rows
-   */
-  @Override
-  public void appendLimitOffset(SQLStatement stat, long limit, long offset) {
-         if (offset > 0) {
-                 throw new IciqlException("iciql does not support offset for MSSQL dialect!");
-         }
-    StringBuilder query = new StringBuilder(stat.getSQL());
-
-    // for databaseVersion >= 2012 need Offset
-    if (limit > 0) {
-      int indexSelect = query.indexOf("SELECT");
-
-      if (indexSelect >= 0) {
-        StringBuilder subPathQuery = new StringBuilder(" TOP ");
-        subPathQuery.append(Long.toString(limit));
-
-        query.insert(indexSelect + "SELECT".length(), subPathQuery);
-
-        stat.setSQL(query.toString());
-      }
+    @Override
+    public String extractColumnName(String name) {
+        return super.extractColumnName(name).replace('[', ' ').replace(']', ' ').trim();
+    }
+
+    /**
+     * Append limit and offset rows
+     *
+     * @param stat   Statement
+     * @param limit  Limit rows
+     * @param offset Offset rows
+     */
+    @Override
+    public void appendLimitOffset(SQLStatement stat, long limit, long offset) {
+        if (offset > 0) {
+            throw new IciqlException("iciql does not support offset for MSSQL dialect!");
+        }
+        StringBuilder query = new StringBuilder(stat.getSQL());
+
+        // for databaseVersion >= 2012 need Offset
+        if (limit > 0) {
+            int indexSelect = query.indexOf("SELECT");
+
+            if (indexSelect >= 0) {
+                StringBuilder subPathQuery = new StringBuilder(" TOP ");
+                subPathQuery.append(Long.toString(limit));
+
+                query.insert(indexSelect + "SELECT".length(), subPathQuery);
+
+                stat.setSQL(query.toString());
+            }
+        }
     }
-  }
 }
index ec5923f6eb7c53bbb3a8a84f35820676809a137d..e78b8a02f85b8baa8624a1503bf77df29aff4c3c 100644 (file)
@@ -24,71 +24,71 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectMySQL extends SQLDialectDefault {\r
 \r
-       @Override\r
-       public String convertSqlType(String sqlType) {\r
-               if (sqlType.equals("CLOB")) {\r
-                       return "TEXT";\r
-               }\r
-               return sqlType;\r
-       }\r
+    @Override\r
+    public String convertSqlType(String sqlType) {\r
+        if (sqlType.equals("CLOB")) {\r
+            return "TEXT";\r
+        }\r
+        return sqlType;\r
+    }\r
 \r
-       @Override\r
-       protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
-               return "CREATE TABLE IF NOT EXISTS";\r
-       }\r
+    @Override\r
+    protected <T> String prepareCreateTable(TableDefinition<T> def) {\r
+        return "CREATE TABLE 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
+    @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 String prepareColumnName(String name) {\r
-               return "`" + name + "`";\r
-       }\r
+    @Override\r
+    public String prepareColumnName(String name) {\r
+        return "`" + name + "`";\r
+    }\r
 \r
-       @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,\r
-                       boolean isPrimaryKey) {\r
-               String convertedType = convertSqlType(dataType);\r
-               buff.append(convertedType);\r
-               if (isIntegerType(dataType) && isAutoIncrement) {\r
-                       buff.append(" AUTO_INCREMENT");\r
-               }\r
-               return false;\r
-       }\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType, boolean isAutoIncrement,\r
+                                              boolean isPrimaryKey) {\r
+        String convertedType = convertSqlType(dataType);\r
+        buff.append(convertedType);\r
+        if (isIntegerType(dataType) && isAutoIncrement) {\r
+            buff.append(" AUTO_INCREMENT");\r
+        }\r
+        return false;\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 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.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(") ON DUPLICATE KEY UPDATE ");\r
-               buff.resetCount();\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(field.columnName);\r
-                       buff.append("=VALUES(");\r
-                       buff.append(field.columnName);\r
-                       buff.append(')');\r
-               }\r
-               stat.setSQL(buff.toString());\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 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.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(") ON DUPLICATE KEY UPDATE ");\r
+        buff.resetCount();\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(field.columnName);\r
+            buff.append("=VALUES(");\r
+            buff.append(field.columnName);\r
+            buff.append(')');\r
+        }\r
+        stat.setSQL(buff.toString());\r
+    }\r
 }
\ No newline at end of file
index 54e47b0aa253cd642f8d15ef7850067dfce8a589..97b92f8bb7a86067907c5257678f688cc8747134 100644 (file)
@@ -25,137 +25,137 @@ import com.iciql.util.StatementBuilder;
  */\r
 public class SQLDialectPostgreSQL extends SQLDialectDefault {\r
 \r
-       @Override\r
-       public Class<? extends java.util.Date> getDateTimeClass() {\r
-               return java.sql.Timestamp.class;\r
-       }\r
-\r
-       @Override\r
-       public String convertSqlType(String sqlType) {\r
-               if ("DOUBLE".equals(sqlType)) {\r
-                       return "DOUBLE PRECISION";\r
-               } else if ("TINYINT".equals(sqlType)) {\r
-                       // PostgreSQL does not have a byte type\r
-                       return "SMALLINT";\r
-               } else if ("CLOB".equals(sqlType)) {\r
-                       return "TEXT";\r
-               } else if ("BLOB".equals(sqlType)) {\r
-                       return "BYTEA";\r
-               }\r
-               return sqlType;\r
-       }\r
-\r
-       @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
-                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
-               String convertedType = convertSqlType(dataType);\r
-               if (isIntegerType(dataType)) {\r
-                       if (isAutoIncrement) {\r
-                               if ("BIGINT".equals(dataType)) {\r
-                                       buff.append("BIGSERIAL");\r
-                               } else {\r
-                                       buff.append("SERIAL");\r
-                               }\r
-                       } else {\r
-                               buff.append(convertedType);\r
-                       }\r
-               } else {\r
-                       buff.append(convertedType);\r
-               }\r
-               return false;\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
-               }\r
-               buff.append("INDEX ");\r
-               buff.append(index.indexName);\r
-               buff.append(" ON ");\r
-               buff.append(tableName);\r
-\r
-               switch (index.type) {\r
-               case HASH:\r
-                       buff.append(" USING HASH");\r
-                       break;\r
-               case UNIQUE_HASH:\r
-                       buff.append(" USING HASH");\r
-                       break;\r
-               }\r
-\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
-\r
-               FieldDefinition primaryKey = null;\r
-               for (FieldDefinition field : def.fields) {\r
-                       if (field.isPrimaryKey) {\r
-                               primaryKey = field;\r
-                       }\r
-               }\r
-\r
-               if (primaryKey == null || databaseVersion < 9.5f) {\r
-                       // simulated UPSERT for <= 9.4 release\r
-                       super.prepareMerge(stat, schemaName, tableName, def, obj);\r
-                       return;\r
-               }\r
-\r
-               // official UPSERT added in 9.5 release\r
-               StatementBuilder buff = new StatementBuilder("INSERT 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.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
-\r
-               buff.append(") ON CONFLICT (");\r
-               buff.resetCount();\r
-               for (FieldDefinition field : def.fields) {\r
-                       if (field.isPrimaryKey) {\r
-                               buff.appendExceptFirst(", ");\r
-                               buff.append(field.columnName);\r
-                       }\r
-               }\r
-               buff.append(") DO UPDATE SET ");\r
-               buff.resetCount();\r
-               for (FieldDefinition field : def.fields) {\r
-                       buff.appendExceptFirst(", ");\r
-                       buff.append(field.columnName);\r
-                       buff.append("=?");\r
-                       Object value = def.getValue(obj, field);\r
-                       Object parameter = serialize(value, field.typeAdapter);\r
-                       stat.addParameter(parameter);\r
-               }\r
-               stat.setSQL(buff.toString());\r
-       }\r
+    @Override\r
+    public Class<? extends java.util.Date> getDateTimeClass() {\r
+        return java.sql.Timestamp.class;\r
+    }\r
+\r
+    @Override\r
+    public String convertSqlType(String sqlType) {\r
+        if ("DOUBLE".equals(sqlType)) {\r
+            return "DOUBLE PRECISION";\r
+        } else if ("TINYINT".equals(sqlType)) {\r
+            // PostgreSQL does not have a byte type\r
+            return "SMALLINT";\r
+        } else if ("CLOB".equals(sqlType)) {\r
+            return "TEXT";\r
+        } else if ("BLOB".equals(sqlType)) {\r
+            return "BYTEA";\r
+        }\r
+        return sqlType;\r
+    }\r
+\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {\r
+        String convertedType = convertSqlType(dataType);\r
+        if (isIntegerType(dataType)) {\r
+            if (isAutoIncrement) {\r
+                if ("BIGINT".equals(dataType)) {\r
+                    buff.append("BIGSERIAL");\r
+                } else {\r
+                    buff.append("SERIAL");\r
+                }\r
+            } else {\r
+                buff.append(convertedType);\r
+            }\r
+        } else {\r
+            buff.append(convertedType);\r
+        }\r
+        return false;\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
+        }\r
+        buff.append("INDEX ");\r
+        buff.append(index.indexName);\r
+        buff.append(" ON ");\r
+        buff.append(tableName);\r
+\r
+        switch (index.type) {\r
+            case HASH:\r
+                buff.append(" USING HASH");\r
+                break;\r
+            case UNIQUE_HASH:\r
+                buff.append(" USING HASH");\r
+                break;\r
+        }\r
+\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
+\r
+        FieldDefinition primaryKey = null;\r
+        for (FieldDefinition field : def.fields) {\r
+            if (field.isPrimaryKey) {\r
+                primaryKey = field;\r
+            }\r
+        }\r
+\r
+        if (primaryKey == null || databaseVersion < 9.5f) {\r
+            // simulated UPSERT for <= 9.4 release\r
+            super.prepareMerge(stat, schemaName, tableName, def, obj);\r
+            return;\r
+        }\r
+\r
+        // official UPSERT added in 9.5 release\r
+        StatementBuilder buff = new StatementBuilder("INSERT 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.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
+\r
+        buff.append(") ON CONFLICT (");\r
+        buff.resetCount();\r
+        for (FieldDefinition field : def.fields) {\r
+            if (field.isPrimaryKey) {\r
+                buff.appendExceptFirst(", ");\r
+                buff.append(field.columnName);\r
+            }\r
+        }\r
+        buff.append(") DO UPDATE SET ");\r
+        buff.resetCount();\r
+        for (FieldDefinition field : def.fields) {\r
+            buff.appendExceptFirst(", ");\r
+            buff.append(field.columnName);\r
+            buff.append("=?");\r
+            Object value = def.getValue(obj, field);\r
+            Object parameter = serialize(value, field.typeAdapter);\r
+            stat.addParameter(parameter);\r
+        }\r
+        stat.setSQL(buff.toString());\r
+    }\r
 \r
 }
\ No newline at end of file
index 436af54f4c3044a47299aab8d284d46d2ce0f94b..b99bf96454fdda68ca41a4bce0c06a2ac7352779 100644 (file)
 \r
 package com.iciql;\r
 \r
-import java.sql.Date;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.sql.Time;\r
-import java.sql.Timestamp;\r
-\r
 import com.iciql.Iciql.DataTypeAdapter;\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
+import java.sql.Date;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.sql.Time;\r
+import java.sql.Timestamp;\r
+\r
 \r
 /**\r
  * SQLite database dialect.\r
  */\r
 public class SQLDialectSQLite extends SQLDialectDefault {\r
 \r
-       @Override\r
-       public boolean supportsSavePoints() {\r
-               // SAVEPOINT support was added after the 3.8.7 release\r
-               String [] chunks = productVersion.split("\\.");\r
-               if (Integer.parseInt(chunks[0]) > 3) {\r
-                       return true;\r
-               }\r
-               float f = Float.parseFloat(chunks[1] + "." + chunks[2]);\r
-               return (f > 8.7);\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 String convertSqlType(String sqlType) {\r
-               if (isIntegerType(sqlType)) {\r
-                       return "INTEGER";\r
-               }\r
-               return sqlType;\r
-       }\r
-\r
-       @Override\r
-       protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
-                       boolean isAutoIncrement, boolean isPrimaryKey) {\r
-               String convertedType = convertSqlType(dataType);\r
-               buff.append(convertedType);\r
-               if (isPrimaryKey) {\r
-                       buff.append(" PRIMARY KEY");\r
-                       if (isAutoIncrement) {\r
-                               buff.append(" AUTOINCREMENT");\r
-                       }\r
-                       return true;\r
-               }\r
-               return false;\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
-               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
-       @Override\r
-       public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) {\r
-               try {\r
-                       return super.deserialize(rs, columnIndex, targetType, typeAdapter);\r
-               } catch (IciqlException e) {\r
-                       if (typeAdapter == null && e.getMessage().startsWith("Can not convert")) {\r
-                               try {\r
-                                       // give the SQLite JDBC driver an opportunity to deserialize DateTime objects\r
-                                       if (Timestamp.class.equals(targetType)) {\r
-                                               return rs.getTimestamp(columnIndex);\r
-                                       } else if (Time.class.equals(targetType)) {\r
-                                               return rs.getTime(columnIndex);\r
-                                       } else if (Date.class.equals(targetType)) {\r
-                                               return rs.getDate(columnIndex);\r
-                                       } else if (java.util.Date.class.equals(targetType)) {\r
-                                               Timestamp timestamp = rs.getTimestamp(columnIndex);\r
-                                               return new java.util.Date(timestamp.getTime());\r
-                                       }\r
-                               } catch (SQLException x) {\r
-                                       throw new IciqlException(x, "Can not convert the value at column {0} to {1}",\r
-                                                       columnIndex, targetType.getName());\r
-                               }\r
-                       }\r
-\r
-                       // rethrow e\r
-                       throw e;\r
-               }\r
-       }\r
-\r
-       @Override\r
-       public String prepareStringParameter(Object o) {\r
-               if (o instanceof Boolean) {\r
-                       // SQLite does not have an explicit BOOLEAN type\r
-                       Boolean bool = (Boolean) o;\r
-                       return bool ? "1" : "0";\r
-               }\r
-               return super.prepareStringParameter(o);\r
-       }\r
-}
+    @Override\r
+    public boolean supportsSavePoints() {\r
+        // SAVEPOINT support was added after the 3.8.7 release\r
+        String[] chunks = productVersion.split("\\.");\r
+        if (Integer.parseInt(chunks[0]) > 3) {\r
+            return true;\r
+        }\r
+        float f = Float.parseFloat(chunks[1] + "." + chunks[2]);\r
+        return (f > 8.7);\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 String convertSqlType(String sqlType) {\r
+        if (isIntegerType(sqlType)) {\r
+            return "INTEGER";\r
+        }\r
+        return sqlType;\r
+    }\r
+\r
+    @Override\r
+    protected boolean prepareColumnDefinition(StatementBuilder buff, String dataType,\r
+                                              boolean isAutoIncrement, boolean isPrimaryKey) {\r
+        String convertedType = convertSqlType(dataType);\r
+        buff.append(convertedType);\r
+        if (isPrimaryKey) {\r
+            buff.append(" PRIMARY KEY");\r
+            if (isAutoIncrement) {\r
+                buff.append(" AUTOINCREMENT");\r
+            }\r
+            return true;\r
+        }\r
+        return false;\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
+        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
+    @Override\r
+    public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) {\r
+        try {\r
+            return super.deserialize(rs, columnIndex, targetType, typeAdapter);\r
+        } catch (IciqlException e) {\r
+            if (typeAdapter == null && e.getMessage().startsWith("Can not convert")) {\r
+                try {\r
+                    // give the SQLite JDBC driver an opportunity to deserialize DateTime objects\r
+                    if (Timestamp.class.equals(targetType)) {\r
+                        return rs.getTimestamp(columnIndex);\r
+                    } else if (Time.class.equals(targetType)) {\r
+                        return rs.getTime(columnIndex);\r
+                    } else if (Date.class.equals(targetType)) {\r
+                        return rs.getDate(columnIndex);\r
+                    } else if (java.util.Date.class.equals(targetType)) {\r
+                        Timestamp timestamp = rs.getTimestamp(columnIndex);\r
+                        return new java.util.Date(timestamp.getTime());\r
+                    }\r
+                } catch (SQLException x) {\r
+                    throw new IciqlException(x, "Can not convert the value at column {0} to {1}",\r
+                            columnIndex, targetType.getName());\r
+                }\r
+            }\r
+\r
+            // rethrow e\r
+            throw e;\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public String prepareStringParameter(Object o) {\r
+        if (o instanceof Boolean) {\r
+            // SQLite does not have an explicit BOOLEAN type\r
+            Boolean bool = (Boolean) o;\r
+            return bool ? "1" : "0";\r
+        }\r
+        return super.prepareStringParameter(o);\r
+    }\r
+}\r
index 7eb0b0421da45aef0ccfbeb57bacf2494c1218c6..d49e72282b05561aaa83a8c595847e8a294a9f45 100644 (file)
 \r
 package com.iciql;\r
 \r
+import com.iciql.util.JdbcUtils;\r
+\r
 import java.sql.PreparedStatement;\r
 import java.sql.ResultSet;\r
 import java.sql.SQLException;\r
 import java.util.ArrayList;\r
 import java.util.StringTokenizer;\r
 \r
-import com.iciql.util.JdbcUtils;\r
-\r
 /**\r
  * This class represents a parameterized SQL statement.\r
  */\r
 \r
 public class SQLStatement {\r
-       private Db db;\r
-       private StringBuilder buff = new StringBuilder();\r
-       private String sql;\r
-       private ArrayList<Object> params = new ArrayList<Object>();\r
-\r
-       SQLStatement(Db db) {\r
-               this.db = db;\r
-       }\r
-\r
-       public void setSQL(String sql) {\r
-               this.sql = sql;\r
-               buff = new StringBuilder(sql);\r
-       }\r
-\r
-       public SQLStatement appendSQL(String s) {\r
-               buff.append(s);\r
-               sql = null;\r
-               return this;\r
-       }\r
-\r
-       public SQLStatement appendTable(String schema, String table) {\r
-               return appendSQL(db.getDialect().prepareTableName(schema, table));\r
-       }\r
-\r
-       public SQLStatement appendColumn(String column) {\r
-               return appendSQL(db.getDialect().prepareColumnName(column));\r
-       }\r
-\r
-       /**\r
-        * getSQL returns a simple string representation of the parameterized\r
-        * statement which will be used later, internally, with prepareStatement.\r
-        * \r
-        * @return a simple sql statement\r
-        */\r
-       String getSQL() {\r
-               if (sql == null) {\r
-                       sql = buff.toString();\r
-               }\r
-               return sql;\r
-       }\r
-\r
-       /**\r
-        * toSQL creates a static sql statement with the referenced parameters\r
-        * encoded in the statement.\r
-        * \r
-        * @return a complete sql statement\r
-        */\r
-       String toSQL() {\r
-               if (sql == null) {\r
-                       sql = buff.toString();\r
-               }\r
-               if (params.size() == 0) {\r
-                       return sql;\r
-               }\r
-               StringBuilder sb = new StringBuilder();\r
-               // TODO this needs to me more sophisticated\r
-               StringTokenizer st = new StringTokenizer(sql, "?", false);\r
-               int i = 0;\r
-               while (st.hasMoreTokens()) {\r
-                       sb.append(st.nextToken());\r
-                       if (i < params.size()) {\r
-                               Object o = params.get(i);\r
-                               if (RuntimeParameter.PARAMETER == o) {\r
-                                       // dynamic parameter\r
-                                       sb.append('?');\r
-                               } else {\r
-                                       // static parameter\r
-                                       sb.append(db.getDialect().prepareStringParameter(o));\r
-                               }\r
-                               i++;\r
-                       }\r
-               }\r
-               return sb.toString();\r
-       }\r
-\r
-       public SQLStatement addParameter(Object o) {\r
-               // Automatically convert java.util.Date to java.sql.Timestamp\r
-               // if the dialect requires java.sql.Timestamp objects (e.g. Derby)\r
-               if (o != null && o.getClass().equals(java.util.Date.class)\r
-                               && db.getDialect().getDateTimeClass().equals(java.sql.Timestamp.class)) {\r
-                       o = new java.sql.Timestamp(((java.util.Date) o).getTime());\r
-               }\r
-               params.add(o);\r
-               return this;\r
-       }\r
-       \r
-       void execute() {\r
-               PreparedStatement ps = null;\r
-               try {\r
-                       ps = prepare(false);\r
-                       ps.execute();\r
-               } catch (SQLException e) {\r
-                       throw IciqlException.fromSQL(getSQL(), e);\r
-               } finally {\r
-                       JdbcUtils.closeSilently(ps);\r
-               }\r
-       }\r
-\r
-       ResultSet executeQuery() {\r
-               try {\r
-                       return prepare(false).executeQuery();\r
-               } catch (SQLException e) {\r
-                       throw IciqlException.fromSQL(getSQL(), e);\r
-               }\r
-       }\r
-\r
-       int executeUpdate() {\r
-               PreparedStatement ps = null;\r
-               try {\r
-                       ps = prepare(false);\r
-                       return ps.executeUpdate();\r
-               } catch (SQLException e) {\r
-                       throw IciqlException.fromSQL(getSQL(), e);\r
-               } finally {\r
-                       JdbcUtils.closeSilently(ps);\r
-               }\r
-       }\r
-\r
-       long executeInsert() {\r
-               PreparedStatement ps = null;\r
-               try {\r
-                       ps = prepare(true);\r
-                       ps.executeUpdate();\r
-                       long identity = -1;\r
-                       ResultSet rs = ps.getGeneratedKeys();\r
-                       if (rs != null && rs.next()) {\r
-                               identity = rs.getLong(1);\r
-                       }\r
-                       JdbcUtils.closeSilently(rs);\r
-                       return identity;\r
-               } catch (SQLException e) {\r
-                       throw IciqlException.fromSQL(getSQL(), e);\r
-               } finally {\r
-                       JdbcUtils.closeSilently(ps);\r
-               }\r
-       }\r
-\r
-       private void setValue(PreparedStatement prep, int parameterIndex, Object x) {\r
-               try {\r
-                       prep.setObject(parameterIndex, x);\r
-               } catch (SQLException e) {\r
-                       IciqlException ix = new IciqlException(e, "error setting parameter {0} as {1}", parameterIndex, x\r
-                                       .getClass().getSimpleName());\r
-                       ix.setSQL(getSQL());\r
-                       throw ix;\r
-               }\r
-       }\r
-\r
-       PreparedStatement prepare(boolean returnGeneratedKeys) {\r
-               PreparedStatement prep = db.prepare(getSQL(), returnGeneratedKeys);\r
-               for (int i = 0; i < params.size(); i++) {\r
-                       Object o = params.get(i);\r
-                       setValue(prep, i + 1, o);\r
-               }\r
-               return prep;\r
-       }\r
+    private Db db;\r
+    private StringBuilder buff = new StringBuilder();\r
+    private String sql;\r
+    private ArrayList<Object> params = new ArrayList<Object>();\r
+\r
+    SQLStatement(Db db) {\r
+        this.db = db;\r
+    }\r
+\r
+    public void setSQL(String sql) {\r
+        this.sql = sql;\r
+        buff = new StringBuilder(sql);\r
+    }\r
+\r
+    public SQLStatement appendSQL(String s) {\r
+        buff.append(s);\r
+        sql = null;\r
+        return this;\r
+    }\r
+\r
+    public SQLStatement appendTable(String schema, String table) {\r
+        return appendSQL(db.getDialect().prepareTableName(schema, table));\r
+    }\r
+\r
+    public SQLStatement appendColumn(String column) {\r
+        return appendSQL(db.getDialect().prepareColumnName(column));\r
+    }\r
+\r
+    /**\r
+     * getSQL returns a simple string representation of the parameterized\r
+     * statement which will be used later, internally, with prepareStatement.\r
+     *\r
+     * @return a simple sql statement\r
+     */\r
+    String getSQL() {\r
+        if (sql == null) {\r
+            sql = buff.toString();\r
+        }\r
+        return sql;\r
+    }\r
+\r
+    /**\r
+     * toSQL creates a static sql statement with the referenced parameters\r
+     * encoded in the statement.\r
+     *\r
+     * @return a complete sql statement\r
+     */\r
+    String toSQL() {\r
+        if (sql == null) {\r
+            sql = buff.toString();\r
+        }\r
+        if (params.size() == 0) {\r
+            return sql;\r
+        }\r
+        StringBuilder sb = new StringBuilder();\r
+        // TODO this needs to me more sophisticated\r
+        StringTokenizer st = new StringTokenizer(sql, "?", false);\r
+        int i = 0;\r
+        while (st.hasMoreTokens()) {\r
+            sb.append(st.nextToken());\r
+            if (i < params.size()) {\r
+                Object o = params.get(i);\r
+                if (RuntimeParameter.PARAMETER == o) {\r
+                    // dynamic parameter\r
+                    sb.append('?');\r
+                } else {\r
+                    // static parameter\r
+                    sb.append(db.getDialect().prepareStringParameter(o));\r
+                }\r
+                i++;\r
+            }\r
+        }\r
+        return sb.toString();\r
+    }\r
+\r
+    public SQLStatement addParameter(Object o) {\r
+        // Automatically convert java.util.Date to java.sql.Timestamp\r
+        // if the dialect requires java.sql.Timestamp objects (e.g. Derby)\r
+        if (o != null && o.getClass().equals(java.util.Date.class)\r
+                && db.getDialect().getDateTimeClass().equals(java.sql.Timestamp.class)) {\r
+            o = new java.sql.Timestamp(((java.util.Date) o).getTime());\r
+        }\r
+        params.add(o);\r
+        return this;\r
+    }\r
+\r
+    void execute() {\r
+        PreparedStatement ps = null;\r
+        try {\r
+            ps = prepare(false);\r
+            ps.execute();\r
+        } catch (SQLException e) {\r
+            throw IciqlException.fromSQL(getSQL(), e);\r
+        } finally {\r
+            JdbcUtils.closeSilently(ps);\r
+        }\r
+    }\r
+\r
+    ResultSet executeQuery() {\r
+        try {\r
+            return prepare(false).executeQuery();\r
+        } catch (SQLException e) {\r
+            throw IciqlException.fromSQL(getSQL(), e);\r
+        }\r
+    }\r
+\r
+    int executeUpdate() {\r
+        PreparedStatement ps = null;\r
+        try {\r
+            ps = prepare(false);\r
+            return ps.executeUpdate();\r
+        } catch (SQLException e) {\r
+            throw IciqlException.fromSQL(getSQL(), e);\r
+        } finally {\r
+            JdbcUtils.closeSilently(ps);\r
+        }\r
+    }\r
+\r
+    long executeInsert() {\r
+        PreparedStatement ps = null;\r
+        try {\r
+            ps = prepare(true);\r
+            ps.executeUpdate();\r
+            long identity = -1;\r
+            ResultSet rs = ps.getGeneratedKeys();\r
+            if (rs != null && rs.next()) {\r
+                identity = rs.getLong(1);\r
+            }\r
+            JdbcUtils.closeSilently(rs);\r
+            return identity;\r
+        } catch (SQLException e) {\r
+            throw IciqlException.fromSQL(getSQL(), e);\r
+        } finally {\r
+            JdbcUtils.closeSilently(ps);\r
+        }\r
+    }\r
+\r
+    private void setValue(PreparedStatement prep, int parameterIndex, Object x) {\r
+        try {\r
+            prep.setObject(parameterIndex, x);\r
+        } catch (SQLException e) {\r
+            IciqlException ix = new IciqlException(e, "error setting parameter {0} as {1}", parameterIndex, x\r
+                    .getClass().getSimpleName());\r
+            ix.setSQL(getSQL());\r
+            throw ix;\r
+        }\r
+    }\r
+\r
+    PreparedStatement prepare(boolean returnGeneratedKeys) {\r
+        PreparedStatement prep = db.prepare(getSQL(), returnGeneratedKeys);\r
+        for (int i = 0; i < params.size(); i++) {\r
+            Object o = params.get(i);\r
+            setValue(prep, i + 1, o);\r
+        }\r
+        return prep;\r
+    }\r
 \r
 }\r
index 43a1a93d5285a782c534c6c161dece77cf5742a8..ef39703991ae592b447842c236217f5769cad3b5 100644 (file)
@@ -21,37 +21,36 @@ import com.iciql.TableDefinition.FieldDefinition;
 \r
 /**\r
  * This class represents a column of a table in a query.\r
- * \r
- * @param <T>\r
- *            the table data type\r
+ *\r
+ * @param <T> the table data type\r
  */\r
 \r
 class SelectColumn<T> {\r
-       private SelectTable<T> selectTable;\r
-       private FieldDefinition fieldDef;\r
-\r
-       SelectColumn(SelectTable<T> table, FieldDefinition fieldDef) {\r
-               this.selectTable = table;\r
-               this.fieldDef = fieldDef;\r
-       }\r
-\r
-       void appendSQL(SQLStatement stat) {\r
-               if (selectTable.getQuery().isJoin()) {\r
-                       stat.appendSQL(selectTable.getAs() + "." + fieldDef.columnName);\r
-               } else {\r
-                       stat.appendColumn(fieldDef.columnName);\r
-               }\r
-       }\r
-\r
-       FieldDefinition getFieldDefinition() {\r
-               return fieldDef;\r
-       }\r
-\r
-       SelectTable<T> getSelectTable() {\r
-               return selectTable;\r
-       }\r
-\r
-       Object getCurrentValue() {\r
-               return fieldDef.getValue(selectTable.getCurrent());\r
-       }\r
+    private SelectTable<T> selectTable;\r
+    private FieldDefinition fieldDef;\r
+\r
+    SelectColumn(SelectTable<T> table, FieldDefinition fieldDef) {\r
+        this.selectTable = table;\r
+        this.fieldDef = fieldDef;\r
+    }\r
+\r
+    void appendSQL(SQLStatement stat) {\r
+        if (selectTable.getQuery().isJoin()) {\r
+            stat.appendSQL(selectTable.getAs() + "." + fieldDef.columnName);\r
+        } else {\r
+            stat.appendColumn(fieldDef.columnName);\r
+        }\r
+    }\r
+\r
+    FieldDefinition getFieldDefinition() {\r
+        return fieldDef;\r
+    }\r
+\r
+    SelectTable<T> getSelectTable() {\r
+        return selectTable;\r
+    }\r
+\r
+    Object getCurrentValue() {\r
+        return fieldDef.getValue(selectTable.getCurrent());\r
+    }\r
 }\r
index 37b42c4914802d3f3ec20eb9d80b90aa78092d04..acb5e17e911798bd23811aa16a41d08aa9877c94 100644 (file)
 \r
 package com.iciql;\r
 \r
-import java.util.ArrayList;\r
-\r
 import com.iciql.util.Utils;\r
 \r
+import java.util.ArrayList;\r
+\r
 /**\r
  * This class represents a table in a query.\r
- * \r
- * @param <T>\r
- *            the table class\r
+ *\r
+ * @param <T> the table class\r
  */\r
 \r
 class SelectTable<T> {\r
 \r
-       private Query<T> query;\r
-       private Class<T> clazz;\r
-       private T current;\r
-       private String as;\r
-       private TableDefinition<T> aliasDef;\r
-       private boolean outerJoin;\r
-       private ArrayList<Token> joinConditions = Utils.newArrayList();\r
-       private T alias;\r
-\r
-       @SuppressWarnings("unchecked")\r
-       SelectTable(Db db, Query<T> query, T alias, boolean outerJoin) {\r
-               this.alias = alias;\r
-               this.query = query;\r
-               this.outerJoin = outerJoin;\r
-               aliasDef = (TableDefinition<T>) db.getTableDefinition(alias.getClass());\r
-               clazz = Utils.getClass(alias);\r
-               as = "T" + Utils.nextAsCount();\r
-       }\r
-\r
-       T getAlias() {\r
-               return alias;\r
-       }\r
-\r
-       T newObject() {\r
-               return Utils.newObject(clazz);\r
-       }\r
-\r
-       TableDefinition<T> getAliasDefinition() {\r
-               return aliasDef;\r
-       }\r
-\r
-       void appendSQL(SQLStatement stat) {\r
-               if (query.isJoin()) {\r
-                       stat.appendTable(aliasDef.schemaName, aliasDef.tableName).appendSQL(" AS " + as);\r
-               } else {\r
-                       stat.appendTable(aliasDef.schemaName, aliasDef.tableName);\r
-               }\r
-       }\r
-\r
-       void appendSQLAsJoin(SQLStatement stat, Query<T> q) {\r
-               if (outerJoin) {\r
-                       stat.appendSQL(" LEFT OUTER JOIN ");\r
-               } else {\r
-                       stat.appendSQL(" INNER JOIN ");\r
-               }\r
-               appendSQL(stat);\r
-               if (!joinConditions.isEmpty()) {\r
-                       stat.appendSQL(" ON ");\r
-                       for (Token token : joinConditions) {\r
-                               token.appendSQL(stat, q);\r
-                               stat.appendSQL(" ");\r
-                       }\r
-               }\r
-       }\r
-\r
-       boolean getOuterJoin() {\r
-               return outerJoin;\r
-       }\r
-\r
-       Query<T> getQuery() {\r
-               return query;\r
-       }\r
-\r
-       String getAs() {\r
-               return as;\r
-       }\r
-\r
-       void addConditionToken(Token condition) {\r
-               joinConditions.add(condition);\r
-       }\r
-\r
-       T getCurrent() {\r
-               return current;\r
-       }\r
-\r
-       void setCurrent(T current) {\r
-               this.current = current;\r
-       }\r
+    private Query<T> query;\r
+    private Class<T> clazz;\r
+    private T current;\r
+    private String as;\r
+    private TableDefinition<T> aliasDef;\r
+    private boolean outerJoin;\r
+    private ArrayList<Token> joinConditions = Utils.newArrayList();\r
+    private T alias;\r
+\r
+    @SuppressWarnings("unchecked")\r
+    SelectTable(Db db, Query<T> query, T alias, boolean outerJoin) {\r
+        this.alias = alias;\r
+        this.query = query;\r
+        this.outerJoin = outerJoin;\r
+        aliasDef = (TableDefinition<T>) db.getTableDefinition(alias.getClass());\r
+        clazz = Utils.getClass(alias);\r
+        as = "T" + Utils.nextAsCount();\r
+    }\r
+\r
+    T getAlias() {\r
+        return alias;\r
+    }\r
+\r
+    T newObject() {\r
+        return Utils.newObject(clazz);\r
+    }\r
+\r
+    TableDefinition<T> getAliasDefinition() {\r
+        return aliasDef;\r
+    }\r
+\r
+    void appendSQL(SQLStatement stat) {\r
+        if (query.isJoin()) {\r
+            stat.appendTable(aliasDef.schemaName, aliasDef.tableName).appendSQL(" AS " + as);\r
+        } else {\r
+            stat.appendTable(aliasDef.schemaName, aliasDef.tableName);\r
+        }\r
+    }\r
+\r
+    void appendSQLAsJoin(SQLStatement stat, Query<T> q) {\r
+        if (outerJoin) {\r
+            stat.appendSQL(" LEFT OUTER JOIN ");\r
+        } else {\r
+            stat.appendSQL(" INNER JOIN ");\r
+        }\r
+        appendSQL(stat);\r
+        if (!joinConditions.isEmpty()) {\r
+            stat.appendSQL(" ON ");\r
+            for (Token token : joinConditions) {\r
+                token.appendSQL(stat, q);\r
+                stat.appendSQL(" ");\r
+            }\r
+        }\r
+    }\r
+\r
+    boolean getOuterJoin() {\r
+        return outerJoin;\r
+    }\r
+\r
+    Query<T> getQuery() {\r
+        return query;\r
+    }\r
+\r
+    String getAs() {\r
+        return as;\r
+    }\r
+\r
+    void addConditionToken(Token condition) {\r
+        joinConditions.add(condition);\r
+    }\r
+\r
+    T getCurrent() {\r
+        return current;\r
+    }\r
+\r
+    void setCurrent(T current) {\r
+        this.current = current;\r
+    }\r
 \r
 }\r
index 398d214e8fb5bdd906977ea39458ab23f719c48d..410a42b6cdaf4770e4c6e8fa25c11f73b207397c 100644 (file)
 package com.iciql;\r
 \r
 public class SubQuery<T, Z> {\r
-       \r
-       final Query<T> query;\r
-       final Z z;\r
-       \r
-       public SubQuery(Query<T> query, Z x) {\r
-               this.query = query;\r
-               this.z = x;\r
-       }\r
 \r
-       public void appendSQL(SQLStatement stat) {              \r
-               stat.appendSQL(query.toSubQuery(z));\r
-       }\r
+    final Query<T> query;\r
+    final Z z;\r
+\r
+    public SubQuery(Query<T> query, Z x) {\r
+        this.query = query;\r
+        this.z = x;\r
+    }\r
+\r
+    public void appendSQL(SQLStatement stat) {\r
+        stat.appendSQL(query.toSubQuery(z));\r
+    }\r
 }\r
index effea3b51326e28c13b26483a610e41cf8fc16e7..c6ca051fbb9c54b22083f1da38d97e384591fb6a 100644 (file)
@@ -18,24 +18,23 @@ package com.iciql;
 \r
 /**\r
  * A condition that contains a subquery.\r
- * \r
- * @param <A>\r
- *            the operand type\r
+ *\r
+ * @param <A> the operand type\r
  */\r
 \r
 class SubQueryCondition<A, Y, Z> implements Token {\r
-       A x;\r
-       SubQuery<Y, Z> subquery;\r
+    A x;\r
+    SubQuery<Y, Z> subquery;\r
 \r
-       SubQueryCondition(A x, SubQuery<Y, Z> subquery) {\r
-               this.x = x;\r
-               this.subquery = subquery;\r
-       }\r
+    SubQueryCondition(A x, SubQuery<Y, Z> subquery) {\r
+        this.x = x;\r
+        this.subquery = subquery;\r
+    }\r
 \r
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-               query.appendSQL(stat, null, x);\r
-               stat.appendSQL(" in (");\r
-               subquery.appendSQL(stat);\r
-               stat.appendSQL(")");\r
-       }\r
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+        query.appendSQL(stat, null, x);\r
+        stat.appendSQL(" in (");\r
+        subquery.appendSQL(stat);\r
+        stat.appendSQL(")");\r
+    }\r
 }\r
index 53ef89507e495a511d6de4c36a6a40310e53df3f..fe273c07a04c8ea8a2762208af37848f88c951cd 100644 (file)
 
 package com.iciql;
 
+import com.iciql.Iciql.*;
+import com.iciql.util.IciqlLogger;
+import com.iciql.util.StatementBuilder;
+import com.iciql.util.StringUtils;
+import com.iciql.util.Utils;
+
 import java.lang.reflect.Field;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -30,1193 +36,1149 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.iciql.Iciql.ConstraintDeferrabilityType;
-import com.iciql.Iciql.ConstraintDeleteType;
-import com.iciql.Iciql.ConstraintUpdateType;
-import com.iciql.Iciql.DataTypeAdapter;
-import com.iciql.Iciql.EnumId;
-import com.iciql.Iciql.EnumType;
-import com.iciql.Iciql.IQColumn;
-import com.iciql.Iciql.IQConstraint;
-import com.iciql.Iciql.IQContraintForeignKey;
-import com.iciql.Iciql.IQContraintUnique;
-import com.iciql.Iciql.IQContraintsForeignKey;
-import com.iciql.Iciql.IQContraintsUnique;
-import com.iciql.Iciql.IQIgnore;
-import com.iciql.Iciql.IQIndex;
-import com.iciql.Iciql.IQIndexes;
-import com.iciql.Iciql.IQSchema;
-import com.iciql.Iciql.IQTable;
-import com.iciql.Iciql.IQVersion;
-import com.iciql.Iciql.IQView;
-import com.iciql.Iciql.IndexType;
-import com.iciql.util.IciqlLogger;
-import com.iciql.util.StatementBuilder;
-import com.iciql.util.StringUtils;
-import com.iciql.util.Utils;
-
 /**
  * A table definition contains the index definitions of a table, the field
  * definitions, the table name, and other meta data.
  *
- * @param <T>
- *            the table type
+ * @param <T> the table type
  */
 
 public class TableDefinition<T> {
 
-       /**
-        * The meta data of an index.
-        */
-
-       public static class IndexDefinition {
-               public IndexType type;
-               public String indexName;
-
-               public List<String> columnNames;
-       }
-
-       /**
-        * The meta data of a constraint on foreign key.
-        */
-
-       public static class ConstraintForeignKeyDefinition {
-
-               public String constraintName;
-               public List<String> foreignColumns;
-               public String referenceTable;
-               public List<String> referenceColumns;
-               public ConstraintDeleteType deleteType = ConstraintDeleteType.UNSET;
-               public ConstraintUpdateType updateType = ConstraintUpdateType.UNSET;
-               public ConstraintDeferrabilityType deferrabilityType = ConstraintDeferrabilityType.UNSET;
-       }
-
-       /**
-        * The meta data of a unique constraint.
-        */
-
-       public static class ConstraintUniqueDefinition {
-
-               public String constraintName;
-               public List<String> uniqueColumns;
-       }
-
-
-       /**
-        * The meta data of a field.
-        */
-
-       static class FieldDefinition {
-               String columnName;
-               Field field;
-               String dataType;
-               int length;
-               int scale;
-               boolean isPrimaryKey;
-               boolean isAutoIncrement;
-               boolean trim;
-               boolean nullable;
-               String defaultValue;
-               EnumType enumType;
-               Class<?> enumTypeClass;
-               boolean isPrimitive;
-               String constraint;
-               Class<? extends DataTypeAdapter<?>> typeAdapter;
-
-               Object getValue(Object obj) {
-                       try {
-                               return field.get(obj);
-                       } catch (Exception e) {
-                               throw new IciqlException(e);
-                       }
-               }
-
-               private Object initWithNewObject(Object obj) {
-                       Object o = Utils.newObject(field.getType());
-                       setValue(obj, o);
-                       return o;
-               }
-
-               private void setValue(Object obj, Object o) {
-                       try {
-                               if (!field.isAccessible()) {
-                                       field.setAccessible(true);
-                               }
-
-                               if (field.getType().isPrimitive() && o == null) {
-                                       // do not attempt to set a primitive to null
-                                       return;
-                               }
-
-                               field.set(obj, o);
-                       } catch (IciqlException e) {
-                               throw e;
-                       } catch (Exception e) {
-                               throw new IciqlException(e);
-                       }
-               }
-
-               @Override
-               public int hashCode() {
-                       return columnName.hashCode();
-               }
-
-               @Override
-               public boolean equals(Object o) {
-                       if (o instanceof FieldDefinition) {
-                               return o.hashCode() == hashCode();
-                       }
-                       return false;
-               }
-       }
-
-       public ArrayList<FieldDefinition> fields = Utils.newArrayList();
-       String schemaName;
-       String tableName;
-       String viewTableName;
-       int tableVersion;
-       List<String> primaryKeyColumnNames;
-       boolean memoryTable;
-       boolean multiplePrimitiveBools;
-
-       private boolean createIfRequired = true;
-       private Class<T> clazz;
-       private IdentityHashMap<Object, FieldDefinition> fieldMap = Utils.newIdentityHashMap();
-       private ArrayList<IndexDefinition> indexes = Utils.newArrayList();
-       ArrayList<ConstraintForeignKeyDefinition> constraintsForeignKey = Utils.newArrayList();
-       ArrayList<ConstraintUniqueDefinition> constraintsUnique = Utils.newArrayList();
-
-       TableDefinition(Class<T> clazz) {
-               this.clazz = clazz;
-               schemaName = null;
-               tableName = clazz.getSimpleName();
-       }
-
-       Class<T> getModelClass() {
-               return clazz;
-       }
-
-       List<FieldDefinition> getFields() {
-               return fields;
-       }
-
-       void defineSchemaName(String schemaName) {
-               this.schemaName = schemaName;
-       }
-
-       void defineTableName(String tableName) {
-               this.tableName = tableName;
-       }
-
-       void defineViewTableName(String viewTableName) {
-               this.viewTableName = viewTableName;
-       }
-
-       void defineMemoryTable() {
-               this.memoryTable = true;
-       }
-
-       void defineSkipCreate() {
-               this.createIfRequired = false;
-       }
-
-       /**
-        * Define a primary key by the specified model fields.
-        *
-        * @param modelFields
-        *            the ordered list of model fields
-        */
-       void definePrimaryKey(Object[] modelFields) {
-               List<String> columnNames = mapColumnNames(modelFields);
-               setPrimaryKey(columnNames);
-       }
-
-       /**
-        * Define a primary key by the specified column names.
-        *
-        * @param columnNames
-        *            the ordered list of column names
-        */
-       private void setPrimaryKey(List<String> columnNames) {
-               primaryKeyColumnNames = Utils.newArrayList(columnNames);
-               List<String> pkNames = Utils.newArrayList();
-               for (String name : columnNames) {
-                       pkNames.add(name.toLowerCase());
-               }
-               // set isPrimaryKey flag for all field definitions
-               for (FieldDefinition fieldDefinition : fieldMap.values()) {
-                       fieldDefinition.isPrimaryKey = pkNames.contains(fieldDefinition.columnName.toLowerCase());
-               }
-       }
-
-       private <A> String getColumnName(A fieldObject) {
-               FieldDefinition def = fieldMap.get(fieldObject);
-               return def == null ? null : def.columnName;
-       }
-
-       private ArrayList<String> mapColumnNames(Object[] columns) {
-               ArrayList<String> columnNames = Utils.newArrayList();
-               for (Object column : columns) {
-                       columnNames.add(getColumnName(column));
-               }
-               return columnNames;
-       }
-
-       /**
-        * Defines an index with the specified model fields.
-        *
-        * @param name
-        *            the index name (optional)
-        * @param type
-        *            the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH)
-        * @param modelFields
-        *            the ordered list of model fields
-        */
-       void defineIndex(String name, IndexType type, Object[] modelFields) {
-               List<String> columnNames = mapColumnNames(modelFields);
-               addIndex(name, type, columnNames);
-       }
-
-       /**
-        * Defines an index with the specified column names.
-        *
-        * @param type
-        *            the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH)
-        * @param columnNames
-        *            the ordered list of column names
-        */
-       private void addIndex(String name, IndexType type, List<String> columnNames) {
-               IndexDefinition index = new IndexDefinition();
-               if (StringUtils.isNullOrEmpty(name)) {
-                       index.indexName = tableName + "_idx_" + indexes.size();
-               } else {
-                       index.indexName = name;
-               }
-               index.columnNames = Utils.newArrayList(columnNames);
-               index.type = type;
-               indexes.add(index);
-       }
-
-       /**
-        * Defines an unique constraint with the specified model fields.
-        *
-        * @param name
-        *            the constraint name (optional)
-        * @param modelFields
-        *            the ordered list of model fields
-        */
-       void defineConstraintUnique(String name, Object[] modelFields) {
-               List<String> columnNames = mapColumnNames(modelFields);
-               addConstraintUnique(name, columnNames);
-       }
-
-       /**
-        * Defines an unique constraint.
-        *
-        * @param name
-        * @param columnNames
-        */
-       private void addConstraintUnique(String name, List<String> columnNames) {
-               ConstraintUniqueDefinition constraint = new ConstraintUniqueDefinition();
-               if (StringUtils.isNullOrEmpty(name)) {
-                       constraint.constraintName = tableName + "_unique_" + constraintsUnique.size();
-               } else {
-                       constraint.constraintName = name;
-               }
-               constraint.uniqueColumns = Utils.newArrayList(columnNames);
-               constraintsUnique.add(constraint);
-       }
-
-       /**
-        * Defines a foreign key constraint with the specified model fields.
-        *
-        * @param name
-        *            the constraint name (optional)
-        * @param modelFields
-        *            the ordered list of model fields
-        */
-       void defineForeignKey(String name, Object[] modelFields, String refTableName, Object[] refModelFields,
-                       ConstraintDeleteType deleteType, ConstraintUpdateType updateType,
-                       ConstraintDeferrabilityType deferrabilityType) {
-               List<String> columnNames = mapColumnNames(modelFields);
-               List<String> referenceColumnNames = mapColumnNames(refModelFields);
-               addConstraintForeignKey(name, columnNames, refTableName, referenceColumnNames,
-                               deleteType, updateType, deferrabilityType);
-       }
-
-       void defineColumnName(Object column, String columnName) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.columnName = columnName;
-               }
-       }
-
-       void defineAutoIncrement(Object column) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.isAutoIncrement = true;
-               }
-       }
-
-       void defineLength(Object column, int length) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.length = length;
-               }
-       }
-
-       void defineScale(Object column, int scale) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.scale = scale;
-               }
-       }
-
-       void defineTrim(Object column) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.trim = true;
-               }
-       }
-
-       void defineNullable(Object column, boolean isNullable) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.nullable = isNullable;
-               }
-       }
-
-       void defineDefaultValue(Object column, String defaultValue) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.defaultValue = defaultValue;
-               }
-       }
-
-       void defineConstraint(Object column, String constraint) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.constraint = constraint;
-               }
-       }
-
-       void defineTypeAdapter(Object column, Class<? extends DataTypeAdapter<?>> typeAdapter) {
-               FieldDefinition def = fieldMap.get(column);
-               if (def != null) {
-                       def.typeAdapter = typeAdapter;
-               }
-       }
-
-       void mapFields(Db db) {
-               boolean byAnnotationsOnly = false;
-               boolean inheritColumns = false;
-               if (clazz.isAnnotationPresent(IQTable.class)) {
-                       IQTable tableAnnotation = clazz.getAnnotation(IQTable.class);
-                       byAnnotationsOnly = tableAnnotation.annotationsOnly();
-                       inheritColumns = tableAnnotation.inheritColumns();
-               }
-
-               if (clazz.isAnnotationPresent(IQView.class)) {
-                       IQView viewAnnotation = clazz.getAnnotation(IQView.class);
-                       byAnnotationsOnly = viewAnnotation.annotationsOnly();
-                       inheritColumns = viewAnnotation.inheritColumns();
-               }
-
-               List<Field> classFields = classFields(inheritColumns);
-
-               Set<FieldDefinition> uniqueFields = new LinkedHashSet<FieldDefinition>();
-               T defaultObject = Db.instance(clazz);
-               for (Field f : classFields) {
-                       // check if we should skip this field
-                       if (f.isAnnotationPresent(IQIgnore.class)) {
-                               continue;
-                       }
-
-                       // default to field name
-                       String columnName = f.getName();
-                       boolean isAutoIncrement = false;
-                       boolean isPrimaryKey = false;
-                       int length = 0;
-                       int scale = 0;
-                       boolean trim = false;
-                       boolean nullable = !f.getType().isPrimitive();
-                       String defaultValue = "";
-                       String constraint = "";
-                       String dataType = null;
-                       Class<? extends DataTypeAdapter<?>> typeAdapter = null;
-
-                       // configure Java -> SQL enum mapping
-                       EnumType enumType = Utils.getEnumType(f);
-                       Class<?> enumTypeClass = Utils.getEnumTypeClass(f);
-
-                       // try using default object
-                       try {
-                               f.setAccessible(true);
-                               Object value = f.get(defaultObject);
-                               if (value != null) {
-                                       if (value.getClass().isEnum()) {
-                                               // enum default, convert to target type
-                                               Enum<?> anEnum = (Enum<?>) value;
-                                               Object o = Utils.convertEnum(anEnum, enumType);
-                                               defaultValue = ModelUtils.formatDefaultValue(o);
-                                       } else {
-                                               // object default
-                                               defaultValue = ModelUtils.formatDefaultValue(value);
-                                       }
-                               }
-                       } catch (IllegalAccessException e) {
-                               throw new IciqlException(e, "failed to get default object for {0}", columnName);
-                       }
-
-                       // identify the type adapter
-                       typeAdapter = Utils.getDataTypeAdapter(f.getAnnotations());
-                       if (typeAdapter == null) {
-                               typeAdapter = Utils.getDataTypeAdapter(f.getType().getAnnotations());
-                       }
-
-                       if (typeAdapter != null) {
-                               DataTypeAdapter<?> dtt = db.getDialect().getAdapter(typeAdapter);
-                               dataType = dtt.getDataType();
-                       }
-
-                       boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class);
-                       if (hasAnnotation) {
-                               IQColumn col = f.getAnnotation(IQColumn.class);
-                               if (!StringUtils.isNullOrEmpty(col.name())) {
-                                       columnName = col.name();
-                               }
-                               isAutoIncrement = col.autoIncrement();
-                               isPrimaryKey = col.primaryKey();
-                               length = col.length();
-                               scale = col.scale();
-                               trim = col.trim();
-                               nullable = col.nullable();
-
-                               // annotation overrides
-                               if (!StringUtils.isNullOrEmpty(col.defaultValue())) {
-                                       defaultValue = col.defaultValue();
-                               }
-                       }
-
-                       boolean hasConstraint = f.isAnnotationPresent(IQConstraint.class);
-                       if (hasConstraint) {
-                               IQConstraint con = f.getAnnotation(IQConstraint.class);
-                               // annotation overrides
-                               if (!StringUtils.isNullOrEmpty(con.value())) {
-                                       constraint = con.value();
-                               }
-                       }
-
-                       boolean reflectiveMatch = !byAnnotationsOnly;
-                       if (reflectiveMatch || hasAnnotation || hasConstraint) {
-                               FieldDefinition fieldDef = new FieldDefinition();
-                               fieldDef.isPrimitive = f.getType().isPrimitive();
-                               fieldDef.field = f;
-                               fieldDef.columnName = columnName;
-                               fieldDef.isAutoIncrement = isAutoIncrement;
-                               fieldDef.isPrimaryKey = isPrimaryKey;
-                               fieldDef.length = length;
-                               fieldDef.scale = scale;
-                               fieldDef.trim = trim;
-                               fieldDef.nullable = nullable;
-                               fieldDef.defaultValue = defaultValue;
-                               fieldDef.enumType = enumType;
-                               fieldDef.enumTypeClass = enumTypeClass;
-                               fieldDef.dataType = StringUtils.isNullOrEmpty(dataType) ? ModelUtils.getDataType(fieldDef) : dataType;
-                               fieldDef.typeAdapter = typeAdapter;
-                               fieldDef.constraint = constraint;
-                               uniqueFields.add(fieldDef);
-                       }
-               }
-               fields.addAll(uniqueFields);
-
-               List<String> primaryKey = Utils.newArrayList();
-               int primitiveBoolean = 0;
-               for (FieldDefinition fieldDef : fields) {
-                       if (fieldDef.isPrimaryKey) {
-                               primaryKey.add(fieldDef.columnName);
-                       }
-                       if (fieldDef.isPrimitive && fieldDef.field.getType().equals(boolean.class)) {
-                               primitiveBoolean++;
-                       }
-               }
-               if (primitiveBoolean > 1) {
-                       multiplePrimitiveBools = true;
-                       IciqlLogger
-                                       .warn("Model {0} has multiple primitive booleans! Possible where,set,join clause problem!", tableName);
-               }
-               if (primaryKey.size() > 0) {
-                       setPrimaryKey(primaryKey);
-               }
-       }
-
-       private List<Field> classFields(boolean inheritColumns) {
-               List<Field> classFields = Utils.newArrayList();
-               classFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
-               Class<?> superClass = clazz;
-               while (inheritColumns) {
-                       superClass = superClass.getSuperclass();
-                       classFields.addAll(Arrays.asList(superClass.getDeclaredFields()));
-
-                       if (superClass.isAnnotationPresent(IQView.class)) {
-                               IQView superView = superClass.getAnnotation(IQView.class);
-                               inheritColumns = superView.inheritColumns();
-                       } else if (superClass.isAnnotationPresent(IQTable.class)) {
-                               IQTable superTable = superClass.getAnnotation(IQTable.class);
-                               inheritColumns = superTable.inheritColumns();
-                       } else {
-                               inheritColumns = false;
-                       }
-               }
-               return classFields;
-       }
-
-       void checkMultipleBooleans() {
-               if (multiplePrimitiveBools) {
-                       throw new IciqlException(
-                                       "Can not explicitly reference a primitive boolean if there are multiple boolean fields in your model class!");
-               }
-       }
-
-       void checkMultipleEnums(Object o) {
-               if (o == null) {
-                       return;
-               }
-               Class<?> clazz = o.getClass();
-               if (!clazz.isEnum()) {
-                       return;
-               }
-
-               int fieldCount = 0;
-               for (FieldDefinition fieldDef : fields) {
-                       Class<?> targetType = fieldDef.field.getType();
-                       if (clazz.equals(targetType)) {
-                               fieldCount++;
-                       }
-               }
-
-               if (fieldCount > 1) {
-                       throw new IciqlException(
-                                       "Can not explicitly reference {0} because there are {1} {0} fields in your model class!",
-                                       clazz.getSimpleName(), fieldCount);
-               }
-       }
-
-       /**
-        * Optionally truncates strings to the maximum length and converts
-        * java.lang.Enum types to Strings or Integers.
-        */
-       Object getValue(Object obj, FieldDefinition field) {
-               Object value = field.getValue(obj);
-               if (value == null) {
-                       return value;
-               }
-               if (field.enumType != null) {
-                       // convert enumeration to INT or STRING
-                       Enum<?> iqenum = (Enum<?>) value;
-                       switch (field.enumType) {
-                       case NAME:
-                               if (field.trim && field.length > 0) {
-                                       if (iqenum.name().length() > field.length) {
-                                               return iqenum.name().substring(0, field.length);
-                                       }
-                               }
-                               return iqenum.name();
-                       case ORDINAL:
-                               return iqenum.ordinal();
-                       case ENUMID:
-                               if (!EnumId.class.isAssignableFrom(value.getClass())) {
-                                       throw new IciqlException(field.field.getName() + " does not implement EnumId!");
-                               }
-                               EnumId<?> enumid = (EnumId<?>) value;
-                               return enumid.enumId();
-                       }
-               }
-
-               if (field.trim && field.length > 0) {
-                       if (value instanceof String) {
-                               // clip strings
-                               String s = (String) value;
-                               if (s.length() > field.length) {
-                                       return s.substring(0, field.length);
-                               }
-                               return s;
-                       }
-                       return value;
-               }
-
-               // return the value unchanged
-               return value;
-       }
-
-       PreparedStatement createInsertStatement(Db db, Object obj, boolean returnKey) {
-               SQLStatement stat = new SQLStatement(db);
-               StatementBuilder buff = new StatementBuilder("INSERT INTO ");
-               buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append('(');
-               for (FieldDefinition field : fields) {
-                       if (skipInsertField(field, obj)) {
-                               continue;
-                       }
-                       buff.appendExceptFirst(", ");
-                       buff.append(db.getDialect().prepareColumnName(field.columnName));
-               }
-               buff.append(") VALUES(");
-               buff.resetCount();
-               for (FieldDefinition field : fields) {
-                       if (skipInsertField(field, obj)) {
-                               continue;
-                       }
-                       buff.appendExceptFirst(", ");
-                       buff.append('?');
-                       Object value = getValue(obj, field);
-                       if (value == null) {
-                               if (!field.nullable) {
-                                       // try to interpret and instantiate a default value
-                                       value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
-                               }
-                       }
-                       Object parameter = db.getDialect().serialize(value, field.typeAdapter);
-                       stat.addParameter(parameter);
-               }
-               buff.append(')');
-               stat.setSQL(buff.toString());
-               IciqlLogger.insert(stat.getSQL());
-               return stat.prepare(returnKey);
-       }
-
-       long insert(Db db, Object obj, boolean returnKey) {
-               if (!StringUtils.isNullOrEmpty(viewTableName)) {
-                       throw new IciqlException("Iciql does not support inserting rows into views!");
-               }
-               SQLStatement stat = new SQLStatement(db);
-               StatementBuilder buff = new StatementBuilder("INSERT INTO ");
-               buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append('(');
-               for (FieldDefinition field : fields) {
-                       if (skipInsertField(field, obj)) {
-                               continue;
-                       }
-                       buff.appendExceptFirst(", ");
-                       buff.append(db.getDialect().prepareColumnName(field.columnName));
-               }
-               buff.append(") VALUES(");
-               buff.resetCount();
-               for (FieldDefinition field : fields) {
-                       if (skipInsertField(field, obj)) {
-                               continue;
-                       }
-                       buff.appendExceptFirst(", ");
-                       buff.append('?');
-                       Object value = getValue(obj, field);
-                       if (value == null && !field.nullable) {
-                               // try to interpret and instantiate a default value
-                               value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
-                       }
-                       Object parameter = db.getDialect().serialize(value, field.typeAdapter);
-                       stat.addParameter(parameter);
-               }
-               buff.append(')');
-               stat.setSQL(buff.toString());
-               IciqlLogger.insert(stat.getSQL());
-               if (returnKey) {
-                       return stat.executeInsert();
-               }
-               return stat.executeUpdate();
-       }
-
-       private boolean skipInsertField(FieldDefinition field, Object obj) {
-               if (field.isAutoIncrement) {
-                       Object value = getValue(obj, field);
-                       if (field.isPrimitive) {
-                               // skip uninitialized primitive autoincrement values
-                               if (value.toString().equals("0")) {
-                                       return true;
-                               }
-                       } else if (value == null) {
-                               // skip null object autoincrement values
-                               return true;
-                       }
-               } else {
-                       // conditionally skip insert of null
-                       Object value = getValue(obj, field);
-                       if (value == null) {
-                               return !StringUtils.isNullOrEmpty(field.defaultValue);
-                       }
-               }
-               return false;
-       }
-
-       int merge(Db db, Object obj) {
-               if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
-                       throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
-                                       + " - no update possible");
-               }
-               SQLStatement stat = new SQLStatement(db);
-               db.getDialect().prepareMerge(stat, schemaName, tableName, this, obj);
-               IciqlLogger.merge(stat.getSQL());
-               return stat.executeUpdate();
-       }
-
-       int update(Db db, Object obj) {
-               if (!StringUtils.isNullOrEmpty(viewTableName)) {
-                       throw new IciqlException("Iciql does not support updating rows in views!");
-               }
-               if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
-                       throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
-                                       + " - no update possible");
-               }
-               SQLStatement stat = new SQLStatement(db);
-               StatementBuilder buff = new StatementBuilder("UPDATE ");
-               buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append(" SET ");
-               buff.resetCount();
-
-               for (FieldDefinition field : fields) {
-                       if (!field.isPrimaryKey) {
-                               Object value = getValue(obj, field);
-                               if (value == null && !field.nullable) {
-                                       // try to interpret and instantiate a default value
-                                       value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
-                               }
-                               buff.appendExceptFirst(", ");
-                               buff.append(db.getDialect().prepareColumnName(field.columnName));
-                               buff.append(" = ?");
-                               Object parameter = db.getDialect().serialize(value, field.typeAdapter);
-                               stat.addParameter(parameter);
-                       }
-               }
-               Object alias = Utils.newObject(obj.getClass());
-               Query<Object> query = Query.from(db, alias);
-               boolean firstCondition = true;
-               for (FieldDefinition field : fields) {
-                       if (field.isPrimaryKey) {
-                               Object fieldAlias = field.getValue(alias);
-                               Object value = field.getValue(obj);
-                               if (field.isPrimitive) {
-                                       fieldAlias = query.getPrimitiveAliasByValue(fieldAlias);
-                               }
-                               if (!firstCondition) {
-                                       query.addConditionToken(ConditionAndOr.AND);
-                               }
-                               firstCondition = false;
-                               query.addConditionToken(new Condition<Object>(fieldAlias, value, CompareType.EQUAL));
-                       }
-               }
-               stat.setSQL(buff.toString());
-               query.appendWhere(stat);
-               IciqlLogger.update(stat.getSQL());
-               return stat.executeUpdate();
-       }
-
-       int delete(Db db, Object obj) {
-               if (!StringUtils.isNullOrEmpty(viewTableName)) {
-                       throw new IciqlException("Iciql does not support deleting rows from views!");
-               }
-               if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
-                       throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
-                                       + " - no update possible");
-               }
-               SQLStatement stat = new SQLStatement(db);
-               StatementBuilder buff = new StatementBuilder("DELETE FROM ");
-               buff.append(db.getDialect().prepareTableName(schemaName, tableName));
-               buff.resetCount();
-               Object alias = Utils.newObject(obj.getClass());
-               Query<Object> query = Query.from(db, alias);
-               boolean firstCondition = true;
-               for (FieldDefinition field : fields) {
-                       if (field.isPrimaryKey) {
-                               Object fieldAlias = field.getValue(alias);
-                               Object value = field.getValue(obj);
-                               if (field.isPrimitive) {
-                                       fieldAlias = query.getPrimitiveAliasByValue(fieldAlias);
-                               }
-                               if (!firstCondition) {
-                                       query.addConditionToken(ConditionAndOr.AND);
-                               }
-                               firstCondition = false;
-                               query.addConditionToken(new Condition<Object>(fieldAlias, value, CompareType.EQUAL));
-                       }
-               }
-               stat.setSQL(buff.toString());
-               query.appendWhere(stat);
-               IciqlLogger.delete(stat.getSQL());
-               return stat.executeUpdate();
-       }
-
-       TableDefinition<T> createIfRequired(Db db) {
-               // globally enable/disable check of create if required
-               if (db.getSkipCreate()) {
-                       return this;
-               }
-               if (!createIfRequired) {
-                       // skip table and index creation
-                       // but still check for upgrades
-                       db.upgradeTable(this);
-                       return this;
-               }
-               if (db.hasCreated(clazz)) {
-                       return this;
-               }
-               SQLStatement stat = new SQLStatement(db);
-               if (StringUtils.isNullOrEmpty(viewTableName)) {
-                       db.getDialect().prepareCreateTable(stat, this);
-               } else {
-                       db.getDialect().prepareCreateView(stat, this);
-               }
-               IciqlLogger.create(stat.getSQL());
-               try {
-                       stat.executeUpdate();
-               } catch (IciqlException e) {
-                       if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS) {
-                               throw e;
-                       }
-               }
-
-               // create indexes
-               for (IndexDefinition index : indexes) {
-                       stat = new SQLStatement(db);
-                       db.getDialect().prepareCreateIndex(stat, schemaName, tableName, index);
-                       IciqlLogger.create(stat.getSQL());
-                       try {
-                               stat.executeUpdate();
-                       } catch (IciqlException e) {
-                               if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS
-                                               && e.getIciqlCode() != IciqlException.CODE_DUPLICATE_KEY) {
-                                       throw e;
-                               }
-                       }
-               }
-
-               // tables are created using IF NOT EXISTS
-               // but we may still need to upgrade
-               db.upgradeTable(this);
-               return this;
-       }
-
-       void mapObject(Object obj) {
-               fieldMap.clear();
-               initObject(obj, fieldMap);
-
-               if (clazz.isAnnotationPresent(IQSchema.class)) {
-                       IQSchema schemaAnnotation = clazz.getAnnotation(IQSchema.class);
-                       // setup schema name mapping, if properly annotated
-                       if (!StringUtils.isNullOrEmpty(schemaAnnotation.value())) {
-                               schemaName = schemaAnnotation.value();
-                       }
-               }
-
-               if (clazz.isAnnotationPresent(IQTable.class)) {
-                       IQTable tableAnnotation = clazz.getAnnotation(IQTable.class);
-
-                       // setup table name mapping, if properly annotated
-                       if (!StringUtils.isNullOrEmpty(tableAnnotation.name())) {
-                               tableName = tableAnnotation.name();
-                       }
-
-                       // allow control over createTableIfRequired()
-                       createIfRequired = tableAnnotation.create();
-
-                       // model version
-                       if (clazz.isAnnotationPresent(IQVersion.class)) {
-                               IQVersion versionAnnotation = clazz.getAnnotation(IQVersion.class);
-                               if (versionAnnotation.value() > 0) {
-                                       tableVersion = versionAnnotation.value();
-                               }
-                       }
-
-                       // setup the primary index, if properly annotated
-                       if (tableAnnotation.primaryKey().length > 0) {
-                               List<String> primaryKey = Utils.newArrayList();
-                               primaryKey.addAll(Arrays.asList(tableAnnotation.primaryKey()));
-                               setPrimaryKey(primaryKey);
-                       }
-               }
-
-               if (clazz.isAnnotationPresent(IQView.class)) {
-                       IQView viewAnnotation = clazz.getAnnotation(IQView.class);
-
-                       // setup view name mapping, if properly annotated
-                       // set this as the table name so it fits in seemlessly with iciql
-                       if (!StringUtils.isNullOrEmpty(viewAnnotation.name())) {
-                               tableName = viewAnnotation.name();
-                       } else {
-                               tableName = clazz.getSimpleName();
-                       }
-
-                       // setup source table name mapping, if properly annotated
-                       if (!StringUtils.isNullOrEmpty(viewAnnotation.tableName())) {
-                               viewTableName = viewAnnotation.tableName();
-                       } else {
-                               // check for IQTable annotation on super class
-                               Class<?> superClass = clazz.getSuperclass();
-                               if (superClass.isAnnotationPresent(IQTable.class)) {
-                                       IQTable table = superClass.getAnnotation(IQTable.class);
-                                       if (StringUtils.isNullOrEmpty(table.name())) {
-                                               // super.SimpleClassName
-                                               viewTableName = superClass.getSimpleName();
-                                       } else {
-                                               // super.IQTable.name()
-                                               viewTableName = table.name();
-                                       }
-                               } else if (superClass.isAnnotationPresent(IQView.class)) {
-                                       // super class is a view
-                                       IQView parentView = superClass.getAnnotation(IQView.class);
-                                       if (StringUtils.isNullOrEmpty(parentView.tableName())) {
-                                               // parent view does not define a tableName, must be inherited
-                                               Class<?> superParent = superClass.getSuperclass();
-                                               if (superParent != null && superParent.isAnnotationPresent(IQTable.class)) {
-                                                       IQTable superParentTable = superParent.getAnnotation(IQTable.class);
-                                                       if (StringUtils.isNullOrEmpty(superParentTable.name())) {
-                                                               // super.super.SimpleClassName
-                                                               viewTableName = superParent.getSimpleName();
-                                                       } else {
-                                                               // super.super.IQTable.name()
-                                                               viewTableName = superParentTable.name();
-                                                       }
-                                               }
-                                       } else {
-                                               // super.IQView.tableName()
-                                               viewTableName = parentView.tableName();
-                                       }
-                               }
-
-                               if (StringUtils.isNullOrEmpty(viewTableName)) {
-                                       // still missing view table name
-                                       throw new IciqlException("View model class \"{0}\" is missing a table name!", tableName);
-                               }
-                       }
-
-                       // allow control over createTableIfRequired()
-                       createIfRequired = viewAnnotation.create();
-               }
-
-               if (clazz.isAnnotationPresent(IQIndex.class)) {
-                       // single table index
-                       IQIndex index = clazz.getAnnotation(IQIndex.class);
-                       addIndex(index);
-               }
-
-               if (clazz.isAnnotationPresent(IQIndexes.class)) {
-                       // multiple table indexes
-                       IQIndexes indexes = clazz.getAnnotation(IQIndexes.class);
-                       for (IQIndex index : indexes.value()) {
-                               addIndex(index);
-                       }
-               }
-
-               if (clazz.isAnnotationPresent(IQContraintUnique.class)) {
-                       // single table unique constraint
-                       IQContraintUnique constraint = clazz.getAnnotation(IQContraintUnique.class);
-                       addConstraintUnique(constraint);
-               }
-
-               if (clazz.isAnnotationPresent(IQContraintsUnique.class)) {
-                       // multiple table unique constraints
-                       IQContraintsUnique constraints = clazz.getAnnotation(IQContraintsUnique.class);
-                       for (IQContraintUnique constraint : constraints.value()) {
-                               addConstraintUnique(constraint);
-                       }
-               }
-
-               if (clazz.isAnnotationPresent(IQContraintForeignKey.class)) {
-                       // single table constraint
-                       IQContraintForeignKey constraint = clazz.getAnnotation(IQContraintForeignKey.class);
-                       addConstraintForeignKey(constraint);
-               }
-
-               if (clazz.isAnnotationPresent(IQContraintsForeignKey.class)) {
-                       // multiple table constraints
-                       IQContraintsForeignKey constraints = clazz.getAnnotation(IQContraintsForeignKey.class);
-                       for (IQContraintForeignKey constraint : constraints.value()) {
-                               addConstraintForeignKey(constraint);
-                       }
-               }
-
-       }
-
-       private void addConstraintForeignKey(IQContraintForeignKey constraint) {
-               List<String> foreignColumns = Arrays.asList(constraint.foreignColumns());
-               List<String> referenceColumns = Arrays.asList(constraint.referenceColumns());
-               addConstraintForeignKey(constraint.name(), foreignColumns, constraint.referenceName(), referenceColumns, constraint.deleteType(), constraint.updateType(), constraint.deferrabilityType());
-       }
-
-       private void addConstraintUnique(IQContraintUnique constraint) {
-               List<String> uniqueColumns = Arrays.asList(constraint.uniqueColumns());
-               addConstraintUnique(constraint.name(), uniqueColumns);
-       }
-
-       /**
-        * Defines a foreign key constraint with the specified parameters.
-        *
-        * @param name
-        *            name of the constraint
-        * @param foreignColumns
-        *            list of columns declared as foreign
-        * @param referenceName
-        *            reference table name
-        * @param referenceColumns
-        *            list of columns used in reference table
-        * @param deleteType
-        *            action on delete
-        * @param updateType
-        *            action on update
-        * @param deferrabilityType
-        *            deferrability mode
-        */
-       private void addConstraintForeignKey(String name,
-                       List<String> foreignColumns, String referenceName,
-                       List<String> referenceColumns, ConstraintDeleteType deleteType,
-                       ConstraintUpdateType updateType, ConstraintDeferrabilityType deferrabilityType) {
-               ConstraintForeignKeyDefinition constraint = new ConstraintForeignKeyDefinition();
-               if (StringUtils.isNullOrEmpty(name)) {
-                       constraint.constraintName = tableName + "_fkey_" + constraintsForeignKey.size();
-               } else {
-                       constraint.constraintName = name;
-               }
-               constraint.foreignColumns = Utils.newArrayList(foreignColumns);
-               constraint.referenceColumns = Utils.newArrayList(referenceColumns);
-               constraint.referenceTable = referenceName;
-               constraint.deleteType = deleteType;
-               constraint.updateType = updateType;
-               constraint.deferrabilityType = deferrabilityType;
-               constraintsForeignKey.add(constraint);
-       }
-
-       private void addIndex(IQIndex index) {
-               List<String> columns = Arrays.asList(index.value());
-               addIndex(index.name(), index.type(), columns);
-       }
-
-       List<IndexDefinition> getIndexes() {
-               return indexes;
-       }
-
-       List<ConstraintUniqueDefinition> getContraintsUnique() {
-               return constraintsUnique;
-       }
-
-       List<ConstraintForeignKeyDefinition> getContraintsForeignKey() {
-               return constraintsForeignKey;
-       }
-
-       private void initObject(Object obj, Map<Object, FieldDefinition> map) {
-               for (FieldDefinition def : fields) {
-                       Object newValue = def.initWithNewObject(obj);
-                       map.put(newValue, def);
-               }
-       }
-
-       void initSelectObject(SelectTable<T> table, Object obj, Map<Object, SelectColumn<T>> map, boolean reuse) {
-               for (FieldDefinition def : fields) {
-                       Object value;
-                       if (!reuse) {
-                               value = def.initWithNewObject(obj);
-                       } else {
-                               value = def.getValue(obj);
-                       }
-                       SelectColumn<T> column = new SelectColumn<T>(table, def);
-                       map.put(value, column);
-               }
-       }
-
-       /**
-        * Most queries executed by iciql have named select lists (select alpha,
-        * beta where...) but sometimes a wildcard select is executed (select *).
-        * When a wildcard query is executed on a table that has more columns than
-        * are mapped in your model object, this creates a column mapping issue.
-        * JaQu assumed that you can always use the integer index of the
-        * reflectively mapped field definition to determine position in the result
-        * set.
-        *
-        * This is not always true.
-        *
-        * iciql identifies when a select * query is executed and maps column names
-        * to a column index from the result set. If the select statement is
-        * explicit, then the standard assumed column index is used instead.
-        *
-        * @param rs
-        * @return
-        */
-       int[] mapColumns(SQLDialect dialect, boolean wildcardSelect, ResultSet rs) {
-               int[] columns = new int[fields.size()];
-               for (int i = 0; i < fields.size(); i++) {
-                       try {
-                               FieldDefinition def = fields.get(i);
-                               int columnIndex;
-                               if (wildcardSelect) {
-                                       // select *
-                                       // create column index by field name
-                                       columnIndex = rs.findColumn(dialect.extractColumnName(def.columnName));
-                               } else {
-                                       // select alpha, beta, gamma, etc
-                                       // explicit select order
-                                       columnIndex = i + 1;
-                               }
-                               columns[i] = columnIndex;
-                       } catch (SQLException s) {
-                               throw new IciqlException(s);
-                       }
-               }
-               return columns;
-       }
-
-       void readRow(SQLDialect dialect, Object item, ResultSet rs, int[] columns) {
-               for (int i = 0; i < fields.size(); i++) {
-                       FieldDefinition def = fields.get(i);
-                       Class<?> targetType = def.field.getType();
-                       Object o;
-                       if (targetType.isEnum()) {
-                               Object obj;
-                               try {
-                                       obj = rs.getObject(columns[i]);
-                               } catch (SQLException e) {
-                                       throw new IciqlException(e);
-                               }
-                               o = Utils.convertEnum(obj, targetType, def.enumType);
-                       } else {
-                               o = dialect.deserialize(rs, columns[i], targetType, def.typeAdapter);
-                       }
-                       def.setValue(item, o);
-               }
-       }
-
-       void appendSelectList(SQLStatement stat) {
-               for (int i = 0; i < fields.size(); i++) {
-                       if (i > 0) {
-                               stat.appendSQL(", ");
-                       }
-                       FieldDefinition def = fields.get(i);
-                       stat.appendColumn(def.columnName);
-               }
-       }
-
-       <Y, X> void appendSelectList(SQLStatement stat, Query<Y> query, X x) {
-               // select t0.col1, t0.col2, t0.col3...
-               // select table1.col1, table1.col2, table1.col3...
-               String selectDot = "";
-               SelectTable<?> sel = query.getSelectTable(x);
-               if (sel != null) {
-                       if (query.isJoin()) {
-                               selectDot = sel.getAs() + ".";
-                       } else {
-                               String sn = sel.getAliasDefinition().schemaName;
-                               String tn = sel.getAliasDefinition().tableName;
-                               selectDot = query.getDb().getDialect().prepareTableName(sn, tn) + ".";
-                       }
-               }
-
-               for (int i = 0; i < fields.size(); i++) {
-                       if (i > 0) {
-                               stat.appendSQL(", ");
-                       }
-                       stat.appendSQL(selectDot);
-                       FieldDefinition def = fields.get(i);
-                       if (def.isPrimitive) {
-                               Object obj = def.getValue(x);
-                               Object alias = query.getPrimitiveAliasByValue(obj);
-                               query.appendSQL(stat, x, alias);
-                       } else {
-                               Object obj = def.getValue(x);
-                               query.appendSQL(stat, x, obj);
-                       }
-               }
-       }
+    /**
+     * The meta data of an index.
+     */
+
+    public static class IndexDefinition {
+        public IndexType type;
+        public String indexName;
+
+        public List<String> columnNames;
+    }
+
+    /**
+     * The meta data of a constraint on foreign key.
+     */
+
+    public static class ConstraintForeignKeyDefinition {
+
+        public String constraintName;
+        public List<String> foreignColumns;
+        public String referenceTable;
+        public List<String> referenceColumns;
+        public ConstraintDeleteType deleteType = ConstraintDeleteType.UNSET;
+        public ConstraintUpdateType updateType = ConstraintUpdateType.UNSET;
+        public ConstraintDeferrabilityType deferrabilityType = ConstraintDeferrabilityType.UNSET;
+    }
+
+    /**
+     * The meta data of a unique constraint.
+     */
+
+    public static class ConstraintUniqueDefinition {
+
+        public String constraintName;
+        public List<String> uniqueColumns;
+    }
+
+
+    /**
+     * The meta data of a field.
+     */
+
+    static class FieldDefinition {
+        String columnName;
+        Field field;
+        String dataType;
+        int length;
+        int scale;
+        boolean isPrimaryKey;
+        boolean isAutoIncrement;
+        boolean trim;
+        boolean nullable;
+        String defaultValue;
+        EnumType enumType;
+        Class<?> enumTypeClass;
+        boolean isPrimitive;
+        String constraint;
+        Class<? extends DataTypeAdapter<?>> typeAdapter;
+
+        Object getValue(Object obj) {
+            try {
+                return field.get(obj);
+            } catch (Exception e) {
+                throw new IciqlException(e);
+            }
+        }
+
+        private Object initWithNewObject(Object obj) {
+            Object o = Utils.newObject(field.getType());
+            setValue(obj, o);
+            return o;
+        }
+
+        private void setValue(Object obj, Object o) {
+            try {
+                if (!field.isAccessible()) {
+                    field.setAccessible(true);
+                }
+
+                if (field.getType().isPrimitive() && o == null) {
+                    // do not attempt to set a primitive to null
+                    return;
+                }
+
+                field.set(obj, o);
+            } catch (IciqlException e) {
+                throw e;
+            } catch (Exception e) {
+                throw new IciqlException(e);
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return columnName.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof FieldDefinition) {
+                return o.hashCode() == hashCode();
+            }
+            return false;
+        }
+    }
+
+    public ArrayList<FieldDefinition> fields = Utils.newArrayList();
+    String schemaName;
+    String tableName;
+    String viewTableName;
+    int tableVersion;
+    List<String> primaryKeyColumnNames;
+    boolean memoryTable;
+    boolean multiplePrimitiveBools;
+
+    private boolean createIfRequired = true;
+    private Class<T> clazz;
+    private IdentityHashMap<Object, FieldDefinition> fieldMap = Utils.newIdentityHashMap();
+    private ArrayList<IndexDefinition> indexes = Utils.newArrayList();
+    ArrayList<ConstraintForeignKeyDefinition> constraintsForeignKey = Utils.newArrayList();
+    ArrayList<ConstraintUniqueDefinition> constraintsUnique = Utils.newArrayList();
+
+    TableDefinition(Class<T> clazz) {
+        this.clazz = clazz;
+        schemaName = null;
+        tableName = clazz.getSimpleName();
+    }
+
+    Class<T> getModelClass() {
+        return clazz;
+    }
+
+    List<FieldDefinition> getFields() {
+        return fields;
+    }
+
+    void defineSchemaName(String schemaName) {
+        this.schemaName = schemaName;
+    }
+
+    void defineTableName(String tableName) {
+        this.tableName = tableName;
+    }
+
+    void defineViewTableName(String viewTableName) {
+        this.viewTableName = viewTableName;
+    }
+
+    void defineMemoryTable() {
+        this.memoryTable = true;
+    }
+
+    void defineSkipCreate() {
+        this.createIfRequired = false;
+    }
+
+    /**
+     * Define a primary key by the specified model fields.
+     *
+     * @param modelFields the ordered list of model fields
+     */
+    void definePrimaryKey(Object[] modelFields) {
+        List<String> columnNames = mapColumnNames(modelFields);
+        setPrimaryKey(columnNames);
+    }
+
+    /**
+     * Define a primary key by the specified column names.
+     *
+     * @param columnNames the ordered list of column names
+     */
+    private void setPrimaryKey(List<String> columnNames) {
+        primaryKeyColumnNames = Utils.newArrayList(columnNames);
+        List<String> pkNames = Utils.newArrayList();
+        for (String name : columnNames) {
+            pkNames.add(name.toLowerCase());
+        }
+        // set isPrimaryKey flag for all field definitions
+        for (FieldDefinition fieldDefinition : fieldMap.values()) {
+            fieldDefinition.isPrimaryKey = pkNames.contains(fieldDefinition.columnName.toLowerCase());
+        }
+    }
+
+    private <A> String getColumnName(A fieldObject) {
+        FieldDefinition def = fieldMap.get(fieldObject);
+        return def == null ? null : def.columnName;
+    }
+
+    private ArrayList<String> mapColumnNames(Object[] columns) {
+        ArrayList<String> columnNames = Utils.newArrayList();
+        for (Object column : columns) {
+            columnNames.add(getColumnName(column));
+        }
+        return columnNames;
+    }
+
+    /**
+     * Defines an index with the specified model fields.
+     *
+     * @param name        the index name (optional)
+     * @param type        the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH)
+     * @param modelFields the ordered list of model fields
+     */
+    void defineIndex(String name, IndexType type, Object[] modelFields) {
+        List<String> columnNames = mapColumnNames(modelFields);
+        addIndex(name, type, columnNames);
+    }
+
+    /**
+     * Defines an index with the specified column names.
+     *
+     * @param type        the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH)
+     * @param columnNames the ordered list of column names
+     */
+    private void addIndex(String name, IndexType type, List<String> columnNames) {
+        IndexDefinition index = new IndexDefinition();
+        if (StringUtils.isNullOrEmpty(name)) {
+            index.indexName = tableName + "_idx_" + indexes.size();
+        } else {
+            index.indexName = name;
+        }
+        index.columnNames = Utils.newArrayList(columnNames);
+        index.type = type;
+        indexes.add(index);
+    }
+
+    /**
+     * Defines an unique constraint with the specified model fields.
+     *
+     * @param name        the constraint name (optional)
+     * @param modelFields the ordered list of model fields
+     */
+    void defineConstraintUnique(String name, Object[] modelFields) {
+        List<String> columnNames = mapColumnNames(modelFields);
+        addConstraintUnique(name, columnNames);
+    }
+
+    /**
+     * Defines an unique constraint.
+     *
+     * @param name
+     * @param columnNames
+     */
+    private void addConstraintUnique(String name, List<String> columnNames) {
+        ConstraintUniqueDefinition constraint = new ConstraintUniqueDefinition();
+        if (StringUtils.isNullOrEmpty(name)) {
+            constraint.constraintName = tableName + "_unique_" + constraintsUnique.size();
+        } else {
+            constraint.constraintName = name;
+        }
+        constraint.uniqueColumns = Utils.newArrayList(columnNames);
+        constraintsUnique.add(constraint);
+    }
+
+    /**
+     * Defines a foreign key constraint with the specified model fields.
+     *
+     * @param name        the constraint name (optional)
+     * @param modelFields the ordered list of model fields
+     */
+    void defineForeignKey(String name, Object[] modelFields, String refTableName, Object[] refModelFields,
+                          ConstraintDeleteType deleteType, ConstraintUpdateType updateType,
+                          ConstraintDeferrabilityType deferrabilityType) {
+        List<String> columnNames = mapColumnNames(modelFields);
+        List<String> referenceColumnNames = mapColumnNames(refModelFields);
+        addConstraintForeignKey(name, columnNames, refTableName, referenceColumnNames,
+                deleteType, updateType, deferrabilityType);
+    }
+
+    void defineColumnName(Object column, String columnName) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.columnName = columnName;
+        }
+    }
+
+    void defineAutoIncrement(Object column) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.isAutoIncrement = true;
+        }
+    }
+
+    void defineLength(Object column, int length) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.length = length;
+        }
+    }
+
+    void defineScale(Object column, int scale) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.scale = scale;
+        }
+    }
+
+    void defineTrim(Object column) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.trim = true;
+        }
+    }
+
+    void defineNullable(Object column, boolean isNullable) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.nullable = isNullable;
+        }
+    }
+
+    void defineDefaultValue(Object column, String defaultValue) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.defaultValue = defaultValue;
+        }
+    }
+
+    void defineConstraint(Object column, String constraint) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.constraint = constraint;
+        }
+    }
+
+    void defineTypeAdapter(Object column, Class<? extends DataTypeAdapter<?>> typeAdapter) {
+        FieldDefinition def = fieldMap.get(column);
+        if (def != null) {
+            def.typeAdapter = typeAdapter;
+        }
+    }
+
+    void mapFields(Db db) {
+        boolean byAnnotationsOnly = false;
+        boolean inheritColumns = false;
+        if (clazz.isAnnotationPresent(IQTable.class)) {
+            IQTable tableAnnotation = clazz.getAnnotation(IQTable.class);
+            byAnnotationsOnly = tableAnnotation.annotationsOnly();
+            inheritColumns = tableAnnotation.inheritColumns();
+        }
+
+        if (clazz.isAnnotationPresent(IQView.class)) {
+            IQView viewAnnotation = clazz.getAnnotation(IQView.class);
+            byAnnotationsOnly = viewAnnotation.annotationsOnly();
+            inheritColumns = viewAnnotation.inheritColumns();
+        }
+
+        List<Field> classFields = classFields(inheritColumns);
+
+        Set<FieldDefinition> uniqueFields = new LinkedHashSet<FieldDefinition>();
+        T defaultObject = Db.instance(clazz);
+        for (Field f : classFields) {
+            // check if we should skip this field
+            if (f.isAnnotationPresent(IQIgnore.class)) {
+                continue;
+            }
+
+            // default to field name
+            String columnName = f.getName();
+            boolean isAutoIncrement = false;
+            boolean isPrimaryKey = false;
+            int length = 0;
+            int scale = 0;
+            boolean trim = false;
+            boolean nullable = !f.getType().isPrimitive();
+            String defaultValue = "";
+            String constraint = "";
+            String dataType = null;
+            Class<? extends DataTypeAdapter<?>> typeAdapter = null;
+
+            // configure Java -> SQL enum mapping
+            EnumType enumType = Utils.getEnumType(f);
+            Class<?> enumTypeClass = Utils.getEnumTypeClass(f);
+
+            // try using default object
+            try {
+                f.setAccessible(true);
+                Object value = f.get(defaultObject);
+                if (value != null) {
+                    if (value.getClass().isEnum()) {
+                        // enum default, convert to target type
+                        Enum<?> anEnum = (Enum<?>) value;
+                        Object o = Utils.convertEnum(anEnum, enumType);
+                        defaultValue = ModelUtils.formatDefaultValue(o);
+                    } else {
+                        // object default
+                        defaultValue = ModelUtils.formatDefaultValue(value);
+                    }
+                }
+            } catch (IllegalAccessException e) {
+                throw new IciqlException(e, "failed to get default object for {0}", columnName);
+            }
+
+            // identify the type adapter
+            typeAdapter = Utils.getDataTypeAdapter(f.getAnnotations());
+            if (typeAdapter == null) {
+                typeAdapter = Utils.getDataTypeAdapter(f.getType().getAnnotations());
+            }
+
+            if (typeAdapter != null) {
+                DataTypeAdapter<?> dtt = db.getDialect().getAdapter(typeAdapter);
+                dataType = dtt.getDataType();
+            }
+
+            boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class);
+            if (hasAnnotation) {
+                IQColumn col = f.getAnnotation(IQColumn.class);
+                if (!StringUtils.isNullOrEmpty(col.name())) {
+                    columnName = col.name();
+                }
+                isAutoIncrement = col.autoIncrement();
+                isPrimaryKey = col.primaryKey();
+                length = col.length();
+                scale = col.scale();
+                trim = col.trim();
+                nullable = col.nullable();
+
+                // annotation overrides
+                if (!StringUtils.isNullOrEmpty(col.defaultValue())) {
+                    defaultValue = col.defaultValue();
+                }
+            }
+
+            boolean hasConstraint = f.isAnnotationPresent(IQConstraint.class);
+            if (hasConstraint) {
+                IQConstraint con = f.getAnnotation(IQConstraint.class);
+                // annotation overrides
+                if (!StringUtils.isNullOrEmpty(con.value())) {
+                    constraint = con.value();
+                }
+            }
+
+            boolean reflectiveMatch = !byAnnotationsOnly;
+            if (reflectiveMatch || hasAnnotation || hasConstraint) {
+                FieldDefinition fieldDef = new FieldDefinition();
+                fieldDef.isPrimitive = f.getType().isPrimitive();
+                fieldDef.field = f;
+                fieldDef.columnName = columnName;
+                fieldDef.isAutoIncrement = isAutoIncrement;
+                fieldDef.isPrimaryKey = isPrimaryKey;
+                fieldDef.length = length;
+                fieldDef.scale = scale;
+                fieldDef.trim = trim;
+                fieldDef.nullable = nullable;
+                fieldDef.defaultValue = defaultValue;
+                fieldDef.enumType = enumType;
+                fieldDef.enumTypeClass = enumTypeClass;
+                fieldDef.dataType = StringUtils.isNullOrEmpty(dataType) ? ModelUtils.getDataType(fieldDef) : dataType;
+                fieldDef.typeAdapter = typeAdapter;
+                fieldDef.constraint = constraint;
+                uniqueFields.add(fieldDef);
+            }
+        }
+        fields.addAll(uniqueFields);
+
+        List<String> primaryKey = Utils.newArrayList();
+        int primitiveBoolean = 0;
+        for (FieldDefinition fieldDef : fields) {
+            if (fieldDef.isPrimaryKey) {
+                primaryKey.add(fieldDef.columnName);
+            }
+            if (fieldDef.isPrimitive && fieldDef.field.getType().equals(boolean.class)) {
+                primitiveBoolean++;
+            }
+        }
+        if (primitiveBoolean > 1) {
+            multiplePrimitiveBools = true;
+            IciqlLogger
+                    .warn("Model {0} has multiple primitive booleans! Possible where,set,join clause problem!", tableName);
+        }
+        if (primaryKey.size() > 0) {
+            setPrimaryKey(primaryKey);
+        }
+    }
+
+    private List<Field> classFields(boolean inheritColumns) {
+        List<Field> classFields = Utils.newArrayList();
+        classFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        Class<?> superClass = clazz;
+        while (inheritColumns) {
+            superClass = superClass.getSuperclass();
+            classFields.addAll(Arrays.asList(superClass.getDeclaredFields()));
+
+            if (superClass.isAnnotationPresent(IQView.class)) {
+                IQView superView = superClass.getAnnotation(IQView.class);
+                inheritColumns = superView.inheritColumns();
+            } else if (superClass.isAnnotationPresent(IQTable.class)) {
+                IQTable superTable = superClass.getAnnotation(IQTable.class);
+                inheritColumns = superTable.inheritColumns();
+            } else {
+                inheritColumns = false;
+            }
+        }
+        return classFields;
+    }
+
+    void checkMultipleBooleans() {
+        if (multiplePrimitiveBools) {
+            throw new IciqlException(
+                    "Can not explicitly reference a primitive boolean if there are multiple boolean fields in your model class!");
+        }
+    }
+
+    void checkMultipleEnums(Object o) {
+        if (o == null) {
+            return;
+        }
+        Class<?> clazz = o.getClass();
+        if (!clazz.isEnum()) {
+            return;
+        }
+
+        int fieldCount = 0;
+        for (FieldDefinition fieldDef : fields) {
+            Class<?> targetType = fieldDef.field.getType();
+            if (clazz.equals(targetType)) {
+                fieldCount++;
+            }
+        }
+
+        if (fieldCount > 1) {
+            throw new IciqlException(
+                    "Can not explicitly reference {0} because there are {1} {0} fields in your model class!",
+                    clazz.getSimpleName(), fieldCount);
+        }
+    }
+
+    /**
+     * Optionally truncates strings to the maximum length and converts
+     * java.lang.Enum types to Strings or Integers.
+     */
+    Object getValue(Object obj, FieldDefinition field) {
+        Object value = field.getValue(obj);
+        if (value == null) {
+            return value;
+        }
+        if (field.enumType != null) {
+            // convert enumeration to INT or STRING
+            Enum<?> iqenum = (Enum<?>) value;
+            switch (field.enumType) {
+                case NAME:
+                    if (field.trim && field.length > 0) {
+                        if (iqenum.name().length() > field.length) {
+                            return iqenum.name().substring(0, field.length);
+                        }
+                    }
+                    return iqenum.name();
+                case ORDINAL:
+                    return iqenum.ordinal();
+                case ENUMID:
+                    if (!EnumId.class.isAssignableFrom(value.getClass())) {
+                        throw new IciqlException(field.field.getName() + " does not implement EnumId!");
+                    }
+                    EnumId<?> enumid = (EnumId<?>) value;
+                    return enumid.enumId();
+            }
+        }
+
+        if (field.trim && field.length > 0) {
+            if (value instanceof String) {
+                // clip strings
+                String s = (String) value;
+                if (s.length() > field.length) {
+                    return s.substring(0, field.length);
+                }
+                return s;
+            }
+            return value;
+        }
+
+        // return the value unchanged
+        return value;
+    }
+
+    PreparedStatement createInsertStatement(Db db, Object obj, boolean returnKey) {
+        SQLStatement stat = new SQLStatement(db);
+        StatementBuilder buff = new StatementBuilder("INSERT INTO ");
+        buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append('(');
+        for (FieldDefinition field : fields) {
+            if (skipInsertField(field, obj)) {
+                continue;
+            }
+            buff.appendExceptFirst(", ");
+            buff.append(db.getDialect().prepareColumnName(field.columnName));
+        }
+        buff.append(") VALUES(");
+        buff.resetCount();
+        for (FieldDefinition field : fields) {
+            if (skipInsertField(field, obj)) {
+                continue;
+            }
+            buff.appendExceptFirst(", ");
+            buff.append('?');
+            Object value = getValue(obj, field);
+            if (value == null) {
+                if (!field.nullable) {
+                    // try to interpret and instantiate a default value
+                    value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
+                }
+            }
+            Object parameter = db.getDialect().serialize(value, field.typeAdapter);
+            stat.addParameter(parameter);
+        }
+        buff.append(')');
+        stat.setSQL(buff.toString());
+        IciqlLogger.insert(stat.getSQL());
+        return stat.prepare(returnKey);
+    }
+
+    long insert(Db db, Object obj, boolean returnKey) {
+        if (!StringUtils.isNullOrEmpty(viewTableName)) {
+            throw new IciqlException("Iciql does not support inserting rows into views!");
+        }
+        SQLStatement stat = new SQLStatement(db);
+        StatementBuilder buff = new StatementBuilder("INSERT INTO ");
+        buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append('(');
+        for (FieldDefinition field : fields) {
+            if (skipInsertField(field, obj)) {
+                continue;
+            }
+            buff.appendExceptFirst(", ");
+            buff.append(db.getDialect().prepareColumnName(field.columnName));
+        }
+        buff.append(") VALUES(");
+        buff.resetCount();
+        for (FieldDefinition field : fields) {
+            if (skipInsertField(field, obj)) {
+                continue;
+            }
+            buff.appendExceptFirst(", ");
+            buff.append('?');
+            Object value = getValue(obj, field);
+            if (value == null && !field.nullable) {
+                // try to interpret and instantiate a default value
+                value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
+            }
+            Object parameter = db.getDialect().serialize(value, field.typeAdapter);
+            stat.addParameter(parameter);
+        }
+        buff.append(')');
+        stat.setSQL(buff.toString());
+        IciqlLogger.insert(stat.getSQL());
+        if (returnKey) {
+            return stat.executeInsert();
+        }
+        return stat.executeUpdate();
+    }
+
+    private boolean skipInsertField(FieldDefinition field, Object obj) {
+        if (field.isAutoIncrement) {
+            Object value = getValue(obj, field);
+            if (field.isPrimitive) {
+                // skip uninitialized primitive autoincrement values
+                if (value.toString().equals("0")) {
+                    return true;
+                }
+            } else if (value == null) {
+                // skip null object autoincrement values
+                return true;
+            }
+        } else {
+            // conditionally skip insert of null
+            Object value = getValue(obj, field);
+            if (value == null) {
+                return !StringUtils.isNullOrEmpty(field.defaultValue);
+            }
+        }
+        return false;
+    }
+
+    int merge(Db db, Object obj) {
+        if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
+            throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
+                    + " - no update possible");
+        }
+        SQLStatement stat = new SQLStatement(db);
+        db.getDialect().prepareMerge(stat, schemaName, tableName, this, obj);
+        IciqlLogger.merge(stat.getSQL());
+        return stat.executeUpdate();
+    }
+
+    int update(Db db, Object obj) {
+        if (!StringUtils.isNullOrEmpty(viewTableName)) {
+            throw new IciqlException("Iciql does not support updating rows in views!");
+        }
+        if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
+            throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
+                    + " - no update possible");
+        }
+        SQLStatement stat = new SQLStatement(db);
+        StatementBuilder buff = new StatementBuilder("UPDATE ");
+        buff.append(db.getDialect().prepareTableName(schemaName, tableName)).append(" SET ");
+        buff.resetCount();
+
+        for (FieldDefinition field : fields) {
+            if (!field.isPrimaryKey) {
+                Object value = getValue(obj, field);
+                if (value == null && !field.nullable) {
+                    // try to interpret and instantiate a default value
+                    value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass());
+                }
+                buff.appendExceptFirst(", ");
+                buff.append(db.getDialect().prepareColumnName(field.columnName));
+                buff.append(" = ?");
+                Object parameter = db.getDialect().serialize(value, field.typeAdapter);
+                stat.addParameter(parameter);
+            }
+        }
+        Object alias = Utils.newObject(obj.getClass());
+        Query<Object> query = Query.from(db, alias);
+        boolean firstCondition = true;
+        for (FieldDefinition field : fields) {
+            if (field.isPrimaryKey) {
+                Object fieldAlias = field.getValue(alias);
+                Object value = field.getValue(obj);
+                if (field.isPrimitive) {
+                    fieldAlias = query.getPrimitiveAliasByValue(fieldAlias);
+                }
+                if (!firstCondition) {
+                    query.addConditionToken(ConditionAndOr.AND);
+                }
+                firstCondition = false;
+                query.addConditionToken(new Condition<Object>(fieldAlias, value, CompareType.EQUAL));
+            }
+        }
+        stat.setSQL(buff.toString());
+        query.appendWhere(stat);
+        IciqlLogger.update(stat.getSQL());
+        return stat.executeUpdate();
+    }
+
+    int delete(Db db, Object obj) {
+        if (!StringUtils.isNullOrEmpty(viewTableName)) {
+            throw new IciqlException("Iciql does not support deleting rows from views!");
+        }
+        if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
+            throw new IllegalStateException("No primary key columns defined for table " + obj.getClass()
+                    + " - no update possible");
+        }
+        SQLStatement stat = new SQLStatement(db);
+        StatementBuilder buff = new StatementBuilder("DELETE FROM ");
+        buff.append(db.getDialect().prepareTableName(schemaName, tableName));
+        buff.resetCount();
+        Object alias = Utils.newObject(obj.getClass());
+        Query<Object> query = Query.from(db, alias);
+        boolean firstCondition = true;
+        for (FieldDefinition field : fields) {
+            if (field.isPrimaryKey) {
+                Object fieldAlias = field.getValue(alias);
+                Object value = field.getValue(obj);
+                if (field.isPrimitive) {
+                    fieldAlias = query.getPrimitiveAliasByValue(fieldAlias);
+                }
+                if (!firstCondition) {
+                    query.addConditionToken(ConditionAndOr.AND);
+                }
+                firstCondition = false;
+                query.addConditionToken(new Condition<Object>(fieldAlias, value, CompareType.EQUAL));
+            }
+        }
+        stat.setSQL(buff.toString());
+        query.appendWhere(stat);
+        IciqlLogger.delete(stat.getSQL());
+        return stat.executeUpdate();
+    }
+
+    TableDefinition<T> createIfRequired(Db db) {
+        // globally enable/disable check of create if required
+        if (db.getSkipCreate()) {
+            return this;
+        }
+        if (!createIfRequired) {
+            // skip table and index creation
+            // but still check for upgrades
+            db.upgradeTable(this);
+            return this;
+        }
+        if (db.hasCreated(clazz)) {
+            return this;
+        }
+        SQLStatement stat = new SQLStatement(db);
+        if (StringUtils.isNullOrEmpty(viewTableName)) {
+            db.getDialect().prepareCreateTable(stat, this);
+        } else {
+            db.getDialect().prepareCreateView(stat, this);
+        }
+        IciqlLogger.create(stat.getSQL());
+        try {
+            stat.executeUpdate();
+        } catch (IciqlException e) {
+            if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS) {
+                throw e;
+            }
+        }
+
+        // create indexes
+        for (IndexDefinition index : indexes) {
+            stat = new SQLStatement(db);
+            db.getDialect().prepareCreateIndex(stat, schemaName, tableName, index);
+            IciqlLogger.create(stat.getSQL());
+            try {
+                stat.executeUpdate();
+            } catch (IciqlException e) {
+                if (e.getIciqlCode() != IciqlException.CODE_OBJECT_ALREADY_EXISTS
+                        && e.getIciqlCode() != IciqlException.CODE_DUPLICATE_KEY) {
+                    throw e;
+                }
+            }
+        }
+
+        // tables are created using IF NOT EXISTS
+        // but we may still need to upgrade
+        db.upgradeTable(this);
+        return this;
+    }
+
+    void mapObject(Object obj) {
+        fieldMap.clear();
+        initObject(obj, fieldMap);
+
+        if (clazz.isAnnotationPresent(IQSchema.class)) {
+            IQSchema schemaAnnotation = clazz.getAnnotation(IQSchema.class);
+            // setup schema name mapping, if properly annotated
+            if (!StringUtils.isNullOrEmpty(schemaAnnotation.value())) {
+                schemaName = schemaAnnotation.value();
+            }
+        }
+
+        if (clazz.isAnnotationPresent(IQTable.class)) {
+            IQTable tableAnnotation = clazz.getAnnotation(IQTable.class);
+
+            // setup table name mapping, if properly annotated
+            if (!StringUtils.isNullOrEmpty(tableAnnotation.name())) {
+                tableName = tableAnnotation.name();
+            }
+
+            // allow control over createTableIfRequired()
+            createIfRequired = tableAnnotation.create();
+
+            // model version
+            if (clazz.isAnnotationPresent(IQVersion.class)) {
+                IQVersion versionAnnotation = clazz.getAnnotation(IQVersion.class);
+                if (versionAnnotation.value() > 0) {
+                    tableVersion = versionAnnotation.value();
+                }
+            }
+
+            // setup the primary index, if properly annotated
+            if (tableAnnotation.primaryKey().length > 0) {
+                List<String> primaryKey = Utils.newArrayList();
+                primaryKey.addAll(Arrays.asList(tableAnnotation.primaryKey()));
+                setPrimaryKey(primaryKey);
+            }
+        }
+
+        if (clazz.isAnnotationPresent(IQView.class)) {
+            IQView viewAnnotation = clazz.getAnnotation(IQView.class);
+
+            // setup view name mapping, if properly annotated
+            // set this as the table name so it fits in seemlessly with iciql
+            if (!StringUtils.isNullOrEmpty(viewAnnotation.name())) {
+                tableName = viewAnnotation.name();
+            } else {
+                tableName = clazz.getSimpleName();
+            }
+
+            // setup source table name mapping, if properly annotated
+            if (!StringUtils.isNullOrEmpty(viewAnnotation.tableName())) {
+                viewTableName = viewAnnotation.tableName();
+            } else {
+                // check for IQTable annotation on super class
+                Class<?> superClass = clazz.getSuperclass();
+                if (superClass.isAnnotationPresent(IQTable.class)) {
+                    IQTable table = superClass.getAnnotation(IQTable.class);
+                    if (StringUtils.isNullOrEmpty(table.name())) {
+                        // super.SimpleClassName
+                        viewTableName = superClass.getSimpleName();
+                    } else {
+                        // super.IQTable.name()
+                        viewTableName = table.name();
+                    }
+                } else if (superClass.isAnnotationPresent(IQView.class)) {
+                    // super class is a view
+                    IQView parentView = superClass.getAnnotation(IQView.class);
+                    if (StringUtils.isNullOrEmpty(parentView.tableName())) {
+                        // parent view does not define a tableName, must be inherited
+                        Class<?> superParent = superClass.getSuperclass();
+                        if (superParent != null && superParent.isAnnotationPresent(IQTable.class)) {
+                            IQTable superParentTable = superParent.getAnnotation(IQTable.class);
+                            if (StringUtils.isNullOrEmpty(superParentTable.name())) {
+                                // super.super.SimpleClassName
+                                viewTableName = superParent.getSimpleName();
+                            } else {
+                                // super.super.IQTable.name()
+                                viewTableName = superParentTable.name();
+                            }
+                        }
+                    } else {
+                        // super.IQView.tableName()
+                        viewTableName = parentView.tableName();
+                    }
+                }
+
+                if (StringUtils.isNullOrEmpty(viewTableName)) {
+                    // still missing view table name
+                    throw new IciqlException("View model class \"{0}\" is missing a table name!", tableName);
+                }
+            }
+
+            // allow control over createTableIfRequired()
+            createIfRequired = viewAnnotation.create();
+        }
+
+        if (clazz.isAnnotationPresent(IQIndex.class)) {
+            // single table index
+            IQIndex index = clazz.getAnnotation(IQIndex.class);
+            addIndex(index);
+        }
+
+        if (clazz.isAnnotationPresent(IQIndexes.class)) {
+            // multiple table indexes
+            IQIndexes indexes = clazz.getAnnotation(IQIndexes.class);
+            for (IQIndex index : indexes.value()) {
+                addIndex(index);
+            }
+        }
+
+        if (clazz.isAnnotationPresent(IQContraintUnique.class)) {
+            // single table unique constraint
+            IQContraintUnique constraint = clazz.getAnnotation(IQContraintUnique.class);
+            addConstraintUnique(constraint);
+        }
+
+        if (clazz.isAnnotationPresent(IQContraintsUnique.class)) {
+            // multiple table unique constraints
+            IQContraintsUnique constraints = clazz.getAnnotation(IQContraintsUnique.class);
+            for (IQContraintUnique constraint : constraints.value()) {
+                addConstraintUnique(constraint);
+            }
+        }
+
+        if (clazz.isAnnotationPresent(IQContraintForeignKey.class)) {
+            // single table constraint
+            IQContraintForeignKey constraint = clazz.getAnnotation(IQContraintForeignKey.class);
+            addConstraintForeignKey(constraint);
+        }
+
+        if (clazz.isAnnotationPresent(IQContraintsForeignKey.class)) {
+            // multiple table constraints
+            IQContraintsForeignKey constraints = clazz.getAnnotation(IQContraintsForeignKey.class);
+            for (IQContraintForeignKey constraint : constraints.value()) {
+                addConstraintForeignKey(constraint);
+            }
+        }
+
+    }
+
+    private void addConstraintForeignKey(IQContraintForeignKey constraint) {
+        List<String> foreignColumns = Arrays.asList(constraint.foreignColumns());
+        List<String> referenceColumns = Arrays.asList(constraint.referenceColumns());
+        addConstraintForeignKey(constraint.name(), foreignColumns, constraint.referenceName(), referenceColumns, constraint.deleteType(), constraint.updateType(), constraint.deferrabilityType());
+    }
+
+    private void addConstraintUnique(IQContraintUnique constraint) {
+        List<String> uniqueColumns = Arrays.asList(constraint.uniqueColumns());
+        addConstraintUnique(constraint.name(), uniqueColumns);
+    }
+
+    /**
+     * Defines a foreign key constraint with the specified parameters.
+     *
+     * @param name              name of the constraint
+     * @param foreignColumns    list of columns declared as foreign
+     * @param referenceName     reference table name
+     * @param referenceColumns  list of columns used in reference table
+     * @param deleteType        action on delete
+     * @param updateType        action on update
+     * @param deferrabilityType deferrability mode
+     */
+    private void addConstraintForeignKey(String name,
+                                         List<String> foreignColumns, String referenceName,
+                                         List<String> referenceColumns, ConstraintDeleteType deleteType,
+                                         ConstraintUpdateType updateType, ConstraintDeferrabilityType deferrabilityType) {
+        ConstraintForeignKeyDefinition constraint = new ConstraintForeignKeyDefinition();
+        if (StringUtils.isNullOrEmpty(name)) {
+            constraint.constraintName = tableName + "_fkey_" + constraintsForeignKey.size();
+        } else {
+            constraint.constraintName = name;
+        }
+        constraint.foreignColumns = Utils.newArrayList(foreignColumns);
+        constraint.referenceColumns = Utils.newArrayList(referenceColumns);
+        constraint.referenceTable = referenceName;
+        constraint.deleteType = deleteType;
+        constraint.updateType = updateType;
+        constraint.deferrabilityType = deferrabilityType;
+        constraintsForeignKey.add(constraint);
+    }
+
+    private void addIndex(IQIndex index) {
+        List<String> columns = Arrays.asList(index.value());
+        addIndex(index.name(), index.type(), columns);
+    }
+
+    List<IndexDefinition> getIndexes() {
+        return indexes;
+    }
+
+    List<ConstraintUniqueDefinition> getContraintsUnique() {
+        return constraintsUnique;
+    }
+
+    List<ConstraintForeignKeyDefinition> getContraintsForeignKey() {
+        return constraintsForeignKey;
+    }
+
+    private void initObject(Object obj, Map<Object, FieldDefinition> map) {
+        for (FieldDefinition def : fields) {
+            Object newValue = def.initWithNewObject(obj);
+            map.put(newValue, def);
+        }
+    }
+
+    void initSelectObject(SelectTable<T> table, Object obj, Map<Object, SelectColumn<T>> map, boolean reuse) {
+        for (FieldDefinition def : fields) {
+            Object value;
+            if (!reuse) {
+                value = def.initWithNewObject(obj);
+            } else {
+                value = def.getValue(obj);
+            }
+            SelectColumn<T> column = new SelectColumn<T>(table, def);
+            map.put(value, column);
+        }
+    }
+
+    /**
+     * Most queries executed by iciql have named select lists (select alpha,
+     * beta where...) but sometimes a wildcard select is executed (select *).
+     * When a wildcard query is executed on a table that has more columns than
+     * are mapped in your model object, this creates a column mapping issue.
+     * JaQu assumed that you can always use the integer index of the
+     * reflectively mapped field definition to determine position in the result
+     * set.
+     * <p>
+     * This is not always true.
+     * <p>
+     * iciql identifies when a select * query is executed and maps column names
+     * to a column index from the result set. If the select statement is
+     * explicit, then the standard assumed column index is used instead.
+     *
+     * @param rs
+     * @return
+     */
+    int[] mapColumns(SQLDialect dialect, boolean wildcardSelect, ResultSet rs) {
+        int[] columns = new int[fields.size()];
+        for (int i = 0; i < fields.size(); i++) {
+            try {
+                FieldDefinition def = fields.get(i);
+                int columnIndex;
+                if (wildcardSelect) {
+                    // select *
+                    // create column index by field name
+                    columnIndex = rs.findColumn(dialect.extractColumnName(def.columnName));
+                } else {
+                    // select alpha, beta, gamma, etc
+                    // explicit select order
+                    columnIndex = i + 1;
+                }
+                columns[i] = columnIndex;
+            } catch (SQLException s) {
+                throw new IciqlException(s);
+            }
+        }
+        return columns;
+    }
+
+    void readRow(SQLDialect dialect, Object item, ResultSet rs, int[] columns) {
+        for (int i = 0; i < fields.size(); i++) {
+            FieldDefinition def = fields.get(i);
+            Class<?> targetType = def.field.getType();
+            Object o;
+            if (targetType.isEnum()) {
+                Object obj;
+                try {
+                    obj = rs.getObject(columns[i]);
+                } catch (SQLException e) {
+                    throw new IciqlException(e);
+                }
+                o = Utils.convertEnum(obj, targetType, def.enumType);
+            } else {
+                o = dialect.deserialize(rs, columns[i], targetType, def.typeAdapter);
+            }
+            def.setValue(item, o);
+        }
+    }
+
+    void appendSelectList(SQLStatement stat) {
+        for (int i = 0; i < fields.size(); i++) {
+            if (i > 0) {
+                stat.appendSQL(", ");
+            }
+            FieldDefinition def = fields.get(i);
+            stat.appendColumn(def.columnName);
+        }
+    }
+
+    <Y, X> void appendSelectList(SQLStatement stat, Query<Y> query, X x) {
+        // select t0.col1, t0.col2, t0.col3...
+        // select table1.col1, table1.col2, table1.col3...
+        String selectDot = "";
+        SelectTable<?> sel = query.getSelectTable(x);
+        if (sel != null) {
+            if (query.isJoin()) {
+                selectDot = sel.getAs() + ".";
+            } else {
+                String sn = sel.getAliasDefinition().schemaName;
+                String tn = sel.getAliasDefinition().tableName;
+                selectDot = query.getDb().getDialect().prepareTableName(sn, tn) + ".";
+            }
+        }
+
+        for (int i = 0; i < fields.size(); i++) {
+            if (i > 0) {
+                stat.appendSQL(", ");
+            }
+            stat.appendSQL(selectDot);
+            FieldDefinition def = fields.get(i);
+            if (def.isPrimitive) {
+                Object obj = def.getValue(x);
+                Object alias = query.getPrimitiveAliasByValue(obj);
+                query.appendSQL(stat, x, alias);
+            } else {
+                Object obj = def.getValue(x);
+                query.appendSQL(stat, x, obj);
+            }
+        }
+    }
 }
index b7172030e40145ed5cc72a99f030a5a105742385..d775f0fc570a67160ddef0d6e2f1449b03b1b6cb 100644 (file)
 
 package com.iciql;
 
-import static com.iciql.ValidationRemark.consider;
-import static com.iciql.ValidationRemark.error;
-import static com.iciql.ValidationRemark.warn;
-import static com.iciql.util.JdbcUtils.closeSilently;
-import static com.iciql.util.StringUtils.isNullOrEmpty;
-import static java.text.MessageFormat.format;
-
-import java.io.Serializable;
-import java.lang.reflect.Modifier;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQIndex;
 import com.iciql.Iciql.IQIndexes;
@@ -51,6 +32,23 @@ import com.iciql.util.StatementBuilder;
 import com.iciql.util.StringUtils;
 import com.iciql.util.Utils;
 
+import java.io.Serializable;
+import java.lang.reflect.Modifier;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static com.iciql.ValidationRemark.*;
+import static com.iciql.util.JdbcUtils.closeSilently;
+import static com.iciql.util.StringUtils.isNullOrEmpty;
+import static java.text.MessageFormat.format;
+
 /**
  * Class to inspect the contents of a particular table including its indexes.
  * This class does the bulk of the work in terms of model generation and model
@@ -58,666 +56,661 @@ import com.iciql.util.Utils;
  */
 public class TableInspector {
 
-       private String schema;
-       private String table;
-       private Class<? extends java.util.Date> dateTimeClass;
-       private List<String> primaryKeys = Utils.newArrayList();
-       private Map<String, IndexInspector> indexes;
-       private Map<String, ColumnInspector> columns;
-       private final String eol = "\n";
-
-       TableInspector(String schema, String table, Class<? extends java.util.Date> dateTimeClass) {
-               this.schema = schema;
-               this.table = table;
-               this.dateTimeClass = dateTimeClass;
-       }
-
-       /**
-        * Tests to see if this TableInspector represents schema.table.
-        * <p>
-        * 
-        * @param schema
-        *            the schema name
-        * @param table
-        *            the table name
-        * @return true if the table matches
-        */
-       boolean matches(String schema, String table) {
-               if (isNullOrEmpty(schema)) {
-                       // table name matching
-                       return this.table.equalsIgnoreCase(table);
-               } else if (isNullOrEmpty(table)) {
-                       // schema name matching
-                       return this.schema.equalsIgnoreCase(schema);
-               } else {
-                       // exact table matching
-                       return this.schema.equalsIgnoreCase(schema) && this.table.equalsIgnoreCase(table);
-               }
-       }
-
-       /**
-        * Reads the DatabaseMetaData for the details of this table including
-        * primary keys and indexes.
-        * 
-        * @param metaData
-        *            the database meta data
-        */
-       void read(DatabaseMetaData metaData) throws SQLException {
-               ResultSet rs = null;
-
-               // primary keys
-               try {
-                       rs = metaData.getPrimaryKeys(null, schema, table);
-                       while (rs.next()) {
-                               String c = rs.getString("COLUMN_NAME");
-                               primaryKeys.add(c);
-                       }
-                       closeSilently(rs);
-
-                       // indexes
-                       rs = metaData.getIndexInfo(null, schema, table, false, true);
-                       indexes = Utils.newHashMap();
-                       while (rs.next()) {
-                               IndexInspector info = new IndexInspector(rs);
-                               if (info.type.equals(IndexType.UNIQUE)) {
-                                       String name = info.name.toLowerCase();
-                                       if (name.startsWith("primary") || name.startsWith("sys_idx_sys_pk")
-                                                       || name.startsWith("sql") || name.endsWith("_pkey")) {
-                                               // skip primary key indexes
-                                               continue;
-                                       }
-                               }
-                               if (indexes.containsKey(info.name)) {
-                                       indexes.get(info.name).addColumn(rs);
-                               } else {
-                                       indexes.put(info.name, info);
-                               }
-                       }
-                       closeSilently(rs);
-
-                       // columns
-                       rs = metaData.getColumns(null, schema, table, null);
-                       columns = Utils.newHashMap();
-                       while (rs.next()) {
-                               ColumnInspector col = new ColumnInspector();
-                               col.name = rs.getString("COLUMN_NAME");
-                               col.type = rs.getString("TYPE_NAME");
-                               col.clazz = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
-                               col.size = rs.getInt("COLUMN_SIZE");
-                               col.nullable = rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable;
-                               try {
-                                       Object autoIncrement = rs.getObject("IS_AUTOINCREMENT");
-                                       if (autoIncrement instanceof Boolean) {
-                                               col.isAutoIncrement = (Boolean) autoIncrement;
-                                       } else if (autoIncrement instanceof String) {
-                                               String val = autoIncrement.toString().toLowerCase();
-                                               col.isAutoIncrement = val.equals("true") | val.equals("yes");
-                                       } else if (autoIncrement instanceof Number) {
-                                               Number n = (Number) autoIncrement;
-                                               col.isAutoIncrement = n.intValue() > 0;
-                                       }
-                               } catch (SQLException s) {
+    private String schema;
+    private String table;
+    private Class<? extends java.util.Date> dateTimeClass;
+    private List<String> primaryKeys = Utils.newArrayList();
+    private Map<String, IndexInspector> indexes;
+    private Map<String, ColumnInspector> columns;
+    private final String eol = "\n";
+
+    TableInspector(String schema, String table, Class<? extends java.util.Date> dateTimeClass) {
+        this.schema = schema;
+        this.table = table;
+        this.dateTimeClass = dateTimeClass;
+    }
+
+    /**
+     * Tests to see if this TableInspector represents schema.table.
+     * <p>
+     *
+     * @param schema the schema name
+     * @param table  the table name
+     * @return true if the table matches
+     */
+    boolean matches(String schema, String table) {
+        if (isNullOrEmpty(schema)) {
+            // table name matching
+            return this.table.equalsIgnoreCase(table);
+        } else if (isNullOrEmpty(table)) {
+            // schema name matching
+            return this.schema.equalsIgnoreCase(schema);
+        } else {
+            // exact table matching
+            return this.schema.equalsIgnoreCase(schema) && this.table.equalsIgnoreCase(table);
+        }
+    }
+
+    /**
+     * Reads the DatabaseMetaData for the details of this table including
+     * primary keys and indexes.
+     *
+     * @param metaData the database meta data
+     */
+    void read(DatabaseMetaData metaData) throws SQLException {
+        ResultSet rs = null;
+
+        // primary keys
+        try {
+            rs = metaData.getPrimaryKeys(null, schema, table);
+            while (rs.next()) {
+                String c = rs.getString("COLUMN_NAME");
+                primaryKeys.add(c);
+            }
+            closeSilently(rs);
+
+            // indexes
+            rs = metaData.getIndexInfo(null, schema, table, false, true);
+            indexes = Utils.newHashMap();
+            while (rs.next()) {
+                IndexInspector info = new IndexInspector(rs);
+                if (info.type.equals(IndexType.UNIQUE)) {
+                    String name = info.name.toLowerCase();
+                    if (name.startsWith("primary") || name.startsWith("sys_idx_sys_pk")
+                            || name.startsWith("sql") || name.endsWith("_pkey")) {
+                        // skip primary key indexes
+                        continue;
+                    }
+                }
+                if (indexes.containsKey(info.name)) {
+                    indexes.get(info.name).addColumn(rs);
+                } else {
+                    indexes.put(info.name, info);
+                }
+            }
+            closeSilently(rs);
+
+            // columns
+            rs = metaData.getColumns(null, schema, table, null);
+            columns = Utils.newHashMap();
+            while (rs.next()) {
+                ColumnInspector col = new ColumnInspector();
+                col.name = rs.getString("COLUMN_NAME");
+                col.type = rs.getString("TYPE_NAME");
+                col.clazz = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
+                col.size = rs.getInt("COLUMN_SIZE");
+                col.nullable = rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable;
+                try {
+                    Object autoIncrement = rs.getObject("IS_AUTOINCREMENT");
+                    if (autoIncrement instanceof Boolean) {
+                        col.isAutoIncrement = (Boolean) autoIncrement;
+                    } else if (autoIncrement instanceof String) {
+                        String val = autoIncrement.toString().toLowerCase();
+                        col.isAutoIncrement = val.equals("true") | val.equals("yes");
+                    } else if (autoIncrement instanceof Number) {
+                        Number n = (Number) autoIncrement;
+                        col.isAutoIncrement = n.intValue() > 0;
+                    }
+                } catch (SQLException s) {
 //                                     throw s;
-                               }
-                               if (primaryKeys.size() == 1) {
-                                       if (col.name.equalsIgnoreCase(primaryKeys.get(0))) {
-                                               col.isPrimaryKey = true;
-                                       }
-                               }
-                               if (!col.isAutoIncrement) {
-                                       col.defaultValue = rs.getString("COLUMN_DEF");
-                               }
-                               columns.put(col.name.toLowerCase(), col);
-                       }
-               } finally {
-                       closeSilently(rs);
-               }
-       }
-
-       /**
-        * Generates a model (class definition) from this table. The model includes
-        * indexes, primary keys, default values, lengths, and nullables.
-        * information.
-        * <p>
-        * The caller may optionally set a destination package name, whether or not
-        * to include the schema name (setting schema can be a problem when using
-        * the model between databases), and if to automatically trim strings for
-        * those that have a maximum length.
-        * <p>
-        * 
-        * @param packageName
-        * @param annotateSchema
-        * @param trimStrings
-        * @return a complete model (class definition) for this table as a string
-        */
-       String generateModel(String packageName, boolean annotateSchema, boolean trimStrings) {
-
-               // import statements
-               Set<String> imports = Utils.newHashSet();
-               imports.add(Serializable.class.getCanonicalName());
-               imports.add(IQSchema.class.getCanonicalName());
-               imports.add(IQTable.class.getCanonicalName());
-               imports.add(IQIndexes.class.getCanonicalName());
-               imports.add(IQIndex.class.getCanonicalName());
-               imports.add(IQColumn.class.getCanonicalName());
-               imports.add(IndexType.class.getCanonicalName());
-
-               // fields
-               StringBuilder fields = new StringBuilder();
-               List<ColumnInspector> sortedColumns = Utils.newArrayList(columns.values());
-               Collections.sort(sortedColumns);
-               for (ColumnInspector col : sortedColumns) {
-                       fields.append(generateColumn(imports, col, trimStrings));
-               }
-
-               // build complete class definition
-               StringBuilder model = new StringBuilder();
-               if (!isNullOrEmpty(packageName)) {
-                       // package
-                       model.append("package " + packageName + ";");
-                       model.append(eol).append(eol);
-               }
-
-               // imports
-               List<String> sortedImports = new ArrayList<String>(imports);
-               Collections.sort(sortedImports);
-               for (String imp : sortedImports) {
-                       model.append("import ").append(imp).append(';').append(eol);
-               }
-               model.append(eol);
-
-               // @IQSchema
-               if (annotateSchema && !isNullOrEmpty(schema)) {
-                       model.append('@').append(IQSchema.class.getSimpleName());
-                       model.append('(');
-                       AnnotationBuilder ap = new AnnotationBuilder();
-                       ap.addParameter(null, schema);
-                       model.append(ap);
-                       model.append(')').append(eol);
-               }
-
-               // @IQTable
-               model.append('@').append(IQTable.class.getSimpleName());
-               model.append('(');
-
-               // IQTable annotation parameters
-               AnnotationBuilder ap = new AnnotationBuilder();
-               ap.addParameter("name", table);
-
-               if (primaryKeys.size() > 1) {
-                       ap.addParameter("primaryKey", primaryKeys);
-               }
-
-               // finish @IQTable annotation
-               model.append(ap);
-               model.append(')').append(eol);
-
-               // @IQIndexes
-               // @IQIndex
-               String indexAnnotations = generateIndexAnnotations();
-               if (!StringUtils.isNullOrEmpty(indexAnnotations)) {
-                       model.append(indexAnnotations);
-               }
-
-               // class declaration
-               String clazzName = ModelUtils.convertTableToClassName(table);
-               model.append(format("public class {0} implements Serializable '{'", clazzName)).append(eol);
-               model.append(eol);
-               model.append("\tprivate static final long serialVersionUID = 1L;").append(eol);
-               model.append(eol);
-
-               // field declarations
-               model.append(fields);
-
-               // default constructor
-               model.append("\t" + "public ").append(clazzName).append("() {").append(eol);
-               model.append("\t}").append(eol);
-
-               // end of class body
-               model.append('}');
-               model.trimToSize();
-               return model.toString();
-       }
-
-       /**
-        * Generates the specified index annotation.
-        * 
-        * @param ap
-        */
-       String generateIndexAnnotations() {
-               if (indexes == null || indexes.size() == 0) {
-                       // no matching indexes
-                       return null;
-               }
-               AnnotationBuilder ap = new AnnotationBuilder();
-               if (indexes.size() == 1) {
-                       // single index
-                       IndexInspector index = indexes.values().toArray(new IndexInspector[1])[0];
-                       ap.append(generateIndexAnnotation(index));
-                       ap.append(eol);
-               } else {
-                       // multiple indexes
-                       ap.append('@').append(IQIndexes.class.getSimpleName());
-                       ap.append("({");
-                       ap.resetCount();
-                       for (IndexInspector index : indexes.values()) {
-                               ap.appendExceptFirst(", ");
-                               ap.append(generateIndexAnnotation(index));
-                       }
-                       ap.append("})").append(eol);
-               }
-               return ap.toString();
-       }
-
-       private String generateIndexAnnotation(IndexInspector index) {
-               AnnotationBuilder ap = new AnnotationBuilder();
-               ap.append('@').append(IQIndex.class.getSimpleName());
-               ap.append('(');
-               ap.resetCount();
-               if (!StringUtils.isNullOrEmpty(index.name)) {
-                       ap.addParameter("name", index.name);
-               }
-               if (!index.type.equals(IndexType.STANDARD)) {
-                       ap.addEnum("type", index.type);
-               }
-               if (ap.getCount() > 0) {
-                       // multiple fields specified
-                       ap.addParameter("value", index.columns);
-               } else {
-                       // default value
-                       ap.addParameter(null, index.columns);
-               }
-               ap.append(')');
-               return ap.toString();
-       }
-
-       private StatementBuilder generateColumn(Set<String> imports, ColumnInspector col, boolean trimStrings) {
-               StatementBuilder sb = new StatementBuilder();
-               Class<?> clazz = col.clazz;
-               String column = ModelUtils.convertColumnToFieldName(col.name.toLowerCase());
-               sb.append('\t');
-               if (clazz == null) {
-                       // unsupported type
-                       clazz = Object.class;
-                       sb.append("// unsupported type " + col.type);
-               } else {
-                       // Imports
-                       // don't import primitives, java.lang classes, or byte []
-                       if (clazz.getPackage() == null) {
-                       } else if (clazz.getPackage().getName().equals("java.lang")) {
-                       } else if (clazz.equals(byte[].class)) {
-                       } else {
-                               imports.add(clazz.getCanonicalName());
-                       }
-                       // @IQColumn
-                       sb.append('@').append(IQColumn.class.getSimpleName());
-
-                       // IQColumn annotation parameters
-                       AnnotationBuilder ap = new AnnotationBuilder();
-
-                       // IQColumn.name
-                       if (!col.name.equalsIgnoreCase(column)) {
-                               ap.addParameter("name", col.name);
-                       }
-
-                       // IQColumn.primaryKey
-                       // composite primary keys are annotated on the table
-                       if (col.isPrimaryKey && primaryKeys.size() == 1) {
-                               ap.addParameter("primaryKey=true");
-                       }
-
-                       // IQColumn.length
-                       if ((clazz == String.class) && (col.size > 0) && (col.size < Integer.MAX_VALUE)) {
-                               ap.addParameter("length", col.size);
-
-                               // IQColumn.trim
-                               if (trimStrings) {
-                                       ap.addParameter("trim=true");
-                               }
-                       } else {
-                               // IQColumn.AutoIncrement
-                               if (col.isAutoIncrement) {
-                                       ap.addParameter("autoIncrement=true");
-                               }
-                       }
-
-                       // IQColumn.nullable
-                       if (!col.nullable) {
-                               ap.addParameter("nullable=false");
-                       }
-
-                       // IQColumn.defaultValue
-                       if (!isNullOrEmpty(col.defaultValue)) {
-                               ap.addParameter("defaultValue=\"" + col.defaultValue + "\"");
-                       }
-
-                       // add leading and trailing ()
-                       if (ap.length() > 0) {
-                               ap.insert(0, '(');
-                               ap.append(')');
-                       }
-                       sb.append(ap);
-               }
-               sb.append(eol);
-
-               // variable declaration
-               sb.append("\t" + "public ");
-               sb.append(clazz.getSimpleName());
-               sb.append(' ');
-               sb.append(column);
-               sb.append(';');
-               sb.append(eol).append(eol);
-               return sb;
-       }
-
-       /**
-        * Validates that a table definition (annotated, interface, or both) matches
-        * the current state of the table and indexes in the database. Results are
-        * returned as a list of validation remarks which includes recommendations,
-        * warnings, and errors about the model. The caller may choose to have
-        * validate throw an exception on any validation ERROR.
-        * 
-        * @param def
-        *            the table definition
-        * @param throwError
-        *            whether or not to throw an exception if an error was found
-        * @return a list if validation remarks
-        */
-       <T> List<ValidationRemark> validate(TableDefinition<T> def, boolean throwError) {
-               List<ValidationRemark> remarks = Utils.newArrayList();
-
-               // model class definition validation
-               if (!Modifier.isPublic(def.getModelClass().getModifiers())) {
-                       remarks.add(error(table, "SCHEMA",
-                                       format("Class {0} MUST BE PUBLIC!", def.getModelClass().getCanonicalName())).throwError(
-                                       throwError));
-               }
-
-               // Schema Validation
-               if (!isNullOrEmpty(schema)) {
-                       if (isNullOrEmpty(def.schemaName)) {
-                               remarks.add(consider(table, "SCHEMA",
-                                               format("@{0}(\"{1}\")", IQSchema.class.getSimpleName(), schema)));
-                       } else if (!schema.equalsIgnoreCase(def.schemaName)) {
-                               remarks.add(error(
-                                               table,
-                                               "SCHEMA",
-                                               format("@{0}(\"{1}\") != {2}", IQSchema.class.getSimpleName(), def.schemaName, schema))
-                                               .throwError(throwError));
-                       }
-               }
-
-               // index validation
-               for (IndexInspector index : indexes.values()) {
-                       validate(remarks, def, index, throwError);
-               }
-
-               // field column validation
-               for (FieldDefinition fieldDef : def.getFields()) {
-                       validate(remarks, fieldDef, throwError);
-               }
-               return remarks;
-       }
-
-       /**
-        * Validates an inspected index from the database against the
-        * IndexDefinition within the TableDefinition.
-        */
-       private <T> void validate(List<ValidationRemark> remarks, TableDefinition<T> def, IndexInspector index,
-                       boolean throwError) {
-               List<IndexDefinition> defIndexes = def.getIndexes();
-               if (defIndexes.size() > indexes.size()) {
-                       remarks.add(warn(table, IndexType.STANDARD.name(), "More model indexes  than database indexes"));
-               } else if (defIndexes.size() < indexes.size()) {
-                       remarks.add(warn(table, IndexType.STANDARD.name(), "Model class is missing indexes"));
-               }
-               // TODO complete index validation.
-               // need to actually compare index types and columns within each index.
-               
-               // TODO add constraints validation
-               List<ConstraintUniqueDefinition> defContraintsU = def.getContraintsUnique();
-               List<ConstraintForeignKeyDefinition> defContraintsFK = def.getContraintsForeignKey();
-       }
-
-       /**
-        * Validates a column against the model's field definition. Checks for
-        * existence, supported type, type mapping, default value, defined lengths,
-        * primary key, autoincrement.
-        */
-       private void validate(List<ValidationRemark> remarks, FieldDefinition fieldDef, boolean throwError) {
-               // unknown field
-               if (!columns.containsKey(fieldDef.columnName.toLowerCase())) {
-                       // unknown column mapping
-                       remarks.add(error(table, fieldDef, "Does not exist in database!").throwError(throwError));
-                       return;
-               }
-               ColumnInspector col = columns.get(fieldDef.columnName.toLowerCase());
-               Class<?> fieldClass = fieldDef.field.getType();
-               Class<?> jdbcClass = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
-
-               // supported type check
-               // iciql maps to VARCHAR for unsupported types.
-               if (fieldDef.dataType.equals("VARCHAR") && (fieldClass != String.class)) {
-                       remarks.add(error(table, fieldDef,
-                                       "iciql does not currently implement support for " + fieldClass.getName()).throwError(
-                                       throwError));
-               }
-               // number types
-               if (!fieldClass.equals(jdbcClass)) {
-                       if (Number.class.isAssignableFrom(fieldClass)) {
-                               remarks.add(warn(
-                                               table,
-                                               col,
-                                               format("Precision mismatch: ModelObject={0}, ColumnObject={1}",
-                                                               fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
-                       } else {
-                               if (!Date.class.isAssignableFrom(jdbcClass)) {
-                                       remarks.add(warn(
-                                                       table,
-                                                       col,
-                                                       format("Object Mismatch: ModelObject={0}, ColumnObject={1}",
-                                                                       fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
-                               }
-                       }
-               }
-
-               // string types
-               if (fieldClass == String.class) {
-                       if ((fieldDef.length != col.size) && (col.size < Integer.MAX_VALUE)) {
-                               remarks.add(warn(
-                                               table,
-                                               col,
-                                               format("{0}.length={1}, ColumnMaxLength={2}", IQColumn.class.getSimpleName(),
-                                                               fieldDef.length, col.size)));
-                       }
-                       if (fieldDef.length > 0 && !fieldDef.trim) {
-                               remarks.add(consider(table, col, format("{0}.trim=true will prevent IciqlExceptions on"
-                                               + " INSERT or UPDATE, but will clip data!", IQColumn.class.getSimpleName())));
-                       }
-               }
-
-               // numeric autoIncrement
-               if (fieldDef.isAutoIncrement != col.isAutoIncrement) {
-                       remarks.add(warn(
-                                       table,
-                                       col,
-                                       format("{0}.autoIncrement={1}" + " while Column autoIncrement={2}",
-                                                       IQColumn.class.getSimpleName(), fieldDef.isAutoIncrement, col.isAutoIncrement)));
-               }
-               // default value
-               if (!col.isAutoIncrement && !col.isPrimaryKey) {
-                       String defaultValue = null;
-                       if (fieldDef.defaultValue != null && fieldDef.defaultValue instanceof String) {
-                               defaultValue = fieldDef.defaultValue.toString();
-                       }
-                       // check Model.defaultValue format
-                       if (!ModelUtils.isProperlyFormattedDefaultValue(defaultValue)) {
-                               remarks.add(error(
-                                               table,
-                                               col,
-                                               format("{0}.defaultValue=\"{1}\"" + " is improperly formatted!",
-                                                               IQColumn.class.getSimpleName(), defaultValue)).throwError(throwError));
-                               // next field
-                               return;
-                       }
-                       // compare Model.defaultValue to Column.defaultValue
-                       if (isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
-                               // Model.defaultValue is NULL, Column.defaultValue is NOT NULL
-                               remarks.add(warn(
-                                               table,
-                                               col,
-                                               format("{0}.defaultValue=\"\"" + " while column default=\"{1}\"",
-                                                               IQColumn.class.getSimpleName(), col.defaultValue)));
-                       } else if (!isNullOrEmpty(defaultValue) && isNullOrEmpty(col.defaultValue)) {
-                               // Column.defaultValue is NULL, Model.defaultValue is NOT NULL
-                               remarks.add(warn(
-                                               table,
-                                               col,
-                                               format("{0}.defaultValue=\"{1}\"" + " while column default=\"\"",
-                                                               IQColumn.class.getSimpleName(), defaultValue)));
-                       } else if (!isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
-                               if (!defaultValue.equals(col.defaultValue)) {
-                                       // Model.defaultValue != Column.defaultValue
-                                       remarks.add(warn(
-                                                       table,
-                                                       col,
-                                                       format("{0}.defaultValue=\"{1}\"" + " while column default=\"{2}\"",
-                                                                       IQColumn.class.getSimpleName(), defaultValue, col.defaultValue)));
-                               }
-                       }
-
-                       // sanity check Model.defaultValue literal value
-                       if (!ModelUtils.isValidDefaultValue(fieldDef.field.getType(), defaultValue)) {
-                               remarks.add(error(
-                                               table,
-                                               col,
-                                               format("{0}.defaultValue=\"{1}\" is invalid!", IQColumn.class.getSimpleName(),
-                                                               defaultValue)));
-                       }
-               }
-       }
-
-       /**
-        * Represents an index as it exists in the database.
-        */
-       private static class IndexInspector {
-
-               String name;
-               IndexType type;
-               private List<String> columns = new ArrayList<String>();
-
-               public IndexInspector(ResultSet rs) throws SQLException {
-                       name = rs.getString("INDEX_NAME");
-
-                       // determine index type
-                       boolean hash = rs.getInt("TYPE") == DatabaseMetaData.tableIndexHashed;
-                       boolean unique = !rs.getBoolean("NON_UNIQUE");
-
-                       if (!hash && !unique) {
-                               type = IndexType.STANDARD;
-                       } else if (hash && unique) {
-                               type = IndexType.UNIQUE_HASH;
-                       } else if (unique) {
-                               type = IndexType.UNIQUE;
-                       } else if (hash) {
-                               type = IndexType.HASH;
-                       }
-                       columns.add(rs.getString("COLUMN_NAME"));
-               }
-
-               public void addColumn(ResultSet rs) throws SQLException {
-                       columns.add(rs.getString("COLUMN_NAME"));
-               }
-       }
-
-       /**
-        * Represents a column as it exists in the database.
-        */
-       static class ColumnInspector implements Comparable<ColumnInspector> {
-               String name;
-               String type;
-               int size;
-               boolean nullable;
-               Class<?> clazz;
-               boolean isPrimaryKey;
-               boolean isAutoIncrement;
-               String defaultValue;
-
-               public int compareTo(ColumnInspector o) {
-                       if (isPrimaryKey && o.isPrimaryKey) {
-                               // both primary sort by name
-                               return name.compareTo(o.name);
-                       } else if (isPrimaryKey && !o.isPrimaryKey) {
-                               // primary first
-                               return -1;
-                       } else if (!isPrimaryKey && o.isPrimaryKey) {
-                               // primary first
-                               return 1;
-                       } else {
-                               // neither primary, sort by name
-                               return name.compareTo(o.name);
-                       }
-               }
-       }
-
-       /**
-        * Convenience class based on StatementBuilder for creating the annotation
-        * parameter list.
-        */
-       private static class AnnotationBuilder extends StatementBuilder {
-
-               AnnotationBuilder() {
-                       super();
-               }
-
-               void addParameter(String parameter) {
-
-                       appendExceptFirst(", ");
-                       append(parameter);
-               }
-
-               <T> void addParameter(String parameter, T value) {
-                       appendExceptFirst(", ");
-                       if (!StringUtils.isNullOrEmpty(parameter)) {
-                               append(parameter);
-                               append('=');
-                       }
-                       if (value instanceof List) {
-                               append("{ ");
-                               List<?> list = (List<?>) value;
-                               StatementBuilder flat = new StatementBuilder();
-                               for (Object o : list) {
-                                       flat.appendExceptFirst(", ");
-                                       if (o instanceof String) {
-                                               flat.append('\"');
-                                       }
-                                       // TODO escape string
-                                       flat.append(o.toString().trim());
-                                       if (o instanceof String) {
-                                               flat.append('\"');
-                                       }
-                               }
-                               append(flat);
-                               append(" }");
-                       } else {
-                               if (value instanceof String) {
-                                       append('\"');
-                               }
-                               // TODO escape
-                               append(value.toString().trim());
-                               if (value instanceof String) {
-                                       append('\"');
-                               }
-                       }
-               }
-
-               void addEnum(String parameter, Enum<?> value) {
-                       appendExceptFirst(", ");
-                       if (!StringUtils.isNullOrEmpty(parameter)) {
-                               append(parameter);
-                               append('=');
-                       }
-                       append(value.getClass().getSimpleName() + "." + value.name());
-               }
-       }
+                }
+                if (primaryKeys.size() == 1) {
+                    if (col.name.equalsIgnoreCase(primaryKeys.get(0))) {
+                        col.isPrimaryKey = true;
+                    }
+                }
+                if (!col.isAutoIncrement) {
+                    col.defaultValue = rs.getString("COLUMN_DEF");
+                }
+                columns.put(col.name.toLowerCase(), col);
+            }
+        } finally {
+            closeSilently(rs);
+        }
+    }
+
+    /**
+     * Generates a model (class definition) from this table. The model includes
+     * indexes, primary keys, default values, lengths, and nullables.
+     * information.
+     * <p>
+     * The caller may optionally set a destination package name, whether or not
+     * to include the schema name (setting schema can be a problem when using
+     * the model between databases), and if to automatically trim strings for
+     * those that have a maximum length.
+     * <p>
+     *
+     * @param packageName
+     * @param annotateSchema
+     * @param trimStrings
+     * @return a complete model (class definition) for this table as a string
+     */
+    String generateModel(String packageName, boolean annotateSchema, boolean trimStrings) {
+
+        // import statements
+        Set<String> imports = Utils.newHashSet();
+        imports.add(Serializable.class.getCanonicalName());
+        imports.add(IQSchema.class.getCanonicalName());
+        imports.add(IQTable.class.getCanonicalName());
+        imports.add(IQIndexes.class.getCanonicalName());
+        imports.add(IQIndex.class.getCanonicalName());
+        imports.add(IQColumn.class.getCanonicalName());
+        imports.add(IndexType.class.getCanonicalName());
+
+        // fields
+        StringBuilder fields = new StringBuilder();
+        List<ColumnInspector> sortedColumns = Utils.newArrayList(columns.values());
+        Collections.sort(sortedColumns);
+        for (ColumnInspector col : sortedColumns) {
+            fields.append(generateColumn(imports, col, trimStrings));
+        }
+
+        // build complete class definition
+        StringBuilder model = new StringBuilder();
+        if (!isNullOrEmpty(packageName)) {
+            // package
+            model.append("package " + packageName + ";");
+            model.append(eol).append(eol);
+        }
+
+        // imports
+        List<String> sortedImports = new ArrayList<String>(imports);
+        Collections.sort(sortedImports);
+        for (String imp : sortedImports) {
+            model.append("import ").append(imp).append(';').append(eol);
+        }
+        model.append(eol);
+
+        // @IQSchema
+        if (annotateSchema && !isNullOrEmpty(schema)) {
+            model.append('@').append(IQSchema.class.getSimpleName());
+            model.append('(');
+            AnnotationBuilder ap = new AnnotationBuilder();
+            ap.addParameter(null, schema);
+            model.append(ap);
+            model.append(')').append(eol);
+        }
+
+        // @IQTable
+        model.append('@').append(IQTable.class.getSimpleName());
+        model.append('(');
+
+        // IQTable annotation parameters
+        AnnotationBuilder ap = new AnnotationBuilder();
+        ap.addParameter("name", table);
+
+        if (primaryKeys.size() > 1) {
+            ap.addParameter("primaryKey", primaryKeys);
+        }
+
+        // finish @IQTable annotation
+        model.append(ap);
+        model.append(')').append(eol);
+
+        // @IQIndexes
+        // @IQIndex
+        String indexAnnotations = generateIndexAnnotations();
+        if (!StringUtils.isNullOrEmpty(indexAnnotations)) {
+            model.append(indexAnnotations);
+        }
+
+        // class declaration
+        String clazzName = ModelUtils.convertTableToClassName(table);
+        model.append(format("public class {0} implements Serializable '{'", clazzName)).append(eol);
+        model.append(eol);
+        model.append("\tprivate static final long serialVersionUID = 1L;").append(eol);
+        model.append(eol);
+
+        // field declarations
+        model.append(fields);
+
+        // default constructor
+        model.append("\t" + "public ").append(clazzName).append("() {").append(eol);
+        model.append("\t}").append(eol);
+
+        // end of class body
+        model.append('}');
+        model.trimToSize();
+        return model.toString();
+    }
+
+    /**
+     * Generates the specified index annotation.
+     *
+     * @param ap
+     */
+    String generateIndexAnnotations() {
+        if (indexes == null || indexes.size() == 0) {
+            // no matching indexes
+            return null;
+        }
+        AnnotationBuilder ap = new AnnotationBuilder();
+        if (indexes.size() == 1) {
+            // single index
+            IndexInspector index = indexes.values().toArray(new IndexInspector[1])[0];
+            ap.append(generateIndexAnnotation(index));
+            ap.append(eol);
+        } else {
+            // multiple indexes
+            ap.append('@').append(IQIndexes.class.getSimpleName());
+            ap.append("({");
+            ap.resetCount();
+            for (IndexInspector index : indexes.values()) {
+                ap.appendExceptFirst(", ");
+                ap.append(generateIndexAnnotation(index));
+            }
+            ap.append("})").append(eol);
+        }
+        return ap.toString();
+    }
+
+    private String generateIndexAnnotation(IndexInspector index) {
+        AnnotationBuilder ap = new AnnotationBuilder();
+        ap.append('@').append(IQIndex.class.getSimpleName());
+        ap.append('(');
+        ap.resetCount();
+        if (!StringUtils.isNullOrEmpty(index.name)) {
+            ap.addParameter("name", index.name);
+        }
+        if (!index.type.equals(IndexType.STANDARD)) {
+            ap.addEnum("type", index.type);
+        }
+        if (ap.getCount() > 0) {
+            // multiple fields specified
+            ap.addParameter("value", index.columns);
+        } else {
+            // default value
+            ap.addParameter(null, index.columns);
+        }
+        ap.append(')');
+        return ap.toString();
+    }
+
+    private StatementBuilder generateColumn(Set<String> imports, ColumnInspector col, boolean trimStrings) {
+        StatementBuilder sb = new StatementBuilder();
+        Class<?> clazz = col.clazz;
+        String column = ModelUtils.convertColumnToFieldName(col.name.toLowerCase());
+        sb.append('\t');
+        if (clazz == null) {
+            // unsupported type
+            clazz = Object.class;
+            sb.append("// unsupported type " + col.type);
+        } else {
+            // Imports
+            // don't import primitives, java.lang classes, or byte []
+            if (clazz.getPackage() == null) {
+            } else if (clazz.getPackage().getName().equals("java.lang")) {
+            } else if (clazz.equals(byte[].class)) {
+            } else {
+                imports.add(clazz.getCanonicalName());
+            }
+            // @IQColumn
+            sb.append('@').append(IQColumn.class.getSimpleName());
+
+            // IQColumn annotation parameters
+            AnnotationBuilder ap = new AnnotationBuilder();
+
+            // IQColumn.name
+            if (!col.name.equalsIgnoreCase(column)) {
+                ap.addParameter("name", col.name);
+            }
+
+            // IQColumn.primaryKey
+            // composite primary keys are annotated on the table
+            if (col.isPrimaryKey && primaryKeys.size() == 1) {
+                ap.addParameter("primaryKey=true");
+            }
+
+            // IQColumn.length
+            if ((clazz == String.class) && (col.size > 0) && (col.size < Integer.MAX_VALUE)) {
+                ap.addParameter("length", col.size);
+
+                // IQColumn.trim
+                if (trimStrings) {
+                    ap.addParameter("trim=true");
+                }
+            } else {
+                // IQColumn.AutoIncrement
+                if (col.isAutoIncrement) {
+                    ap.addParameter("autoIncrement=true");
+                }
+            }
+
+            // IQColumn.nullable
+            if (!col.nullable) {
+                ap.addParameter("nullable=false");
+            }
+
+            // IQColumn.defaultValue
+            if (!isNullOrEmpty(col.defaultValue)) {
+                ap.addParameter("defaultValue=\"" + col.defaultValue + "\"");
+            }
+
+            // add leading and trailing ()
+            if (ap.length() > 0) {
+                ap.insert(0, '(');
+                ap.append(')');
+            }
+            sb.append(ap);
+        }
+        sb.append(eol);
+
+        // variable declaration
+        sb.append("\t" + "public ");
+        sb.append(clazz.getSimpleName());
+        sb.append(' ');
+        sb.append(column);
+        sb.append(';');
+        sb.append(eol).append(eol);
+        return sb;
+    }
+
+    /**
+     * Validates that a table definition (annotated, interface, or both) matches
+     * the current state of the table and indexes in the database. Results are
+     * returned as a list of validation remarks which includes recommendations,
+     * warnings, and errors about the model. The caller may choose to have
+     * validate throw an exception on any validation ERROR.
+     *
+     * @param def        the table definition
+     * @param throwError whether or not to throw an exception if an error was found
+     * @return a list if validation remarks
+     */
+    <T> List<ValidationRemark> validate(TableDefinition<T> def, boolean throwError) {
+        List<ValidationRemark> remarks = Utils.newArrayList();
+
+        // model class definition validation
+        if (!Modifier.isPublic(def.getModelClass().getModifiers())) {
+            remarks.add(error(table, "SCHEMA",
+                    format("Class {0} MUST BE PUBLIC!", def.getModelClass().getCanonicalName())).throwError(
+                    throwError));
+        }
+
+        // Schema Validation
+        if (!isNullOrEmpty(schema)) {
+            if (isNullOrEmpty(def.schemaName)) {
+                remarks.add(consider(table, "SCHEMA",
+                        format("@{0}(\"{1}\")", IQSchema.class.getSimpleName(), schema)));
+            } else if (!schema.equalsIgnoreCase(def.schemaName)) {
+                remarks.add(error(
+                        table,
+                        "SCHEMA",
+                        format("@{0}(\"{1}\") != {2}", IQSchema.class.getSimpleName(), def.schemaName, schema))
+                        .throwError(throwError));
+            }
+        }
+
+        // index validation
+        for (IndexInspector index : indexes.values()) {
+            validate(remarks, def, index, throwError);
+        }
+
+        // field column validation
+        for (FieldDefinition fieldDef : def.getFields()) {
+            validate(remarks, fieldDef, throwError);
+        }
+        return remarks;
+    }
+
+    /**
+     * Validates an inspected index from the database against the
+     * IndexDefinition within the TableDefinition.
+     */
+    private <T> void validate(List<ValidationRemark> remarks, TableDefinition<T> def, IndexInspector index,
+                              boolean throwError) {
+        List<IndexDefinition> defIndexes = def.getIndexes();
+        if (defIndexes.size() > indexes.size()) {
+            remarks.add(warn(table, IndexType.STANDARD.name(), "More model indexes  than database indexes"));
+        } else if (defIndexes.size() < indexes.size()) {
+            remarks.add(warn(table, IndexType.STANDARD.name(), "Model class is missing indexes"));
+        }
+        // TODO complete index validation.
+        // need to actually compare index types and columns within each index.
+
+        // TODO add constraints validation
+        List<ConstraintUniqueDefinition> defContraintsU = def.getContraintsUnique();
+        List<ConstraintForeignKeyDefinition> defContraintsFK = def.getContraintsForeignKey();
+    }
+
+    /**
+     * Validates a column against the model's field definition. Checks for
+     * existence, supported type, type mapping, default value, defined lengths,
+     * primary key, autoincrement.
+     */
+    private void validate(List<ValidationRemark> remarks, FieldDefinition fieldDef, boolean throwError) {
+        // unknown field
+        if (!columns.containsKey(fieldDef.columnName.toLowerCase())) {
+            // unknown column mapping
+            remarks.add(error(table, fieldDef, "Does not exist in database!").throwError(throwError));
+            return;
+        }
+        ColumnInspector col = columns.get(fieldDef.columnName.toLowerCase());
+        Class<?> fieldClass = fieldDef.field.getType();
+        Class<?> jdbcClass = ModelUtils.getClassForSqlType(col.type, dateTimeClass);
+
+        // supported type check
+        // iciql maps to VARCHAR for unsupported types.
+        if (fieldDef.dataType.equals("VARCHAR") && (fieldClass != String.class)) {
+            remarks.add(error(table, fieldDef,
+                    "iciql does not currently implement support for " + fieldClass.getName()).throwError(
+                    throwError));
+        }
+        // number types
+        if (!fieldClass.equals(jdbcClass)) {
+            if (Number.class.isAssignableFrom(fieldClass)) {
+                remarks.add(warn(
+                        table,
+                        col,
+                        format("Precision mismatch: ModelObject={0}, ColumnObject={1}",
+                                fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
+            } else {
+                if (!Date.class.isAssignableFrom(jdbcClass)) {
+                    remarks.add(warn(
+                            table,
+                            col,
+                            format("Object Mismatch: ModelObject={0}, ColumnObject={1}",
+                                    fieldClass.getSimpleName(), jdbcClass.getSimpleName())));
+                }
+            }
+        }
+
+        // string types
+        if (fieldClass == String.class) {
+            if ((fieldDef.length != col.size) && (col.size < Integer.MAX_VALUE)) {
+                remarks.add(warn(
+                        table,
+                        col,
+                        format("{0}.length={1}, ColumnMaxLength={2}", IQColumn.class.getSimpleName(),
+                                fieldDef.length, col.size)));
+            }
+            if (fieldDef.length > 0 && !fieldDef.trim) {
+                remarks.add(consider(table, col, format("{0}.trim=true will prevent IciqlExceptions on"
+                        + " INSERT or UPDATE, but will clip data!", IQColumn.class.getSimpleName())));
+            }
+        }
+
+        // numeric autoIncrement
+        if (fieldDef.isAutoIncrement != col.isAutoIncrement) {
+            remarks.add(warn(
+                    table,
+                    col,
+                    format("{0}.autoIncrement={1}" + " while Column autoIncrement={2}",
+                            IQColumn.class.getSimpleName(), fieldDef.isAutoIncrement, col.isAutoIncrement)));
+        }
+        // default value
+        if (!col.isAutoIncrement && !col.isPrimaryKey) {
+            String defaultValue = null;
+            if (fieldDef.defaultValue != null && fieldDef.defaultValue instanceof String) {
+                defaultValue = fieldDef.defaultValue.toString();
+            }
+            // check Model.defaultValue format
+            if (!ModelUtils.isProperlyFormattedDefaultValue(defaultValue)) {
+                remarks.add(error(
+                        table,
+                        col,
+                        format("{0}.defaultValue=\"{1}\"" + " is improperly formatted!",
+                                IQColumn.class.getSimpleName(), defaultValue)).throwError(throwError));
+                // next field
+                return;
+            }
+            // compare Model.defaultValue to Column.defaultValue
+            if (isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
+                // Model.defaultValue is NULL, Column.defaultValue is NOT NULL
+                remarks.add(warn(
+                        table,
+                        col,
+                        format("{0}.defaultValue=\"\"" + " while column default=\"{1}\"",
+                                IQColumn.class.getSimpleName(), col.defaultValue)));
+            } else if (!isNullOrEmpty(defaultValue) && isNullOrEmpty(col.defaultValue)) {
+                // Column.defaultValue is NULL, Model.defaultValue is NOT NULL
+                remarks.add(warn(
+                        table,
+                        col,
+                        format("{0}.defaultValue=\"{1}\"" + " while column default=\"\"",
+                                IQColumn.class.getSimpleName(), defaultValue)));
+            } else if (!isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) {
+                if (!defaultValue.equals(col.defaultValue)) {
+                    // Model.defaultValue != Column.defaultValue
+                    remarks.add(warn(
+                            table,
+                            col,
+                            format("{0}.defaultValue=\"{1}\"" + " while column default=\"{2}\"",
+                                    IQColumn.class.getSimpleName(), defaultValue, col.defaultValue)));
+                }
+            }
+
+            // sanity check Model.defaultValue literal value
+            if (!ModelUtils.isValidDefaultValue(fieldDef.field.getType(), defaultValue)) {
+                remarks.add(error(
+                        table,
+                        col,
+                        format("{0}.defaultValue=\"{1}\" is invalid!", IQColumn.class.getSimpleName(),
+                                defaultValue)));
+            }
+        }
+    }
+
+    /**
+     * Represents an index as it exists in the database.
+     */
+    private static class IndexInspector {
+
+        String name;
+        IndexType type;
+        private List<String> columns = new ArrayList<String>();
+
+        public IndexInspector(ResultSet rs) throws SQLException {
+            name = rs.getString("INDEX_NAME");
+
+            // determine index type
+            boolean hash = rs.getInt("TYPE") == DatabaseMetaData.tableIndexHashed;
+            boolean unique = !rs.getBoolean("NON_UNIQUE");
+
+            if (!hash && !unique) {
+                type = IndexType.STANDARD;
+            } else if (hash && unique) {
+                type = IndexType.UNIQUE_HASH;
+            } else if (unique) {
+                type = IndexType.UNIQUE;
+            } else if (hash) {
+                type = IndexType.HASH;
+            }
+            columns.add(rs.getString("COLUMN_NAME"));
+        }
+
+        public void addColumn(ResultSet rs) throws SQLException {
+            columns.add(rs.getString("COLUMN_NAME"));
+        }
+    }
+
+    /**
+     * Represents a column as it exists in the database.
+     */
+    static class ColumnInspector implements Comparable<ColumnInspector> {
+        String name;
+        String type;
+        int size;
+        boolean nullable;
+        Class<?> clazz;
+        boolean isPrimaryKey;
+        boolean isAutoIncrement;
+        String defaultValue;
+
+        public int compareTo(ColumnInspector o) {
+            if (isPrimaryKey && o.isPrimaryKey) {
+                // both primary sort by name
+                return name.compareTo(o.name);
+            } else if (isPrimaryKey && !o.isPrimaryKey) {
+                // primary first
+                return -1;
+            } else if (!isPrimaryKey && o.isPrimaryKey) {
+                // primary first
+                return 1;
+            } else {
+                // neither primary, sort by name
+                return name.compareTo(o.name);
+            }
+        }
+    }
+
+    /**
+     * Convenience class based on StatementBuilder for creating the annotation
+     * parameter list.
+     */
+    private static class AnnotationBuilder extends StatementBuilder {
+
+        AnnotationBuilder() {
+            super();
+        }
+
+        void addParameter(String parameter) {
+
+            appendExceptFirst(", ");
+            append(parameter);
+        }
+
+        <T> void addParameter(String parameter, T value) {
+            appendExceptFirst(", ");
+            if (!StringUtils.isNullOrEmpty(parameter)) {
+                append(parameter);
+                append('=');
+            }
+            if (value instanceof List) {
+                append("{ ");
+                List<?> list = (List<?>) value;
+                StatementBuilder flat = new StatementBuilder();
+                for (Object o : list) {
+                    flat.appendExceptFirst(", ");
+                    if (o instanceof String) {
+                        flat.append('\"');
+                    }
+                    // TODO escape string
+                    flat.append(o.toString().trim());
+                    if (o instanceof String) {
+                        flat.append('\"');
+                    }
+                }
+                append(flat);
+                append(" }");
+            } else {
+                if (value instanceof String) {
+                    append('\"');
+                }
+                // TODO escape
+                append(value.toString().trim());
+                if (value instanceof String) {
+                    append('\"');
+                }
+            }
+        }
+
+        void addEnum(String parameter, Enum<?> value) {
+            appendExceptFirst(", ");
+            if (!StringUtils.isNullOrEmpty(parameter)) {
+                append(parameter);
+                append('=');
+            }
+            append(value.getClass().getSimpleName() + "." + value.name());
+        }
+    }
 }
\ No newline at end of file
index 010f5a18708aec2ce6bdbc2d8bb8039f556818a5..3c08eece4c878dfe3bd3b1f0f5bb04a2d5984667 100644 (file)
@@ -21,95 +21,94 @@ import com.iciql.util.Utils;
 \r
 /**\r
  * This class represents an incomplete condition.\r
- * \r
- * @param <A>\r
- *            the incomplete condition data type\r
+ *\r
+ * @param <A> the incomplete condition data type\r
  */\r
 \r
 public class TestCondition<A> {\r
 \r
-       private A x;\r
+    private A x;\r
 \r
-       public TestCondition(A x) {\r
-               this.x = x;\r
-       }\r
+    public TestCondition(A x) {\r
+        this.x = x;\r
+    }\r
 \r
-       public Boolean is(A y) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function("=", x, y) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" = ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean is(A y) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function("=", x, y) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" = ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
-       public Boolean exceeds(A y) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function(">", x, y) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" > ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean exceeds(A y) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function(">", x, y) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" > ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
-       public Boolean atLeast(A y) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function(">=", x, y) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" >= ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean atLeast(A y) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function(">=", x, y) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" >= ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
-       public Boolean lessThan(A y) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function("<", x, y) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" < ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean lessThan(A y) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function("<", x, y) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" < ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
-       public Boolean atMost(A y) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function("<=", x, y) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" <= ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean atMost(A y) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function("<=", x, y) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" <= ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
-       public Boolean like(A pattern) {\r
-               Boolean o = Utils.newObject(Boolean.class);\r
-               return Db.registerToken(o, new Function("LIKE", x, pattern) {\r
-                       public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
-                               stat.appendSQL("(");\r
-                               query.appendSQL(stat, null, x[0]);\r
-                               stat.appendSQL(" LIKE ");\r
-                               query.appendSQL(stat, x[0], x[1]);\r
-                               stat.appendSQL(")");\r
-                       }\r
-               });\r
-       }\r
+    public Boolean like(A pattern) {\r
+        Boolean o = Utils.newObject(Boolean.class);\r
+        return Db.registerToken(o, new Function("LIKE", x, pattern) {\r
+            public <T> void appendSQL(SQLStatement stat, Query<T> query) {\r
+                stat.appendSQL("(");\r
+                query.appendSQL(stat, null, x[0]);\r
+                stat.appendSQL(" LIKE ");\r
+                query.appendSQL(stat, x[0], x[1]);\r
+                stat.appendSQL(")");\r
+            }\r
+        });\r
+    }\r
 \r
 }\r
index cc2203ce6af1b2b79c5638a62e270152ec7bc509..acc25c486d51b633eff16123854ffefa55d2fe41 100644 (file)
@@ -21,15 +21,13 @@ package com.iciql;
  * Classes implementing this interface can be used as a token in a statement.\r
  */\r
 public interface Token {\r
-       /**\r
-        * Append the SQL to the given statement using the given query.\r
-        * \r
-        * @param stat\r
-        *            the statement to append the SQL to\r
-        * @param query\r
-        *            the query to use\r
-        */\r
+    /**\r
+     * Append the SQL to the given statement using the given query.\r
+     *\r
+     * @param stat  the statement to append the SQL to\r
+     * @param query the query to use\r
+     */\r
 \r
-       <T> void appendSQL(SQLStatement stat, Query<T> query);\r
+    <T> void appendSQL(SQLStatement stat, Query<T> query);\r
 \r
 }\r
index 1eaf14c3eded9b61f08e8c95e9ab5c5bf81a36b6..970ec612dba488a00b066c0e5ccea193d0143794 100644 (file)
@@ -23,13 +23,12 @@ package com.iciql;
  */
 public interface UpdateColumn {
 
-       /**
-        * Append the SQL to the given statement using the given query.
-        * 
-        * @param stat
-        *            the statement to append the SQL to
-        */
+    /**
+     * Append the SQL to the given statement using the given query.
+     *
+     * @param stat the statement to append the SQL to
+     */
 
-       void appendSQL(SQLStatement stat);
+    void appendSQL(SQLStatement stat);
 
 }
index 143ce4840caf70a4e11df6a218292e7318c00f26..e8f96e3be69f254f8c88fb76d882cbdd36db6acf 100644 (file)
@@ -19,37 +19,35 @@ package com.iciql;
 
 /**
  * This class represents "SET column = (column + x)" in an UPDATE statement.
- * 
- * @param <T>
- *            the query type
- * @param <A>
- *            the new value data type
+ *
+ * @param <T> the query type
+ * @param <A> the new value data type
  */
 
 public class UpdateColumnIncrement<T, A> implements UpdateColumn {
 
-       private Query<T> query;
-       private A x;
-       private A y;
-
-       UpdateColumnIncrement(Query<T> query, A x) {
-               this.query = query;
-               this.x = x;
-       }
-
-       public Query<T> by(A y) {
-               query.addUpdateColumnDeclaration(this);
-               this.y = y;
-               return query;
-       }
-
-       public void appendSQL(SQLStatement stat) {
-               query.appendSQL(stat, null, x);
-               stat.appendSQL("=(");
-               query.appendSQL(stat, null, x);
-               stat.appendSQL("+");
-               query.appendSQL(stat, x, y);
-               stat.appendSQL(")");
-       }
+    private Query<T> query;
+    private A x;
+    private A y;
+
+    UpdateColumnIncrement(Query<T> query, A x) {
+        this.query = query;
+        this.x = x;
+    }
+
+    public Query<T> by(A y) {
+        query.addUpdateColumnDeclaration(this);
+        this.y = y;
+        return query;
+    }
+
+    public void appendSQL(SQLStatement stat) {
+        query.appendSQL(stat, null, x);
+        stat.appendSQL("=(");
+        query.appendSQL(stat, null, x);
+        stat.appendSQL("+");
+        query.appendSQL(stat, x, y);
+        stat.appendSQL(")");
+    }
 
 }
index a961480574413a10b6e2c267a8a5d262653311fa..7ae74a08f1c7af18003de3676a82650ea83c7238 100644 (file)
@@ -19,45 +19,43 @@ package com.iciql;
 
 /**
  * This class represents "SET column = value" in an UPDATE statement.
- * 
- * @param <T>
- *            the query type
- * @param <A>
- *            the new value data type
+ *
+ * @param <T> the query type
+ * @param <A> the new value data type
  */
 
 public class UpdateColumnSet<T, A> implements UpdateColumn {
 
-       private Query<T> query;
-       private A x;
-       private A y;
-       private boolean isParameter;
-
-       UpdateColumnSet(Query<T> query, A x) {
-               this.query = query;
-               this.x = x;
-       }
-
-       public Query<T> to(A y) {
-               query.addUpdateColumnDeclaration(this);
-               this.y = y;
-               return query;
-       }
-
-       public Query<T> toParameter() {
-               query.addUpdateColumnDeclaration(this);
-               isParameter = true;
-               return query;
-       }
-
-       public void appendSQL(SQLStatement stat) {
-               query.appendSQL(stat, null, x);
-               stat.appendSQL(" = ");
-               if (isParameter) {                      
-                       query.appendSQL(stat, x, RuntimeParameter.PARAMETER);
-               } else {
-                       query.appendSQL(stat, x, y);
-               }
-       }
+    private Query<T> query;
+    private A x;
+    private A y;
+    private boolean isParameter;
+
+    UpdateColumnSet(Query<T> query, A x) {
+        this.query = query;
+        this.x = x;
+    }
+
+    public Query<T> to(A y) {
+        query.addUpdateColumnDeclaration(this);
+        this.y = y;
+        return query;
+    }
+
+    public Query<T> toParameter() {
+        query.addUpdateColumnDeclaration(this);
+        isParameter = true;
+        return query;
+    }
+
+    public void appendSQL(SQLStatement stat) {
+        query.appendSQL(stat, null, x);
+        stat.appendSQL(" = ");
+        if (isParameter) {
+            query.appendSQL(stat, x, RuntimeParameter.PARAMETER);
+        } else {
+            query.appendSQL(stat, x, y);
+        }
+    }
 
 }
index 33320abc4124165cef4bb1eeaa11bb5fd2fe1bb0..74b334e5103978508272276d921a7f8d25de3a90 100644 (file)
@@ -28,100 +28,100 @@ import com.iciql.util.StringUtils;
  */
 public class ValidationRemark {
 
-       /**
-        * The validation message level.
-        */
-       public static enum Level {
-               CONSIDER, WARN, ERROR;
-       }
-
-       public final Level level;
-       public final String table;
-       public final String fieldType;
-       public final String fieldName;
-       public final String message;
-
-       private ValidationRemark(Level level, String table, String type, String message) {
-               this.level = level;
-               this.table = table;
-               this.fieldType = type;
-               this.fieldName = "";
-               this.message = message;
-       }
-
-       private ValidationRemark(Level level, String table, FieldDefinition field, String message) {
-               this.level = level;
-               this.table = table;
-               this.fieldType = field.dataType;
-               this.fieldName = field.columnName;
-               this.message = message;
-       }
-
-       private ValidationRemark(Level level, String table, ColumnInspector col, String message) {
-               this.level = level;
-               this.table = table;
-               this.fieldType = col.type;
-               this.fieldName = col.name;
-               this.message = message;
-       }
-
-       public static ValidationRemark consider(String table, String type, String message) {
-               return new ValidationRemark(Level.CONSIDER, table, type, message);
-       }
-
-       public static ValidationRemark consider(String table, ColumnInspector col, String message) {
-               return new ValidationRemark(Level.CONSIDER, table, col, message);
-       }
-
-       public static ValidationRemark warn(String table, ColumnInspector col, String message) {
-               return new ValidationRemark(Level.WARN, table, col, message);
-       }
-
-       public static ValidationRemark warn(String table, String type, String message) {
-               return new ValidationRemark(Level.WARN, table, type, message);
-       }
-
-       public static ValidationRemark error(String table, ColumnInspector col, String message) {
-               return new ValidationRemark(Level.ERROR, table, col, message);
-       }
-
-       public static ValidationRemark error(String table, String type, String message) {
-               return new ValidationRemark(Level.ERROR, table, type, message);
-       }
-
-       public static ValidationRemark error(String table, FieldDefinition field, String message) {
-               return new ValidationRemark(Level.ERROR, table, field, message);
-       }
-
-       public ValidationRemark throwError(boolean throwOnError) {
-               if (throwOnError && isError()) {
-                       throw new IciqlException(toString());
-               }
-               return this;
-       }
-
-       public boolean isError() {
-               return level.equals(Level.ERROR);
-       }
-
-       public String toString() {
-               StringBuilder sb = new StringBuilder();
-               sb.append(StringUtils.pad(level.name(), 9, " ", true));
-               sb.append(StringUtils.pad(table, 25, " ", true));
-               sb.append(StringUtils.pad(fieldName, 20, " ", true));
-               sb.append(' ');
-               sb.append(message);
-               return sb.toString();
-       }
-
-       public String toCSVString() {
-               StringBuilder sb = new StringBuilder();
-               sb.append(level.name()).append(',');
-               sb.append(table).append(',');
-               sb.append(fieldType).append(',');
-               sb.append(fieldName).append(',');
-               sb.append(message);
-               return sb.toString();
-       }
+    /**
+     * The validation message level.
+     */
+    public static enum Level {
+        CONSIDER, WARN, ERROR;
+    }
+
+    public final Level level;
+    public final String table;
+    public final String fieldType;
+    public final String fieldName;
+    public final String message;
+
+    private ValidationRemark(Level level, String table, String type, String message) {
+        this.level = level;
+        this.table = table;
+        this.fieldType = type;
+        this.fieldName = "";
+        this.message = message;
+    }
+
+    private ValidationRemark(Level level, String table, FieldDefinition field, String message) {
+        this.level = level;
+        this.table = table;
+        this.fieldType = field.dataType;
+        this.fieldName = field.columnName;
+        this.message = message;
+    }
+
+    private ValidationRemark(Level level, String table, ColumnInspector col, String message) {
+        this.level = level;
+        this.table = table;
+        this.fieldType = col.type;
+        this.fieldName = col.name;
+        this.message = message;
+    }
+
+    public static ValidationRemark consider(String table, String type, String message) {
+        return new ValidationRemark(Level.CONSIDER, table, type, message);
+    }
+
+    public static ValidationRemark consider(String table, ColumnInspector col, String message) {
+        return new ValidationRemark(Level.CONSIDER, table, col, message);
+    }
+
+    public static ValidationRemark warn(String table, ColumnInspector col, String message) {
+        return new ValidationRemark(Level.WARN, table, col, message);
+    }
+
+    public static ValidationRemark warn(String table, String type, String message) {
+        return new ValidationRemark(Level.WARN, table, type, message);
+    }
+
+    public static ValidationRemark error(String table, ColumnInspector col, String message) {
+        return new ValidationRemark(Level.ERROR, table, col, message);
+    }
+
+    public static ValidationRemark error(String table, String type, String message) {
+        return new ValidationRemark(Level.ERROR, table, type, message);
+    }
+
+    public static ValidationRemark error(String table, FieldDefinition field, String message) {
+        return new ValidationRemark(Level.ERROR, table, field, message);
+    }
+
+    public ValidationRemark throwError(boolean throwOnError) {
+        if (throwOnError && isError()) {
+            throw new IciqlException(toString());
+        }
+        return this;
+    }
+
+    public boolean isError() {
+        return level.equals(Level.ERROR);
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(StringUtils.pad(level.name(), 9, " ", true));
+        sb.append(StringUtils.pad(table, 25, " ", true));
+        sb.append(StringUtils.pad(fieldName, 20, " ", true));
+        sb.append(' ');
+        sb.append(message);
+        return sb.toString();
+    }
+
+    public String toCSVString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(level.name()).append(',');
+        sb.append(table).append(',');
+        sb.append(fieldType).append(',');
+        sb.append(fieldName).append(',');
+        sb.append(message);
+        return sb.toString();
+    }
 
 }
index 8d23cfdc79a9ec634262514c781cc5da5c6ee4d7..83cbe5140c9b10d74a14e3cd475c697249d85d21 100644 (file)
@@ -26,13 +26,13 @@ import com.iciql.Iciql.Mode;
  * <p>
  * You use this by creating a subclass which defines your object class.
  * </p>
- *
+ * <p>
  * <pre>
  * public class CustomObjectAdapter extends GsonTypeAdapter&lt;CustomObject&gt; {
  *
  *     public Class&lt;CustomObject&gt; getJavaType() {
  *             return CustomObject.class;
- *     }
+ *    }
  * }
  * </pre>
  *
@@ -40,32 +40,32 @@ import com.iciql.Iciql.Mode;
  */
 public abstract class GsonTypeAdapter<T> implements DataTypeAdapter<T> {
 
-       protected Mode mode;
+    protected Mode mode;
 
-       protected Gson gson() {
-               return new GsonBuilder().create();
-       }
+    protected Gson gson() {
+        return new GsonBuilder().create();
+    }
 
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
 
-       @Override
-       public String getDataType() {
-               return "TEXT";
-       }
+    @Override
+    public String getDataType() {
+        return "TEXT";
+    }
 
-       @Override
-       public Object serialize(T value) {
-               return gson().toJson(value);
-       }
+    @Override
+    public Object serialize(T value) {
+        return gson().toJson(value);
+    }
 
-       @Override
-       public T deserialize(Object value) {
-               String json = value.toString();
-               Gson gson = gson();
-               T t = gson.fromJson(json, getJavaType());
-               return t;
-       }
+    @Override
+    public T deserialize(Object value) {
+        String json = value.toString();
+        Gson gson = gson();
+        T t = gson.fromJson(json, getJavaType());
+        return t;
+    }
 }
index df2449501737c7637536ab69a07e4b4d491f3082..bebb8fa750758bfc986dbf656dae60651e1375d4 100644 (file)
 
 package com.iciql.adapter;
 
+import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
+import com.iciql.IciqlException;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -25,10 +29,6 @@ import java.io.ObjectOutputStream;
 import java.sql.Blob;
 import java.sql.SQLException;
 
-import com.iciql.Iciql.DataTypeAdapter;
-import com.iciql.Iciql.Mode;
-import com.iciql.IciqlException;
-
 /**
  * Base class for inserting/retrieving a Java Object as a BLOB field using Java Serialization.
  * <p>You use this by creating a subclass which defines your object class.</p>
@@ -40,68 +40,69 @@ import com.iciql.IciqlException;
  *    }
  * }
  * </pre>
+ *
  * @param <T>
  */
 public abstract class JavaSerializationTypeAdapter<T> implements DataTypeAdapter<T> {
 
-       protected Mode mode;
+    protected Mode mode;
 
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
 
-       @Override
-       public final String getDataType() {
-               return "BLOB";
-       }
+    @Override
+    public final String getDataType() {
+        return "BLOB";
+    }
 
-       @Override
-       public final Object serialize(T value) {
-               ByteArrayOutputStream os = new ByteArrayOutputStream();
-               try {
-                       new ObjectOutputStream(os).writeObject(value);
-                       return os.toByteArray();
-               } catch (IOException e) {
-                       throw new IciqlException(e);
-               } finally {
-                       try {
-                               os.close();
-                       } catch (IOException e) {
-                               throw new IciqlException (e);
-                       }
-               }
-       }
+    @Override
+    public final Object serialize(T value) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        try {
+            new ObjectOutputStream(os).writeObject(value);
+            return os.toByteArray();
+        } catch (IOException e) {
+            throw new IciqlException(e);
+        } finally {
+            try {
+                os.close();
+            } catch (IOException e) {
+                throw new IciqlException(e);
+            }
+        }
+    }
 
-       @SuppressWarnings("unchecked")
-       @Override
-       public final T deserialize(Object value) {
-               InputStream is = null;
-               if (value instanceof Blob) {
-                       Blob blob = (Blob) value;
-                       try {
-                               is = blob.getBinaryStream();
-                       } catch (SQLException e) {
-                               throw new IciqlException(e);
-                       }
-               } else if (value instanceof byte[]) {
-                       byte [] bytes = (byte []) value;
-                       is = new ByteArrayInputStream(bytes);
-               }
+    @SuppressWarnings("unchecked")
+    @Override
+    public final T deserialize(Object value) {
+        InputStream is = null;
+        if (value instanceof Blob) {
+            Blob blob = (Blob) value;
+            try {
+                is = blob.getBinaryStream();
+            } catch (SQLException e) {
+                throw new IciqlException(e);
+            }
+        } else if (value instanceof byte[]) {
+            byte[] bytes = (byte[]) value;
+            is = new ByteArrayInputStream(bytes);
+        }
 
-               try {
-                       T object = (T) new ObjectInputStream(is).readObject();
-                       return object;
-               } catch (Exception e) {
-                       throw new IciqlException(e);
-               } finally {
-                       if (is != null) {
-                               try {
-                                       is.close();
-                               } catch (IOException e) {
-                                       throw new IciqlException (e);
-                               }
-                       }
-               }
-       }
+        try {
+            T object = (T) new ObjectInputStream(is).readObject();
+            return object;
+        } catch (Exception e) {
+            throw new IciqlException(e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    throw new IciqlException(e);
+                }
+            }
+        }
+    }
 }
index da3b20b6546d96a8eac0e6eea8fd24c053c2b90e..f96afcb45e2dcd0194fa31d2103ec555cddc0cbb 100644 (file)
 
 package com.iciql.adapter;
 
+import com.iciql.Iciql.DataTypeAdapter;
+import com.iciql.Iciql.Mode;
 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.nodes.Tag;
 
-import com.iciql.Iciql.DataTypeAdapter;
-import com.iciql.Iciql.Mode;
-
 /**
  * Base class for inserting/retrieving a Java Object (de)serialized as YAML using SnakeYaml.
  */
 public abstract class SnakeYamlTypeAdapter<T> implements DataTypeAdapter<T> {
 
-       protected Mode mode;
-
-       protected Yaml yaml() {
-               return new Yaml();
-       }
-
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
-
-       @Override
-       public String getDataType() {
-               return "TEXT";
-       }
-
-       @Override
-       public abstract Class<T> getJavaType();
-
-       @Override
-       public Object serialize(Object value) {
-               return yaml().dumpAs(value, Tag.MAP, FlowStyle.BLOCK);
-       }
-
-       @Override
-       public T deserialize(Object value) {
-               String yaml = value.toString();
-               Yaml processor = yaml();
-               T t = processor.loadAs(yaml, getJavaType());
-               return t;
-       }
+    protected Mode mode;
+
+    protected Yaml yaml() {
+        return new Yaml();
+    }
+
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public String getDataType() {
+        return "TEXT";
+    }
+
+    @Override
+    public abstract Class<T> getJavaType();
+
+    @Override
+    public Object serialize(Object value) {
+        return yaml().dumpAs(value, Tag.MAP, FlowStyle.BLOCK);
+    }
+
+    @Override
+    public T deserialize(Object value) {
+        String yaml = value.toString();
+        Yaml processor = yaml();
+        T t = processor.loadAs(yaml, getJavaType());
+        return t;
+    }
 
 }
index a554724f87e5416dbca0309d8a85321895b8edf7..224e7bbd7c42bb5da97c6fe89c266611d10fe50e 100644 (file)
@@ -25,38 +25,38 @@ import com.thoughtworks.xstream.XStream;
  */
 public class XStreamTypeAdapter implements DataTypeAdapter<Object> {
 
-       protected Mode mode;
-
-       protected XStream xstream() {
-               return new XStream();
-       }
-
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
-
-       @Override
-       public String getDataType() {
-               return "TEXT";
-       }
-
-       @Override
-       public Class<Object> getJavaType() {
-               return Object.class;
-       }
-
-       @Override
-       public Object serialize(Object value) {
-               return xstream().toXML(value);
-       }
-
-       @Override
-       public Object deserialize(Object value) {
-               String xml = value.toString();
-               XStream xstream = xstream();
-               Object t = xstream.fromXML(xml);
-               return t;
-       }
+    protected Mode mode;
+
+    protected XStream xstream() {
+        return new XStream();
+    }
+
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public String getDataType() {
+        return "TEXT";
+    }
+
+    @Override
+    public Class<Object> getJavaType() {
+        return Object.class;
+    }
+
+    @Override
+    public Object serialize(Object value) {
+        return xstream().toXML(value);
+    }
+
+    @Override
+    public Object deserialize(Object value) {
+        String xml = value.toString();
+        XStream xstream = xstream();
+        Object t = xstream.fromXML(xml);
+        return t;
+    }
 
 }
index 118cfc1fa4d1fbdf7f45a2ad4a791344ae0f16f2..91f989a3f70255773f31d5d10b8fafd4c5108989 100644 (file)
  */
 package com.iciql.adapter.postgresql;
 
-import java.sql.SQLException;
-
+import com.iciql.adapter.GsonTypeAdapter;
 import org.postgresql.util.PGobject;
 
-import com.iciql.adapter.GsonTypeAdapter;
+import java.sql.SQLException;
 
 /**
  * Postgres JSON data type adapter maps a JSON column to a domain object using
  * Google GSON.
  *
- * @author James Moger
- *
  * @param <T>
+ * @author James Moger
  */
 public abstract class JsonObjectAdapter<T> extends GsonTypeAdapter<T> {
 
-       @Override
-       public String getDataType() {
-               return "json";
-       }
+    @Override
+    public String getDataType() {
+        return "json";
+    }
 
-       @Override
-       public Object serialize(T value) {
+    @Override
+    public Object serialize(T value) {
 
-               String json = gson().toJson(value);
-               PGobject pg = new PGobject();
-               pg.setType(getDataType());
-               try {
-                       pg.setValue(json);
-               } catch (SQLException e) {
-                       // not thrown on base PGobject
-               }
-               return pg;
-       }
+        String json = gson().toJson(value);
+        PGobject pg = new PGobject();
+        pg.setType(getDataType());
+        try {
+            pg.setValue(json);
+        } catch (SQLException e) {
+            // not thrown on base PGobject
+        }
+        return pg;
+    }
 }
index 01d2834e696256aa7fec2c075a24afdbea2f6f56..5295d522d7e5b345d06fba9067fa406af6896f56 100644 (file)
  */
 package com.iciql.adapter.postgresql;
 
-import java.sql.SQLException;
-
-import org.postgresql.util.PGobject;
-
 import com.iciql.Iciql.DataTypeAdapter;
 import com.iciql.Iciql.Mode;
+import org.postgresql.util.PGobject;
+
+import java.sql.SQLException;
 
 /**
  * Handles transforming raw strings to/from the Postgres JSON data type.
  */
 public class JsonStringAdapter implements DataTypeAdapter<String> {
 
-       protected Mode mode;
-
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
-
-       @Override
-       public String getDataType() {
-               return "json";
-       }
-
-       @Override
-       public Class<String> getJavaType() {
-               return String.class;
-       }
-
-       @Override
-       public Object serialize(String value) {
-               PGobject pg = new PGobject();
-               pg.setType(getDataType());
-               try {
-                       pg.setValue(value);
-               } catch (SQLException e) {
-                       // not thrown on base PGobject
-               }
-               return pg;
-       }
-
-       @Override
-       public String deserialize(Object value) {
-               return value.toString();
-       }
+    protected Mode mode;
+
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public String getDataType() {
+        return "json";
+    }
+
+    @Override
+    public Class<String> getJavaType() {
+        return String.class;
+    }
+
+    @Override
+    public Object serialize(String value) {
+        PGobject pg = new PGobject();
+        pg.setType(getDataType());
+        try {
+            pg.setValue(value);
+        } catch (SQLException e) {
+            // not thrown on base PGobject
+        }
+        return pg;
+    }
+
+    @Override
+    public String deserialize(Object value) {
+        return value.toString();
+    }
 }
\ No newline at end of file
index 6d8ad2c494a76d7024fc00b608d2fd9dd5cdc6ad..947778bc35d8832f31686de8159c6a6cbd3e697c 100644 (file)
  */
 package com.iciql.adapter.postgresql;
 
-import java.sql.SQLException;
-
+import com.iciql.adapter.GsonTypeAdapter;
 import org.postgresql.util.PGobject;
 
-import com.iciql.adapter.GsonTypeAdapter;
+import java.sql.SQLException;
 
 /**
  * Postgres JSONB data type adapter maps a JSONB column to a domain object using
  * Google GSON.
  *
- * @author James Moger
- *
  * @param <T>
+ * @author James Moger
  */
 public abstract class JsonbObjectAdapter<T> extends GsonTypeAdapter<T> {
 
-       @Override
-       public String getDataType() {
-               return "jsonb";
-       }
+    @Override
+    public String getDataType() {
+        return "jsonb";
+    }
 
-       @Override
-       public Object serialize(T value) {
+    @Override
+    public Object serialize(T value) {
 
-               String json = gson().toJson(value);
-               PGobject pg = new PGobject();
-               pg.setType(getDataType());
-               try {
-                       pg.setValue(json);
-               } catch (SQLException e) {
-                       // not thrown on base PGobject
-               }
-               return pg;
-       }
+        String json = gson().toJson(value);
+        PGobject pg = new PGobject();
+        pg.setType(getDataType());
+        try {
+            pg.setValue(json);
+        } catch (SQLException e) {
+            // not thrown on base PGobject
+        }
+        return pg;
+    }
 }
index 9d7388b8f97ee2fca21f7a33e5df2af0fa5d743f..88d69c6fe84d22fefd151a07717fdb76e37223b7 100644 (file)
  */
 package com.iciql.adapter.postgresql;
 
-import java.sql.SQLException;
-
-import org.postgresql.util.PGobject;
-
 import com.iciql.Iciql.DataTypeAdapter;
 import com.iciql.Iciql.Mode;
+import org.postgresql.util.PGobject;
+
+import java.sql.SQLException;
 
 /**
  * Handles transforming raw strings to/from the Postgres JSONB data type.
  */
 public class JsonbStringAdapter implements DataTypeAdapter<String> {
 
-       protected Mode mode;
-
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
-
-       @Override
-       public String getDataType() {
-               return "jsonb";
-       }
-
-       @Override
-       public Class<String> getJavaType() {
-               return String.class;
-       }
-
-       @Override
-       public Object serialize(String value) {
-               PGobject pg = new PGobject();
-               pg.setType(getDataType());
-               try {
-                       pg.setValue(value);
-               } catch (SQLException e) {
-                       // not thrown on base PGobject
-               }
-               return pg;
-       }
-
-       @Override
-       public String deserialize(Object value) {
-               return value.toString();
-       }
+    protected Mode mode;
+
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public String getDataType() {
+        return "jsonb";
+    }
+
+    @Override
+    public Class<String> getJavaType() {
+        return String.class;
+    }
+
+    @Override
+    public Object serialize(String value) {
+        PGobject pg = new PGobject();
+        pg.setType(getDataType());
+        try {
+            pg.setValue(value);
+        } catch (SQLException e) {
+            // not thrown on base PGobject
+        }
+        return pg;
+    }
+
+    @Override
+    public String deserialize(Object value) {
+        return value.toString();
+    }
 }
\ No newline at end of file
index eba7c061f9b05f87f02eaf590f89c8f28d58ffb7..f5160d3279da5a63bf387fa21f1fd862eb9b02d9 100644 (file)
@@ -23,13 +23,12 @@ import com.iciql.adapter.XStreamTypeAdapter;
  * XStream.
  *
  * @author James Moger
- *
  */
 public abstract class XmlObjectAdapter extends XStreamTypeAdapter {
 
-       @Override
-       public String getDataType() {
-               return "xml";
-       }
+    @Override
+    public String getDataType() {
+        return "xml";
+    }
 
 }
index 0aea77e912018677e6ba5cf87715ffb1546b6e5b..a795e4ff3863bdc60a26fea55030cf37b9309aa5 100644 (file)
  */
 package com.iciql.adapter.postgresql;
 
-import java.sql.SQLException;
-
-import org.postgresql.util.PGobject;
-
 import com.iciql.Iciql.DataTypeAdapter;
 import com.iciql.Iciql.Mode;
+import org.postgresql.util.PGobject;
+
+import java.sql.SQLException;
 
 /**
  * Handles transforming raw strings to/from the Postgres XML data type.
  */
 public class XmlStringAdapter implements DataTypeAdapter<String> {
 
-       protected Mode mode;
-
-       @Override
-       public void setMode(Mode mode) {
-               this.mode = mode;
-       }
-
-       @Override
-       public String getDataType() {
-               return "xml";
-       }
-
-       @Override
-       public Class<String> getJavaType() {
-               return String.class;
-       }
-
-       @Override
-       public Object serialize(String value) {
-               PGobject pg = new PGobject();
-               pg.setType(getDataType());
-               try {
-                       pg.setValue(value);
-               } catch (SQLException e) {
-                       // not thrown on base PGobject
-               }
-               return pg;
-       }
-
-       @Override
-       public String deserialize(Object value) {
-               return value.toString();
-       }
+    protected Mode mode;
+
+    @Override
+    public void setMode(Mode mode) {
+        this.mode = mode;
+    }
+
+    @Override
+    public String getDataType() {
+        return "xml";
+    }
+
+    @Override
+    public Class<String> getJavaType() {
+        return String.class;
+    }
+
+    @Override
+    public Object serialize(String value) {
+        PGobject pg = new PGobject();
+        pg.setType(getDataType());
+        try {
+            pg.setValue(value);
+        } catch (SQLException e) {
+            // not thrown on base PGobject
+        }
+        return pg;
+    }
+
+    @Override
+    public String deserialize(Object value) {
+        return value.toString();
+    }
 }
\ No newline at end of file
index 808a9c18d95c6a60421c6d9234a9748abb266a42..0b0452586434d2aa105796031a5b4343399b5eaf 100644 (file)
@@ -26,21 +26,21 @@ import com.iciql.Token;
  */
 public class And implements Token {
 
-       private final Token left, right;
-
-       private And(Token left, Token right) {
-               this.left = left;
-               this.right = right;
-       }
-
-       static And get(Token left, Token right) {
-               return new And(left, right);
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               left.appendSQL(stat, query);
-               stat.appendSQL(" AND ");
-               right.appendSQL(stat, query);
-       }
+    private final Token left, right;
+
+    private And(Token left, Token right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    static And get(Token left, Token right) {
+        return new And(left, right);
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        left.appendSQL(stat, query);
+        stat.appendSQL(" AND ");
+        right.appendSQL(stat, query);
+    }
 
 }
index 29516c2101b4138bd2958a363aad274128b44909..5ea2b74125ec3c47f00c109e8c1eefdc82adb1fe 100644 (file)
@@ -26,24 +26,24 @@ import com.iciql.Token;
  */
 public class ArrayGet implements Token {
 
-       private final Token variable;
-       private final Token index;
-
-       private ArrayGet(Token variable, Token index) {
-               this.variable = variable;
-               this.index = index;
-       }
-
-       static ArrayGet get(Token variable, Token index) {
-               return new ArrayGet(variable, index);
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               // untested
-               variable.appendSQL(stat, query);
-               stat.appendSQL("[");
-               index.appendSQL(stat, query);
-               stat.appendSQL("]");
-       }
+    private final Token variable;
+    private final Token index;
+
+    private ArrayGet(Token variable, Token index) {
+        this.variable = variable;
+        this.index = index;
+    }
+
+    static ArrayGet get(Token variable, Token index) {
+        return new ArrayGet(variable, index);
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        // untested
+        variable.appendSQL(stat, query);
+        stat.appendSQL("[");
+        index.appendSQL(stat, query);
+        stat.appendSQL("]");
+    }
 
 }
index 2a1d69e61c784157098bdfea2f75256493b041ca..bdf7fc5816dd5590a314d6cc5774aa3cfd81b8db 100644 (file)
@@ -26,37 +26,37 @@ import com.iciql.Token;
  */
 public class CaseWhen implements Token {
 
-       private final Token condition, ifTrue, ifFalse;
-
-       private CaseWhen(Token condition, Token ifTrue, Token ifFalse) {
-               this.condition = condition;
-               this.ifTrue = ifTrue;
-               this.ifFalse = ifFalse;
-       }
-
-       static Token get(Token condition, Token ifTrue, Token ifFalse) {
-               if ("0".equals(ifTrue.toString()) && "1".equals(ifFalse.toString())) {
-                       return Not.get(condition);
-               } else if ("1".equals(ifTrue.toString()) && "0".equals(ifFalse.toString())) {
-                       return condition;
-               } else if ("0".equals(ifTrue.toString())) {
-                       return And.get(Not.get(condition), ifFalse);
-               }
-               return new CaseWhen(condition, ifTrue, ifFalse);
-       }
-
-       public String toString() {
-               return "CASEWHEN(" + condition + ", " + ifTrue + ", " + ifFalse + ")";
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               stat.appendSQL("CASEWHEN ");
-               condition.appendSQL(stat, query);
-               stat.appendSQL(" THEN ");
-               ifTrue.appendSQL(stat, query);
-               stat.appendSQL(" ELSE ");
-               ifFalse.appendSQL(stat, query);
-               stat.appendSQL(" END");
-       }
+    private final Token condition, ifTrue, ifFalse;
+
+    private CaseWhen(Token condition, Token ifTrue, Token ifFalse) {
+        this.condition = condition;
+        this.ifTrue = ifTrue;
+        this.ifFalse = ifFalse;
+    }
+
+    static Token get(Token condition, Token ifTrue, Token ifFalse) {
+        if ("0".equals(ifTrue.toString()) && "1".equals(ifFalse.toString())) {
+            return Not.get(condition);
+        } else if ("1".equals(ifTrue.toString()) && "0".equals(ifFalse.toString())) {
+            return condition;
+        } else if ("0".equals(ifTrue.toString())) {
+            return And.get(Not.get(condition), ifFalse);
+        }
+        return new CaseWhen(condition, ifTrue, ifFalse);
+    }
+
+    public String toString() {
+        return "CASEWHEN(" + condition + ", " + ifTrue + ", " + ifFalse + ")";
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        stat.appendSQL("CASEWHEN ");
+        condition.appendSQL(stat, query);
+        stat.appendSQL(" THEN ");
+        ifTrue.appendSQL(stat, query);
+        stat.appendSQL(" ELSE ");
+        ifFalse.appendSQL(stat, query);
+        stat.appendSQL(" END");
+    }
 
 }
index 38fd2f56c9f8720a9dea3bee8053d8a3318025c7..52c71b4ae106f6aed16b5c335a302fc801e0c017 100644 (file)
@@ -17,6 +17,9 @@
 
 package com.iciql.bytecode;
 
+import com.iciql.IciqlException;
+import com.iciql.Token;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -25,1433 +28,1430 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
 
-import com.iciql.IciqlException;
-import com.iciql.Token;
-
 /**
  * This class converts a method to a SQL Token by interpreting (decompiling) the
  * bytecode of the class.
  */
 public class ClassReader {
 
-       private static final boolean DEBUG = false;
+    private static final boolean DEBUG = false;
 
-       private byte[] data;
-       private int pos;
-       private Constant[] constantPool;
-       private int startByteCode;
-       private String methodName;
+    private byte[] data;
+    private int pos;
+    private Constant[] constantPool;
+    private int startByteCode;
+    private String methodName;
 
-       private String convertMethodName;
-       private Token result;
-       private Stack<Token> stack = new Stack<Token>();
-       private ArrayList<Token> variables = new ArrayList<Token>();
-       private boolean endOfMethod;
-       private boolean condition;
-       private int nextPc;
-       private Map<String, Object> fieldMap = new HashMap<String, Object>();
+    private String convertMethodName;
+    private Token result;
+    private Stack<Token> stack = new Stack<Token>();
+    private ArrayList<Token> variables = new ArrayList<Token>();
+    private boolean endOfMethod;
+    private boolean condition;
+    private int nextPc;
+    private Map<String, Object> fieldMap = new HashMap<String, Object>();
 
-       private static void debug(String s) {
-               if (DEBUG) {
-                       System.out.println(s);
-               }
-       }
+    private static void debug(String s) {
+        if (DEBUG) {
+            System.out.println(s);
+        }
+    }
 
-       public Token decompile(Object instance, Map<String, Object> fields, String method) {
-               this.fieldMap = fields;
-               this.convertMethodName = method;
-               Class<?> clazz = instance.getClass();
-               String className = clazz.getName();
-               debug("class name " + className);
-               ByteArrayOutputStream buff = new ByteArrayOutputStream();
-               try {
-                       InputStream in = clazz.getClassLoader().getResource(className.replace('.', '/') + ".class")
-                                       .openStream();
-                       while (true) {
-                               int x = in.read();
-                               if (x < 0) {
-                                       break;
-                               }
-                               buff.write(x);
-                       }
-               } catch (IOException e) {
-                       throw new IciqlException("Could not read class bytecode", e);
-               }
-               data = buff.toByteArray();
-               int header = readInt();
-               debug("header: " + Integer.toHexString(header));
-               int minorVersion = readShort();
-               int majorVersion = readShort();
-               debug("version: " + majorVersion + "." + minorVersion);
-               int constantPoolCount = readShort();
-               constantPool = new Constant[constantPoolCount];
-               for (int i = 1; i < constantPoolCount; i++) {
-                       int type = readByte();
-                       switch (type) {
-                       case 1:
-                               constantPool[i] = ConstantString.get(readString());
-                               break;
-                       case 3: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get(x);
-                               break;
-                       }
-                       case 4: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get("" + Float.intBitsToFloat(x), x, Constant.Type.FLOAT);
-                               break;
-                       }
-                       case 5: {
-                               long x = readLong();
-                               constantPool[i] = ConstantNumber.get(x);
-                               i++;
-                               break;
-                       }
-                       case 6: {
-                               long x = readLong();
-                               constantPool[i] = ConstantNumber
-                                               .get("" + Double.longBitsToDouble(x), x, Constant.Type.DOUBLE);
-                               i++;
-                               break;
-                       }
-                       case 7: {
-                               int x = readShort();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.CLASS_REF);
-                               break;
-                       }
-                       case 8: {
-                               int x = readShort();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.STRING_REF);
-                               break;
-                       }
-                       case 9: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.FIELD_REF);
-                               break;
-                       }
-                       case 10: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.METHOD_REF);
-                               break;
-                       }
-                       case 11: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.INTERFACE_METHOD_REF);
-                               break;
-                       }
-                       case 12: {
-                               int x = readInt();
-                               constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.NAME_AND_TYPE);
-                               break;
-                       }
-                       default:
-                               throw new IciqlException("Unsupported constant pool tag: " + type);
-                       }
-               }
-               int accessFlags = readShort();
-               debug("access flags: " + accessFlags);
-               int classRef = readShort();
-               debug("class: " + constantPool[constantPool[classRef].intValue()]);
-               int superClassRef = readShort();
-               debug(" extends " + constantPool[constantPool[superClassRef].intValue()]);
-               int interfaceCount = readShort();
-               for (int i = 0; i < interfaceCount; i++) {
-                       int interfaceRef = readShort();
-                       debug(" implements " + constantPool[constantPool[interfaceRef].intValue()]);
-               }
-               int fieldCount = readShort();
-               for (int i = 0; i < fieldCount; i++) {
-                       readField();
-               }
-               int methodCount = readShort();
-               for (int i = 0; i < methodCount; i++) {
-                       readMethod();
-               }
-               readAttributes();
-               return result;
-       }
+    public Token decompile(Object instance, Map<String, Object> fields, String method) {
+        this.fieldMap = fields;
+        this.convertMethodName = method;
+        Class<?> clazz = instance.getClass();
+        String className = clazz.getName();
+        debug("class name " + className);
+        ByteArrayOutputStream buff = new ByteArrayOutputStream();
+        try {
+            InputStream in = clazz.getClassLoader().getResource(className.replace('.', '/') + ".class")
+                    .openStream();
+            while (true) {
+                int x = in.read();
+                if (x < 0) {
+                    break;
+                }
+                buff.write(x);
+            }
+        } catch (IOException e) {
+            throw new IciqlException("Could not read class bytecode", e);
+        }
+        data = buff.toByteArray();
+        int header = readInt();
+        debug("header: " + Integer.toHexString(header));
+        int minorVersion = readShort();
+        int majorVersion = readShort();
+        debug("version: " + majorVersion + "." + minorVersion);
+        int constantPoolCount = readShort();
+        constantPool = new Constant[constantPoolCount];
+        for (int i = 1; i < constantPoolCount; i++) {
+            int type = readByte();
+            switch (type) {
+                case 1:
+                    constantPool[i] = ConstantString.get(readString());
+                    break;
+                case 3: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get(x);
+                    break;
+                }
+                case 4: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get("" + Float.intBitsToFloat(x), x, Constant.Type.FLOAT);
+                    break;
+                }
+                case 5: {
+                    long x = readLong();
+                    constantPool[i] = ConstantNumber.get(x);
+                    i++;
+                    break;
+                }
+                case 6: {
+                    long x = readLong();
+                    constantPool[i] = ConstantNumber
+                            .get("" + Double.longBitsToDouble(x), x, Constant.Type.DOUBLE);
+                    i++;
+                    break;
+                }
+                case 7: {
+                    int x = readShort();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.CLASS_REF);
+                    break;
+                }
+                case 8: {
+                    int x = readShort();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.STRING_REF);
+                    break;
+                }
+                case 9: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.FIELD_REF);
+                    break;
+                }
+                case 10: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.METHOD_REF);
+                    break;
+                }
+                case 11: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.INTERFACE_METHOD_REF);
+                    break;
+                }
+                case 12: {
+                    int x = readInt();
+                    constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.NAME_AND_TYPE);
+                    break;
+                }
+                default:
+                    throw new IciqlException("Unsupported constant pool tag: " + type);
+            }
+        }
+        int accessFlags = readShort();
+        debug("access flags: " + accessFlags);
+        int classRef = readShort();
+        debug("class: " + constantPool[constantPool[classRef].intValue()]);
+        int superClassRef = readShort();
+        debug(" extends " + constantPool[constantPool[superClassRef].intValue()]);
+        int interfaceCount = readShort();
+        for (int i = 0; i < interfaceCount; i++) {
+            int interfaceRef = readShort();
+            debug(" implements " + constantPool[constantPool[interfaceRef].intValue()]);
+        }
+        int fieldCount = readShort();
+        for (int i = 0; i < fieldCount; i++) {
+            readField();
+        }
+        int methodCount = readShort();
+        for (int i = 0; i < methodCount; i++) {
+            readMethod();
+        }
+        readAttributes();
+        return result;
+    }
 
-       private void readField() {
-               int accessFlags = readShort();
-               int nameIndex = readShort();
-               int descIndex = readShort();
-               debug("    " + constantPool[descIndex] + " " + constantPool[nameIndex] + " " + accessFlags);
-               readAttributes();
-       }
+    private void readField() {
+        int accessFlags = readShort();
+        int nameIndex = readShort();
+        int descIndex = readShort();
+        debug("    " + constantPool[descIndex] + " " + constantPool[nameIndex] + " " + accessFlags);
+        readAttributes();
+    }
 
-       private void readMethod() {
-               int accessFlags = readShort();
-               int nameIndex = readShort();
-               int descIndex = readShort();
-               String desc = constantPool[descIndex].toString();
-               methodName = constantPool[nameIndex].toString();
-               debug("    " + desc + " " + methodName + " " + accessFlags);
-               readAttributes();
-       }
+    private void readMethod() {
+        int accessFlags = readShort();
+        int nameIndex = readShort();
+        int descIndex = readShort();
+        String desc = constantPool[descIndex].toString();
+        methodName = constantPool[nameIndex].toString();
+        debug("    " + desc + " " + methodName + " " + accessFlags);
+        readAttributes();
+    }
 
-       private void readAttributes() {
-               int attributeCount = readShort();
-               for (int i = 0; i < attributeCount; i++) {
-                       int attributeNameIndex = readShort();
-                       String attributeName = constantPool[attributeNameIndex].toString();
-                       debug("        attribute " + attributeName);
-                       int attributeLength = readInt();
-                       int end = pos + attributeLength;
-                       if ("Code".equals(attributeName)) {
-                               readCode();
-                       }
-                       pos = end;
-               }
-       }
+    private void readAttributes() {
+        int attributeCount = readShort();
+        for (int i = 0; i < attributeCount; i++) {
+            int attributeNameIndex = readShort();
+            String attributeName = constantPool[attributeNameIndex].toString();
+            debug("        attribute " + attributeName);
+            int attributeLength = readInt();
+            int end = pos + attributeLength;
+            if ("Code".equals(attributeName)) {
+                readCode();
+            }
+            pos = end;
+        }
+    }
 
-       void decompile() {
-               int maxStack = readShort();
-               int maxLocals = readShort();
-               debug("stack: " + maxStack + " locals: " + maxLocals);
-               int codeLength = readInt();
-               startByteCode = pos;
-               int end = pos + codeLength;
-               while (pos < end) {
-                       readByteCode();
-               }
-               debug("");
-               pos = startByteCode + codeLength;
-               int exceptionTableLength = readShort();
-               pos += 2 * exceptionTableLength;
-               readAttributes();
-       }
+    void decompile() {
+        int maxStack = readShort();
+        int maxLocals = readShort();
+        debug("stack: " + maxStack + " locals: " + maxLocals);
+        int codeLength = readInt();
+        startByteCode = pos;
+        int end = pos + codeLength;
+        while (pos < end) {
+            readByteCode();
+        }
+        debug("");
+        pos = startByteCode + codeLength;
+        int exceptionTableLength = readShort();
+        pos += 2 * exceptionTableLength;
+        readAttributes();
+    }
 
-       private void readCode() {
-               variables.clear();
-               stack.clear();
-               int maxStack = readShort();
-               int maxLocals = readShort();
-               debug("stack: " + maxStack + " locals: " + maxLocals);
-               int codeLength = readInt();
-               startByteCode = pos;
-               if (methodName.startsWith(convertMethodName)) {
-                       result = getResult();
-               }
-               pos = startByteCode + codeLength;
-               int exceptionTableLength = readShort();
-               pos += 2 * exceptionTableLength;
-               readAttributes();
-       }
+    private void readCode() {
+        variables.clear();
+        stack.clear();
+        int maxStack = readShort();
+        int maxLocals = readShort();
+        debug("stack: " + maxStack + " locals: " + maxLocals);
+        int codeLength = readInt();
+        startByteCode = pos;
+        if (methodName.startsWith(convertMethodName)) {
+            result = getResult();
+        }
+        pos = startByteCode + codeLength;
+        int exceptionTableLength = readShort();
+        pos += 2 * exceptionTableLength;
+        readAttributes();
+    }
 
-       private Token getResult() {
-               while (true) {
-                       readByteCode();
-                       if (endOfMethod) {
-                               return stack.pop();
-                       }
-                       if (condition) {
-                               Token c = stack.pop();
-                               Stack<Token> currentStack = new Stack<Token>();
-                               currentStack.addAll(stack);
-                               ArrayList<Token> currentVariables = new ArrayList<Token>();
-                               currentVariables.addAll(variables);
-                               int branch = nextPc;
-                               Token a = getResult();
-                               stack = currentStack;
-                               variables = currentVariables;
-                               pos = branch + startByteCode;
-                               Token b = getResult();
-                               if (a.equals("0") && b.equals("1")) {
-                                       return c;
-                               } else if (a.equals("1") && b.equals("0")) {
-                                       return Not.get(c);
-                               } else if (b.equals("0")) {
-                                       return And.get(Not.get(c), a);
-                               } else if (a.equals("0")) {
-                                       return And.get(c, b);
-                               } else if (b.equals("1")) {
-                                       return Or.get(c, a);
-                               } else if (a.equals("1")) {
-                                       return And.get(Not.get(c), b);
-                               }
-                               return CaseWhen.get(c, b, a);
-                       }
-                       if (nextPc != 0) {
-                               pos = nextPc + startByteCode;
-                       }
-               }
-       }
+    private Token getResult() {
+        while (true) {
+            readByteCode();
+            if (endOfMethod) {
+                return stack.pop();
+            }
+            if (condition) {
+                Token c = stack.pop();
+                Stack<Token> currentStack = new Stack<Token>();
+                currentStack.addAll(stack);
+                ArrayList<Token> currentVariables = new ArrayList<Token>();
+                currentVariables.addAll(variables);
+                int branch = nextPc;
+                Token a = getResult();
+                stack = currentStack;
+                variables = currentVariables;
+                pos = branch + startByteCode;
+                Token b = getResult();
+                if (a.equals("0") && b.equals("1")) {
+                    return c;
+                } else if (a.equals("1") && b.equals("0")) {
+                    return Not.get(c);
+                } else if (b.equals("0")) {
+                    return And.get(Not.get(c), a);
+                } else if (a.equals("0")) {
+                    return And.get(c, b);
+                } else if (b.equals("1")) {
+                    return Or.get(c, a);
+                } else if (a.equals("1")) {
+                    return And.get(Not.get(c), b);
+                }
+                return CaseWhen.get(c, b, a);
+            }
+            if (nextPc != 0) {
+                pos = nextPc + startByteCode;
+            }
+        }
+    }
 
-       private void readByteCode() {
-               int startPos = pos - startByteCode;
-               int opCode = readByte();
-               String op;
-               endOfMethod = false;
-               condition = false;
-               nextPc = 0;
-               switch (opCode) {
-               case 0:
-                       op = "nop";
-                       break;
-               case 1:
-                       op = "aconst_null";
-                       stack.push(Null.INSTANCE);
-                       break;
-               case 2:
-                       op = "iconst_m1";
-                       stack.push(ConstantNumber.get("-1"));
-                       break;
-               case 3:
-                       op = "iconst_0";
-                       stack.push(ConstantNumber.get("0"));
-                       break;
-               case 4:
-                       op = "iconst_1";
-                       stack.push(ConstantNumber.get("1"));
-                       break;
-               case 5:
-                       op = "iconst_2";
-                       stack.push(ConstantNumber.get("2"));
-                       break;
-               case 6:
-                       op = "iconst_3";
-                       stack.push(ConstantNumber.get("3"));
-                       break;
-               case 7:
-                       op = "iconst_4";
-                       stack.push(ConstantNumber.get("4"));
-                       break;
-               case 8:
-                       op = "iconst_5";
-                       stack.push(ConstantNumber.get("5"));
-                       break;
-               case 9:
-                       op = "lconst_0";
-                       stack.push(ConstantNumber.get("0"));
-                       break;
-               case 10:
-                       op = "lconst_1";
-                       stack.push(ConstantNumber.get("1"));
-                       break;
-               case 11:
-                       op = "fconst_0";
-                       stack.push(ConstantNumber.get("0.0"));
-                       break;
-               case 12:
-                       op = "fconst_1";
-                       stack.push(ConstantNumber.get("1.0"));
-                       break;
-               case 13:
-                       op = "fconst_2";
-                       stack.push(ConstantNumber.get("2.0"));
-                       break;
-               case 14:
-                       op = "dconst_0";
-                       stack.push(ConstantNumber.get("0.0"));
-                       break;
-               case 15:
-                       op = "dconst_1";
-                       stack.push(ConstantNumber.get("1.0"));
-                       break;
-               case 16: {
-                       int x = (byte) readByte();
-                       op = "bipush " + x;
-                       stack.push(ConstantNumber.get(x));
-                       break;
-               }
-               case 17: {
-                       int x = (short) readShort();
-                       op = "sipush " + x;
-                       stack.push(ConstantNumber.get(x));
-                       break;
-               }
-               case 18: {
-                       Token s = getConstant(readByte());
-                       op = "ldc " + s;
-                       stack.push(s);
-                       break;
-               }
-               case 19: {
-                       Token s = getConstant(readShort());
-                       op = "ldc_w " + s;
-                       stack.push(s);
-                       break;
-               }
-               case 20: {
-                       Token s = getConstant(readShort());
-                       op = "ldc2_w " + s;
-                       stack.push(s);
-                       break;
-               }
-               case 21: {
-                       int x = readByte();
-                       op = "iload " + x;
-                       stack.push(getVariable(x));
-                       break;
-               }
-               case 22: {
-                       int x = readByte();
-                       op = "lload " + x;
-                       stack.push(getVariable(x));
-                       break;
-               }
-               case 23: {
-                       int x = readByte();
-                       op = "fload " + x;
-                       stack.push(getVariable(x));
-                       break;
-               }
-               case 24: {
-                       int x = readByte();
-                       op = "dload " + x;
-                       stack.push(getVariable(x));
-                       break;
-               }
-               case 25: {
-                       int x = readByte();
-                       op = "aload " + x;
-                       stack.push(getVariable(x));
-                       break;
-               }
-               case 26:
-                       op = "iload_0";
-                       stack.push(getVariable(0));
-                       break;
-               case 27:
-                       op = "iload_1";
-                       stack.push(getVariable(1));
-                       break;
-               case 28:
-                       op = "iload_2";
-                       stack.push(getVariable(2));
-                       break;
-               case 29:
-                       op = "iload_3";
-                       stack.push(getVariable(3));
-                       break;
-               case 30:
-                       op = "lload_0";
-                       stack.push(getVariable(0));
-                       break;
-               case 31:
-                       op = "lload_1";
-                       stack.push(getVariable(1));
-                       break;
-               case 32:
-                       op = "lload_2";
-                       stack.push(getVariable(2));
-                       break;
-               case 33:
-                       op = "lload_3";
-                       stack.push(getVariable(3));
-                       break;
-               case 34:
-                       op = "fload_0";
-                       stack.push(getVariable(0));
-                       break;
-               case 35:
-                       op = "fload_1";
-                       stack.push(getVariable(1));
-                       break;
-               case 36:
-                       op = "fload_2";
-                       stack.push(getVariable(2));
-                       break;
-               case 37:
-                       op = "fload_3";
-                       stack.push(getVariable(3));
-                       break;
-               case 38:
-                       op = "dload_0";
-                       stack.push(getVariable(0));
-                       break;
-               case 39:
-                       op = "dload_1";
-                       stack.push(getVariable(1));
-                       break;
-               case 40:
-                       op = "dload_2";
-                       stack.push(getVariable(2));
-                       break;
-               case 41:
-                       op = "dload_3";
-                       stack.push(getVariable(3));
-                       break;
-               case 42:
-                       op = "aload_0";
-                       stack.push(getVariable(0));
-                       break;
-               case 43:
-                       op = "aload_1";
-                       stack.push(getVariable(1));
-                       break;
-               case 44:
-                       op = "aload_2";
-                       stack.push(getVariable(2));
-                       break;
-               case 45:
-                       op = "aload_3";
-                       stack.push(getVariable(3));
-                       break;
-               case 46: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "iaload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 47: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "laload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 48: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "faload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 49: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "daload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 50: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "aaload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 51: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "baload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 52: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "caload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 53: {
-                       Token index = stack.pop();
-                       Token ref = stack.pop();
-                       op = "saload";
-                       stack.push(ArrayGet.get(ref, index));
-                       break;
-               }
-               case 54: {
-                       int var = readByte();
-                       op = "istore " + var;
-                       setVariable(var, stack.pop());
-                       break;
-               }
-               case 55: {
-                       int var = readByte();
-                       op = "lstore " + var;
-                       setVariable(var, stack.pop());
-                       break;
-               }
-               case 56: {
-                       int var = readByte();
-                       op = "fstore " + var;
-                       setVariable(var, stack.pop());
-                       break;
-               }
-               case 57: {
-                       int var = readByte();
-                       op = "dstore " + var;
-                       setVariable(var, stack.pop());
-                       break;
-               }
-               case 58: {
-                       int var = readByte();
-                       op = "astore " + var;
-                       setVariable(var, stack.pop());
-                       break;
-               }
-               case 59:
-                       op = "istore_0";
-                       setVariable(0, stack.pop());
-                       break;
-               case 60:
-                       op = "istore_1";
-                       setVariable(1, stack.pop());
-                       break;
-               case 61:
-                       op = "istore_2";
-                       setVariable(2, stack.pop());
-                       break;
-               case 62:
-                       op = "istore_3";
-                       setVariable(3, stack.pop());
-                       break;
-               case 63:
-                       op = "lstore_0";
-                       setVariable(0, stack.pop());
-                       break;
-               case 64:
-                       op = "lstore_1";
-                       setVariable(1, stack.pop());
-                       break;
-               case 65:
-                       op = "lstore_2";
-                       setVariable(2, stack.pop());
-                       break;
-               case 66:
-                       op = "lstore_3";
-                       setVariable(3, stack.pop());
-                       break;
-               case 67:
-                       op = "fstore_0";
-                       setVariable(0, stack.pop());
-                       break;
-               case 68:
-                       op = "fstore_1";
-                       setVariable(1, stack.pop());
-                       break;
-               case 69:
-                       op = "fstore_2";
-                       setVariable(2, stack.pop());
-                       break;
-               case 70:
-                       op = "fstore_3";
-                       setVariable(3, stack.pop());
-                       break;
-               case 71:
-                       op = "dstore_0";
-                       setVariable(0, stack.pop());
-                       break;
-               case 72:
-                       op = "dstore_1";
-                       setVariable(1, stack.pop());
-                       break;
-               case 73:
-                       op = "dstore_2";
-                       setVariable(2, stack.pop());
-                       break;
-               case 74:
-                       op = "dstore_3";
-                       setVariable(3, stack.pop());
-                       break;
-               case 75:
-                       op = "astore_0";
-                       setVariable(0, stack.pop());
-                       break;
-               case 76:
-                       op = "astore_1";
-                       setVariable(1, stack.pop());
-                       break;
-               case 77:
-                       op = "astore_2";
-                       setVariable(2, stack.pop());
-                       break;
-               case 78:
-                       op = "astore_3";
-                       setVariable(3, stack.pop());
-                       break;
-               case 79: {
-                       // String value = stack.pop();
-                       // String index = stack.pop();
-                       // String ref = stack.pop();
-                       op = "iastore";
-                       // TODO side effect - not supported
-                       break;
-               }
-               case 80:
-                       op = "lastore";
-                       // TODO side effect - not supported
-                       break;
-               case 81:
-                       op = "fastore";
-                       // TODO side effect - not supported
-                       break;
-               case 82:
-                       op = "dastore";
-                       // TODO side effect - not supported
-                       break;
-               case 83:
-                       op = "aastore";
-                       // TODO side effect - not supported
-                       break;
-               case 84:
-                       op = "bastore";
-                       // TODO side effect - not supported
-                       break;
-               case 85:
-                       op = "castore";
-                       // TODO side effect - not supported
-                       break;
-               case 86:
-                       op = "sastore";
-                       // TODO side effect - not supported
-                       break;
-               case 87:
-                       op = "pop";
-                       stack.pop();
-                       break;
-               case 88:
-                       op = "pop2";
-                       // TODO currently we don't know the stack types
-                       stack.pop();
-                       stack.pop();
-                       break;
-               case 89: {
-                       op = "dup";
-                       Token x = stack.pop();
-                       stack.push(x);
-                       stack.push(x);
-                       break;
-               }
-               case 90: {
-                       op = "dup_x1";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       stack.push(a);
-                       stack.push(b);
-                       stack.push(a);
-                       break;
-               }
-               case 91: {
-                       // TODO currently we don't know the stack types
-                       op = "dup_x2";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       Token c = stack.pop();
-                       stack.push(a);
-                       stack.push(c);
-                       stack.push(b);
-                       stack.push(a);
-                       break;
-               }
-               case 92: {
-                       // TODO currently we don't know the stack types
-                       op = "dup2";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       stack.push(b);
-                       stack.push(a);
-                       stack.push(b);
-                       stack.push(a);
-                       break;
-               }
-               case 93: {
-                       // TODO currently we don't know the stack types
-                       op = "dup2_x1";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       Token c = stack.pop();
-                       stack.push(b);
-                       stack.push(a);
-                       stack.push(c);
-                       stack.push(b);
-                       stack.push(a);
-                       break;
-               }
-               case 94: {
-                       // TODO currently we don't know the stack types
-                       op = "dup2_x2";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       Token c = stack.pop();
-                       Token d = stack.pop();
-                       stack.push(b);
-                       stack.push(a);
-                       stack.push(d);
-                       stack.push(c);
-                       stack.push(b);
-                       stack.push(a);
-                       break;
-               }
-               case 95: {
-                       op = "swap";
-                       Token a = stack.pop();
-                       Token b = stack.pop();
-                       stack.push(a);
-                       stack.push(b);
-                       break;
-               }
-               case 96: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "iadd";
-                       stack.push(Operation.get(a, Operation.Type.ADD, b));
-                       break;
-               }
-               case 97: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "ladd";
-                       stack.push(Operation.get(a, Operation.Type.ADD, b));
-                       break;
-               }
-               case 98: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "fadd";
-                       stack.push(Operation.get(a, Operation.Type.ADD, b));
-                       break;
-               }
-               case 99: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "dadd";
-                       stack.push(Operation.get(a, Operation.Type.ADD, b));
-                       break;
-               }
-               case 100: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "isub";
-                       stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
-                       break;
-               }
-               case 101: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "lsub";
-                       stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
-                       break;
-               }
-               case 102: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "fsub";
-                       stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
-                       break;
-               }
-               case 103: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "dsub";
-                       stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
-                       break;
-               }
-               case 104: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "imul";
-                       stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
-                       break;
-               }
-               case 105: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "lmul";
-                       stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
-                       break;
-               }
-               case 106: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "fmul";
-                       stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
-                       break;
-               }
-               case 107: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "dmul";
-                       stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
-                       break;
-               }
-               case 108: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "idiv";
-                       stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
-                       break;
-               }
-               case 109: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "ldiv";
-                       stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
-                       break;
-               }
-               case 110: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "fdiv";
-                       stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
-                       break;
-               }
-               case 111: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "ddiv";
-                       stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
-                       break;
-               }
-               case 112: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "irem";
-                       stack.push(Operation.get(a, Operation.Type.MOD, b));
-                       break;
-               }
-               case 113: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "lrem";
-                       stack.push(Operation.get(a, Operation.Type.MOD, b));
-                       break;
-               }
-               case 114: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "frem";
-                       stack.push(Operation.get(a, Operation.Type.MOD, b));
-                       break;
-               }
-               case 115: {
-                       Token b = stack.pop();
-                       Token a = stack.pop();
-                       op = "drem";
-                       stack.push(Operation.get(a, Operation.Type.MOD, b));
-                       break;
-               }
-               // case 116:
-               // op = "ineg";
-               // break;
-               // case 117:
-               // op = "lneg";
-               // break;
-               // case 118:
-               // op = "fneg";
-               // break;
-               // case 119:
-               // op = "dneg";
-               // break;
-               // case 120:
-               // op = "ishl";
-               // break;
-               // case 121:
-               // op = "lshl";
-               // break;
-               // case 122:
-               // op = "ishr";
-               // break;
-               // case 123:
-               // op = "lshr";
-               // break;
-               // case 124:
-               // op = "iushr";
-               // break;
-               // case 125:
-               // op = "lushr";
-               // break;
-               // case 126:
-               // op = "iand";
-               // break;
-               // case 127:
-               // op = "land";
-               // break;
-               // case 128:
-               // op = "ior";
-               // break;
-               // case 129:
-               // op = "lor";
-               // break;
-               // case 130:
-               // op = "ixor";
-               // break;
-               // case 131:
-               // op = "lxor";
-               // break;
-               // case 132: {
-               // int var = readByte();
-               // int off = (byte) readByte();
-               // op = "iinc " + var + " " + off;
-               // break;
-               // }
-               // case 133:
-               // op = "i2l";
-               // break;
-               // case 134:
-               // op = "i2f";
-               // break;
-               // case 135:
-               // op = "i2d";
-               // break;
-               // case 136:
-               // op = "l2i";
-               // break;
-               // case 137:
-               // op = "l2f";
-               // break;
-               // case 138:
-               // op = "l2d";
-               // break;
-               // case 139:
-               // op = "f2i";
-               // break;
-               // case 140:
-               // op = "f2l";
-               // break;
-               // case 141:
-               // op = "f2d";
-               // break;
-               // case 142:
-               // op = "d2i";
-               // break;
-               // case 143:
-               // op = "d2l";
-               // break;
-               // case 144:
-               // op = "d2f";
-               // break;
-               // case 145:
-               // op = "i2b";
-               // break;
-               // case 146:
-               // op = "i2c";
-               // break;
-               // case 147:
-               // op = "i2s";
-               // break;
-               case 148: {
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(new Function("SIGN", Operation.get(a, Operation.Type.SUBTRACT, b)));
-                       op = "lcmp";
-                       break;
-               }
-               // case 149:
-               // op = "fcmpl";
-               // break;
-               // case 150:
-               // op = "fcmpg";
-               // break;
-               // case 151:
-               // op = "dcmpl";
-               // break;
-               // case 152:
-               // op = "dcmpg";
-               // break;
-               case 153:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.EQUALS, ConstantNumber.get(0)));
-                       op = "ifeq " + nextPc;
-                       break;
-               case 154:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.NOT_EQUALS, ConstantNumber.get(0)));
-                       op = "ifne " + nextPc;
-                       break;
-               case 155:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER, ConstantNumber.get(0)));
-                       op = "iflt " + nextPc;
-                       break;
-               case 156:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER_EQUALS, ConstantNumber.get(0)));
-                       op = "ifge " + nextPc;
-                       break;
-               case 157:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER, ConstantNumber.get(0)));
-                       op = "ifgt " + nextPc;
-                       break;
-               case 158:
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER_EQUALS, ConstantNumber.get(0)));
-                       op = "ifle " + nextPc;
-                       break;
-               case 159: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.EQUALS, b));
-                       op = "if_icmpeq " + nextPc;
-                       break;
-               }
-               case 160: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
-                       op = "if_icmpne " + nextPc;
-                       break;
-               }
-               case 161: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.SMALLER, b));
-                       op = "if_icmplt " + nextPc;
-                       break;
-               }
-               case 162: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.BIGGER_EQUALS, b));
-                       op = "if_icmpge " + nextPc;
-                       break;
-               }
-               case 163: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.BIGGER, b));
-                       op = "if_icmpgt " + nextPc;
-                       break;
-               }
-               case 164: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.SMALLER_EQUALS, b));
-                       op = "if_icmple " + nextPc;
-                       break;
-               }
-               case 165: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.EQUALS, b));
-                       op = "if_acmpeq " + nextPc;
-                       break;
-               }
-               case 166: {
-                       condition = true;
-                       nextPc = getAbsolutePos(pos, readShort());
-                       Token b = stack.pop(), a = stack.pop();
-                       stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
-                       op = "if_acmpne " + nextPc;
-                       break;
-               }
-               case 167:
-                       nextPc = getAbsolutePos(pos, readShort());
-                       op = "goto " + nextPc;
-                       break;
-               // case 168:
-               // // TODO not supported yet
-               // op = "jsr " + getAbsolutePos(pos, readShort());
-               // break;
-               // case 169:
-               // // TODO not supported yet
-               // op = "ret " + readByte();
-               // break;
-               // case 170: {
-               // int start = pos;
-               // pos += 4 - ((pos - startByteCode) & 3);
-               // int def = readInt();
-               // int low = readInt(), high = readInt();
-               // int n = high - low + 1;
-               // op = "tableswitch default:" + getAbsolutePos(start, def);
-               // StringBuilder buff = new StringBuilder();
-               // for (int i = 0; i < n; i++) {
-               // buff.append(' ').append(low++).
-               // append(":").
-               // append(getAbsolutePos(start, readInt()));
-               // }
-               // op += buff.toString();
-               // // pos += n * 4;
-               // break;
-               // }
-               // case 171: {
-               // int start = pos;
-               // pos += 4 - ((pos - startByteCode) & 3);
-               // int def = readInt();
-               // int n = readInt();
-               // op = "lookupswitch default:" + getAbsolutePos(start, def);
-               // StringBuilder buff = new StringBuilder();
-               // for (int i = 0; i < n; i++) {
-               // buff.append(' ').
-               // append(readInt()).
-               // append(":").
-               // append(getAbsolutePos(start, readInt()));
-               // }
-               // op += buff.toString();
-               // // pos += n * 8;
-               // break;
-               // }
-               case 172:
-                       op = "ireturn";
-                       endOfMethod = true;
-                       break;
-               case 173:
-                       op = "lreturn";
-                       endOfMethod = true;
-                       break;
-               case 174:
-                       op = "freturn";
-                       endOfMethod = true;
-                       break;
-               case 175:
-                       op = "dreturn";
-                       endOfMethod = true;
-                       break;
-               case 176:
-                       op = "areturn";
-                       endOfMethod = true;
-                       break;
-               case 177:
-                       op = "return";
-                       // no value returned
-                       stack.push(null);
-                       endOfMethod = true;
-                       break;
-               // case 178:
-               // op = "getstatic " + getField(readShort());
-               // break;
-               // case 179:
-               // op = "putstatic " + getField(readShort());
-               // break;
-               case 180: {
-                       String field = getField(readShort());
-                       Token p = stack.pop();
-                       String s = p + "." + field.substring(field.lastIndexOf('.') + 1, field.indexOf(' '));
-                       if (s.startsWith("this.")) {
-                               s = s.substring(5);
-                       }
-                       stack.push(Variable.get(s, fieldMap.get(s)));
-                       op = "getfield " + field;
-                       break;
-               }
-               // case 181:
-               // op = "putfield " + getField(readShort());
-               // break;
-               case 182: {
-                       String method = getMethod(readShort());
-                       op = "invokevirtual " + method;
-                       if (method.equals("java/lang/String.equals (Ljava/lang/Object;)Z")) {
-                               Token a = stack.pop();
-                               Token b = stack.pop();
-                               stack.push(Operation.get(a, Operation.Type.EQUALS, b));
-                       } else if (method.equals("java/lang/Integer.intValue ()I")) {
-                               // ignore
-                       } else if (method.equals("java/lang/Long.longValue ()J")) {
-                               // ignore
-                       }
-                       break;
-               }
-               case 183: {
-                       String method = getMethod(readShort());
-                       op = "invokespecial " + method;
-                       break;
-               }
-               case 184:
-                       op = "invokestatic " + getMethod(readShort());
-                       break;
-               // case 185: {
-               // int methodRef = readShort();
-               // readByte();
-               // readByte();
-               // op = "invokeinterface " + getMethod(methodRef);
-               // break;
-               // }
-               case 187: {
-                       String className = constantPool[constantPool[readShort()].intValue()].toString();
-                       op = "new " + className;
-                       break;
-               }
-               // case 188:
-               // op = "newarray " + readByte();
-               // break;
-               // case 189:
-               // op = "anewarray " + cpString[readShort()];
-               // break;
-               // case 190:
-               // op = "arraylength";
-               // break;
-               // case 191:
-               // op = "athrow";
-               // break;
-               // case 192:
-               // op = "checkcast " + cpString[readShort()];
-               // break;
-               // case 193:
-               // op = "instanceof " + cpString[readShort()];
-               // break;
-               // case 194:
-               // op = "monitorenter";
-               // break;
-               // case 195:
-               // op = "monitorexit";
-               // break;
-               // case 196: {
-               // opCode = readByte();
-               // switch (opCode) {
-               // case 21:
-               // op = "wide iload " + readShort();
-               // break;
-               // case 22:
-               // op = "wide lload " + readShort();
-               // break;
-               // case 23:
-               // op = "wide fload " + readShort();
-               // break;
-               // case 24:
-               // op = "wide dload " + readShort();
-               // break;
-               // case 25:
-               // op = "wide aload " + readShort();
-               // break;
-               // case 54:
-               // op = "wide istore " + readShort();
-               // break;
-               // case 55:
-               // op = "wide lstore " + readShort();
-               // break;
-               // case 56:
-               // op = "wide fstore " + readShort();
-               // break;
-               // case 57:
-               // op = "wide dstore " + readShort();
-               // break;
-               // case 58:
-               // op = "wide astore " + readShort();
-               // break;
-               // case 132: {
-               // int var = readShort();
-               // int off = (short) readShort();
-               // op = "wide iinc " + var + " " + off;
-               // break;
-               // }
-               // case 169:
-               // op = "wide ret " + readShort();
-               // break;
-               // default:
-               // throw new IciqlException(
-               // "Unsupported wide opCode " + opCode);
-               // }
-               // break;
-               // }
-               // case 197:
-               // op = "multianewarray " + cpString[readShort()] + " " + readByte();
-               // break;
-               // case 198: {
-               // condition = true;
-               // nextPc = getAbsolutePos(pos, readShort());
-               // Token a = stack.pop();
-               // stack.push("(" + a + " IS NULL)");
-               // op = "ifnull " + nextPc;
-               // break;
-               // }
-               // case 199: {
-               // condition = true;
-               // nextPc = getAbsolutePos(pos, readShort());
-               // Token a = stack.pop();
-               // stack.push("(" + a + " IS NOT NULL)");
-               // op = "ifnonnull " + nextPc;
-               // break;
-               // }
-               case 200:
-                       op = "goto_w " + getAbsolutePos(pos, readInt());
-                       break;
-               case 201:
-                       op = "jsr_w " + getAbsolutePos(pos, readInt());
-                       break;
-               default:
-                       throw new IciqlException("Unsupported opCode " + opCode);
-               }
-               debug("    " + startPos + ": " + op);
-       }
+    private void readByteCode() {
+        int startPos = pos - startByteCode;
+        int opCode = readByte();
+        String op;
+        endOfMethod = false;
+        condition = false;
+        nextPc = 0;
+        switch (opCode) {
+            case 0:
+                op = "nop";
+                break;
+            case 1:
+                op = "aconst_null";
+                stack.push(Null.INSTANCE);
+                break;
+            case 2:
+                op = "iconst_m1";
+                stack.push(ConstantNumber.get("-1"));
+                break;
+            case 3:
+                op = "iconst_0";
+                stack.push(ConstantNumber.get("0"));
+                break;
+            case 4:
+                op = "iconst_1";
+                stack.push(ConstantNumber.get("1"));
+                break;
+            case 5:
+                op = "iconst_2";
+                stack.push(ConstantNumber.get("2"));
+                break;
+            case 6:
+                op = "iconst_3";
+                stack.push(ConstantNumber.get("3"));
+                break;
+            case 7:
+                op = "iconst_4";
+                stack.push(ConstantNumber.get("4"));
+                break;
+            case 8:
+                op = "iconst_5";
+                stack.push(ConstantNumber.get("5"));
+                break;
+            case 9:
+                op = "lconst_0";
+                stack.push(ConstantNumber.get("0"));
+                break;
+            case 10:
+                op = "lconst_1";
+                stack.push(ConstantNumber.get("1"));
+                break;
+            case 11:
+                op = "fconst_0";
+                stack.push(ConstantNumber.get("0.0"));
+                break;
+            case 12:
+                op = "fconst_1";
+                stack.push(ConstantNumber.get("1.0"));
+                break;
+            case 13:
+                op = "fconst_2";
+                stack.push(ConstantNumber.get("2.0"));
+                break;
+            case 14:
+                op = "dconst_0";
+                stack.push(ConstantNumber.get("0.0"));
+                break;
+            case 15:
+                op = "dconst_1";
+                stack.push(ConstantNumber.get("1.0"));
+                break;
+            case 16: {
+                int x = (byte) readByte();
+                op = "bipush " + x;
+                stack.push(ConstantNumber.get(x));
+                break;
+            }
+            case 17: {
+                int x = (short) readShort();
+                op = "sipush " + x;
+                stack.push(ConstantNumber.get(x));
+                break;
+            }
+            case 18: {
+                Token s = getConstant(readByte());
+                op = "ldc " + s;
+                stack.push(s);
+                break;
+            }
+            case 19: {
+                Token s = getConstant(readShort());
+                op = "ldc_w " + s;
+                stack.push(s);
+                break;
+            }
+            case 20: {
+                Token s = getConstant(readShort());
+                op = "ldc2_w " + s;
+                stack.push(s);
+                break;
+            }
+            case 21: {
+                int x = readByte();
+                op = "iload " + x;
+                stack.push(getVariable(x));
+                break;
+            }
+            case 22: {
+                int x = readByte();
+                op = "lload " + x;
+                stack.push(getVariable(x));
+                break;
+            }
+            case 23: {
+                int x = readByte();
+                op = "fload " + x;
+                stack.push(getVariable(x));
+                break;
+            }
+            case 24: {
+                int x = readByte();
+                op = "dload " + x;
+                stack.push(getVariable(x));
+                break;
+            }
+            case 25: {
+                int x = readByte();
+                op = "aload " + x;
+                stack.push(getVariable(x));
+                break;
+            }
+            case 26:
+                op = "iload_0";
+                stack.push(getVariable(0));
+                break;
+            case 27:
+                op = "iload_1";
+                stack.push(getVariable(1));
+                break;
+            case 28:
+                op = "iload_2";
+                stack.push(getVariable(2));
+                break;
+            case 29:
+                op = "iload_3";
+                stack.push(getVariable(3));
+                break;
+            case 30:
+                op = "lload_0";
+                stack.push(getVariable(0));
+                break;
+            case 31:
+                op = "lload_1";
+                stack.push(getVariable(1));
+                break;
+            case 32:
+                op = "lload_2";
+                stack.push(getVariable(2));
+                break;
+            case 33:
+                op = "lload_3";
+                stack.push(getVariable(3));
+                break;
+            case 34:
+                op = "fload_0";
+                stack.push(getVariable(0));
+                break;
+            case 35:
+                op = "fload_1";
+                stack.push(getVariable(1));
+                break;
+            case 36:
+                op = "fload_2";
+                stack.push(getVariable(2));
+                break;
+            case 37:
+                op = "fload_3";
+                stack.push(getVariable(3));
+                break;
+            case 38:
+                op = "dload_0";
+                stack.push(getVariable(0));
+                break;
+            case 39:
+                op = "dload_1";
+                stack.push(getVariable(1));
+                break;
+            case 40:
+                op = "dload_2";
+                stack.push(getVariable(2));
+                break;
+            case 41:
+                op = "dload_3";
+                stack.push(getVariable(3));
+                break;
+            case 42:
+                op = "aload_0";
+                stack.push(getVariable(0));
+                break;
+            case 43:
+                op = "aload_1";
+                stack.push(getVariable(1));
+                break;
+            case 44:
+                op = "aload_2";
+                stack.push(getVariable(2));
+                break;
+            case 45:
+                op = "aload_3";
+                stack.push(getVariable(3));
+                break;
+            case 46: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "iaload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 47: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "laload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 48: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "faload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 49: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "daload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 50: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "aaload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 51: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "baload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 52: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "caload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 53: {
+                Token index = stack.pop();
+                Token ref = stack.pop();
+                op = "saload";
+                stack.push(ArrayGet.get(ref, index));
+                break;
+            }
+            case 54: {
+                int var = readByte();
+                op = "istore " + var;
+                setVariable(var, stack.pop());
+                break;
+            }
+            case 55: {
+                int var = readByte();
+                op = "lstore " + var;
+                setVariable(var, stack.pop());
+                break;
+            }
+            case 56: {
+                int var = readByte();
+                op = "fstore " + var;
+                setVariable(var, stack.pop());
+                break;
+            }
+            case 57: {
+                int var = readByte();
+                op = "dstore " + var;
+                setVariable(var, stack.pop());
+                break;
+            }
+            case 58: {
+                int var = readByte();
+                op = "astore " + var;
+                setVariable(var, stack.pop());
+                break;
+            }
+            case 59:
+                op = "istore_0";
+                setVariable(0, stack.pop());
+                break;
+            case 60:
+                op = "istore_1";
+                setVariable(1, stack.pop());
+                break;
+            case 61:
+                op = "istore_2";
+                setVariable(2, stack.pop());
+                break;
+            case 62:
+                op = "istore_3";
+                setVariable(3, stack.pop());
+                break;
+            case 63:
+                op = "lstore_0";
+                setVariable(0, stack.pop());
+                break;
+            case 64:
+                op = "lstore_1";
+                setVariable(1, stack.pop());
+                break;
+            case 65:
+                op = "lstore_2";
+                setVariable(2, stack.pop());
+                break;
+            case 66:
+                op = "lstore_3";
+                setVariable(3, stack.pop());
+                break;
+            case 67:
+                op = "fstore_0";
+                setVariable(0, stack.pop());
+                break;
+            case 68:
+                op = "fstore_1";
+                setVariable(1, stack.pop());
+                break;
+            case 69:
+                op = "fstore_2";
+                setVariable(2, stack.pop());
+                break;
+            case 70:
+                op = "fstore_3";
+                setVariable(3, stack.pop());
+                break;
+            case 71:
+                op = "dstore_0";
+                setVariable(0, stack.pop());
+                break;
+            case 72:
+                op = "dstore_1";
+                setVariable(1, stack.pop());
+                break;
+            case 73:
+                op = "dstore_2";
+                setVariable(2, stack.pop());
+                break;
+            case 74:
+                op = "dstore_3";
+                setVariable(3, stack.pop());
+                break;
+            case 75:
+                op = "astore_0";
+                setVariable(0, stack.pop());
+                break;
+            case 76:
+                op = "astore_1";
+                setVariable(1, stack.pop());
+                break;
+            case 77:
+                op = "astore_2";
+                setVariable(2, stack.pop());
+                break;
+            case 78:
+                op = "astore_3";
+                setVariable(3, stack.pop());
+                break;
+            case 79: {
+                // String value = stack.pop();
+                // String index = stack.pop();
+                // String ref = stack.pop();
+                op = "iastore";
+                // TODO side effect - not supported
+                break;
+            }
+            case 80:
+                op = "lastore";
+                // TODO side effect - not supported
+                break;
+            case 81:
+                op = "fastore";
+                // TODO side effect - not supported
+                break;
+            case 82:
+                op = "dastore";
+                // TODO side effect - not supported
+                break;
+            case 83:
+                op = "aastore";
+                // TODO side effect - not supported
+                break;
+            case 84:
+                op = "bastore";
+                // TODO side effect - not supported
+                break;
+            case 85:
+                op = "castore";
+                // TODO side effect - not supported
+                break;
+            case 86:
+                op = "sastore";
+                // TODO side effect - not supported
+                break;
+            case 87:
+                op = "pop";
+                stack.pop();
+                break;
+            case 88:
+                op = "pop2";
+                // TODO currently we don't know the stack types
+                stack.pop();
+                stack.pop();
+                break;
+            case 89: {
+                op = "dup";
+                Token x = stack.pop();
+                stack.push(x);
+                stack.push(x);
+                break;
+            }
+            case 90: {
+                op = "dup_x1";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                stack.push(a);
+                stack.push(b);
+                stack.push(a);
+                break;
+            }
+            case 91: {
+                // TODO currently we don't know the stack types
+                op = "dup_x2";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                Token c = stack.pop();
+                stack.push(a);
+                stack.push(c);
+                stack.push(b);
+                stack.push(a);
+                break;
+            }
+            case 92: {
+                // TODO currently we don't know the stack types
+                op = "dup2";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                stack.push(b);
+                stack.push(a);
+                stack.push(b);
+                stack.push(a);
+                break;
+            }
+            case 93: {
+                // TODO currently we don't know the stack types
+                op = "dup2_x1";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                Token c = stack.pop();
+                stack.push(b);
+                stack.push(a);
+                stack.push(c);
+                stack.push(b);
+                stack.push(a);
+                break;
+            }
+            case 94: {
+                // TODO currently we don't know the stack types
+                op = "dup2_x2";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                Token c = stack.pop();
+                Token d = stack.pop();
+                stack.push(b);
+                stack.push(a);
+                stack.push(d);
+                stack.push(c);
+                stack.push(b);
+                stack.push(a);
+                break;
+            }
+            case 95: {
+                op = "swap";
+                Token a = stack.pop();
+                Token b = stack.pop();
+                stack.push(a);
+                stack.push(b);
+                break;
+            }
+            case 96: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "iadd";
+                stack.push(Operation.get(a, Operation.Type.ADD, b));
+                break;
+            }
+            case 97: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "ladd";
+                stack.push(Operation.get(a, Operation.Type.ADD, b));
+                break;
+            }
+            case 98: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "fadd";
+                stack.push(Operation.get(a, Operation.Type.ADD, b));
+                break;
+            }
+            case 99: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "dadd";
+                stack.push(Operation.get(a, Operation.Type.ADD, b));
+                break;
+            }
+            case 100: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "isub";
+                stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
+                break;
+            }
+            case 101: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "lsub";
+                stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
+                break;
+            }
+            case 102: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "fsub";
+                stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
+                break;
+            }
+            case 103: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "dsub";
+                stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
+                break;
+            }
+            case 104: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "imul";
+                stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
+                break;
+            }
+            case 105: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "lmul";
+                stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
+                break;
+            }
+            case 106: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "fmul";
+                stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
+                break;
+            }
+            case 107: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "dmul";
+                stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
+                break;
+            }
+            case 108: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "idiv";
+                stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
+                break;
+            }
+            case 109: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "ldiv";
+                stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
+                break;
+            }
+            case 110: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "fdiv";
+                stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
+                break;
+            }
+            case 111: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "ddiv";
+                stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
+                break;
+            }
+            case 112: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "irem";
+                stack.push(Operation.get(a, Operation.Type.MOD, b));
+                break;
+            }
+            case 113: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "lrem";
+                stack.push(Operation.get(a, Operation.Type.MOD, b));
+                break;
+            }
+            case 114: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "frem";
+                stack.push(Operation.get(a, Operation.Type.MOD, b));
+                break;
+            }
+            case 115: {
+                Token b = stack.pop();
+                Token a = stack.pop();
+                op = "drem";
+                stack.push(Operation.get(a, Operation.Type.MOD, b));
+                break;
+            }
+            // case 116:
+            // op = "ineg";
+            // break;
+            // case 117:
+            // op = "lneg";
+            // break;
+            // case 118:
+            // op = "fneg";
+            // break;
+            // case 119:
+            // op = "dneg";
+            // break;
+            // case 120:
+            // op = "ishl";
+            // break;
+            // case 121:
+            // op = "lshl";
+            // break;
+            // case 122:
+            // op = "ishr";
+            // break;
+            // case 123:
+            // op = "lshr";
+            // break;
+            // case 124:
+            // op = "iushr";
+            // break;
+            // case 125:
+            // op = "lushr";
+            // break;
+            // case 126:
+            // op = "iand";
+            // break;
+            // case 127:
+            // op = "land";
+            // break;
+            // case 128:
+            // op = "ior";
+            // break;
+            // case 129:
+            // op = "lor";
+            // break;
+            // case 130:
+            // op = "ixor";
+            // break;
+            // case 131:
+            // op = "lxor";
+            // break;
+            // case 132: {
+            // int var = readByte();
+            // int off = (byte) readByte();
+            // op = "iinc " + var + " " + off;
+            // break;
+            // }
+            // case 133:
+            // op = "i2l";
+            // break;
+            // case 134:
+            // op = "i2f";
+            // break;
+            // case 135:
+            // op = "i2d";
+            // break;
+            // case 136:
+            // op = "l2i";
+            // break;
+            // case 137:
+            // op = "l2f";
+            // break;
+            // case 138:
+            // op = "l2d";
+            // break;
+            // case 139:
+            // op = "f2i";
+            // break;
+            // case 140:
+            // op = "f2l";
+            // break;
+            // case 141:
+            // op = "f2d";
+            // break;
+            // case 142:
+            // op = "d2i";
+            // break;
+            // case 143:
+            // op = "d2l";
+            // break;
+            // case 144:
+            // op = "d2f";
+            // break;
+            // case 145:
+            // op = "i2b";
+            // break;
+            // case 146:
+            // op = "i2c";
+            // break;
+            // case 147:
+            // op = "i2s";
+            // break;
+            case 148: {
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(new Function("SIGN", Operation.get(a, Operation.Type.SUBTRACT, b)));
+                op = "lcmp";
+                break;
+            }
+            // case 149:
+            // op = "fcmpl";
+            // break;
+            // case 150:
+            // op = "fcmpg";
+            // break;
+            // case 151:
+            // op = "dcmpl";
+            // break;
+            // case 152:
+            // op = "dcmpg";
+            // break;
+            case 153:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.EQUALS, ConstantNumber.get(0)));
+                op = "ifeq " + nextPc;
+                break;
+            case 154:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.NOT_EQUALS, ConstantNumber.get(0)));
+                op = "ifne " + nextPc;
+                break;
+            case 155:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER, ConstantNumber.get(0)));
+                op = "iflt " + nextPc;
+                break;
+            case 156:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER_EQUALS, ConstantNumber.get(0)));
+                op = "ifge " + nextPc;
+                break;
+            case 157:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER, ConstantNumber.get(0)));
+                op = "ifgt " + nextPc;
+                break;
+            case 158:
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER_EQUALS, ConstantNumber.get(0)));
+                op = "ifle " + nextPc;
+                break;
+            case 159: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.EQUALS, b));
+                op = "if_icmpeq " + nextPc;
+                break;
+            }
+            case 160: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
+                op = "if_icmpne " + nextPc;
+                break;
+            }
+            case 161: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.SMALLER, b));
+                op = "if_icmplt " + nextPc;
+                break;
+            }
+            case 162: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.BIGGER_EQUALS, b));
+                op = "if_icmpge " + nextPc;
+                break;
+            }
+            case 163: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.BIGGER, b));
+                op = "if_icmpgt " + nextPc;
+                break;
+            }
+            case 164: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.SMALLER_EQUALS, b));
+                op = "if_icmple " + nextPc;
+                break;
+            }
+            case 165: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.EQUALS, b));
+                op = "if_acmpeq " + nextPc;
+                break;
+            }
+            case 166: {
+                condition = true;
+                nextPc = getAbsolutePos(pos, readShort());
+                Token b = stack.pop(), a = stack.pop();
+                stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
+                op = "if_acmpne " + nextPc;
+                break;
+            }
+            case 167:
+                nextPc = getAbsolutePos(pos, readShort());
+                op = "goto " + nextPc;
+                break;
+            // case 168:
+            // // TODO not supported yet
+            // op = "jsr " + getAbsolutePos(pos, readShort());
+            // break;
+            // case 169:
+            // // TODO not supported yet
+            // op = "ret " + readByte();
+            // break;
+            // case 170: {
+            // int start = pos;
+            // pos += 4 - ((pos - startByteCode) & 3);
+            // int def = readInt();
+            // int low = readInt(), high = readInt();
+            // int n = high - low + 1;
+            // op = "tableswitch default:" + getAbsolutePos(start, def);
+            // StringBuilder buff = new StringBuilder();
+            // for (int i = 0; i < n; i++) {
+            // buff.append(' ').append(low++).
+            // append(":").
+            // append(getAbsolutePos(start, readInt()));
+            // }
+            // op += buff.toString();
+            // // pos += n * 4;
+            // break;
+            // }
+            // case 171: {
+            // int start = pos;
+            // pos += 4 - ((pos - startByteCode) & 3);
+            // int def = readInt();
+            // int n = readInt();
+            // op = "lookupswitch default:" + getAbsolutePos(start, def);
+            // StringBuilder buff = new StringBuilder();
+            // for (int i = 0; i < n; i++) {
+            // buff.append(' ').
+            // append(readInt()).
+            // append(":").
+            // append(getAbsolutePos(start, readInt()));
+            // }
+            // op += buff.toString();
+            // // pos += n * 8;
+            // break;
+            // }
+            case 172:
+                op = "ireturn";
+                endOfMethod = true;
+                break;
+            case 173:
+                op = "lreturn";
+                endOfMethod = true;
+                break;
+            case 174:
+                op = "freturn";
+                endOfMethod = true;
+                break;
+            case 175:
+                op = "dreturn";
+                endOfMethod = true;
+                break;
+            case 176:
+                op = "areturn";
+                endOfMethod = true;
+                break;
+            case 177:
+                op = "return";
+                // no value returned
+                stack.push(null);
+                endOfMethod = true;
+                break;
+            // case 178:
+            // op = "getstatic " + getField(readShort());
+            // break;
+            // case 179:
+            // op = "putstatic " + getField(readShort());
+            // break;
+            case 180: {
+                String field = getField(readShort());
+                Token p = stack.pop();
+                String s = p + "." + field.substring(field.lastIndexOf('.') + 1, field.indexOf(' '));
+                if (s.startsWith("this.")) {
+                    s = s.substring(5);
+                }
+                stack.push(Variable.get(s, fieldMap.get(s)));
+                op = "getfield " + field;
+                break;
+            }
+            // case 181:
+            // op = "putfield " + getField(readShort());
+            // break;
+            case 182: {
+                String method = getMethod(readShort());
+                op = "invokevirtual " + method;
+                if (method.equals("java/lang/String.equals (Ljava/lang/Object;)Z")) {
+                    Token a = stack.pop();
+                    Token b = stack.pop();
+                    stack.push(Operation.get(a, Operation.Type.EQUALS, b));
+                } else if (method.equals("java/lang/Integer.intValue ()I")) {
+                    // ignore
+                } else if (method.equals("java/lang/Long.longValue ()J")) {
+                    // ignore
+                }
+                break;
+            }
+            case 183: {
+                String method = getMethod(readShort());
+                op = "invokespecial " + method;
+                break;
+            }
+            case 184:
+                op = "invokestatic " + getMethod(readShort());
+                break;
+            // case 185: {
+            // int methodRef = readShort();
+            // readByte();
+            // readByte();
+            // op = "invokeinterface " + getMethod(methodRef);
+            // break;
+            // }
+            case 187: {
+                String className = constantPool[constantPool[readShort()].intValue()].toString();
+                op = "new " + className;
+                break;
+            }
+            // case 188:
+            // op = "newarray " + readByte();
+            // break;
+            // case 189:
+            // op = "anewarray " + cpString[readShort()];
+            // break;
+            // case 190:
+            // op = "arraylength";
+            // break;
+            // case 191:
+            // op = "athrow";
+            // break;
+            // case 192:
+            // op = "checkcast " + cpString[readShort()];
+            // break;
+            // case 193:
+            // op = "instanceof " + cpString[readShort()];
+            // break;
+            // case 194:
+            // op = "monitorenter";
+            // break;
+            // case 195:
+            // op = "monitorexit";
+            // break;
+            // case 196: {
+            // opCode = readByte();
+            // switch (opCode) {
+            // case 21:
+            // op = "wide iload " + readShort();
+            // break;
+            // case 22:
+            // op = "wide lload " + readShort();
+            // break;
+            // case 23:
+            // op = "wide fload " + readShort();
+            // break;
+            // case 24:
+            // op = "wide dload " + readShort();
+            // break;
+            // case 25:
+            // op = "wide aload " + readShort();
+            // break;
+            // case 54:
+            // op = "wide istore " + readShort();
+            // break;
+            // case 55:
+            // op = "wide lstore " + readShort();
+            // break;
+            // case 56:
+            // op = "wide fstore " + readShort();
+            // break;
+            // case 57:
+            // op = "wide dstore " + readShort();
+            // break;
+            // case 58:
+            // op = "wide astore " + readShort();
+            // break;
+            // case 132: {
+            // int var = readShort();
+            // int off = (short) readShort();
+            // op = "wide iinc " + var + " " + off;
+            // break;
+            // }
+            // case 169:
+            // op = "wide ret " + readShort();
+            // break;
+            // default:
+            // throw new IciqlException(
+            // "Unsupported wide opCode " + opCode);
+            // }
+            // break;
+            // }
+            // case 197:
+            // op = "multianewarray " + cpString[readShort()] + " " + readByte();
+            // break;
+            // case 198: {
+            // condition = true;
+            // nextPc = getAbsolutePos(pos, readShort());
+            // Token a = stack.pop();
+            // stack.push("(" + a + " IS NULL)");
+            // op = "ifnull " + nextPc;
+            // break;
+            // }
+            // case 199: {
+            // condition = true;
+            // nextPc = getAbsolutePos(pos, readShort());
+            // Token a = stack.pop();
+            // stack.push("(" + a + " IS NOT NULL)");
+            // op = "ifnonnull " + nextPc;
+            // break;
+            // }
+            case 200:
+                op = "goto_w " + getAbsolutePos(pos, readInt());
+                break;
+            case 201:
+                op = "jsr_w " + getAbsolutePos(pos, readInt());
+                break;
+            default:
+                throw new IciqlException("Unsupported opCode " + opCode);
+        }
+        debug("    " + startPos + ": " + op);
+    }
 
-       private void setVariable(int x, Token value) {
-               while (x >= variables.size()) {
-                       variables.add(Variable.get("p" + variables.size(), null));
-               }
-               variables.set(x, value);
-       }
+    private void setVariable(int x, Token value) {
+        while (x >= variables.size()) {
+            variables.add(Variable.get("p" + variables.size(), null));
+        }
+        variables.set(x, value);
+    }
 
-       private Token getVariable(int x) {
-               if (x == 0) {
-                       return Variable.THIS;
-               }
-               while (x >= variables.size()) {
-                       variables.add(Variable.get("p" + variables.size(), null));
-               }
-               return variables.get(x);
-       }
+    private Token getVariable(int x) {
+        if (x == 0) {
+            return Variable.THIS;
+        }
+        while (x >= variables.size()) {
+            variables.add(Variable.get("p" + variables.size(), null));
+        }
+        return variables.get(x);
+    }
 
-       private String getField(int fieldRef) {
-               int field = constantPool[fieldRef].intValue();
-               int classIndex = field >>> 16;
-               int nameAndType = constantPool[field & 0xffff].intValue();
-               String className = constantPool[constantPool[classIndex].intValue()] + "."
-                               + constantPool[nameAndType >>> 16] + " " + constantPool[nameAndType & 0xffff];
-               return className;
-       }
+    private String getField(int fieldRef) {
+        int field = constantPool[fieldRef].intValue();
+        int classIndex = field >>> 16;
+        int nameAndType = constantPool[field & 0xffff].intValue();
+        String className = constantPool[constantPool[classIndex].intValue()] + "."
+                + constantPool[nameAndType >>> 16] + " " + constantPool[nameAndType & 0xffff];
+        return className;
+    }
 
-       private String getMethod(int methodRef) {
-               int method = constantPool[methodRef].intValue();
-               int classIndex = method >>> 16;
-               int nameAndType = constantPool[method & 0xffff].intValue();
-               String className = constantPool[constantPool[classIndex].intValue()] + "."
-                               + constantPool[nameAndType >>> 16] + " " + constantPool[nameAndType & 0xffff];
-               return className;
-       }
+    private String getMethod(int methodRef) {
+        int method = constantPool[methodRef].intValue();
+        int classIndex = method >>> 16;
+        int nameAndType = constantPool[method & 0xffff].intValue();
+        String className = constantPool[constantPool[classIndex].intValue()] + "."
+                + constantPool[nameAndType >>> 16] + " " + constantPool[nameAndType & 0xffff];
+        return className;
+    }
 
-       private Constant getConstant(int constantRef) {
-               Constant c = constantPool[constantRef];
-               switch (c.getType()) {
-               case INT:
-               case FLOAT:
-               case DOUBLE:
-               case LONG:
-                       return c;
-               case STRING_REF:
-                       return constantPool[c.intValue()];
-               default:
-                       throw new IciqlException("Not a constant: " + constantRef);
-               }
-       }
+    private Constant getConstant(int constantRef) {
+        Constant c = constantPool[constantRef];
+        switch (c.getType()) {
+            case INT:
+            case FLOAT:
+            case DOUBLE:
+            case LONG:
+                return c;
+            case STRING_REF:
+                return constantPool[c.intValue()];
+            default:
+                throw new IciqlException("Not a constant: " + constantRef);
+        }
+    }
 
-       private String readString() {
-               int size = readShort();
-               byte[] buff = data;
-               int p = pos, end = p + size;
-               char[] chars = new char[size];
-               int j = 0;
-               for (; p < end; j++) {
-                       int x = buff[p++] & 0xff;
-                       if (x < 0x80) {
-                               chars[j] = (char) x;
-                       } else if (x >= 0xe0) {
-                               chars[j] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
-                       } else {
-                               chars[j] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
-                       }
-               }
-               pos = p;
-               return new String(chars, 0, j);
-       }
+    private String readString() {
+        int size = readShort();
+        byte[] buff = data;
+        int p = pos, end = p + size;
+        char[] chars = new char[size];
+        int j = 0;
+        for (; p < end; j++) {
+            int x = buff[p++] & 0xff;
+            if (x < 0x80) {
+                chars[j] = (char) x;
+            } else if (x >= 0xe0) {
+                chars[j] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
+            } else {
+                chars[j] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
+            }
+        }
+        pos = p;
+        return new String(chars, 0, j);
+    }
 
-       private int getAbsolutePos(int start, int offset) {
-               return start - startByteCode - 1 + (short) offset;
-       }
+    private int getAbsolutePos(int start, int offset) {
+        return start - startByteCode - 1 + (short) offset;
+    }
 
-       private int readByte() {
-               return data[pos++] & 0xff;
-       }
+    private int readByte() {
+        return data[pos++] & 0xff;
+    }
 
-       private int readShort() {
-               byte[] buff = data;
-               return ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
-       }
+    private int readShort() {
+        byte[] buff = data;
+        return ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
+    }
 
-       private int readInt() {
-               byte[] buff = data;
-               return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8)
-                               + (buff[pos++] & 0xff);
-       }
+    private int readInt() {
+        byte[] buff = data;
+        return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8)
+                + (buff[pos++] & 0xff);
+    }
 
-       private long readLong() {
-               return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
-       }
+    private long readLong() {
+        return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
+    }
 
 }
index 65cd66b8479347cee24576abceec1c687f8f0328..7adf8a96cf7ac427e11bbdfa6eedba199fddd8b1 100644 (file)
@@ -24,15 +24,15 @@ import com.iciql.Token;
  */
 public interface Constant extends Token {
 
-       /**
-        * The constant pool type.
-        */
-       enum Type {
-               STRING, INT, FLOAT, DOUBLE, LONG, CLASS_REF, STRING_REF, FIELD_REF, METHOD_REF, INTERFACE_METHOD_REF, NAME_AND_TYPE
-       }
+    /**
+     * The constant pool type.
+     */
+    enum Type {
+        STRING, INT, FLOAT, DOUBLE, LONG, CLASS_REF, STRING_REF, FIELD_REF, METHOD_REF, INTERFACE_METHOD_REF, NAME_AND_TYPE
+    }
 
-       Constant.Type getType();
+    Constant.Type getType();
 
-       int intValue();
+    int intValue();
 
 }
index 934de3ddb7703a7fe38e16ab5a0ed4f8cc66f184..b0c25b819829c89ee879b57122371fa1817168d0 100644 (file)
@@ -25,46 +25,46 @@ import com.iciql.SQLStatement;
  */
 public class ConstantNumber implements Constant {
 
-       private final String value;
-       private final Type type;
-       private final long longValue;
+    private final String value;
+    private final Type type;
+    private final long longValue;
 
-       private ConstantNumber(String value, long longValue, Type type) {
-               this.value = value;
-               this.longValue = longValue;
-               this.type = type;
-       }
+    private ConstantNumber(String value, long longValue, Type type) {
+        this.value = value;
+        this.longValue = longValue;
+        this.type = type;
+    }
 
-       static ConstantNumber get(String v) {
-               return new ConstantNumber(v, 0, Type.STRING);
-       }
+    static ConstantNumber get(String v) {
+        return new ConstantNumber(v, 0, Type.STRING);
+    }
 
-       static ConstantNumber get(int v) {
-               return new ConstantNumber("" + v, v, Type.INT);
-       }
+    static ConstantNumber get(int v) {
+        return new ConstantNumber("" + v, v, Type.INT);
+    }
 
-       static ConstantNumber get(long v) {
-               return new ConstantNumber("" + v, v, Type.LONG);
-       }
+    static ConstantNumber get(long v) {
+        return new ConstantNumber("" + v, v, Type.LONG);
+    }
 
-       static ConstantNumber get(String s, long x, Type type) {
-               return new ConstantNumber(s, x, type);
-       }
+    static ConstantNumber get(String s, long x, Type type) {
+        return new ConstantNumber(s, x, type);
+    }
 
-       public int intValue() {
-               return (int) longValue;
-       }
+    public int intValue() {
+        return (int) longValue;
+    }
 
-       public String toString() {
-               return value;
-       }
+    public String toString() {
+        return value;
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               stat.appendSQL(toString());
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        stat.appendSQL(toString());
+    }
 
-       public Constant.Type getType() {
-               return type;
-       }
+    public Constant.Type getType() {
+        return type;
+    }
 
 }
index 985f97d6aef336531d0fbd5dc333fceeb829a712..937082bece9471d64c45b17819dd3e9b9065ddb2 100644 (file)
@@ -26,30 +26,30 @@ import com.iciql.util.StringUtils;
  */
 public class ConstantString implements Constant {
 
-       private final String value;
+    private final String value;
 
-       private ConstantString(String value) {
-               this.value = value;
-       }
+    private ConstantString(String value) {
+        this.value = value;
+    }
 
-       static ConstantString get(String v) {
-               return new ConstantString(v);
-       }
+    static ConstantString get(String v) {
+        return new ConstantString(v);
+    }
 
-       public String toString() {
-               return value;
-       }
+    public String toString() {
+        return value;
+    }
 
-       public int intValue() {
-               return 0;
-       }
+    public int intValue() {
+        return 0;
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               stat.appendSQL(StringUtils.quoteStringSQL(value));
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        stat.appendSQL(StringUtils.quoteStringSQL(value));
+    }
 
-       public Constant.Type getType() {
-               return Constant.Type.STRING;
-       }
+    public Constant.Type getType() {
+        return Constant.Type.STRING;
+    }
 
 }
index 56a55eadd725070ae998121ddf7f641dd384e517..31506c894f9cae8b4df36db1739236990d7674f8 100644 (file)
@@ -26,22 +26,22 @@ import com.iciql.Token;
  */
 class Function implements Token {
 
-       private final String name;
-       private final Token expr;
+    private final String name;
+    private final Token expr;
 
-       Function(String name, Token expr) {
-               this.name = name;
-               this.expr = expr;
-       }
+    Function(String name, Token expr) {
+        this.name = name;
+        this.expr = expr;
+    }
 
-       public String toString() {
-               return name + "(" + expr + ")";
-       }
+    public String toString() {
+        return name + "(" + expr + ")";
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               // untested
-               stat.appendSQL(name + "(");
-               expr.appendSQL(stat, query);
-               stat.appendSQL(")");
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        // untested
+        stat.appendSQL(name + "(");
+        expr.appendSQL(stat, query);
+        stat.appendSQL(")");
+    }
 }
index ab5ab84b8053b531c398ffdd260ec4bf768cfdab..d6d53331f9c00d08558cc0d0fb539692158b404a 100644 (file)
@@ -26,30 +26,30 @@ import com.iciql.Token;
  */
 public class Not implements Token {
 
-       private Token expr;
-
-       private Not(Token expr) {
-               this.expr = expr;
-       }
-
-       static Token get(Token expr) {
-               if (expr instanceof Not) {
-                       return ((Not) expr).expr;
-               } else if (expr instanceof Operation) {
-                       return ((Operation) expr).reverse();
-               }
-               return new Not(expr);
-       }
-
-       Token not() {
-               return expr;
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               // untested
-               stat.appendSQL("NOT(");
-               expr.appendSQL(stat, query);
-               stat.appendSQL(")");
-       }
+    private Token expr;
+
+    private Not(Token expr) {
+        this.expr = expr;
+    }
+
+    static Token get(Token expr) {
+        if (expr instanceof Not) {
+            return ((Not) expr).expr;
+        } else if (expr instanceof Operation) {
+            return ((Operation) expr).reverse();
+        }
+        return new Not(expr);
+    }
+
+    Token not() {
+        return expr;
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        // untested
+        stat.appendSQL("NOT(");
+        expr.appendSQL(stat, query);
+        stat.appendSQL(")");
+    }
 
 }
index a28de5654a689da343fbe88a00f74a7847bf3561..a036b6e84f248b3279b8eae76bc9d4f72602d286 100644 (file)
@@ -26,19 +26,19 @@ import com.iciql.Token;
  */
 public class Null implements Token {
 
-       static final Null INSTANCE = new Null();
+    static final Null INSTANCE = new Null();
 
-       private Null() {
-               // don't allow to create new instances
-       }
+    private Null() {
+        // don't allow to create new instances
+    }
 
-       public String toString() {
-               return "null";
-       }
+    public String toString() {
+        return "null";
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               // untested
-               stat.appendSQL("NULL");
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        // untested
+        stat.appendSQL("NULL");
+    }
 
 }
index 7cd42d96e42823374bdd4e168b9e34e7b3e055f8..5b385b6c8d919033724698cbada45df15b99878f 100644 (file)
@@ -26,86 +26,86 @@ import com.iciql.Token;
  */
 class Operation implements Token {
 
-       /**
-        * The operation type.
-        */
-       enum Type {
-               EQUALS("=") {
-                       Type reverse() {
-                               return NOT_EQUALS;
-                       }
-               },
-               NOT_EQUALS("<>") {
-                       Type reverse() {
-                               return EQUALS;
-                       }
-               },
-               BIGGER(">") {
-                       Type reverse() {
-                               return SMALLER_EQUALS;
-                       }
-               },
-               BIGGER_EQUALS(">=") {
-                       Type reverse() {
-                               return SMALLER;
-                       }
-               },
-               SMALLER_EQUALS("<=") {
-                       Type reverse() {
-                               return BIGGER;
-                       }
-               },
-               SMALLER("<") {
-                       Type reverse() {
-                               return BIGGER_EQUALS;
-                       }
-               },
-               ADD("+"), SUBTRACT("-"), MULTIPLY("*"), DIVIDE("/"), MOD("%");
-
-               private String name;
-
-               Type(String name) {
-                       this.name = name;
-               }
-
-               public String toString() {
-                       return name;
-               }
-
-               Type reverse() {
-                       return null;
-               }
-
-       }
-
-       private final Token left, right;
-       private final Type op;
-
-       private Operation(Token left, Type op, Token right) {
-               this.left = left;
-               this.op = op;
-               this.right = right;
-       }
-
-       static Token get(Token left, Type op, Token right) {
-               if (op == Type.NOT_EQUALS && "0".equals(right.toString())) {
-                       return left;
-               }
-               return new Operation(left, op, right);
-       }
-
-       public String toString() {
-               return left + " " + op + " " + right;
-       }
-
-       public Token reverse() {
-               return get(left, op.reverse(), right);
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               left.appendSQL(stat, query);
-               stat.appendSQL(op.toString());
-               right.appendSQL(stat, query);
-       }
+    /**
+     * The operation type.
+     */
+    enum Type {
+        EQUALS("=") {
+            Type reverse() {
+                return NOT_EQUALS;
+            }
+        },
+        NOT_EQUALS("<>") {
+            Type reverse() {
+                return EQUALS;
+            }
+        },
+        BIGGER(">") {
+            Type reverse() {
+                return SMALLER_EQUALS;
+            }
+        },
+        BIGGER_EQUALS(">=") {
+            Type reverse() {
+                return SMALLER;
+            }
+        },
+        SMALLER_EQUALS("<=") {
+            Type reverse() {
+                return BIGGER;
+            }
+        },
+        SMALLER("<") {
+            Type reverse() {
+                return BIGGER_EQUALS;
+            }
+        },
+        ADD("+"), SUBTRACT("-"), MULTIPLY("*"), DIVIDE("/"), MOD("%");
+
+        private String name;
+
+        Type(String name) {
+            this.name = name;
+        }
+
+        public String toString() {
+            return name;
+        }
+
+        Type reverse() {
+            return null;
+        }
+
+    }
+
+    private final Token left, right;
+    private final Type op;
+
+    private Operation(Token left, Type op, Token right) {
+        this.left = left;
+        this.op = op;
+        this.right = right;
+    }
+
+    static Token get(Token left, Type op, Token right) {
+        if (op == Type.NOT_EQUALS && "0".equals(right.toString())) {
+            return left;
+        }
+        return new Operation(left, op, right);
+    }
+
+    public String toString() {
+        return left + " " + op + " " + right;
+    }
+
+    public Token reverse() {
+        return get(left, op.reverse(), right);
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        left.appendSQL(stat, query);
+        stat.appendSQL(op.toString());
+        right.appendSQL(stat, query);
+    }
 
 }
index 37da2a630b0b8d1fb54d50eaf82dc0e5491886eb..00e326e00065e0f45866240b3e677f1906994a13 100644 (file)
@@ -26,22 +26,22 @@ import com.iciql.Token;
  */
 public class Or implements Token {
 
-       private final Token left, right;
-
-       private Or(Token left, Token right) {
-               this.left = left;
-               this.right = right;
-       }
-
-       static Or get(Token left, Token right) {
-               return new Or(left, right);
-       }
-
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               // untested
-               left.appendSQL(stat, query);
-               stat.appendSQL(" OR ");
-               right.appendSQL(stat, query);
-       }
+    private final Token left, right;
+
+    private Or(Token left, Token right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    static Or get(Token left, Token right) {
+        return new Or(left, right);
+    }
+
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        // untested
+        left.appendSQL(stat, query);
+        stat.appendSQL(" OR ");
+        right.appendSQL(stat, query);
+    }
 
 }
index f3dbc017cf24a289af0cafb7d68643077a521c75..da2a634ded3ff4dc435bd80a86c20dced82afc72 100644 (file)
@@ -26,26 +26,26 @@ import com.iciql.Token;
  */
 public class Variable implements Token {
 
-       static final Variable THIS = new Variable("this", null);
+    static final Variable THIS = new Variable("this", null);
 
-       private final String name;
-       private final Object obj;
+    private final String name;
+    private final Object obj;
 
-       private Variable(String name, Object obj) {
-               this.name = name;
-               this.obj = obj;
-       }
+    private Variable(String name, Object obj) {
+        this.name = name;
+        this.obj = obj;
+    }
 
-       static Variable get(String name, Object obj) {
-               return new Variable(name, obj);
-       }
+    static Variable get(String name, Object obj) {
+        return new Variable(name, obj);
+    }
 
-       public String toString() {
-               return name;
-       }
+    public String toString() {
+        return name;
+    }
 
-       public <T> void appendSQL(SQLStatement stat, Query<T> query) {
-               query.appendSQL(stat, null, obj);
-       }
+    public <T> void appendSQL(SQLStatement stat, Query<T> query) {
+        query.appendSQL(stat, null, obj);
+    }
 
 }
index 5107481df00680fac224ab88dc22be579b5d9671..b5a73a125abcc5200674042361b9df1eda4a35ac 100644 (file)
@@ -16,8 +16,9 @@
  limitations under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
-<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-<title>Javadoc package documentation</title>
+<head>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
+    <title>Javadoc package documentation</title>
 </head>
 <body>
 The class decompiler for natural syntax iciql clauses.
index 769837b310ee86246a222e0c5409ff64e57ea5b6..4afe92750345308417161b7824747e38721fabe9 100644 (file)
@@ -16,8 +16,9 @@
  limitations under the License.\r
 -->\r
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
-<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\r
-<title>Javadoc package documentation</title>\r
+<head>\r
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>\r
+    <title>Javadoc package documentation</title>\r
 </head>\r
 <body>\r
 <i>iciql</i> (pronounced "icicle") is a Java JDBC SQL statement generator and simple object mapper\r
index eac9f6cc0ecef1d5eb822910121fc720c1749153..b8dcaa4363d68b473f7cd6a9ef6c44ec648a27d5 100644 (file)
@@ -17,6 +17,9 @@
 
 package com.iciql.util;
 
+import com.iciql.Db;
+import com.iciql.DbInspector;
+
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
@@ -29,165 +32,152 @@ import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import com.iciql.Db;
-import com.iciql.DbInspector;
-
 /**
  * Generates iciql models.
  */
 public class GenerateModels {
 
-       /**
-        * The output stream where this tool writes to.
-        */
-       protected PrintStream out = System.out;
+    /**
+     * The output stream where this tool writes to.
+     */
+    protected PrintStream out = System.out;
 
-       public static void main(String... args) {
-               GenerateModels tool = new GenerateModels();
-               try {
-                       tool.runTool(args);
-               } catch (SQLException e) {
-                       tool.out.print("Error: ");
-                       tool.out.println(e.getMessage());
-                       tool.out.println();
-                       tool.showUsage();
-               }
-       }
+    public static void main(String... args) {
+        GenerateModels tool = new GenerateModels();
+        try {
+            tool.runTool(args);
+        } catch (SQLException e) {
+            tool.out.print("Error: ");
+            tool.out.println(e.getMessage());
+            tool.out.println();
+            tool.showUsage();
+        }
+    }
 
-       public void runTool(String... args) throws SQLException {
-               String url = null;
-               String user = "sa";
-               String password = "";
-               String schema = null;
-               String table = null;
-               String packageName = "";
-               String folder = null;
-               boolean annotateSchema = true;
-               boolean trimStrings = false;
-               for (int i = 0; args != null && i < args.length; i++) {
-                       String arg = args[i];
-                       if (arg.equals("-url")) {
-                               url = args[++i];
-                       } else if (arg.equals("-user")) {
-                               user = args[++i];
-                       } else if (arg.equals("-password")) {
-                               password = args[++i];
-                       } else if (arg.equals("-schema")) {
-                               schema = args[++i];
-                       } else if (arg.equals("-table")) {
-                               table = args[++i];
-                       } else if (arg.equals("-package")) {
-                               packageName = args[++i];
-                       } else if (arg.equals("-folder")) {
-                               folder = args[++i];
-                       } else if (arg.equals("-annotateSchema")) {
-                               try {
-                                       annotateSchema = Boolean.parseBoolean(args[++i]);
-                               } catch (Throwable t) {
-                                       throw new SQLException("Can not parse -annotateSchema value");
-                               }
-                       } else if (arg.equals("-trimStrings")) {
-                               try {
-                                       trimStrings = Boolean.parseBoolean(args[++i]);
-                               } catch (Throwable t) {
-                                       throw new SQLException("Can not parse -trimStrings value");
-                               }
-                       } else {
-                               throwUnsupportedOption(arg);
-                       }
-               }
-               if (url == null) {
-                       throw new SQLException("URL not set");
-               }
-               execute(url, user, password, schema, table, packageName, folder, annotateSchema, trimStrings);
-       }
+    public void runTool(String... args) throws SQLException {
+        String url = null;
+        String user = "sa";
+        String password = "";
+        String schema = null;
+        String table = null;
+        String packageName = "";
+        String folder = null;
+        boolean annotateSchema = true;
+        boolean trimStrings = false;
+        for (int i = 0; args != null && i < args.length; i++) {
+            String arg = args[i];
+            if (arg.equals("-url")) {
+                url = args[++i];
+            } else if (arg.equals("-user")) {
+                user = args[++i];
+            } else if (arg.equals("-password")) {
+                password = args[++i];
+            } else if (arg.equals("-schema")) {
+                schema = args[++i];
+            } else if (arg.equals("-table")) {
+                table = args[++i];
+            } else if (arg.equals("-package")) {
+                packageName = args[++i];
+            } else if (arg.equals("-folder")) {
+                folder = args[++i];
+            } else if (arg.equals("-annotateSchema")) {
+                try {
+                    annotateSchema = Boolean.parseBoolean(args[++i]);
+                } catch (Throwable t) {
+                    throw new SQLException("Can not parse -annotateSchema value");
+                }
+            } else if (arg.equals("-trimStrings")) {
+                try {
+                    trimStrings = Boolean.parseBoolean(args[++i]);
+                } catch (Throwable t) {
+                    throw new SQLException("Can not parse -trimStrings value");
+                }
+            } else {
+                throwUnsupportedOption(arg);
+            }
+        }
+        if (url == null) {
+            throw new SQLException("URL not set");
+        }
+        execute(url, user, password, schema, table, packageName, folder, annotateSchema, trimStrings);
+    }
 
-       /**
-        * Generates models from the database.
-        * 
-        * @param url
-        *            the database URL
-        * @param user
-        *            the user name
-        * @param password
-        *            the password
-        * @param schema
-        *            the schema to read from. null for all schemas.
-        * @param table
-        *            the table to model. null for all tables within schema.
-        * @param packageName
-        *            the package name of the model classes.
-        * @param folder
-        *            destination folder for model classes (package path not
-        *            included)
-        * @param annotateSchema
-        *            includes the schema in the table model annotations
-        * @param trimStrings
-        *            automatically trim strings that exceed maxLength
-        */
-       public static void execute(String url, String user, String password, String schema, String table,
-                       String packageName, String folder, boolean annotateSchema, boolean trimStrings)
-                       throws SQLException {
-               try {
-                       Db db;
-                       if (password == null) {
-                               db = Db.open(url, user, (String) null);
-                       } else {
-                               db = Db.open(url, user, password);
-                       }
-                       DbInspector inspector = new DbInspector(db);
-                       List<String> models = inspector.generateModel(schema, table, packageName, annotateSchema,
-                                       trimStrings);
-                       File parentFile;
-                       if (StringUtils.isNullOrEmpty(folder)) {
-                               parentFile = new File(System.getProperty("user.dir"));
-                       } else {
-                               parentFile = new File(folder);
-                       }
-                       parentFile.mkdirs();
-                       Pattern p = Pattern.compile("class ([a-zA-Z0-9]+)");
-                       for (String model : models) {
-                               Matcher m = p.matcher(model);
-                               if (m.find()) {
-                                       String className = m.group().substring("class".length()).trim();
-                                       File classFile = new File(parentFile, className + ".java");
-                                       Writer o = new FileWriter(classFile, false);
-                                       PrintWriter writer = new PrintWriter(new BufferedWriter(o));
-                                       writer.write(model);
-                                       writer.close();
-                                       System.out.println("Generated " + classFile.getAbsolutePath());
-                               }
-                       }
-               } catch (IOException io) {
-                       throw new SQLException("could not generate model", io);
-               }
-       }
+    /**
+     * Generates models from the database.
+     *
+     * @param url            the database URL
+     * @param user           the user name
+     * @param password       the password
+     * @param schema         the schema to read from. null for all schemas.
+     * @param table          the table to model. null for all tables within schema.
+     * @param packageName    the package name of the model classes.
+     * @param folder         destination folder for model classes (package path not
+     *                       included)
+     * @param annotateSchema includes the schema in the table model annotations
+     * @param trimStrings    automatically trim strings that exceed maxLength
+     */
+    public static void execute(String url, String user, String password, String schema, String table,
+                               String packageName, String folder, boolean annotateSchema, boolean trimStrings)
+            throws SQLException {
+        try {
+            Db db;
+            if (password == null) {
+                db = Db.open(url, user, (String) null);
+            } else {
+                db = Db.open(url, user, password);
+            }
+            DbInspector inspector = new DbInspector(db);
+            List<String> models = inspector.generateModel(schema, table, packageName, annotateSchema,
+                    trimStrings);
+            File parentFile;
+            if (StringUtils.isNullOrEmpty(folder)) {
+                parentFile = new File(System.getProperty("user.dir"));
+            } else {
+                parentFile = new File(folder);
+            }
+            parentFile.mkdirs();
+            Pattern p = Pattern.compile("class ([a-zA-Z0-9]+)");
+            for (String model : models) {
+                Matcher m = p.matcher(model);
+                if (m.find()) {
+                    String className = m.group().substring("class".length()).trim();
+                    File classFile = new File(parentFile, className + ".java");
+                    Writer o = new FileWriter(classFile, false);
+                    PrintWriter writer = new PrintWriter(new BufferedWriter(o));
+                    writer.write(model);
+                    writer.close();
+                    System.out.println("Generated " + classFile.getAbsolutePath());
+                }
+            }
+        } catch (IOException io) {
+            throw new SQLException("could not generate model", io);
+        }
+    }
 
-       /**
-        * Throw a SQLException saying this command line option is not supported.
-        * 
-        * @param option
-        *            the unsupported option
-        * @return this method never returns normally
-        */
-       protected SQLException throwUnsupportedOption(String option) throws SQLException {
-               showUsage();
-               throw new SQLException("Unsupported option: " + option);
-       }
+    /**
+     * Throw a SQLException saying this command line option is not supported.
+     *
+     * @param option the unsupported option
+     * @return this method never returns normally
+     */
+    protected SQLException throwUnsupportedOption(String option) throws SQLException {
+        showUsage();
+        throw new SQLException("Unsupported option: " + option);
+    }
 
-       protected void showUsage() {
-               out.println("GenerateModels");
-               out.println("Usage:");
-               out.println();
-               out.println("(*) -url jdbc:h2:~test");
-               out.println("    -user <string>");
-               out.println("    -password <string>");
-               out.println("    -schema <string>");
-               out.println("    -table <string>");
-               out.println("    -package <string>");
-               out.println("    -folder <string>");
-               out.println("    -annotateSchema <boolean>");
-               out.println("    -trimStrings <boolean>");
-       }
+    protected void showUsage() {
+        out.println("GenerateModels");
+        out.println("Usage:");
+        out.println();
+        out.println("(*) -url jdbc:h2:~test");
+        out.println("    -user <string>");
+        out.println("    -password <string>");
+        out.println("    -schema <string>");
+        out.println("    -table <string>");
+        out.println("    -package <string>");
+        out.println("    -folder <string>");
+        out.println("    -annotateSchema <boolean>");
+        out.println("    -trimStrings <boolean>");
+    }
 
 }
index d8005bbe55de854e2adb217407292c6d40f2675d..2a2caf6986c7fdc206cca6b1b905957504a9ee64 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.iciql.util;
 
+import com.iciql.IciqlException;
+
 import java.text.DecimalFormat;
 import java.text.MessageFormat;
 import java.util.Set;
@@ -23,192 +25,189 @@ 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 IciqlListeners.<br>
  * Statement logging is disabled by default.
  * <p>
  * This class also tracks the counts for generated statements by major type.
- * 
  */
 public class IciqlLogger {
 
-       /**
-        * Enumeration of the different statement types that are logged.
-        */
-       public enum StatementType {
-               STAT, TOTAL, CREATE, INSERT, UPDATE, MERGE, DELETE, SELECT, DROP, WARN;
-       }
-
-       /**
-        * Interface that defines an iciql listener.
-        */
-       public interface IciqlListener {
-               void logIciql(StatementType type, String statement);
-       }
-
-       private static final ExecutorService EXEC = Executors.newSingleThreadExecutor();
-       private static final Set<IciqlListener> LISTENERS = Utils.newHashSet();
-       private static final IciqlListener CONSOLE = new IciqlListener() {
-
-               @Override
-               public void logIciql(StatementType type, String message) {
-                       System.out.println(message);
-               }
-       };
-
-       private static final AtomicLong SELECT_COUNT = new AtomicLong();
-       private static final AtomicLong CREATE_COUNT = new AtomicLong();
-       private static final AtomicLong INSERT_COUNT = new AtomicLong();
-       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();
-       private static final AtomicLong WARN_COUNT = new AtomicLong();
-
-       /**
-        * Activates the Console Logger.
-        */
-       public static void activateConsoleLogger() {
-               registerListener(CONSOLE);
-       }
-
-       /**
-        * Deactivates the Console Logger.
-        */
-       public static void deactivateConsoleLogger() {
-               unregisterListener(CONSOLE);
-       }
-
-       /**
-        * Registers a listener with the relay.
-        * 
-        * @param listener
-        */
-       public static void registerListener(IciqlListener listener) {
-               LISTENERS.add(listener);
-       }
-
-       /**
-        * Unregisters a listener with the relay.
-        * 
-        * @param listener
-        */
-       public static void unregisterListener(IciqlListener listener) {
-               if (!LISTENERS.remove(listener)) {
-                       throw new IciqlException("Failed to remove iciql listener {0}", listener);
-               }
-       }
-
-       public static void create(String statement) {
-               CREATE_COUNT.incrementAndGet();
-               logStatement(StatementType.CREATE, statement);
-       }
-
-       public static void insert(String statement) {
-               INSERT_COUNT.incrementAndGet();
-               logStatement(StatementType.INSERT, statement);
-       }
-
-       public static void update(String statement) {
-               UPDATE_COUNT.incrementAndGet();
-               logStatement(StatementType.UPDATE, statement);
-       }
-
-       public static void merge(String statement) {
-               MERGE_COUNT.incrementAndGet();
-               logStatement(StatementType.MERGE, statement);
-       }
-
-       public static void delete(String statement) {
-               DELETE_COUNT.incrementAndGet();
-               logStatement(StatementType.DELETE, statement);
-       }
-
-       public static void select(String statement) {
-               SELECT_COUNT.incrementAndGet();
-               logStatement(StatementType.SELECT, statement);
-       }
-
-       public static void drop(String statement) {
-               DROP_COUNT.incrementAndGet();
-               logStatement(StatementType.DROP, statement);
-       }
-
-       public static void warn(String message, Object... args) {
-               WARN_COUNT.incrementAndGet();
-               logStatement(StatementType.WARN, args.length > 0 ? MessageFormat.format(message, args) : message);
-       }
-
-       private static void logStatement(final StatementType type, final String statement) {
-               for (final IciqlListener listener : LISTENERS) {
-                       EXEC.execute(new Runnable() {
-                               public void run() {
-                                       listener.logIciql(type, statement);
-                               }
-                       });
-               }
-       }
-
-       public static long getCreateCount() {
-               return CREATE_COUNT.longValue();
-       }
-
-       public static long getInsertCount() {
-               return INSERT_COUNT.longValue();
-       }
-
-       public static long getUpdateCount() {
-               return UPDATE_COUNT.longValue();
-       }
-
-       public static long getMergeCount() {
-               return MERGE_COUNT.longValue();
-       }
-
-       public static long getDeleteCount() {
-               return DELETE_COUNT.longValue();
-       }
-
-       public static long getSelectCount() {
-               return SELECT_COUNT.longValue();
-       }
-
-       public static long getDropCount() {
-               return DROP_COUNT.longValue();
-       }
-
-       public static long getWarnCount() {
-               return WARN_COUNT.longValue();
-       }
-
-       public static long getTotalCount() {
-               return getCreateCount() + getInsertCount() + getUpdateCount() + getDeleteCount() + getMergeCount()
-                               + getSelectCount() + getDropCount();
-       }
-
-       public static void logStats() {
-               logStatement(StatementType.STAT, "iciql Runtime Statistics");
-               logStatement(StatementType.STAT, "========================");
-               logStat(StatementType.WARN, getWarnCount());
-               logStatement(StatementType.STAT, "========================");
-               logStat(StatementType.CREATE, getCreateCount());
-               logStat(StatementType.INSERT, getInsertCount());
-               logStat(StatementType.UPDATE, getUpdateCount());
-               logStat(StatementType.MERGE, getMergeCount());
-               logStat(StatementType.DELETE, getDeleteCount());
-               logStat(StatementType.SELECT, getSelectCount());
-               logStat(StatementType.DROP, getDropCount());
-               logStatement(StatementType.STAT, "========================");
-               logStat(StatementType.TOTAL, getTotalCount());
-       }
-
-       private static void logStat(StatementType type, long value) {
-               if (value > 0) {
-                       DecimalFormat df = new DecimalFormat("###,###,###,###");
-                       logStatement(StatementType.STAT,
-                                       StringUtils.pad(type.name(), 6, " ", true) + " = " + df.format(value));
-               }
-       }
+    /**
+     * Enumeration of the different statement types that are logged.
+     */
+    public enum StatementType {
+        STAT, TOTAL, CREATE, INSERT, UPDATE, MERGE, DELETE, SELECT, DROP, WARN;
+    }
+
+    /**
+     * Interface that defines an iciql listener.
+     */
+    public interface IciqlListener {
+        void logIciql(StatementType type, String statement);
+    }
+
+    private static final ExecutorService EXEC = Executors.newSingleThreadExecutor();
+    private static final Set<IciqlListener> LISTENERS = Utils.newHashSet();
+    private static final IciqlListener CONSOLE = new IciqlListener() {
+
+        @Override
+        public void logIciql(StatementType type, String message) {
+            System.out.println(message);
+        }
+    };
+
+    private static final AtomicLong SELECT_COUNT = new AtomicLong();
+    private static final AtomicLong CREATE_COUNT = new AtomicLong();
+    private static final AtomicLong INSERT_COUNT = new AtomicLong();
+    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();
+    private static final AtomicLong WARN_COUNT = new AtomicLong();
+
+    /**
+     * Activates the Console Logger.
+     */
+    public static void activateConsoleLogger() {
+        registerListener(CONSOLE);
+    }
+
+    /**
+     * Deactivates the Console Logger.
+     */
+    public static void deactivateConsoleLogger() {
+        unregisterListener(CONSOLE);
+    }
+
+    /**
+     * Registers a listener with the relay.
+     *
+     * @param listener
+     */
+    public static void registerListener(IciqlListener listener) {
+        LISTENERS.add(listener);
+    }
+
+    /**
+     * Unregisters a listener with the relay.
+     *
+     * @param listener
+     */
+    public static void unregisterListener(IciqlListener listener) {
+        if (!LISTENERS.remove(listener)) {
+            throw new IciqlException("Failed to remove iciql listener {0}", listener);
+        }
+    }
+
+    public static void create(String statement) {
+        CREATE_COUNT.incrementAndGet();
+        logStatement(StatementType.CREATE, statement);
+    }
+
+    public static void insert(String statement) {
+        INSERT_COUNT.incrementAndGet();
+        logStatement(StatementType.INSERT, statement);
+    }
+
+    public static void update(String statement) {
+        UPDATE_COUNT.incrementAndGet();
+        logStatement(StatementType.UPDATE, statement);
+    }
+
+    public static void merge(String statement) {
+        MERGE_COUNT.incrementAndGet();
+        logStatement(StatementType.MERGE, statement);
+    }
+
+    public static void delete(String statement) {
+        DELETE_COUNT.incrementAndGet();
+        logStatement(StatementType.DELETE, statement);
+    }
+
+    public static void select(String statement) {
+        SELECT_COUNT.incrementAndGet();
+        logStatement(StatementType.SELECT, statement);
+    }
+
+    public static void drop(String statement) {
+        DROP_COUNT.incrementAndGet();
+        logStatement(StatementType.DROP, statement);
+    }
+
+    public static void warn(String message, Object... args) {
+        WARN_COUNT.incrementAndGet();
+        logStatement(StatementType.WARN, args.length > 0 ? MessageFormat.format(message, args) : message);
+    }
+
+    private static void logStatement(final StatementType type, final String statement) {
+        for (final IciqlListener listener : LISTENERS) {
+            EXEC.execute(new Runnable() {
+                public void run() {
+                    listener.logIciql(type, statement);
+                }
+            });
+        }
+    }
+
+    public static long getCreateCount() {
+        return CREATE_COUNT.longValue();
+    }
+
+    public static long getInsertCount() {
+        return INSERT_COUNT.longValue();
+    }
+
+    public static long getUpdateCount() {
+        return UPDATE_COUNT.longValue();
+    }
+
+    public static long getMergeCount() {
+        return MERGE_COUNT.longValue();
+    }
+
+    public static long getDeleteCount() {
+        return DELETE_COUNT.longValue();
+    }
+
+    public static long getSelectCount() {
+        return SELECT_COUNT.longValue();
+    }
+
+    public static long getDropCount() {
+        return DROP_COUNT.longValue();
+    }
+
+    public static long getWarnCount() {
+        return WARN_COUNT.longValue();
+    }
+
+    public static long getTotalCount() {
+        return getCreateCount() + getInsertCount() + getUpdateCount() + getDeleteCount() + getMergeCount()
+                + getSelectCount() + getDropCount();
+    }
+
+    public static void logStats() {
+        logStatement(StatementType.STAT, "iciql Runtime Statistics");
+        logStatement(StatementType.STAT, "========================");
+        logStat(StatementType.WARN, getWarnCount());
+        logStatement(StatementType.STAT, "========================");
+        logStat(StatementType.CREATE, getCreateCount());
+        logStat(StatementType.INSERT, getInsertCount());
+        logStat(StatementType.UPDATE, getUpdateCount());
+        logStat(StatementType.MERGE, getMergeCount());
+        logStat(StatementType.DELETE, getDeleteCount());
+        logStat(StatementType.SELECT, getSelectCount());
+        logStat(StatementType.DROP, getDropCount());
+        logStatement(StatementType.STAT, "========================");
+        logStat(StatementType.TOTAL, getTotalCount());
+    }
+
+    private static void logStat(StatementType type, long value) {
+        if (value > 0) {
+            DecimalFormat df = new DecimalFormat("###,###,###,###");
+            logStatement(StatementType.STAT,
+                    StringUtils.pad(type.name(), 6, " ", true) + " = " + df.format(value));
+        }
+    }
 }
\ No newline at end of file
index 4a4a2b612a46ee680dcee41babffacaf54612676..0f15eb6d8e289d6769d1de5337801f50aeabf44b 100644 (file)
@@ -17,6 +17,9 @@
 
 package com.iciql.util;
 
+import javax.naming.Context;
+import javax.sql.DataSource;
+import javax.sql.XAConnection;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.ResultSet;
@@ -24,231 +27,212 @@ import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Properties;
 
-import javax.naming.Context;
-import javax.sql.DataSource;
-import javax.sql.XAConnection;
-
 /**
  * This is a utility class with JDBC helper functions.
  */
 public class JdbcUtils {
 
-       private static final String[] DRIVERS = { "h2:", "org.h2.Driver", "Cache:",
-                       "com.intersys.jdbc.CacheDriver", "daffodilDB://", "in.co.daffodil.db.rmi.RmiDaffodilDBDriver",
-                       "daffodil", "in.co.daffodil.db.jdbc.DaffodilDBDriver", "db2:", "COM.ibm.db2.jdbc.net.DB2Driver",
-                       "derby:net:", "org.apache.derby.jdbc.ClientDriver", "derby://",
-                       "org.apache.derby.jdbc.ClientDriver", "derby:", "org.apache.derby.jdbc.EmbeddedDriver",
-                       "FrontBase:", "com.frontbase.jdbc.FBJDriver", "firebirdsql:", "org.firebirdsql.jdbc.FBDriver",
-                       "hsqldb:", "org.hsqldb.jdbcDriver", "informix-sqli:", "com.informix.jdbc.IfxDriver", "jtds:",
-                       "net.sourceforge.jtds.jdbc.Driver", "microsoft:", "com.microsoft.jdbc.sqlserver.SQLServerDriver",
-                       "mimer:", "com.mimer.jdbc.Driver", "mysql:", "com.mysql.jdbc.Driver", "odbc:",
-                       "sun.jdbc.odbc.JdbcOdbcDriver", "oracle:", "oracle.jdbc.driver.OracleDriver", "pervasive:",
-                       "com.pervasive.jdbc.v2.Driver", "pointbase:micro:", "com.pointbase.me.jdbc.jdbcDriver",
-                       "pointbase:", "com.pointbase.jdbc.jdbcUniversalDriver", "postgresql:", "org.postgresql.Driver",
-                       "sybase:", "com.sybase.jdbc3.jdbc.SybDriver", "sqlserver:",
-                       "com.microsoft.sqlserver.jdbc.SQLServerDriver", "teradata:", "com.ncr.teradata.TeraDriver", };
-
-       private JdbcUtils() {
-               // utility class
-       }
-
-       /**
-        * Close a statement without throwing an exception.
-        * 
-        * @param stat
-        *            the statement or null
-        */
-       public static void closeSilently(Statement stat) {
-               if (stat != null) {
-                       try {
-                               stat.close();
-                       } catch (SQLException e) {
-                               // ignore
-                       }
-               }
-       }
-
-       /**
-        * Close a connection without throwing an exception.
-        * 
-        * @param conn
-        *            the connection or null
-        */
-       public static void closeSilently(Connection conn) {
-               if (conn != null) {
-                       try {
-                               conn.close();
-                       } catch (SQLException e) {
-                               // ignore
-                       }
-               }
-       }
-
-       /**
-        * Close a result set without throwing an exception.
-        * 
-        * @param rs
-        *            the result set or null
-        */
-       public static void closeSilently(ResultSet rs) {
-               closeSilently(rs, false);
-       }
-
-       /**
-        * Close a result set, and optionally its statement without throwing an
-        * exception.
-        * 
-        * @param rs
-        *            the result set or null
-        */
-       public static void closeSilently(ResultSet rs, boolean closeStatement) {
-               if (rs != null) {
-                       Statement stat = null;
-                       if (closeStatement) {
-                               try {
-                                       stat = rs.getStatement();
-                               } catch (SQLException e) {
-                                       // ignore
-                               }
-                       }
-                       try {
-                               rs.close();
-                       } catch (SQLException e) {
-                               // ignore
-                       }
-                       closeSilently(stat);
-               }
-       }
-
-       /**
-        * Close an XA connection set without throwing an exception.
-        * 
-        * @param conn
-        *            the XA connection or null
-        */
-       public static void closeSilently(XAConnection conn) {
-               if (conn != null) {
-                       try {
-                               conn.close();
-                       } catch (SQLException e) {
-                               // ignore
-                       }
-               }
-       }
-
-       /**
-        * Open a new database connection with the given settings.
-        * 
-        * @param driver
-        *            the driver class name
-        * @param url
-        *            the database URL
-        * @param user
-        *            the user name
-        * @param password
-        *            the password
-        * @return the database connection
-        */
-       public static Connection getConnection(String driver, String url, String user, String password)
-                       throws SQLException {
-               Properties prop = new Properties();
-               if (user != null) {
-                       prop.setProperty("user", user);
-               }
-               if (password != null) {
-                       prop.setProperty("password", password);
-               }
-               return getConnection(driver, url, prop);
-       }
-
-       /**
-        * Escape table or schema patterns used for DatabaseMetaData functions.
-        * 
-        * @param pattern
-        *            the pattern
-        * @return the escaped pattern
-        */
-       public static String escapeMetaDataPattern(String pattern) {
-               if (pattern == null || pattern.length() == 0) {
-                       return pattern;
-               }
-               return StringUtils.replaceAll(pattern, "\\", "\\\\");
-       }
-
-       /**
-        * Open a new database connection with the given settings.
-        * 
-        * @param driver
-        *            the driver class name
-        * @param url
-        *            the database URL
-        * @param prop
-        *            the properties containing at least the user name and password
-        * @return the database connection
-        */
-       public static Connection getConnection(String driver, String url, Properties prop) throws SQLException {
-               if (StringUtils.isNullOrEmpty(driver)) {
-                       JdbcUtils.load(url);
-               } else {
-                       Class<?> d = Utils.loadClass(driver);
-                       if (java.sql.Driver.class.isAssignableFrom(d)) {
-                               return DriverManager.getConnection(url, prop);
-                       } else if (javax.naming.Context.class.isAssignableFrom(d)) {
-                               // JNDI context
-                               try {
-                                       Context context = (Context) d.newInstance();
-                                       DataSource ds = (DataSource) context.lookup(url);
-                                       String user = prop.getProperty("user");
-                                       String password = prop.getProperty("password");
-                                       if (StringUtils.isNullOrEmpty(user) && StringUtils.isNullOrEmpty(password)) {
-                                               return ds.getConnection();
-                                       }
-                                       return ds.getConnection(user, password);
-                               } catch (SQLException e) {
-                                       throw e;
-                               } catch (Exception e) {
-                                       throw new SQLException("Failed to get connection for " + url, e);
-                               }
-                       } else {
-                               // Don't know, but maybe it loaded a JDBC Driver
-                               return DriverManager.getConnection(url, prop);
-                       }
-               }
-               return DriverManager.getConnection(url, prop);
-       }
-
-       /**
-        * Get the driver class name for the given URL, or null if the URL is
-        * unknown.
-        * 
-        * @param url
-        *            the database URL
-        * @return the driver class name
-        */
-       public static String getDriver(String url) {
-               if (url.startsWith("jdbc:")) {
-                       url = url.substring("jdbc:".length());
-                       for (int i = 0; i < DRIVERS.length; i += 2) {
-                               String prefix = DRIVERS[i];
-                               if (url.startsWith(prefix)) {
-                                       return DRIVERS[i + 1];
-                               }
-                       }
-               }
-               return null;
-       }
-
-       /**
-        * Load the driver class for the given URL, if the database URL is known.
-        * 
-        * @param url
-        *            the database URL
-        */
-       public static void load(String url) {
-               String driver = getDriver(url);
-               if (driver != null) {
-                       Utils.loadClass(driver);
-               }
-       }
+    private static final String[] DRIVERS = {"h2:", "org.h2.Driver", "Cache:",
+            "com.intersys.jdbc.CacheDriver", "daffodilDB://", "in.co.daffodil.db.rmi.RmiDaffodilDBDriver",
+            "daffodil", "in.co.daffodil.db.jdbc.DaffodilDBDriver", "db2:", "COM.ibm.db2.jdbc.net.DB2Driver",
+            "derby:net:", "org.apache.derby.jdbc.ClientDriver", "derby://",
+            "org.apache.derby.jdbc.ClientDriver", "derby:", "org.apache.derby.jdbc.EmbeddedDriver",
+            "FrontBase:", "com.frontbase.jdbc.FBJDriver", "firebirdsql:", "org.firebirdsql.jdbc.FBDriver",
+            "hsqldb:", "org.hsqldb.jdbcDriver", "informix-sqli:", "com.informix.jdbc.IfxDriver", "jtds:",
+            "net.sourceforge.jtds.jdbc.Driver", "microsoft:", "com.microsoft.jdbc.sqlserver.SQLServerDriver",
+            "mimer:", "com.mimer.jdbc.Driver", "mysql:", "com.mysql.jdbc.Driver", "odbc:",
+            "sun.jdbc.odbc.JdbcOdbcDriver", "oracle:", "oracle.jdbc.driver.OracleDriver", "pervasive:",
+            "com.pervasive.jdbc.v2.Driver", "pointbase:micro:", "com.pointbase.me.jdbc.jdbcDriver",
+            "pointbase:", "com.pointbase.jdbc.jdbcUniversalDriver", "postgresql:", "org.postgresql.Driver",
+            "sybase:", "com.sybase.jdbc3.jdbc.SybDriver", "sqlserver:",
+            "com.microsoft.sqlserver.jdbc.SQLServerDriver", "teradata:", "com.ncr.teradata.TeraDriver",};
+
+    private JdbcUtils() {
+        // utility class
+    }
+
+    /**
+     * Close a statement without throwing an exception.
+     *
+     * @param stat the statement or null
+     */
+    public static void closeSilently(Statement stat) {
+        if (stat != null) {
+            try {
+                stat.close();
+            } catch (SQLException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Close a connection without throwing an exception.
+     *
+     * @param conn the connection or null
+     */
+    public static void closeSilently(Connection conn) {
+        if (conn != null) {
+            try {
+                conn.close();
+            } catch (SQLException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Close a result set without throwing an exception.
+     *
+     * @param rs the result set or null
+     */
+    public static void closeSilently(ResultSet rs) {
+        closeSilently(rs, false);
+    }
+
+    /**
+     * Close a result set, and optionally its statement without throwing an
+     * exception.
+     *
+     * @param rs the result set or null
+     */
+    public static void closeSilently(ResultSet rs, boolean closeStatement) {
+        if (rs != null) {
+            Statement stat = null;
+            if (closeStatement) {
+                try {
+                    stat = rs.getStatement();
+                } catch (SQLException e) {
+                    // ignore
+                }
+            }
+            try {
+                rs.close();
+            } catch (SQLException e) {
+                // ignore
+            }
+            closeSilently(stat);
+        }
+    }
+
+    /**
+     * Close an XA connection set without throwing an exception.
+     *
+     * @param conn the XA connection or null
+     */
+    public static void closeSilently(XAConnection conn) {
+        if (conn != null) {
+            try {
+                conn.close();
+            } catch (SQLException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Open a new database connection with the given settings.
+     *
+     * @param driver   the driver class name
+     * @param url      the database URL
+     * @param user     the user name
+     * @param password the password
+     * @return the database connection
+     */
+    public static Connection getConnection(String driver, String url, String user, String password)
+            throws SQLException {
+        Properties prop = new Properties();
+        if (user != null) {
+            prop.setProperty("user", user);
+        }
+        if (password != null) {
+            prop.setProperty("password", password);
+        }
+        return getConnection(driver, url, prop);
+    }
+
+    /**
+     * Escape table or schema patterns used for DatabaseMetaData functions.
+     *
+     * @param pattern the pattern
+     * @return the escaped pattern
+     */
+    public static String escapeMetaDataPattern(String pattern) {
+        if (pattern == null || pattern.length() == 0) {
+            return pattern;
+        }
+        return StringUtils.replaceAll(pattern, "\\", "\\\\");
+    }
+
+    /**
+     * Open a new database connection with the given settings.
+     *
+     * @param driver the driver class name
+     * @param url    the database URL
+     * @param prop   the properties containing at least the user name and password
+     * @return the database connection
+     */
+    public static Connection getConnection(String driver, String url, Properties prop) throws SQLException {
+        if (StringUtils.isNullOrEmpty(driver)) {
+            JdbcUtils.load(url);
+        } else {
+            Class<?> d = Utils.loadClass(driver);
+            if (java.sql.Driver.class.isAssignableFrom(d)) {
+                return DriverManager.getConnection(url, prop);
+            } else if (javax.naming.Context.class.isAssignableFrom(d)) {
+                // JNDI context
+                try {
+                    Context context = (Context) d.newInstance();
+                    DataSource ds = (DataSource) context.lookup(url);
+                    String user = prop.getProperty("user");
+                    String password = prop.getProperty("password");
+                    if (StringUtils.isNullOrEmpty(user) && StringUtils.isNullOrEmpty(password)) {
+                        return ds.getConnection();
+                    }
+                    return ds.getConnection(user, password);
+                } catch (SQLException e) {
+                    throw e;
+                } catch (Exception e) {
+                    throw new SQLException("Failed to get connection for " + url, e);
+                }
+            } else {
+                // Don't know, but maybe it loaded a JDBC Driver
+                return DriverManager.getConnection(url, prop);
+            }
+        }
+        return DriverManager.getConnection(url, prop);
+    }
+
+    /**
+     * Get the driver class name for the given URL, or null if the URL is
+     * unknown.
+     *
+     * @param url the database URL
+     * @return the driver class name
+     */
+    public static String getDriver(String url) {
+        if (url.startsWith("jdbc:")) {
+            url = url.substring("jdbc:".length());
+            for (int i = 0; i < DRIVERS.length; i += 2) {
+                String prefix = DRIVERS[i];
+                if (url.startsWith(prefix)) {
+                    return DRIVERS[i + 1];
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Load the driver class for the given URL, if the database URL is known.
+     *
+     * @param url the database URL
+     */
+    public static void load(String url) {
+        String driver = getDriver(url);
+        if (driver != null) {
+            Utils.loadClass(driver);
+        }
+    }
 
 }
index ded393f1d704d3d22042cd68553dfd07a707fe19..383d80f5156b13ff18c412219f7fa5a0f970190a 100644 (file)
 \r
 package com.iciql.util;\r
 \r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
 import com.iciql.Iciql;\r
 import com.iciql.util.IciqlLogger.IciqlListener;\r
 import com.iciql.util.IciqlLogger.StatementType;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
 \r
 /**\r
  * Slf4jIciqlListener interfaces the IciqlLogger to the SLF4J logging framework.\r
  */\r
 public class Slf4jIciqlListener implements IciqlListener {\r
 \r
-       private Logger logger = LoggerFactory.getLogger(Iciql.class);\r
+    private Logger logger = LoggerFactory.getLogger(Iciql.class);\r
 \r
-       /**\r
-        * Enumeration representing the SLF4J log levels.\r
-        */\r
-       public enum Level {\r
-               ERROR, WARN, INFO, DEBUG, TRACE, OFF;\r
-       }\r
+    /**\r
+     * Enumeration representing the SLF4J log levels.\r
+     */\r
+    public enum Level {\r
+        ERROR, WARN, INFO, DEBUG, TRACE, OFF;\r
+    }\r
 \r
-       private final Level defaultLevel;\r
+    private final Level defaultLevel;\r
 \r
-       private final Map<StatementType, Level> levels;\r
+    private final Map<StatementType, Level> levels;\r
 \r
-       public Slf4jIciqlListener() {\r
-               this(Level.TRACE);\r
-       }\r
+    public Slf4jIciqlListener() {\r
+        this(Level.TRACE);\r
+    }\r
 \r
-       public Slf4jIciqlListener(Level defaultLevel) {\r
-               this.defaultLevel = defaultLevel;\r
-               levels = new HashMap<StatementType, Level>();\r
-               for (StatementType type : StatementType.values()) {\r
-                       levels.put(type, defaultLevel);\r
-               }\r
-       }\r
+    public Slf4jIciqlListener(Level defaultLevel) {\r
+        this.defaultLevel = defaultLevel;\r
+        levels = new HashMap<StatementType, Level>();\r
+        for (StatementType type : StatementType.values()) {\r
+            levels.put(type, defaultLevel);\r
+        }\r
+    }\r
 \r
-       /**\r
-        * Sets the logging level for a particular statement type.\r
-        * \r
-        * @param type\r
-        * @param level\r
-        */\r
-       public void setLevel(StatementType type, Level level) {\r
-               levels.put(type, defaultLevel);\r
-       }\r
+    /**\r
+     * Sets the logging level for a particular statement type.\r
+     *\r
+     * @param type\r
+     * @param level\r
+     */\r
+    public void setLevel(StatementType type, Level level) {\r
+        levels.put(type, defaultLevel);\r
+    }\r
 \r
-       @Override\r
-       public void logIciql(StatementType type, String statement) {\r
-               Level level = levels.get(type);\r
-               switch (level) {\r
-               case ERROR:\r
-                       logger.error(statement);\r
-                       break;\r
-               case WARN:\r
-                       logger.warn(statement);\r
-                       break;\r
-               case INFO:\r
-                       logger.info(statement);\r
-                       break;\r
-               case DEBUG:\r
-                       logger.debug(statement);\r
-                       break;\r
-               case TRACE:\r
-                       logger.trace(statement);\r
-                       break;\r
-               case OFF:\r
-                       break;\r
-               }\r
-       }\r
+    @Override\r
+    public void logIciql(StatementType type, String statement) {\r
+        Level level = levels.get(type);\r
+        switch (level) {\r
+            case ERROR:\r
+                logger.error(statement);\r
+                break;\r
+            case WARN:\r
+                logger.warn(statement);\r
+                break;\r
+            case INFO:\r
+                logger.info(statement);\r
+                break;\r
+            case DEBUG:\r
+                logger.debug(statement);\r
+                break;\r
+            case TRACE:\r
+                logger.trace(statement);\r
+                break;\r
+            case OFF:\r
+                break;\r
+        }\r
+    }\r
 }\r
index 47e80547dae49b156d4dcbd24ff17438eee1e0be..469d1d9fb42382892f57c4cf911359ab6caa4fe0 100644 (file)
@@ -21,19 +21,19 @@ package com.iciql.util;
  * A utility class to build a statement. In addition to the methods supported by
  * StringBuilder, it allows to add a text only in the second iteration. This
  * simplified constructs such as:
- * 
+ * <p>
  * <pre>
  * StringBuilder buff = new StringBuilder();
  * for (int i = 0; i &lt; args.length; i++) {
  *     if (i &gt; 0) {
  *             buff.append(&quot;, &quot;);
- *     }
+ *    }
  *     buff.append(args[i]);
  * }
  * </pre>
- * 
+ * <p>
  * to
- * 
+ * <p>
  * <pre>
  * StatementBuilder buff = new StatementBuilder();
  * for (String s : args) {
@@ -44,123 +44,117 @@ package com.iciql.util;
  */
 public class StatementBuilder {
 
-       private final StringBuilder builder = new StringBuilder();
-       private int index;
-
-       /**
-        * Create a new builder.
-        */
-       public StatementBuilder() {
-               // nothing to do
-       }
-
-       /**
-        * Create a new builder.
-        * 
-        * @param string
-        *            the initial string
-        */
-       public StatementBuilder(String string) {
-               builder.append(string);
-       }
-
-       /**
-        * Append a text.
-        * 
-        * @param s
-        *            the text to append
-        * @return itself
-        */
-       public StatementBuilder append(String s) {
-               builder.append(s);
-               return this;
-       }
-
-       /**
-        * Append a character.
-        * 
-        * @param c
-        *            the character to append
-        * @return itself
-        */
-       public StatementBuilder append(char c) {
-               builder.append(c);
-               return this;
-       }
-
-       /**
-        * Append a number.
-        * 
-        * @param x
-        *            the number to append
-        * @return itself
-        */
-       public StatementBuilder append(long x) {
-               builder.append(x);
-               return this;
-       }
-
-       /**
-        * Returns the current value of the loop counter.
-        * 
-        * @return the loop counter
-        */
-       public int getCount() {
-               return index;
-       }
-
-       /**
-        * Reset the loop counter.
-        * 
-        * @return itself
-        */
-       public StatementBuilder resetCount() {
-               index = 0;
-               return this;
-       }
-
-       /**
-        * Append a text, but only if appendExceptFirst was never called.
-        * 
-        * @param s
-        *            the text to append
-        */
-       public void appendOnlyFirst(String s) {
-               if (index == 0) {
-                       builder.append(s);
-               }
-       }
-
-       /**
-        * Append a text, except when this method is called the first time.
-        * 
-        * @param s
-        *            the text to append
-        */
-       public void appendExceptFirst(String s) {
-               if (index++ > 0) {
-                       builder.append(s);
-               }
-       }
-
-       public void append(StatementBuilder sb) {
-               builder.append(sb);
-       }
-
-       public void insert(int offset, char c) {
-               builder.insert(offset, c);
-       }
-
-       public String toString() {
-               return builder.toString();
-       }
-
-       /**
-        * Get the length.
-        * 
-        * @return the length
-        */
-       public int length() {
-               return builder.length();
-       }
+    private final StringBuilder builder = new StringBuilder();
+    private int index;
+
+    /**
+     * Create a new builder.
+     */
+    public StatementBuilder() {
+        // nothing to do
+    }
+
+    /**
+     * Create a new builder.
+     *
+     * @param string the initial string
+     */
+    public StatementBuilder(String string) {
+        builder.append(string);
+    }
+
+    /**
+     * Append a text.
+     *
+     * @param s the text to append
+     * @return itself
+     */
+    public StatementBuilder append(String s) {
+        builder.append(s);
+        return this;
+    }
+
+    /**
+     * Append a character.
+     *
+     * @param c the character to append
+     * @return itself
+     */
+    public StatementBuilder append(char c) {
+        builder.append(c);
+        return this;
+    }
+
+    /**
+     * Append a number.
+     *
+     * @param x the number to append
+     * @return itself
+     */
+    public StatementBuilder append(long x) {
+        builder.append(x);
+        return this;
+    }
+
+    /**
+     * Returns the current value of the loop counter.
+     *
+     * @return the loop counter
+     */
+    public int getCount() {
+        return index;
+    }
+
+    /**
+     * Reset the loop counter.
+     *
+     * @return itself
+     */
+    public StatementBuilder resetCount() {
+        index = 0;
+        return this;
+    }
+
+    /**
+     * Append a text, but only if appendExceptFirst was never called.
+     *
+     * @param s the text to append
+     */
+    public void appendOnlyFirst(String s) {
+        if (index == 0) {
+            builder.append(s);
+        }
+    }
+
+    /**
+     * Append a text, except when this method is called the first time.
+     *
+     * @param s the text to append
+     */
+    public void appendExceptFirst(String s) {
+        if (index++ > 0) {
+            builder.append(s);
+        }
+    }
+
+    public void append(StatementBuilder sb) {
+        builder.append(sb);
+    }
+
+    public void insert(int offset, char c) {
+        builder.insert(offset, c);
+    }
+
+    public String toString() {
+        return builder.toString();
+    }
+
+    /**
+     * Get the length.
+     *
+     * @return the length
+     */
+    public int length() {
+        return builder.length();
+    }
 }
index dd3f180a7f428d00a760fec4d9d79aa577bf4ce0..3cf8f8315d63a37bd1f42ddc1a5a29753b4cb74c 100644 (file)
@@ -29,354 +29,338 @@ import java.util.ArrayList;
 
 /**
  * Common string utilities.
- * 
  */
 public class StringUtils {
 
-       /**
-        * Replace all occurrences of the before string with the after string.
-        * 
-        * @param s
-        *            the string
-        * @param before
-        *            the old text
-        * @param after
-        *            the new text
-        * @return the string with the before string replaced
-        */
-       public static String replaceAll(String s, String before, String after) {
-               int next = s.indexOf(before);
-               if (next < 0) {
-                       return s;
-               }
-               StringBuilder buff = new StringBuilder(s.length() - before.length() + after.length());
-               int index = 0;
-               while (true) {
-                       buff.append(s.substring(index, next)).append(after);
-                       index = next + before.length();
-                       next = s.indexOf(before, index);
-                       if (next < 0) {
-                               buff.append(s.substring(index));
-                               break;
-                       }
-               }
-               return buff.toString();
-       }
+    /**
+     * Replace all occurrences of the before string with the after string.
+     *
+     * @param s      the string
+     * @param before the old text
+     * @param after  the new text
+     * @return the string with the before string replaced
+     */
+    public static String replaceAll(String s, String before, String after) {
+        int next = s.indexOf(before);
+        if (next < 0) {
+            return s;
+        }
+        StringBuilder buff = new StringBuilder(s.length() - before.length() + after.length());
+        int index = 0;
+        while (true) {
+            buff.append(s.substring(index, next)).append(after);
+            index = next + before.length();
+            next = s.indexOf(before, index);
+            if (next < 0) {
+                buff.append(s.substring(index));
+                break;
+            }
+        }
+        return buff.toString();
+    }
 
-       /**
-        * Check if a String is null or empty (the length is null).
-        * 
-        * @param s
-        *            the string to check
-        * @return true if it is null or empty
-        */
-       public static boolean isNullOrEmpty(String s) {
-               return s == null || s.length() == 0;
-       }
+    /**
+     * Check if a String is null or empty (the length is null).
+     *
+     * @param s the string to check
+     * @return true if it is null or empty
+     */
+    public static boolean isNullOrEmpty(String s) {
+        return s == null || s.length() == 0;
+    }
 
-       /**
-        * Convert a string to a Java literal using the correct escape sequences.
-        * The literal is not enclosed in double quotes. The result can be used in
-        * properties files or in Java source code.
-        * 
-        * @param s
-        *            the text to convert
-        * @return the Java representation
-        */
-       public static String javaEncode(String s) {
-               int length = s.length();
-               StringBuilder buff = new StringBuilder(length);
-               for (int i = 0; i < length; i++) {
-                       char c = s.charAt(i);
-                       switch (c) {
-                       // case '\b':
-                       // // BS backspace
-                       // // not supported in properties files
-                       // buff.append("\\b");
-                       // break;
-                       case '\t':
-                               // HT horizontal tab
-                               buff.append("\\t");
-                               break;
-                       case '\n':
-                               // LF linefeed
-                               buff.append("\\n");
-                               break;
-                       case '\f':
-                               // FF form feed
-                               buff.append("\\f");
-                               break;
-                       case '\r':
-                               // CR carriage return
-                               buff.append("\\r");
-                               break;
-                       case '"':
-                               // double quote
-                               buff.append("\\\"");
-                               break;
-                       case '\\':
-                               // backslash
-                               buff.append("\\\\");
-                               break;
-                       default:
-                               int ch = c & 0xffff;
-                               if (ch >= ' ' && (ch < 0x80)) {
-                                       buff.append(c);
-                                       // not supported in properties files
-                                       // } else if(ch < 0xff) {
-                                       // buff.append("\\");
-                                       // // make sure it's three characters (0x200 is octal 1000)
-                                       // buff.append(Integer.toOctalString(0x200 |
-                                       // ch).substring(1));
-                               } else {
-                                       buff.append("\\u");
-                                       // make sure it's four characters
-                                       buff.append(Integer.toHexString(0x10000 | ch).substring(1));
-                               }
-                       }
-               }
-               return buff.toString();
-       }
+    /**
+     * Convert a string to a Java literal using the correct escape sequences.
+     * The literal is not enclosed in double quotes. The result can be used in
+     * properties files or in Java source code.
+     *
+     * @param s the text to convert
+     * @return the Java representation
+     */
+    public static String javaEncode(String s) {
+        int length = s.length();
+        StringBuilder buff = new StringBuilder(length);
+        for (int i = 0; i < length; i++) {
+            char c = s.charAt(i);
+            switch (c) {
+                // case '\b':
+                // // BS backspace
+                // // not supported in properties files
+                // buff.append("\\b");
+                // break;
+                case '\t':
+                    // HT horizontal tab
+                    buff.append("\\t");
+                    break;
+                case '\n':
+                    // LF linefeed
+                    buff.append("\\n");
+                    break;
+                case '\f':
+                    // FF form feed
+                    buff.append("\\f");
+                    break;
+                case '\r':
+                    // CR carriage return
+                    buff.append("\\r");
+                    break;
+                case '"':
+                    // double quote
+                    buff.append("\\\"");
+                    break;
+                case '\\':
+                    // backslash
+                    buff.append("\\\\");
+                    break;
+                default:
+                    int ch = c & 0xffff;
+                    if (ch >= ' ' && (ch < 0x80)) {
+                        buff.append(c);
+                        // not supported in properties files
+                        // } else if(ch < 0xff) {
+                        // buff.append("\\");
+                        // // make sure it's three characters (0x200 is octal 1000)
+                        // buff.append(Integer.toOctalString(0x200 |
+                        // ch).substring(1));
+                    } else {
+                        buff.append("\\u");
+                        // make sure it's four characters
+                        buff.append(Integer.toHexString(0x10000 | ch).substring(1));
+                    }
+            }
+        }
+        return buff.toString();
+    }
 
-       /**
-        * Pad a string. This method is used for the SQL function RPAD and LPAD.
-        * 
-        * @param string
-        *            the original string
-        * @param n
-        *            the target length
-        * @param padding
-        *            the padding string
-        * @param right
-        *            true if the padding should be appended at the end
-        * @return the padded string
-        */
-       public static String pad(String string, int n, String padding, boolean right) {
-               if (n < 0) {
-                       n = 0;
-               }
-               if (n < string.length()) {
-                       return string.substring(0, n);
-               } else if (n == string.length()) {
-                       return string;
-               }
-               char paddingChar;
-               if (padding == null || padding.length() == 0) {
-                       paddingChar = ' ';
-               } else {
-                       paddingChar = padding.charAt(0);
-               }
-               StringBuilder buff = new StringBuilder(n);
-               n -= string.length();
-               if (right) {
-                       buff.append(string);
-               }
-               for (int i = 0; i < n; i++) {
-                       buff.append(paddingChar);
-               }
-               if (!right) {
-                       buff.append(string);
-               }
-               return buff.toString();
-       }
+    /**
+     * Pad a string. This method is used for the SQL function RPAD and LPAD.
+     *
+     * @param string  the original string
+     * @param n       the target length
+     * @param padding the padding string
+     * @param right   true if the padding should be appended at the end
+     * @return the padded string
+     */
+    public static String pad(String string, int n, String padding, boolean right) {
+        if (n < 0) {
+            n = 0;
+        }
+        if (n < string.length()) {
+            return string.substring(0, n);
+        } else if (n == string.length()) {
+            return string;
+        }
+        char paddingChar;
+        if (padding == null || padding.length() == 0) {
+            paddingChar = ' ';
+        } else {
+            paddingChar = padding.charAt(0);
+        }
+        StringBuilder buff = new StringBuilder(n);
+        n -= string.length();
+        if (right) {
+            buff.append(string);
+        }
+        for (int i = 0; i < n; i++) {
+            buff.append(paddingChar);
+        }
+        if (!right) {
+            buff.append(string);
+        }
+        return buff.toString();
+    }
 
-       /**
-        * Convert a string to a SQL literal. Null is converted to NULL. The text is
-        * enclosed in single quotes. If there are any special characters, the
-        * method STRINGDECODE is used.
-        * 
-        * @param s
-        *            the text to convert.
-        * @return the SQL literal
-        */
-       public static String quoteStringSQL(String s) {
-               if (s == null) {
-                       return "NULL";
-               }
-               int length = s.length();
-               StringBuilder buff = new StringBuilder(length + 2);
-               buff.append('\'');
-               for (int i = 0; i < length; i++) {
-                       char c = s.charAt(i);
-                       if (c == '\'') {
-                               buff.append(c);
-                       } else if (c < ' ' || c > 127) {
-                               // need to start from the beginning because maybe there was a \
-                               // that was not quoted
-                               return "STRINGDECODE(" + quoteStringSQL(javaEncode(s)) + ")";
-                       }
-                       buff.append(c);
-               }
-               buff.append('\'');
-               return buff.toString();
-       }
+    /**
+     * Convert a string to a SQL literal. Null is converted to NULL. The text is
+     * enclosed in single quotes. If there are any special characters, the
+     * method STRINGDECODE is used.
+     *
+     * @param s the text to convert.
+     * @return the SQL literal
+     */
+    public static String quoteStringSQL(String s) {
+        if (s == null) {
+            return "NULL";
+        }
+        int length = s.length();
+        StringBuilder buff = new StringBuilder(length + 2);
+        buff.append('\'');
+        for (int i = 0; i < length; i++) {
+            char c = s.charAt(i);
+            if (c == '\'') {
+                buff.append(c);
+            } else if (c < ' ' || c > 127) {
+                // need to start from the beginning because maybe there was a \
+                // that was not quoted
+                return "STRINGDECODE(" + quoteStringSQL(javaEncode(s)) + ")";
+            }
+            buff.append(c);
+        }
+        buff.append('\'');
+        return buff.toString();
+    }
 
-       /**
-        * Split a string into an array of strings using the given separator. A null
-        * string will result in a null array, and an empty string in a zero element
-        * array.
-        * 
-        * @param s
-        *            the string to split
-        * @param separatorChar
-        *            the separator character
-        * @param trim
-        *            whether each element should be trimmed
-        * @return the array list
-        */
-       public static String[] arraySplit(String s, char separatorChar, boolean trim) {
-               if (s == null) {
-                       return null;
-               }
-               int length = s.length();
-               if (length == 0) {
-                       return new String[0];
-               }
-               ArrayList<String> list = Utils.newArrayList();
-               StringBuilder buff = new StringBuilder(length);
-               for (int i = 0; i < length; i++) {
-                       char c = s.charAt(i);
-                       if (c == separatorChar) {
-                               String e = buff.toString();
-                               list.add(trim ? e.trim() : e);
-                               buff.setLength(0);
-                       } else if (c == '\\' && i < length - 1) {
-                               buff.append(s.charAt(++i));
-                       } else {
-                               buff.append(c);
-                       }
-               }
-               String e = buff.toString();
-               list.add(trim ? e.trim() : e);
-               String[] array = new String[list.size()];
-               list.toArray(array);
-               return array;
-       }
+    /**
+     * Split a string into an array of strings using the given separator. A null
+     * string will result in a null array, and an empty string in a zero element
+     * array.
+     *
+     * @param s             the string to split
+     * @param separatorChar the separator character
+     * @param trim          whether each element should be trimmed
+     * @return the array list
+     */
+    public static String[] arraySplit(String s, char separatorChar, boolean trim) {
+        if (s == null) {
+            return null;
+        }
+        int length = s.length();
+        if (length == 0) {
+            return new String[0];
+        }
+        ArrayList<String> list = Utils.newArrayList();
+        StringBuilder buff = new StringBuilder(length);
+        for (int i = 0; i < length; i++) {
+            char c = s.charAt(i);
+            if (c == separatorChar) {
+                String e = buff.toString();
+                list.add(trim ? e.trim() : e);
+                buff.setLength(0);
+            } else if (c == '\\' && i < length - 1) {
+                buff.append(s.charAt(++i));
+            } else {
+                buff.append(c);
+            }
+        }
+        String e = buff.toString();
+        list.add(trim ? e.trim() : e);
+        String[] array = new String[list.size()];
+        list.toArray(array);
+        return array;
+    }
 
-       /**
-        * Calculates the SHA1 of the string.
-        * 
-        * @param text
-        * @return sha1 of the string
-        */
-       public static String calculateSHA1(String text) {
-               try {
-                       byte[] bytes = text.getBytes("iso-8859-1");
-                       return calculateSHA1(bytes);
-               } catch (UnsupportedEncodingException u) {
-                       throw new RuntimeException(u);
-               }
-       }
+    /**
+     * Calculates the SHA1 of the string.
+     *
+     * @param text
+     * @return sha1 of the string
+     */
+    public static String calculateSHA1(String text) {
+        try {
+            byte[] bytes = text.getBytes("iso-8859-1");
+            return calculateSHA1(bytes);
+        } catch (UnsupportedEncodingException u) {
+            throw new RuntimeException(u);
+        }
+    }
 
-       /**
-        * Calculates the SHA1 of the byte array.
-        * 
-        * @param bytes
-        * @return sha1 of the byte array
-        */
-       public static String calculateSHA1(byte[] bytes) {
-               try {
-                       MessageDigest md = MessageDigest.getInstance("SHA-1");
-                       md.update(bytes, 0, bytes.length);
-                       byte[] digest = md.digest();
-                       StringBuilder sb = new StringBuilder(digest.length * 2);
-                       for (int i = 0; i < digest.length; i++) {
-                               if (((int) digest[i] & 0xff) < 0x10) {
-                                       sb.append('0');
-                               }
-                               sb.append(Integer.toHexString((int) digest[i] & 0xff));
-                       }
-                       return sb.toString();
-               } catch (NoSuchAlgorithmException t) {
-                       throw new RuntimeException(t);
-               }
-       }
+    /**
+     * Calculates the SHA1 of the byte array.
+     *
+     * @param bytes
+     * @return sha1 of the byte array
+     */
+    public static String calculateSHA1(byte[] bytes) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            md.update(bytes, 0, bytes.length);
+            byte[] digest = md.digest();
+            StringBuilder sb = new StringBuilder(digest.length * 2);
+            for (int i = 0; i < digest.length; i++) {
+                if (((int) digest[i] & 0xff) < 0x10) {
+                    sb.append('0');
+                }
+                sb.append(Integer.toHexString((int) digest[i] & 0xff));
+            }
+            return sb.toString();
+        } catch (NoSuchAlgorithmException t) {
+            throw new RuntimeException(t);
+        }
+    }
 
-       /**
-        * Counts the occurrences of char c in the given string.
-        * 
-        * @param c
-        *            the character to count
-        * @param value
-        *            the source string
-        * @return the count of c in value
-        */
-       public static int count(char c, String value) {
-               int count = 0;
-               for (char cv : value.toCharArray()) {
-                       if (cv == c) {
-                               count++;
-                       }
-               }
-               return count;
-       }
+    /**
+     * Counts the occurrences of char c in the given string.
+     *
+     * @param c     the character to count
+     * @param value the source string
+     * @return the count of c in value
+     */
+    public static int count(char c, String value) {
+        int count = 0;
+        for (char cv : value.toCharArray()) {
+            if (cv == c) {
+                count++;
+            }
+        }
+        return count;
+    }
 
-       /**
-        * Prepare text for html presentation. Replace sensitive characters with
-        * html entities.
-        * 
-        * @param inStr
-        * @param changeSpace
-        * @return plain text escaped for html
-        */
-       public static String escapeForHtml(String inStr, boolean changeSpace) {
-               StringBuffer retStr = new StringBuffer();
-               int i = 0;
-               while (i < inStr.length()) {
-                       if (inStr.charAt(i) == '&') {
-                               retStr.append("&amp;");
-                       } else if (inStr.charAt(i) == '<') {
-                               retStr.append("&lt;");
-                       } else if (inStr.charAt(i) == '>') {
-                               retStr.append("&gt;");
-                       } else if (inStr.charAt(i) == '\"') {
-                               retStr.append("&quot;");
-                       } else if (changeSpace && inStr.charAt(i) == ' ') {
-                               retStr.append("&nbsp;");
-                       } else if (changeSpace && inStr.charAt(i) == '\t') {
-                               retStr.append(" &nbsp; &nbsp;");
-                       } else {
-                               retStr.append(inStr.charAt(i));
-                       }
-                       i++;
-               }
-               return retStr.toString();
-       }
+    /**
+     * Prepare text for html presentation. Replace sensitive characters with
+     * html entities.
+     *
+     * @param inStr
+     * @param changeSpace
+     * @return plain text escaped for html
+     */
+    public static String escapeForHtml(String inStr, boolean changeSpace) {
+        StringBuffer retStr = new StringBuffer();
+        int i = 0;
+        while (i < inStr.length()) {
+            if (inStr.charAt(i) == '&') {
+                retStr.append("&amp;");
+            } else if (inStr.charAt(i) == '<') {
+                retStr.append("&lt;");
+            } else if (inStr.charAt(i) == '>') {
+                retStr.append("&gt;");
+            } else if (inStr.charAt(i) == '\"') {
+                retStr.append("&quot;");
+            } else if (changeSpace && inStr.charAt(i) == ' ') {
+                retStr.append("&nbsp;");
+            } else if (changeSpace && inStr.charAt(i) == '\t') {
+                retStr.append(" &nbsp; &nbsp;");
+            } else {
+                retStr.append(inStr.charAt(i));
+            }
+            i++;
+        }
+        return retStr.toString();
+    }
 
-       /**
-        * Replaces carriage returns and line feeds with html line breaks.
-        * 
-        * @param string
-        * @return plain text with html line breaks
-        */
-       public static String breakLinesForHtml(String string) {
-               return string.replace("\r\n", "<br/>").replace("\r", "<br/>").replace("\n", "<br/>");
-       }
+    /**
+     * Replaces carriage returns and line feeds with html line breaks.
+     *
+     * @param string
+     * @return plain text with html line breaks
+     */
+    public static String breakLinesForHtml(String string) {
+        return string.replace("\r\n", "<br/>").replace("\r", "<br/>").replace("\n", "<br/>");
+    }
 
-       /**
-        * Returns the string content of the specified file.
-        * 
-        * @param file
-        * @param lineEnding
-        * @return the string content of the file
-        */
-       public static String readContent(File file, String lineEnding) {
-               StringBuilder sb = new StringBuilder();
-               try {
-                       InputStreamReader is = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
-                       BufferedReader reader = new BufferedReader(is);
-                       String line = null;
-                       while ((line = reader.readLine()) != null) {
-                               sb.append(line);
-                               if (lineEnding != null) {
-                                       sb.append(lineEnding);
-                               }
-                       }
-                       reader.close();
-               } catch (Throwable t) {
-                       System.err.println("Failed to read content of " + file.getAbsolutePath());
-                       t.printStackTrace();
-               }
-               return sb.toString();
-       }
+    /**
+     * Returns the string content of the specified file.
+     *
+     * @param file
+     * @param lineEnding
+     * @return the string content of the file
+     */
+    public static String readContent(File file, String lineEnding) {
+        StringBuilder sb = new StringBuilder();
+        try {
+            InputStreamReader is = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
+            BufferedReader reader = new BufferedReader(is);
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+                if (lineEnding != null) {
+                    sb.append(lineEnding);
+                }
+            }
+            reader.close();
+        } catch (Throwable t) {
+            System.err.println("Failed to read content of " + file.getAbsolutePath());
+            t.printStackTrace();
+        }
+        return sb.toString();
+    }
 }
index ada7c3486bf362567c3f690d449176fd013fe018..16528d87c88d159fbd69168606a7861e5c481a3b 100644 (file)
 \r
 package com.iciql.util;\r
 \r
+import com.iciql.Iciql.DataTypeAdapter;\r
+import com.iciql.Iciql.EnumId;\r
+import com.iciql.Iciql.EnumType;\r
+import com.iciql.Iciql.IQEnum;\r
+import com.iciql.Iciql.TypeAdapter;\r
+import com.iciql.IciqlException;\r
+\r
 import java.io.ByteArrayOutputStream;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
@@ -44,581 +51,570 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;\r
 import java.util.concurrent.atomic.AtomicLong;\r
 \r
-import com.iciql.Iciql.DataTypeAdapter;\r
-import com.iciql.Iciql.EnumId;\r
-import com.iciql.Iciql.EnumType;\r
-import com.iciql.Iciql.IQEnum;\r
-import com.iciql.Iciql.TypeAdapter;\r
-import com.iciql.IciqlException;\r
-\r
 /**\r
  * Generic utility methods.\r
  */\r
 public class Utils {\r
 \r
-       public static final AtomicLong COUNTER = new AtomicLong(0);\r
-\r
-       public static final AtomicInteger AS_COUNTER = new AtomicInteger(0);\r
-\r
-       private static final boolean MAKE_ACCESSIBLE = true;\r
-\r
-       private static final int BUFFER_BLOCK_SIZE = 4 * 1024;\r
-\r
-       public static synchronized int nextAsCount() {\r
-               // prevent negative values and use a threadsafe counter\r
-               int count = AS_COUNTER.incrementAndGet();\r
-               if (count == Integer.MAX_VALUE) {\r
-                       count = 0;\r
-                       AS_COUNTER.set(count);\r
-               }\r
-               return count;\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       public static <X> Class<X> getClass(X x) {\r
-               return (Class<X>) x.getClass();\r
-       }\r
-\r
-       public static Class<?> loadClass(String className) {\r
-               try {\r
-                       return Class.forName(className);\r
-               } catch (Exception e) {\r
-                       throw new IciqlException(e);\r
-               }\r
-       }\r
-\r
-       public static <T> Iterable<T> newArrayIterable(final T[] a) {\r
-               return Arrays.asList(a);\r
-       }\r
-\r
-       public static <T> ArrayList<T> newArrayList() {\r
-               return new ArrayList<T>();\r
-       }\r
-\r
-       public static <T> ArrayList<T> newArrayList(Collection<T> c) {\r
-               return new ArrayList<T>(c);\r
-       }\r
-\r
-       public static <T> HashSet<T> newHashSet() {\r
-               return new HashSet<T>();\r
-       }\r
-\r
-       public static <T> HashSet<T> newHashSet(Collection<T> list) {\r
-               return new HashSet<T>(list);\r
-       }\r
-\r
-       public static <A, B> HashMap<A, B> newHashMap() {\r
-               return new HashMap<A, B>();\r
-       }\r
-\r
-       public static <A, B> Map<A, B> newSynchronizedHashMap() {\r
-               HashMap<A, B> map = newHashMap();\r
-               return Collections.synchronizedMap(map);\r
-       }\r
-\r
-       public static <A, B> IdentityHashMap<A, B> newIdentityHashMap() {\r
-               return new IdentityHashMap<A, B>();\r
-       }\r
-\r
-       public static <T> ThreadLocal<T> newThreadLocal(final Class<? extends T> clazz) {\r
-               return new ThreadLocal<T>() {\r
-                       @SuppressWarnings("rawtypes")\r
-                       @Override\r
-                       protected T initialValue() {\r
-                               try {\r
-                                       return clazz.newInstance();\r
-                               } catch (Exception e) {\r
-                                       if (MAKE_ACCESSIBLE) {\r
-                                               Constructor[] constructors = clazz.getDeclaredConstructors();\r
-                                               // try 0 length constructors\r
-                                               for (Constructor c : constructors) {\r
-                                                       if (c.getParameterTypes().length == 0) {\r
-                                                               c.setAccessible(true);\r
-                                                               try {\r
-                                                                       return clazz.newInstance();\r
-                                                               } catch (Exception e2) {\r
-                                                                       // ignore\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       throw new IciqlException(e,\r
-                                                       "Missing default constructor?  Exception trying to instantiate {0}: {1}", clazz.getName(),\r
-                                                       e.getMessage());\r
-                               }\r
-                       }\r
-               };\r
-       }\r
-\r
-       @SuppressWarnings({ "unchecked", "rawtypes" })\r
-       public static <T> T newObject(Class<T> clazz) {\r
-               // must create new instances\r
-               if (clazz == int.class || clazz == Integer.class) {\r
-                       return (T) new Integer((int) (COUNTER.getAndIncrement() % Integer.MAX_VALUE));\r
-               } else if (clazz == String.class) {\r
-                       return (T) ("" + COUNTER.getAndIncrement());\r
-               } else if (clazz == long.class || clazz == Long.class) {\r
-                       return (T) new Long(COUNTER.getAndIncrement());\r
-               } else if (clazz == short.class || clazz == Short.class) {\r
-                       return (T) new Short((short) (COUNTER.getAndIncrement() % Short.MAX_VALUE));\r
-               } else if (clazz == byte.class || clazz == Byte.class) {\r
-                       return (T) new Byte((byte) (COUNTER.getAndIncrement() % Byte.MAX_VALUE));\r
-               } else if (clazz == float.class || clazz == Float.class) {\r
-                       return (T) new Float(COUNTER.getAndIncrement());\r
-               } else if (clazz == double.class || clazz == Double.class) {\r
-                       return (T) new Double(COUNTER.getAndIncrement());\r
-               } else if (clazz == boolean.class || clazz == Boolean.class) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) new Boolean(false);\r
-               } else if (clazz == BigDecimal.class) {\r
-                       return (T) new BigDecimal(COUNTER.getAndIncrement());\r
-               } else if (clazz == BigInteger.class) {\r
-                       return (T) new BigInteger("" + COUNTER.getAndIncrement());\r
-               } else if (clazz == java.sql.Date.class) {\r
-                       return (T) new java.sql.Date(COUNTER.getAndIncrement());\r
-               } else if (clazz == java.sql.Time.class) {\r
-                       return (T) new java.sql.Time(COUNTER.getAndIncrement());\r
-               } else if (clazz == java.sql.Timestamp.class) {\r
-                       return (T) new java.sql.Timestamp(COUNTER.getAndIncrement());\r
-               } else if (clazz == java.util.Date.class) {\r
-                       return (T) new java.util.Date(COUNTER.getAndIncrement());\r
-               } else if (clazz == byte[].class) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) new byte[0];\r
-               } else if (clazz.isEnum()) {\r
-                       COUNTER.getAndIncrement();\r
-                       // enums can not be instantiated reflectively\r
-                       // return first constant as reference\r
-                       return clazz.getEnumConstants()[0];\r
-               } else if (clazz == java.util.UUID.class) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) UUID.randomUUID();\r
-               } else if (Set.class == clazz) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) new HashSet();\r
-               } else if (List.class == clazz) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) new ArrayList();\r
-               } else if (Map.class == clazz) {\r
-                       COUNTER.getAndIncrement();\r
-                       return (T) new HashMap();\r
-               }\r
-               try {\r
-                       return clazz.newInstance();\r
-               } catch (Exception e) {\r
-                       if (MAKE_ACCESSIBLE) {\r
-                               Constructor[] constructors = clazz.getDeclaredConstructors();\r
-                               // try 0 length constructors\r
-                               for (Constructor c : constructors) {\r
-                                       if (c.getParameterTypes().length == 0) {\r
-                                               c.setAccessible(true);\r
-                                               try {\r
-                                                       return clazz.newInstance();\r
-                                               } catch (Exception e2) {\r
-                                                       // ignore\r
-                                               }\r
-                                       }\r
-                               }\r
-                               // try 1 length constructors\r
-                               for (Constructor c : constructors) {\r
-                                       if (c.getParameterTypes().length == 1) {\r
-                                               c.setAccessible(true);\r
-                                               try {\r
-                                                       return (T) c.newInstance(new Object[1]);\r
-                                               } catch (Exception e2) {\r
-                                                       // ignore\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-                       throw new IciqlException(e, "Missing default constructor?! Exception trying to instantiate {0}: {1}",\r
-                                       clazz.getName(), e.getMessage());\r
-               }\r
-       }\r
-\r
-       public static <T> boolean isSimpleType(Class<T> clazz) {\r
-               if (Number.class.isAssignableFrom(clazz)) {\r
-                       return true;\r
-               } else if (clazz == String.class) {\r
-                       return true;\r
-               }\r
-               return false;\r
-       }\r
-\r
-       public static Object convert(Object o, Class<?> targetType) {\r
-               if (o == null) {\r
-                       return null;\r
-               }\r
-               Class<?> currentType = o.getClass();\r
-               if (targetType.isAssignableFrom(currentType)) {\r
-                       return o;\r
-               }\r
-\r
-               // convert from CLOB/TEXT/VARCHAR to String\r
-               if (targetType == String.class) {\r
-                       if (Clob.class.isAssignableFrom(currentType)) {\r
-                               Clob c = (Clob) o;\r
-                               try {\r
-                                       Reader r = c.getCharacterStream();\r
-                                       return readStringAndClose(r, -1);\r
-                               } catch (Exception e) {\r
-                                       throw new IciqlException(e, "error converting CLOB to String: ", e.toString());\r
-                               }\r
-                       }\r
-                       return o.toString();\r
-               }\r
-\r
-               if (Boolean.class.isAssignableFrom(targetType) || boolean.class.isAssignableFrom(targetType)) {\r
-                       // convert from number to boolean\r
-                       if (Number.class.isAssignableFrom(currentType)) {\r
-                               Number n = (Number) o;\r
-                               return n.intValue() > 0;\r
-                       }\r
-                       // convert from string to boolean\r
-                       if (String.class.isAssignableFrom(currentType)) {\r
-                               String s = o.toString().toLowerCase();\r
-                               float f = 0f;\r
-                               try {\r
-                                       f = Float.parseFloat(s);\r
-                               } catch (Exception e) {\r
-                               }\r
-                               return f > 0 || s.equals("true") || s.equals("yes") || s.equals("y") || s.equals("on");\r
-                       }\r
-               }\r
-\r
-               // convert from boolean to number\r
-               if (Boolean.class.isAssignableFrom(currentType)) {\r
-                       Boolean b = (Boolean) o;\r
-                       Integer n = b ? 1 : 0;\r
-                       if (Number.class.isAssignableFrom(targetType)) {\r
-                               return n.intValue();\r
-                       } else if (byte.class.isAssignableFrom(targetType)) {\r
-                               return n.byteValue();\r
-                       } else if (short.class.isAssignableFrom(targetType)) {\r
-                               return n.shortValue();\r
-                       } else if (int.class.isAssignableFrom(targetType)) {\r
-                               return n.intValue();\r
-                       } else if (long.class.isAssignableFrom(targetType)) {\r
-                               return n.longValue();\r
-                       } else if (float.class.isAssignableFrom(targetType)) {\r
-                               return n.floatValue();\r
-                       } else if (double.class.isAssignableFrom(targetType)) {\r
-                               return n.doubleValue();\r
-                       } else if (boolean.class.isAssignableFrom(targetType)) {\r
-                               return b.booleanValue();\r
-                       }\r
-               }\r
-\r
-               // convert from number to number\r
-               if (Number.class.isAssignableFrom(currentType)) {\r
-                       Number n = (Number) o;\r
-                       if (targetType == byte.class || targetType == Byte.class) {\r
-                               return n.byteValue();\r
-                       } else if (targetType == short.class || targetType == Short.class) {\r
-                               return n.shortValue();\r
-                       } else if (targetType == int.class || targetType == Integer.class) {\r
-                               return n.intValue();\r
-                       } else if (targetType == long.class || targetType == Long.class) {\r
-                               return n.longValue();\r
-                       } else if (targetType == double.class || targetType == Double.class) {\r
-                               return n.doubleValue();\r
-                       } else if (targetType == float.class || targetType == Float.class) {\r
-                               return n.floatValue();\r
-                       } else if (targetType == BigDecimal.class) {\r
-                               return new BigDecimal(n.doubleValue());\r
-                       } else if (targetType == java.util.Date.class) {\r
-                               return new java.util.Date(n.longValue());\r
-                       } else if (targetType == java.sql.Date.class) {\r
-                               return new java.sql.Date(n.longValue());\r
-                       } else if (targetType == java.sql.Time.class) {\r
-                               return new java.sql.Time(n.longValue());\r
-                       } else if (targetType == java.sql.Timestamp.class) {\r
-                               return new java.sql.Timestamp(n.longValue());\r
-                       }\r
-               }\r
-\r
-               if (Date.class.isAssignableFrom(currentType)) {\r
-                       Date d = (Date) o;\r
-                       if (targetType == Date.class) {\r
-                               return o;\r
-                       } else if (targetType == java.sql.Date.class) {\r
-                               return new java.sql.Date(d.getTime());\r
-                       } else if (targetType == java.sql.Time.class) {\r
-                               return new java.sql.Time(d.getTime());\r
-                       } else if (targetType == java.sql.Timestamp.class) {\r
-                               return new java.sql.Timestamp(d.getTime());\r
-                       }\r
-               }\r
-\r
-               // convert from BLOB\r
-               if (targetType == byte[].class) {\r
-                       if (Blob.class.isAssignableFrom(currentType)) {\r
-                               Blob b = (Blob) o;\r
-                               try {\r
-                                       InputStream is = b.getBinaryStream();\r
-                                       return readBlobAndClose(is, -1);\r
-                               } catch (Exception e) {\r
-                                       throw new IciqlException(e, "error converting BLOB to byte[]: ", e.toString());\r
-                               }\r
-                       }\r
-               }\r
-               throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
-       }\r
-\r
-       /**\r
-        * Identify the EnumType for the field.\r
-        *\r
-        * @param f\r
-        * @return null or the EnumType\r
-        */\r
-       public static EnumType getEnumType(Field f) {\r
-               EnumType enumType = null;\r
-               if (f.getType().isEnum()) {\r
-                       enumType = EnumType.DEFAULT_TYPE;\r
-                       if (f.getType().isAnnotationPresent(IQEnum.class)) {\r
-                               // enum definition is annotated for all instances\r
-                               IQEnum iqenum = f.getType().getAnnotation(IQEnum.class);\r
-                               enumType = iqenum.value();\r
-                       }\r
-                       if (f.isAnnotationPresent(IQEnum.class)) {\r
-                               // this instance of the enum is annotated\r
-                               IQEnum iqenum = f.getAnnotation(IQEnum.class);\r
-                               enumType = iqenum.value();\r
-                       }\r
-               }\r
-               return enumType;\r
-       }\r
-\r
-       /**\r
-        * Identify the EnumType from the annotations.\r
-        *\r
-        * @param annotations\r
-        * @return null or the EnumType\r
-        */\r
-       public static EnumType getEnumType(Annotation [] annotations) {\r
-               EnumType enumType = null;\r
-               if (annotations != null) {\r
-                       for (Annotation annotation : annotations) {\r
-                               if (annotation instanceof IQEnum) {\r
-                                       enumType = ((IQEnum) annotation).value();\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-               return enumType;\r
-       }\r
-\r
-       public static Class<?> getEnumTypeClass(Field f) {\r
-               if (f.getType().isEnum()) {\r
-                       if (EnumId.class.isAssignableFrom(f.getType())) {\r
-                               // custom enumid mapping\r
-                               return ((EnumId<?>) f.getType().getEnumConstants()[0]).enumIdClass();\r
-                       }\r
-               }\r
-               return null;\r
-       }\r
-\r
-       public static Object convertEnum(Enum<?> o, EnumType type) {\r
-               if (o == null) {\r
-                       return null;\r
-               }\r
-               switch (type) {\r
-               case ORDINAL:\r
-                       return o.ordinal();\r
-               case ENUMID:\r
-                       if (!EnumId.class.isAssignableFrom(o.getClass())) {\r
-                               throw new IciqlException("Can not convert the enum {0} using ENUMID", o);\r
-                       }\r
-                       EnumId<?> enumid = (EnumId<?>) o;\r
-                       return enumid.enumId();\r
-               case NAME:\r
-               default:\r
-                       return o.name();\r
-               }\r
-       }\r
-\r
-       public static Object convertEnum(Object o, Class<?> targetType, EnumType type) {\r
-               if (o == null) {\r
-                       return null;\r
-               }\r
-               Class<?> currentType = o.getClass();\r
-               if (targetType.isAssignableFrom(currentType)) {\r
-                       return o;\r
-               }\r
-               // convert from VARCHAR/TEXT/INT to Enum\r
-               Enum<?>[] values = (Enum[]) targetType.getEnumConstants();\r
-               if (Clob.class.isAssignableFrom(currentType)) {\r
-                       // TEXT/CLOB field\r
-                       Clob c = (Clob) o;\r
-                       String name = null;\r
-                       try {\r
-                               Reader r = c.getCharacterStream();\r
-                               name = readStringAndClose(r, -1);\r
-                       } catch (Exception e) {\r
-                               throw new IciqlException(e, "error converting CLOB to String: ", e.toString());\r
-                       }\r
-\r
-                       // find name match\r
-                       if (type.equals(EnumType.ENUMID)) {\r
-                               // ENUMID mapping\r
-                               for (Enum<?> value : values) {\r
-                                       EnumId<?> enumid = (EnumId<?>) value;\r
-                                       if (enumid.enumId().equals(name)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       } else if (type.equals(EnumType.NAME)) {\r
-                               // standard Enum.name() mapping\r
-                               for (Enum<?> value : values) {\r
-                                       if (value.name().equalsIgnoreCase(name)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       }\r
-               } else if (String.class.isAssignableFrom(currentType)) {\r
-                       // VARCHAR field\r
-                       String name = (String) o;\r
-                       if (type.equals(EnumType.ENUMID)) {\r
-                               // ENUMID mapping\r
-                               for (Enum<?> value : values) {\r
-                                       EnumId<?> enumid = (EnumId<?>) value;\r
-                                       if (enumid.enumId().equals(name)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       } else if (type.equals(EnumType.NAME)) {\r
-                               // standard Enum.name() mapping\r
-                               for (Enum<?> value : values) {\r
-                                       if (value.name().equalsIgnoreCase(name)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       }\r
-               } else if (Number.class.isAssignableFrom(currentType)) {\r
-                       // INT field\r
-                       int n = ((Number) o).intValue();\r
-                       if (type.equals(EnumType.ORDINAL)) {\r
-                               // ORDINAL mapping\r
-                               for (Enum<?> value : values) {\r
-                                       if (value.ordinal() == n) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       } else if (type.equals(EnumType.ENUMID)) {\r
-                               if (!EnumId.class.isAssignableFrom(targetType)) {\r
-                                       throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o,\r
-                                                       currentType, targetType);\r
-                               }\r
-                               // ENUMID mapping\r
-                               for (Enum<?> value : values) {\r
-                                       EnumId<?> enumid = (EnumId<?>) value;\r
-                                       if (enumid.enumId().equals(n)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       }\r
-               } else {\r
-                       // custom object mapping\r
-                       if (type.equals(EnumType.ENUMID)) {\r
-                               if (!EnumId.class.isAssignableFrom(targetType)) {\r
-                                       throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o,\r
-                                                       currentType, targetType);\r
-                               }\r
-                               // ENUMID mapping\r
-                               for (Enum<?> value : values) {\r
-                                       EnumId<?> enumid = (EnumId<?>) value;\r
-                                       if (enumid.enumId().equals(o)) {\r
-                                               return value;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
-       }\r
-\r
-       /**\r
-        * Read a number of characters from a reader and close it.\r
-        *\r
-        * @param in\r
-        *            the reader\r
-        * @param length\r
-        *            the maximum number of characters to read, or -1 to read until\r
-        *            the end of file\r
-        * @return the string read\r
-        */\r
-       public static String readStringAndClose(Reader in, int length) throws IOException {\r
-               try {\r
-                       if (length <= 0) {\r
-                               length = Integer.MAX_VALUE;\r
-                       }\r
-                       int block = Math.min(BUFFER_BLOCK_SIZE, length);\r
-                       StringWriter out = new StringWriter(length == Integer.MAX_VALUE ? block : length);\r
-                       char[] buff = new char[block];\r
-                       while (length > 0) {\r
-                               int len = Math.min(block, length);\r
-                               len = in.read(buff, 0, len);\r
-                               if (len < 0) {\r
-                                       break;\r
-                               }\r
-                               out.write(buff, 0, len);\r
-                               length -= len;\r
-                       }\r
-                       return out.toString();\r
-               } finally {\r
-                       in.close();\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Read a number of bytes from a stream and close it.\r
-        *\r
-        * @param in\r
-        *            the stream\r
-        * @param length\r
-        *            the maximum number of bytes to read, or -1 to read until the\r
-        *            end of file\r
-        * @return the string read\r
-        */\r
-       public static byte[] readBlobAndClose(InputStream in, int length) throws IOException {\r
-               try {\r
-                       if (length <= 0) {\r
-                               length = Integer.MAX_VALUE;\r
-                       }\r
-                       int block = Math.min(BUFFER_BLOCK_SIZE, length);\r
-                       ByteArrayOutputStream out = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? block : length);\r
-                       byte[] buff = new byte[block];\r
-                       while (length > 0) {\r
-                               int len = Math.min(block, length);\r
-                               len = in.read(buff, 0, len);\r
-                               if (len < 0) {\r
-                                       break;\r
-                               }\r
-                               out.write(buff, 0, len);\r
-                               length -= len;\r
-                       }\r
-                       return out.toByteArray();\r
-               } finally {\r
-                       in.close();\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Identify the data type adapter class in the annotations.\r
-        *\r
-        * @param annotations\r
-        * @return null or the data type adapter class\r
-        */\r
-       public static Class<? extends DataTypeAdapter<?>> getDataTypeAdapter(Annotation [] annotations) {\r
-               Class<? extends DataTypeAdapter<?>> typeAdapter = null;\r
-               if (annotations != null) {\r
-                       for (Annotation annotation : annotations) {\r
-                               if (annotation instanceof TypeAdapter) {\r
-                                       typeAdapter = ((TypeAdapter) annotation).value();\r
-                               } else if (annotation.annotationType().isAnnotationPresent(TypeAdapter.class)) {\r
-                                       typeAdapter = annotation.annotationType().getAnnotation(TypeAdapter.class).value();\r
-                               }\r
-                       }\r
-               }\r
-               return typeAdapter;\r
-       }\r
+    public static final AtomicLong COUNTER = new AtomicLong(0);\r
+\r
+    public static final AtomicInteger AS_COUNTER = new AtomicInteger(0);\r
+\r
+    private static final boolean MAKE_ACCESSIBLE = true;\r
+\r
+    private static final int BUFFER_BLOCK_SIZE = 4 * 1024;\r
+\r
+    public static synchronized int nextAsCount() {\r
+        // prevent negative values and use a threadsafe counter\r
+        int count = AS_COUNTER.incrementAndGet();\r
+        if (count == Integer.MAX_VALUE) {\r
+            count = 0;\r
+            AS_COUNTER.set(count);\r
+        }\r
+        return count;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <X> Class<X> getClass(X x) {\r
+        return (Class<X>) x.getClass();\r
+    }\r
+\r
+    public static Class<?> loadClass(String className) {\r
+        try {\r
+            return Class.forName(className);\r
+        } catch (Exception e) {\r
+            throw new IciqlException(e);\r
+        }\r
+    }\r
+\r
+    public static <T> Iterable<T> newArrayIterable(final T[] a) {\r
+        return Arrays.asList(a);\r
+    }\r
+\r
+    public static <T> ArrayList<T> newArrayList() {\r
+        return new ArrayList<T>();\r
+    }\r
+\r
+    public static <T> ArrayList<T> newArrayList(Collection<T> c) {\r
+        return new ArrayList<T>(c);\r
+    }\r
+\r
+    public static <T> HashSet<T> newHashSet() {\r
+        return new HashSet<T>();\r
+    }\r
+\r
+    public static <T> HashSet<T> newHashSet(Collection<T> list) {\r
+        return new HashSet<T>(list);\r
+    }\r
+\r
+    public static <A, B> HashMap<A, B> newHashMap() {\r
+        return new HashMap<A, B>();\r
+    }\r
+\r
+    public static <A, B> Map<A, B> newSynchronizedHashMap() {\r
+        HashMap<A, B> map = newHashMap();\r
+        return Collections.synchronizedMap(map);\r
+    }\r
+\r
+    public static <A, B> IdentityHashMap<A, B> newIdentityHashMap() {\r
+        return new IdentityHashMap<A, B>();\r
+    }\r
+\r
+    public static <T> ThreadLocal<T> newThreadLocal(final Class<? extends T> clazz) {\r
+        return new ThreadLocal<T>() {\r
+            @SuppressWarnings("rawtypes")\r
+            @Override\r
+            protected T initialValue() {\r
+                try {\r
+                    return clazz.newInstance();\r
+                } catch (Exception e) {\r
+                    if (MAKE_ACCESSIBLE) {\r
+                        Constructor[] constructors = clazz.getDeclaredConstructors();\r
+                        // try 0 length constructors\r
+                        for (Constructor c : constructors) {\r
+                            if (c.getParameterTypes().length == 0) {\r
+                                c.setAccessible(true);\r
+                                try {\r
+                                    return clazz.newInstance();\r
+                                } catch (Exception e2) {\r
+                                    // ignore\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                    throw new IciqlException(e,\r
+                            "Missing default constructor?  Exception trying to instantiate {0}: {1}", clazz.getName(),\r
+                            e.getMessage());\r
+                }\r
+            }\r
+        };\r
+    }\r
+\r
+    @SuppressWarnings({"unchecked", "rawtypes"})\r
+    public static <T> T newObject(Class<T> clazz) {\r
+        // must create new instances\r
+        if (clazz == int.class || clazz == Integer.class) {\r
+            return (T) new Integer((int) (COUNTER.getAndIncrement() % Integer.MAX_VALUE));\r
+        } else if (clazz == String.class) {\r
+            return (T) ("" + COUNTER.getAndIncrement());\r
+        } else if (clazz == long.class || clazz == Long.class) {\r
+            return (T) new Long(COUNTER.getAndIncrement());\r
+        } else if (clazz == short.class || clazz == Short.class) {\r
+            return (T) new Short((short) (COUNTER.getAndIncrement() % Short.MAX_VALUE));\r
+        } else if (clazz == byte.class || clazz == Byte.class) {\r
+            return (T) new Byte((byte) (COUNTER.getAndIncrement() % Byte.MAX_VALUE));\r
+        } else if (clazz == float.class || clazz == Float.class) {\r
+            return (T) new Float(COUNTER.getAndIncrement());\r
+        } else if (clazz == double.class || clazz == Double.class) {\r
+            return (T) new Double(COUNTER.getAndIncrement());\r
+        } else if (clazz == boolean.class || clazz == Boolean.class) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) new Boolean(false);\r
+        } else if (clazz == BigDecimal.class) {\r
+            return (T) new BigDecimal(COUNTER.getAndIncrement());\r
+        } else if (clazz == BigInteger.class) {\r
+            return (T) new BigInteger("" + COUNTER.getAndIncrement());\r
+        } else if (clazz == java.sql.Date.class) {\r
+            return (T) new java.sql.Date(COUNTER.getAndIncrement());\r
+        } else if (clazz == java.sql.Time.class) {\r
+            return (T) new java.sql.Time(COUNTER.getAndIncrement());\r
+        } else if (clazz == java.sql.Timestamp.class) {\r
+            return (T) new java.sql.Timestamp(COUNTER.getAndIncrement());\r
+        } else if (clazz == java.util.Date.class) {\r
+            return (T) new java.util.Date(COUNTER.getAndIncrement());\r
+        } else if (clazz == byte[].class) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) new byte[0];\r
+        } else if (clazz.isEnum()) {\r
+            COUNTER.getAndIncrement();\r
+            // enums can not be instantiated reflectively\r
+            // return first constant as reference\r
+            return clazz.getEnumConstants()[0];\r
+        } else if (clazz == java.util.UUID.class) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) UUID.randomUUID();\r
+        } else if (Set.class == clazz) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) new HashSet();\r
+        } else if (List.class == clazz) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) new ArrayList();\r
+        } else if (Map.class == clazz) {\r
+            COUNTER.getAndIncrement();\r
+            return (T) new HashMap();\r
+        }\r
+        try {\r
+            return clazz.newInstance();\r
+        } catch (Exception e) {\r
+            if (MAKE_ACCESSIBLE) {\r
+                Constructor[] constructors = clazz.getDeclaredConstructors();\r
+                // try 0 length constructors\r
+                for (Constructor c : constructors) {\r
+                    if (c.getParameterTypes().length == 0) {\r
+                        c.setAccessible(true);\r
+                        try {\r
+                            return clazz.newInstance();\r
+                        } catch (Exception e2) {\r
+                            // ignore\r
+                        }\r
+                    }\r
+                }\r
+                // try 1 length constructors\r
+                for (Constructor c : constructors) {\r
+                    if (c.getParameterTypes().length == 1) {\r
+                        c.setAccessible(true);\r
+                        try {\r
+                            return (T) c.newInstance(new Object[1]);\r
+                        } catch (Exception e2) {\r
+                            // ignore\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            throw new IciqlException(e, "Missing default constructor?! Exception trying to instantiate {0}: {1}",\r
+                    clazz.getName(), e.getMessage());\r
+        }\r
+    }\r
+\r
+    public static <T> boolean isSimpleType(Class<T> clazz) {\r
+        if (Number.class.isAssignableFrom(clazz)) {\r
+            return true;\r
+        } else if (clazz == String.class) {\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    public static Object convert(Object o, Class<?> targetType) {\r
+        if (o == null) {\r
+            return null;\r
+        }\r
+        Class<?> currentType = o.getClass();\r
+        if (targetType.isAssignableFrom(currentType)) {\r
+            return o;\r
+        }\r
+\r
+        // convert from CLOB/TEXT/VARCHAR to String\r
+        if (targetType == String.class) {\r
+            if (Clob.class.isAssignableFrom(currentType)) {\r
+                Clob c = (Clob) o;\r
+                try {\r
+                    Reader r = c.getCharacterStream();\r
+                    return readStringAndClose(r, -1);\r
+                } catch (Exception e) {\r
+                    throw new IciqlException(e, "error converting CLOB to String: ", e.toString());\r
+                }\r
+            }\r
+            return o.toString();\r
+        }\r
+\r
+        if (Boolean.class.isAssignableFrom(targetType) || boolean.class.isAssignableFrom(targetType)) {\r
+            // convert from number to boolean\r
+            if (Number.class.isAssignableFrom(currentType)) {\r
+                Number n = (Number) o;\r
+                return n.intValue() > 0;\r
+            }\r
+            // convert from string to boolean\r
+            if (String.class.isAssignableFrom(currentType)) {\r
+                String s = o.toString().toLowerCase();\r
+                float f = 0f;\r
+                try {\r
+                    f = Float.parseFloat(s);\r
+                } catch (Exception e) {\r
+                }\r
+                return f > 0 || s.equals("true") || s.equals("yes") || s.equals("y") || s.equals("on");\r
+            }\r
+        }\r
+\r
+        // convert from boolean to number\r
+        if (Boolean.class.isAssignableFrom(currentType)) {\r
+            Boolean b = (Boolean) o;\r
+            Integer n = b ? 1 : 0;\r
+            if (Number.class.isAssignableFrom(targetType)) {\r
+                return n.intValue();\r
+            } else if (byte.class.isAssignableFrom(targetType)) {\r
+                return n.byteValue();\r
+            } else if (short.class.isAssignableFrom(targetType)) {\r
+                return n.shortValue();\r
+            } else if (int.class.isAssignableFrom(targetType)) {\r
+                return n.intValue();\r
+            } else if (long.class.isAssignableFrom(targetType)) {\r
+                return n.longValue();\r
+            } else if (float.class.isAssignableFrom(targetType)) {\r
+                return n.floatValue();\r
+            } else if (double.class.isAssignableFrom(targetType)) {\r
+                return n.doubleValue();\r
+            } else if (boolean.class.isAssignableFrom(targetType)) {\r
+                return b.booleanValue();\r
+            }\r
+        }\r
+\r
+        // convert from number to number\r
+        if (Number.class.isAssignableFrom(currentType)) {\r
+            Number n = (Number) o;\r
+            if (targetType == byte.class || targetType == Byte.class) {\r
+                return n.byteValue();\r
+            } else if (targetType == short.class || targetType == Short.class) {\r
+                return n.shortValue();\r
+            } else if (targetType == int.class || targetType == Integer.class) {\r
+                return n.intValue();\r
+            } else if (targetType == long.class || targetType == Long.class) {\r
+                return n.longValue();\r
+            } else if (targetType == double.class || targetType == Double.class) {\r
+                return n.doubleValue();\r
+            } else if (targetType == float.class || targetType == Float.class) {\r
+                return n.floatValue();\r
+            } else if (targetType == BigDecimal.class) {\r
+                return new BigDecimal(n.doubleValue());\r
+            } else if (targetType == java.util.Date.class) {\r
+                return new java.util.Date(n.longValue());\r
+            } else if (targetType == java.sql.Date.class) {\r
+                return new java.sql.Date(n.longValue());\r
+            } else if (targetType == java.sql.Time.class) {\r
+                return new java.sql.Time(n.longValue());\r
+            } else if (targetType == java.sql.Timestamp.class) {\r
+                return new java.sql.Timestamp(n.longValue());\r
+            }\r
+        }\r
+\r
+        if (Date.class.isAssignableFrom(currentType)) {\r
+            Date d = (Date) o;\r
+            if (targetType == Date.class) {\r
+                return o;\r
+            } else if (targetType == java.sql.Date.class) {\r
+                return new java.sql.Date(d.getTime());\r
+            } else if (targetType == java.sql.Time.class) {\r
+                return new java.sql.Time(d.getTime());\r
+            } else if (targetType == java.sql.Timestamp.class) {\r
+                return new java.sql.Timestamp(d.getTime());\r
+            }\r
+        }\r
+\r
+        // convert from BLOB\r
+        if (targetType == byte[].class) {\r
+            if (Blob.class.isAssignableFrom(currentType)) {\r
+                Blob b = (Blob) o;\r
+                try {\r
+                    InputStream is = b.getBinaryStream();\r
+                    return readBlobAndClose(is, -1);\r
+                } catch (Exception e) {\r
+                    throw new IciqlException(e, "error converting BLOB to byte[]: ", e.toString());\r
+                }\r
+            }\r
+        }\r
+        throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
+    }\r
+\r
+    /**\r
+     * Identify the EnumType for the field.\r
+     *\r
+     * @param f\r
+     * @return null or the EnumType\r
+     */\r
+    public static EnumType getEnumType(Field f) {\r
+        EnumType enumType = null;\r
+        if (f.getType().isEnum()) {\r
+            enumType = EnumType.DEFAULT_TYPE;\r
+            if (f.getType().isAnnotationPresent(IQEnum.class)) {\r
+                // enum definition is annotated for all instances\r
+                IQEnum iqenum = f.getType().getAnnotation(IQEnum.class);\r
+                enumType = iqenum.value();\r
+            }\r
+            if (f.isAnnotationPresent(IQEnum.class)) {\r
+                // this instance of the enum is annotated\r
+                IQEnum iqenum = f.getAnnotation(IQEnum.class);\r
+                enumType = iqenum.value();\r
+            }\r
+        }\r
+        return enumType;\r
+    }\r
+\r
+    /**\r
+     * Identify the EnumType from the annotations.\r
+     *\r
+     * @param annotations\r
+     * @return null or the EnumType\r
+     */\r
+    public static EnumType getEnumType(Annotation[] annotations) {\r
+        EnumType enumType = null;\r
+        if (annotations != null) {\r
+            for (Annotation annotation : annotations) {\r
+                if (annotation instanceof IQEnum) {\r
+                    enumType = ((IQEnum) annotation).value();\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+        return enumType;\r
+    }\r
+\r
+    public static Class<?> getEnumTypeClass(Field f) {\r
+        if (f.getType().isEnum()) {\r
+            if (EnumId.class.isAssignableFrom(f.getType())) {\r
+                // custom enumid mapping\r
+                return ((EnumId<?>) f.getType().getEnumConstants()[0]).enumIdClass();\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+\r
+    public static Object convertEnum(Enum<?> o, EnumType type) {\r
+        if (o == null) {\r
+            return null;\r
+        }\r
+        switch (type) {\r
+            case ORDINAL:\r
+                return o.ordinal();\r
+            case ENUMID:\r
+                if (!EnumId.class.isAssignableFrom(o.getClass())) {\r
+                    throw new IciqlException("Can not convert the enum {0} using ENUMID", o);\r
+                }\r
+                EnumId<?> enumid = (EnumId<?>) o;\r
+                return enumid.enumId();\r
+            case NAME:\r
+            default:\r
+                return o.name();\r
+        }\r
+    }\r
+\r
+    public static Object convertEnum(Object o, Class<?> targetType, EnumType type) {\r
+        if (o == null) {\r
+            return null;\r
+        }\r
+        Class<?> currentType = o.getClass();\r
+        if (targetType.isAssignableFrom(currentType)) {\r
+            return o;\r
+        }\r
+        // convert from VARCHAR/TEXT/INT to Enum\r
+        Enum<?>[] values = (Enum[]) targetType.getEnumConstants();\r
+        if (Clob.class.isAssignableFrom(currentType)) {\r
+            // TEXT/CLOB field\r
+            Clob c = (Clob) o;\r
+            String name = null;\r
+            try {\r
+                Reader r = c.getCharacterStream();\r
+                name = readStringAndClose(r, -1);\r
+            } catch (Exception e) {\r
+                throw new IciqlException(e, "error converting CLOB to String: ", e.toString());\r
+            }\r
+\r
+            // find name match\r
+            if (type.equals(EnumType.ENUMID)) {\r
+                // ENUMID mapping\r
+                for (Enum<?> value : values) {\r
+                    EnumId<?> enumid = (EnumId<?>) value;\r
+                    if (enumid.enumId().equals(name)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            } else if (type.equals(EnumType.NAME)) {\r
+                // standard Enum.name() mapping\r
+                for (Enum<?> value : values) {\r
+                    if (value.name().equalsIgnoreCase(name)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            }\r
+        } else if (String.class.isAssignableFrom(currentType)) {\r
+            // VARCHAR field\r
+            String name = (String) o;\r
+            if (type.equals(EnumType.ENUMID)) {\r
+                // ENUMID mapping\r
+                for (Enum<?> value : values) {\r
+                    EnumId<?> enumid = (EnumId<?>) value;\r
+                    if (enumid.enumId().equals(name)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            } else if (type.equals(EnumType.NAME)) {\r
+                // standard Enum.name() mapping\r
+                for (Enum<?> value : values) {\r
+                    if (value.name().equalsIgnoreCase(name)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            }\r
+        } else if (Number.class.isAssignableFrom(currentType)) {\r
+            // INT field\r
+            int n = ((Number) o).intValue();\r
+            if (type.equals(EnumType.ORDINAL)) {\r
+                // ORDINAL mapping\r
+                for (Enum<?> value : values) {\r
+                    if (value.ordinal() == n) {\r
+                        return value;\r
+                    }\r
+                }\r
+            } else if (type.equals(EnumType.ENUMID)) {\r
+                if (!EnumId.class.isAssignableFrom(targetType)) {\r
+                    throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o,\r
+                            currentType, targetType);\r
+                }\r
+                // ENUMID mapping\r
+                for (Enum<?> value : values) {\r
+                    EnumId<?> enumid = (EnumId<?>) value;\r
+                    if (enumid.enumId().equals(n)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            }\r
+        } else {\r
+            // custom object mapping\r
+            if (type.equals(EnumType.ENUMID)) {\r
+                if (!EnumId.class.isAssignableFrom(targetType)) {\r
+                    throw new IciqlException("Can not convert the value {0} from {1} to {2} using ENUMID", o,\r
+                            currentType, targetType);\r
+                }\r
+                // ENUMID mapping\r
+                for (Enum<?> value : values) {\r
+                    EnumId<?> enumid = (EnumId<?>) value;\r
+                    if (enumid.enumId().equals(o)) {\r
+                        return value;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType);\r
+    }\r
+\r
+    /**\r
+     * Read a number of characters from a reader and close it.\r
+     *\r
+     * @param in     the reader\r
+     * @param length the maximum number of characters to read, or -1 to read until\r
+     *               the end of file\r
+     * @return the string read\r
+     */\r
+    public static String readStringAndClose(Reader in, int length) throws IOException {\r
+        try {\r
+            if (length <= 0) {\r
+                length = Integer.MAX_VALUE;\r
+            }\r
+            int block = Math.min(BUFFER_BLOCK_SIZE, length);\r
+            StringWriter out = new StringWriter(length == Integer.MAX_VALUE ? block : length);\r
+            char[] buff = new char[block];\r
+            while (length > 0) {\r
+                int len = Math.min(block, length);\r
+                len = in.read(buff, 0, len);\r
+                if (len < 0) {\r
+                    break;\r
+                }\r
+                out.write(buff, 0, len);\r
+                length -= len;\r
+            }\r
+            return out.toString();\r
+        } finally {\r
+            in.close();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Read a number of bytes from a stream and close it.\r
+     *\r
+     * @param in     the stream\r
+     * @param length the maximum number of bytes to read, or -1 to read until the\r
+     *               end of file\r
+     * @return the string read\r
+     */\r
+    public static byte[] readBlobAndClose(InputStream in, int length) throws IOException {\r
+        try {\r
+            if (length <= 0) {\r
+                length = Integer.MAX_VALUE;\r
+            }\r
+            int block = Math.min(BUFFER_BLOCK_SIZE, length);\r
+            ByteArrayOutputStream out = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? block : length);\r
+            byte[] buff = new byte[block];\r
+            while (length > 0) {\r
+                int len = Math.min(block, length);\r
+                len = in.read(buff, 0, len);\r
+                if (len < 0) {\r
+                    break;\r
+                }\r
+                out.write(buff, 0, len);\r
+                length -= len;\r
+            }\r
+            return out.toByteArray();\r
+        } finally {\r
+            in.close();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Identify the data type adapter class in the annotations.\r
+     *\r
+     * @param annotations\r
+     * @return null or the data type adapter class\r
+     */\r
+    public static Class<? extends DataTypeAdapter<?>> getDataTypeAdapter(Annotation[] annotations) {\r
+        Class<? extends DataTypeAdapter<?>> typeAdapter = null;\r
+        if (annotations != null) {\r
+            for (Annotation annotation : annotations) {\r
+                if (annotation instanceof TypeAdapter) {\r
+                    typeAdapter = ((TypeAdapter) annotation).value();\r
+                } else if (annotation.annotationType().isAnnotationPresent(TypeAdapter.class)) {\r
+                    typeAdapter = annotation.annotationType().getAnnotation(TypeAdapter.class).value();\r
+                }\r
+            }\r
+        }\r
+        return typeAdapter;\r
+    }\r
 }\r
index bc03cd06d69126140a5276ba0d71d78512cb2c35..0a2ad1e0b6f9f9a685e94a451163ed9872415ef0 100644 (file)
 \r
 package com.iciql.util;\r
 \r
+import com.iciql.IciqlException;\r
+\r
 import java.lang.ref.WeakReference;\r
 import java.util.Collection;\r
 import java.util.Map;\r
 import java.util.Set;\r
 \r
-import com.iciql.IciqlException;\r
-\r
 /**\r
  * This hash map uses weak references, so that elements that are no longer\r
  * referenced elsewhere can be garbage collected. It also uses object identity\r
  * to compare keys. The garbage collection happens when trying to add new data,\r
  * or when resizing.\r
- * \r
- * @param <K>\r
- *            the keys\r
- * @param <V>\r
- *            the value\r
+ *\r
+ * @param <K> the keys\r
+ * @param <V> the value\r
  */\r
 \r
 public class WeakIdentityHashMap<K, V> implements Map<K, V> {\r
 \r
-       private static final int MAX_LOAD = 90;\r
-       private static final WeakReference<Object> DELETED_KEY = new WeakReference<Object>(null);\r
-       private int mask, len, size, deletedCount, level;\r
-       private int maxSize, minSize, maxDeleted;\r
-       private WeakReference<K>[] keys;\r
-       private V[] values;\r
-\r
-       public WeakIdentityHashMap() {\r
-               reset(2);\r
-       }\r
-\r
-       public int size() {\r
-               return size;\r
-       }\r
-\r
-       private void checkSizePut() {\r
-               if (deletedCount > size) {\r
-                       rehash(level);\r
-               }\r
-               if (size + deletedCount >= maxSize) {\r
-                       rehash(level + 1);\r
-               }\r
-       }\r
-\r
-       private void checkSizeRemove() {\r
-               if (size < minSize && level > 0) {\r
-                       rehash(level - 1);\r
-               } else if (deletedCount > maxDeleted) {\r
-                       rehash(level);\r
-               }\r
-       }\r
-\r
-       private int getIndex(Object key) {\r
-               return System.identityHashCode(key) & mask;\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       private void reset(int newLevel) {\r
-               minSize = size * 3 / 4;\r
-               size = 0;\r
-               level = newLevel;\r
-               len = 2 << level;\r
-               mask = len - 1;\r
-               maxSize = (int) (len * MAX_LOAD / 100L);\r
-               deletedCount = 0;\r
-               maxDeleted = 20 + len / 2;\r
-               keys = new WeakReference[len];\r
-               values = (V[]) new Object[len];\r
-       }\r
-\r
-       public V put(K key, V value) {\r
-               checkSizePut();\r
-               int index = getIndex(key);\r
-               int plus = 1;\r
-               int deleted = -1;\r
-               do {\r
-                       WeakReference<K> k = keys[index];\r
-                       if (k == null) {\r
-                               // found an empty record\r
-                               if (deleted >= 0) {\r
-                                       index = deleted;\r
-                                       deletedCount--;\r
-                               }\r
-                               size++;\r
-                               keys[index] = new WeakReference<K>(key);\r
-                               values[index] = value;\r
-                               return null;\r
-                       } else if (k == DELETED_KEY) {\r
-                               if (deleted < 0) {\r
-                                       // found the first deleted record\r
-                                       deleted = index;\r
-                               }\r
-                       } else {\r
-                               Object r = k.get();\r
-                               if (r == null) {\r
-                                       delete(index);\r
-                               } else if (r == key) {\r
-                                       // update existing\r
-                                       V old = values[index];\r
-                                       values[index] = value;\r
-                                       return old;\r
-                               }\r
-                       }\r
-                       index = (index + plus++) & mask;\r
-               } while (plus <= len);\r
-               throw new IciqlException("Hashmap is full");\r
-       }\r
-\r
-       public V remove(Object key) {\r
-               checkSizeRemove();\r
-               int index = getIndex(key);\r
-               int plus = 1;\r
-               do {\r
-                       WeakReference<K> k = keys[index];\r
-                       if (k == null) {\r
-                               // found an empty record\r
-                               return null;\r
-                       } else if (k == DELETED_KEY) {\r
-                               // continue\r
-                       } else {\r
-                               Object r = k.get();\r
-                               if (r == null) {\r
-                                       delete(index);\r
-                               } else if (r == key) {\r
-                                       // found the record\r
-                                       V old = values[index];\r
-                                       delete(index);\r
-                                       return old;\r
-                               }\r
-                       }\r
-                       index = (index + plus++) & mask;\r
-                       k = keys[index];\r
-               } while (plus <= len);\r
-               // not found\r
-               return null;\r
-       }\r
-\r
-       @SuppressWarnings("unchecked")\r
-       private void delete(int index) {\r
-               keys[index] = (WeakReference<K>) DELETED_KEY;\r
-               values[index] = null;\r
-               deletedCount++;\r
-               size--;\r
-       }\r
-\r
-       private void rehash(int newLevel) {\r
-               WeakReference<K>[] oldKeys = keys;\r
-               V[] oldValues = values;\r
-               reset(newLevel);\r
-               for (int i = 0; i < oldKeys.length; i++) {\r
-                       WeakReference<K> k = oldKeys[i];\r
-                       if (k != null && k != DELETED_KEY) {\r
-                               K key = k.get();\r
-                               if (key != null) {\r
-                                       put(key, oldValues[i]);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       public V get(Object key) {\r
-               int index = getIndex(key);\r
-               int plus = 1;\r
-               do {\r
-                       WeakReference<K> k = keys[index];\r
-                       if (k == null) {\r
-                               return null;\r
-                       } else if (k == DELETED_KEY) {\r
-                               // continue\r
-                       } else {\r
-                               Object r = k.get();\r
-                               if (r == null) {\r
-                                       delete(index);\r
-                               } else if (r == key) {\r
-                                       return values[index];\r
-                               }\r
-                       }\r
-                       index = (index + plus++) & mask;\r
-               } while (plus <= len);\r
-               return null;\r
-       }\r
-\r
-       public void clear() {\r
-               reset(2);\r
-       }\r
-\r
-       public boolean containsKey(Object key) {\r
-               return get(key) != null;\r
-       }\r
-\r
-       public boolean containsValue(Object value) {\r
-               if (value == null) {\r
-                       return false;\r
-               }\r
-               for (V item : values) {\r
-                       if (value.equals(item)) {\r
-                               return true;\r
-                       }\r
-               }\r
-               return false;\r
-       }\r
-\r
-       public Set<java.util.Map.Entry<K, V>> entrySet() {\r
-               throw new UnsupportedOperationException();\r
-       }\r
-\r
-       public boolean isEmpty() {\r
-               return size == 0;\r
-       }\r
-\r
-       public Set<K> keySet() {\r
-               throw new UnsupportedOperationException();\r
-       }\r
-\r
-       public void putAll(Map<? extends K, ? extends V> m) {\r
-               throw new UnsupportedOperationException();\r
-       }\r
-\r
-       public Collection<V> values() {\r
-               throw new UnsupportedOperationException();\r
-       }\r
+    private static final int MAX_LOAD = 90;\r
+    private static final WeakReference<Object> DELETED_KEY = new WeakReference<Object>(null);\r
+    private int mask, len, size, deletedCount, level;\r
+    private int maxSize, minSize, maxDeleted;\r
+    private WeakReference<K>[] keys;\r
+    private V[] values;\r
+\r
+    public WeakIdentityHashMap() {\r
+        reset(2);\r
+    }\r
+\r
+    public int size() {\r
+        return size;\r
+    }\r
+\r
+    private void checkSizePut() {\r
+        if (deletedCount > size) {\r
+            rehash(level);\r
+        }\r
+        if (size + deletedCount >= maxSize) {\r
+            rehash(level + 1);\r
+        }\r
+    }\r
+\r
+    private void checkSizeRemove() {\r
+        if (size < minSize && level > 0) {\r
+            rehash(level - 1);\r
+        } else if (deletedCount > maxDeleted) {\r
+            rehash(level);\r
+        }\r
+    }\r
+\r
+    private int getIndex(Object key) {\r
+        return System.identityHashCode(key) & mask;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    private void reset(int newLevel) {\r
+        minSize = size * 3 / 4;\r
+        size = 0;\r
+        level = newLevel;\r
+        len = 2 << level;\r
+        mask = len - 1;\r
+        maxSize = (int) (len * MAX_LOAD / 100L);\r
+        deletedCount = 0;\r
+        maxDeleted = 20 + len / 2;\r
+        keys = new WeakReference[len];\r
+        values = (V[]) new Object[len];\r
+    }\r
+\r
+    public V put(K key, V value) {\r
+        checkSizePut();\r
+        int index = getIndex(key);\r
+        int plus = 1;\r
+        int deleted = -1;\r
+        do {\r
+            WeakReference<K> k = keys[index];\r
+            if (k == null) {\r
+                // found an empty record\r
+                if (deleted >= 0) {\r
+                    index = deleted;\r
+                    deletedCount--;\r
+                }\r
+                size++;\r
+                keys[index] = new WeakReference<K>(key);\r
+                values[index] = value;\r
+                return null;\r
+            } else if (k == DELETED_KEY) {\r
+                if (deleted < 0) {\r
+                    // found the first deleted record\r
+                    deleted = index;\r
+                }\r
+            } else {\r
+                Object r = k.get();\r
+                if (r == null) {\r
+                    delete(index);\r
+                } else if (r == key) {\r
+                    // update existing\r
+                    V old = values[index];\r
+                    values[index] = value;\r
+                    return old;\r
+                }\r
+            }\r
+            index = (index + plus++) & mask;\r
+        } while (plus <= len);\r
+        throw new IciqlException("Hashmap is full");\r
+    }\r
+\r
+    public V remove(Object key) {\r
+        checkSizeRemove();\r
+        int index = getIndex(key);\r
+        int plus = 1;\r
+        do {\r
+            WeakReference<K> k = keys[index];\r
+            if (k == null) {\r
+                // found an empty record\r
+                return null;\r
+            } else if (k == DELETED_KEY) {\r
+                // continue\r
+            } else {\r
+                Object r = k.get();\r
+                if (r == null) {\r
+                    delete(index);\r
+                } else if (r == key) {\r
+                    // found the record\r
+                    V old = values[index];\r
+                    delete(index);\r
+                    return old;\r
+                }\r
+            }\r
+            index = (index + plus++) & mask;\r
+            k = keys[index];\r
+        } while (plus <= len);\r
+        // not found\r
+        return null;\r
+    }\r
+\r
+    @SuppressWarnings("unchecked")\r
+    private void delete(int index) {\r
+        keys[index] = (WeakReference<K>) DELETED_KEY;\r
+        values[index] = null;\r
+        deletedCount++;\r
+        size--;\r
+    }\r
+\r
+    private void rehash(int newLevel) {\r
+        WeakReference<K>[] oldKeys = keys;\r
+        V[] oldValues = values;\r
+        reset(newLevel);\r
+        for (int i = 0; i < oldKeys.length; i++) {\r
+            WeakReference<K> k = oldKeys[i];\r
+            if (k != null && k != DELETED_KEY) {\r
+                K key = k.get();\r
+                if (key != null) {\r
+                    put(key, oldValues[i]);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    public V get(Object key) {\r
+        int index = getIndex(key);\r
+        int plus = 1;\r
+        do {\r
+            WeakReference<K> k = keys[index];\r
+            if (k == null) {\r
+                return null;\r
+            } else if (k == DELETED_KEY) {\r
+                // continue\r
+            } else {\r
+                Object r = k.get();\r
+                if (r == null) {\r
+                    delete(index);\r
+                } else if (r == key) {\r
+                    return values[index];\r
+                }\r
+            }\r
+            index = (index + plus++) & mask;\r
+        } while (plus <= len);\r
+        return null;\r
+    }\r
+\r
+    public void clear() {\r
+        reset(2);\r
+    }\r
+\r
+    public boolean containsKey(Object key) {\r
+        return get(key) != null;\r
+    }\r
+\r
+    public boolean containsValue(Object value) {\r
+        if (value == null) {\r
+            return false;\r
+        }\r
+        for (V item : values) {\r
+            if (value.equals(item)) {\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    public Set<java.util.Map.Entry<K, V>> entrySet() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public boolean isEmpty() {\r
+        return size == 0;\r
+    }\r
+\r
+    public Set<K> keySet() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public void putAll(Map<? extends K, ? extends V> m) {\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    public Collection<V> values() {\r
+        throw new UnsupportedOperationException();\r
+    }\r
 \r
 }\r
index 3d24dee0b1acb44c81b28108d51dbca565d3c4d2..62adcb593dc12fe16852205e41c33828715eb89a 100644 (file)
@@ -16,8 +16,9 @@
  limitations under the License.\r
 -->\r
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
-<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\r
-<title>Javadoc package documentation</title>\r
+<head>\r
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>\r
+    <title>Javadoc package documentation</title>\r
 </head>\r
 <body>\r
 Utility classes for iciql.\r
index 2141fbc1ba18388ce66eb7a3c567d72ffe4c272c..4484403e471bfb0b4949213eb2ad4adeb91ea3b1 100644 (file)
@@ -36,18 +36,18 @@ public interface AutoCloseable {
      * Closes this resource, relinquishing any underlying resources.
      * This method is invoked automatically by the {@code
      * try}-with-resources statement.
-     *
+     * <p>
      * <p>Classes implementing this method are strongly encouraged to
      * be declared to throw more specific exceptions (or no exception
      * at all, if the close cannot fail).
-     *
+     * <p>
      * <p>Note that unlike the {@link java.io.Closeable#close close}
      * method of {@link java.io.Closeable}, this {@code close} method
      * is <em>not</em> required to be idempotent.  In other words,
      * calling this {@code close} method more than once may have some
      * visible side effect, unlike {@code Closeable.close} which is
      * required to have no effect if called more than once.
-     *
+     * <p>
      * However, while not required to be idempotent, implementers of
      * this interface are strongly encouraged to make their {@code
      * close} methods idempotent.
index 092f38bac21d3b61f0c95427de900b4e5f58f20f..a5e7eee6e4f9bd0e4b910ab9253c21404f806fce 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.IciqlException;
 import com.iciql.test.models.PrimitivesModel;
 import com.iciql.test.models.Product;
 import com.iciql.util.Utils;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests object and primitive alias referencing.
  */
 public class AliasMapTest {
 
-       /**
-        * Tests that columns (p.unitsInStock) are not compared by value with the
-        * value (9), but by reference (using an identity hash map). See
-        * http://code.google.com/p/h2database/issues/detail?id=119
-        * 
-        * @author d moebius at scoop dash gmbh dot de
-        */
-       @Test
-       public void testObjectAliasMapping() throws Exception {
-               Db db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
+    /**
+     * Tests that columns (p.unitsInStock) are not compared by value with the
+     * value (9), but by reference (using an identity hash map). See
+     * http://code.google.com/p/h2database/issues/detail?id=119
+     *
+     * @author d moebius at scoop dash gmbh dot de
+     */
+    @Test
+    public void testObjectAliasMapping() throws Exception {
+        Db db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
 
-               // baseline count is the next id value
-               long bc = Utils.COUNTER.get();
-               // number of fields in primitives model class
-               // each from() call will increment Utils.COUNTER by this amount
-               int fc = Product.class.getFields().length;
+        // baseline count is the next id value
+        long bc = Utils.COUNTER.get();
+        // number of fields in primitives model class
+        // each from() call will increment Utils.COUNTER by this amount
+        int fc = Product.class.getFields().length;
 
-               Product p = new Product();
-               // This test confirms standard object referencing querying.
-               long count = db.from(p).where(p.productId).is(9).selectCount();
-               assertEquals(1, count);
-               // Confirms that productId counter value is baseline counter value
-               assertEquals(bc, p.productId.intValue());
-               try {
-                       // This test compares "bc + fc" which is the counter value of
-                       // unitsInStock assigned by Utils.newObject() after the 2nd pass
-                       // through from().
-                       //
-                       // Object fields map by REFERENCE, not value.
-                       db.from(p).where(Long.valueOf(bc + fc).intValue()).is(9).orderBy(p.productId).select();
-                       assertTrue("Fail: object field is mapping by value.", false);
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
-                       assertEquals(bc + 5, p.productId.intValue());
-               }
+        Product p = new Product();
+        // This test confirms standard object referencing querying.
+        long count = db.from(p).where(p.productId).is(9).selectCount();
+        assertEquals(1, count);
+        // Confirms that productId counter value is baseline counter value
+        assertEquals(bc, p.productId.intValue());
+        try {
+            // This test compares "bc + fc" which is the counter value of
+            // unitsInStock assigned by Utils.newObject() after the 2nd pass
+            // through from().
+            //
+            // Object fields map by REFERENCE, not value.
+            db.from(p).where(Long.valueOf(bc + fc).intValue()).is(9).orderBy(p.productId).select();
+            assertTrue("Fail: object field is mapping by value.", false);
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
+            assertEquals(bc + 5, p.productId.intValue());
+        }
 
-               try {
-                       // This test compares Integer(bc) which is the counter value of
-                       // unitsInStock assigned by Utils.newObject() after the 3rd pass
-                       // through from().
-                       //
-                       // Object fields map by REFERENCE, not value.
-                       db.from(p).where(Long.valueOf(bc).intValue()).is(9).orderBy(p.productId).select();
-                       assertTrue("Fail: object field is mapping by value.", false);
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
-                       assertEquals(bc + (2 * fc), p.productId.intValue());
-               }
+        try {
+            // This test compares Integer(bc) which is the counter value of
+            // unitsInStock assigned by Utils.newObject() after the 3rd pass
+            // through from().
+            //
+            // Object fields map by REFERENCE, not value.
+            db.from(p).where(Long.valueOf(bc).intValue()).is(9).orderBy(p.productId).select();
+            assertTrue("Fail: object field is mapping by value.", false);
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
+            assertEquals(bc + (2 * fc), p.productId.intValue());
+        }
 
-               db.close();
-       }
+        db.close();
+    }
 
-       /**
-        * Confirms that primitive aliases ARE mapped by value.
-        */
-       @Test
-       public void testPrimitiveAliasMapping() throws Exception {
-               Db db = IciqlSuite.openNewDb();
-               PrimitivesModel model = new PrimitivesModel();
-               model.myLong = 100L;
-               db.insert(model);
-               model.myLong = 200L;
-               db.insert(model);
+    /**
+     * Confirms that primitive aliases ARE mapped by value.
+     */
+    @Test
+    public void testPrimitiveAliasMapping() throws Exception {
+        Db db = IciqlSuite.openNewDb();
+        PrimitivesModel model = new PrimitivesModel();
+        model.myLong = 100L;
+        db.insert(model);
+        model.myLong = 200L;
+        db.insert(model);
 
-               // baseline count is the next id value
-               long bc = Utils.COUNTER.get();
-               // number of fields in primitives model class
-               // each from() call will increment Utils.COUNTER by this amount
-               int fc = PrimitivesModel.class.getFields().length;
+        // baseline count is the next id value
+        long bc = Utils.COUNTER.get();
+        // number of fields in primitives model class
+        // each from() call will increment Utils.COUNTER by this amount
+        int fc = PrimitivesModel.class.getFields().length;
 
-               PrimitivesModel p = new PrimitivesModel();
-               // This test confirms standard primitive referencing querying.
-               long count = db.from(p).where(p.myLong).is(100L).selectCount();
-               assertEquals(1, count);
-               // Confirms that myLong counter value is bc
-               assertEquals(bc, p.myLong);
-               try {
-                       // This test compares "bc + fc" which is the counter value
-                       // of myLong assigned by Utils.newObject() after the 2nd pass
-                       // through from().
-                       //
-                       // Primitive fields map by VALUE.
-                       count = db.from(p).where(bc + fc).is(100L).selectCount();
-                       assertEquals(1, count);
-                       assertEquals(bc + fc, p.myLong);
-               } catch (IciqlException e) {
-                       assertTrue(e.getMessage(), false);
-               }
-               try {
-                       // This test compares "bc" which was the counter value of
-                       // myLong assigned by Utils.newObject() after the 1st pass
-                       // through from(). "bc" is unmapped now and will throw an
-                       // exception.
-                       //
-                       // Primitive fields map by VALUE.
-                       db.from(p).where(bc).is(100L).select();
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
-                       assertEquals(bc + (2 * fc), p.myLong);
-               }
-               db.close();
-       }
+        PrimitivesModel p = new PrimitivesModel();
+        // This test confirms standard primitive referencing querying.
+        long count = db.from(p).where(p.myLong).is(100L).selectCount();
+        assertEquals(1, count);
+        // Confirms that myLong counter value is bc
+        assertEquals(bc, p.myLong);
+        try {
+            // This test compares "bc + fc" which is the counter value
+            // of myLong assigned by Utils.newObject() after the 2nd pass
+            // through from().
+            //
+            // Primitive fields map by VALUE.
+            count = db.from(p).where(bc + fc).is(100L).selectCount();
+            assertEquals(1, count);
+            assertEquals(bc + fc, p.myLong);
+        } catch (IciqlException e) {
+            assertTrue(e.getMessage(), false);
+        }
+        try {
+            // This test compares "bc" which was the counter value of
+            // myLong assigned by Utils.newObject() after the 1st pass
+            // through from(). "bc" is unmapped now and will throw an
+            // exception.
+            //
+            // Primitive fields map by VALUE.
+            db.from(p).where(bc).is(100L).select();
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
+            assertEquals(bc + (2 * fc), p.myLong);
+        }
+        db.close();
+    }
 }
\ No newline at end of file
index 6aa75ad083608306b8798f82e6969244171ad5c1..f96fe76ef5e1cd5efd534d0e30b37587581a1033 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.IciqlException;
 import com.iciql.test.models.Product;
@@ -37,160 +25,171 @@ import com.iciql.test.models.ProductInheritedAnnotation;
 import com.iciql.test.models.ProductMixedAnnotation;
 import com.iciql.test.models.ProductNoCreateTable;
 import com.iciql.util.Utils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test annotation processing.
  */
 public class AnnotationsTest {
 
-       /**
-        * This object represents a database (actually a connection to the
-        * database).
-        */
-
-       private Db db;
-
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
-               db.insertAll(ProductAnnotationOnly.getList());
-               db.insertAll(ProductMixedAnnotation.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testIndexCreation() throws SQLException {
-               // test indexes are created, and columns are in the right order
-               DatabaseMetaData meta = db.getConnection().getMetaData();
-               String schema = IciqlSuite.getDefaultSchema(db);
-               boolean toUpper = meta.storesUpperCaseIdentifiers();
-               boolean toLower = meta.storesLowerCaseIdentifiers();
-               ResultSet rs = meta.getIndexInfo(null, prepName(schema, toUpper, toLower),
-                               prepName("ANNOTATEDPRODUCT", toUpper, toLower), false, true);
-
-               List<String> list = Utils.newArrayList();
-               while (rs.next()) {
-                       String col = rs.getString("COLUMN_NAME");
-                       String index = rs.getString("INDEX_NAME");
-                       list.add((col + ":" +  index).toLowerCase());
-               }
-               assertTrue(list.contains("name:annotatedproduct_idx_0"));
-               assertTrue(list.contains("cat:annotatedproduct_idx_0"));
-               assertTrue(list.contains("name:nameidx"));
-       }
-
-       private String prepName(String name, boolean upper, boolean lower) {
-               if (name == null) {
-                       return null;
-               }
-               if (upper) {
-                       return name.toUpperCase();
-               } else if (lower) {
-                       return name.toLowerCase();
-               }
-               return name;
-       }
-
-       @Test
-       public void testProductAnnotationOnly() {
-               ProductAnnotationOnly p = new ProductAnnotationOnly();
-               assertEquals(10, db.from(p).selectCount());
-
-               // test IQColumn.name="cat"
-               assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
-
-               // test IQTable.annotationsOnly=true
-               // public String unmappedField is ignored by iciql
-               try {
-                       db.from(p).where(p.unmappedField).is("unmapped").selectCount();
-                       assertTrue("this should never execute", false);
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
-               }
-
-               // 10 objects, 10 autoIncremented unique values
-               assertEquals(10, db.from(p).selectDistinct(p.productName).size());
-
-               // test IQTable.primaryKey=id
-               try {
-                       db.insertAll(ProductAnnotationOnly.getList());
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_DUPLICATE_KEY, e.getIciqlCode());
-               }
-       }
-
-       @Test
-       public void testProductMixedAnnotation() {
-               ProductMixedAnnotation p = new ProductMixedAnnotation();
-
-               // test IQColumn.name="cat"
-               assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
-
-               // test IQTable.annotationsOnly=false
-               // public String mappedField is reflectively mapped by iciql
-               assertEquals(10, db.from(p).where(p.mappedField).is("mapped").selectCount());
-
-               // test IQIgnore annotation
-               assertEquals(null, db.from(p).selectFirst().productDescription);
-
-               // test IQColumn.primaryKey=true
-               try {
-                       db.insertAll(ProductMixedAnnotation.getList());
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_DUPLICATE_KEY, e.getIciqlCode());
-               }
-       }
-
-       @Test
-       public void testTrimStringAnnotation() {
-               ProductAnnotationOnly p = new ProductAnnotationOnly();
-               ProductAnnotationOnly prod = db.from(p).selectFirst();
-               String oldValue = prod.category;
-               String newValue = "01234567890123456789";
-               // 2 chars exceeds field max
-               prod.category = newValue;
-               db.update(prod);
-
-               ProductAnnotationOnly newProd = db.from(p).where(p.productId).is(prod.productId).selectFirst();
-               assertEquals(newValue.substring(0, 15), newProd.category);
-
-               newProd.category = oldValue;
-               db.update(newProd);
-       }
-
-       @Test
-       public void testColumnInheritanceAnnotation() {
-               ProductInheritedAnnotation table = new ProductInheritedAnnotation();
-               List<ProductInheritedAnnotation> inserted = ProductInheritedAnnotation.getData();
-               db.insertAll(inserted);
-
-               List<ProductInheritedAnnotation> retrieved = db.from(table).select();
-
-               for (int j = 0; j < retrieved.size(); j++) {
-                       ProductInheritedAnnotation i = inserted.get(j);
-                       ProductInheritedAnnotation r = retrieved.get(j);
-                       assertEquals(i.category, r.category);
-                       assertEquals(i.mappedField, r.mappedField);
-                       assertEquals(i.unitsInStock, r.unitsInStock);
-                       assertEquals(i.unitPrice, r.unitPrice);
-                       assertEquals(i.name(), r.name());
-                       assertEquals(i.id(), r.id());
-               }
-       }
-
-       @Test
-       public void testCreateTableIfRequiredAnnotation() {
-               // tests IQTable.createTableIfRequired=false
-               try {
-                       db.insertAll(ProductNoCreateTable.getList());
-               } catch (IciqlException e) {
-                       assertEquals(IciqlException.CODE_OBJECT_NOT_FOUND, e.getIciqlCode());
-               }
-       }
+    /**
+     * This object represents a database (actually a connection to the
+     * database).
+     */
+
+    private Db db;
+
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
+        db.insertAll(ProductAnnotationOnly.getList());
+        db.insertAll(ProductMixedAnnotation.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testIndexCreation() throws SQLException {
+        // test indexes are created, and columns are in the right order
+        DatabaseMetaData meta = db.getConnection().getMetaData();
+        String schema = IciqlSuite.getDefaultSchema(db);
+        boolean toUpper = meta.storesUpperCaseIdentifiers();
+        boolean toLower = meta.storesLowerCaseIdentifiers();
+        ResultSet rs = meta.getIndexInfo(null, prepName(schema, toUpper, toLower),
+                prepName("ANNOTATEDPRODUCT", toUpper, toLower), false, true);
+
+        List<String> list = Utils.newArrayList();
+        while (rs.next()) {
+            String col = rs.getString("COLUMN_NAME");
+            String index = rs.getString("INDEX_NAME");
+            list.add((col + ":" + index).toLowerCase());
+        }
+        assertTrue(list.contains("name:annotatedproduct_idx_0"));
+        assertTrue(list.contains("cat:annotatedproduct_idx_0"));
+        assertTrue(list.contains("name:nameidx"));
+    }
+
+    private String prepName(String name, boolean upper, boolean lower) {
+        if (name == null) {
+            return null;
+        }
+        if (upper) {
+            return name.toUpperCase();
+        } else if (lower) {
+            return name.toLowerCase();
+        }
+        return name;
+    }
+
+    @Test
+    public void testProductAnnotationOnly() {
+        ProductAnnotationOnly p = new ProductAnnotationOnly();
+        assertEquals(10, db.from(p).selectCount());
+
+        // test IQColumn.name="cat"
+        assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
+
+        // test IQTable.annotationsOnly=true
+        // public String unmappedField is ignored by iciql
+        try {
+            db.from(p).where(p.unmappedField).is("unmapped").selectCount();
+            assertTrue("this should never execute", false);
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
+        }
+
+        // 10 objects, 10 autoIncremented unique values
+        assertEquals(10, db.from(p).selectDistinct(p.productName).size());
+
+        // test IQTable.primaryKey=id
+        try {
+            db.insertAll(ProductAnnotationOnly.getList());
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_DUPLICATE_KEY, e.getIciqlCode());
+        }
+    }
+
+    @Test
+    public void testProductMixedAnnotation() {
+        ProductMixedAnnotation p = new ProductMixedAnnotation();
+
+        // test IQColumn.name="cat"
+        assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
+
+        // test IQTable.annotationsOnly=false
+        // public String mappedField is reflectively mapped by iciql
+        assertEquals(10, db.from(p).where(p.mappedField).is("mapped").selectCount());
+
+        // test IQIgnore annotation
+        assertEquals(null, db.from(p).selectFirst().productDescription);
+
+        // test IQColumn.primaryKey=true
+        try {
+            db.insertAll(ProductMixedAnnotation.getList());
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_DUPLICATE_KEY, e.getIciqlCode());
+        }
+    }
+
+    @Test
+    public void testTrimStringAnnotation() {
+        ProductAnnotationOnly p = new ProductAnnotationOnly();
+        ProductAnnotationOnly prod = db.from(p).selectFirst();
+        String oldValue = prod.category;
+        String newValue = "01234567890123456789";
+        // 2 chars exceeds field max
+        prod.category = newValue;
+        db.update(prod);
+
+        ProductAnnotationOnly newProd = db.from(p).where(p.productId).is(prod.productId).selectFirst();
+        assertEquals(newValue.substring(0, 15), newProd.category);
+
+        newProd.category = oldValue;
+        db.update(newProd);
+    }
+
+    @Test
+    public void testColumnInheritanceAnnotation() {
+        ProductInheritedAnnotation table = new ProductInheritedAnnotation();
+        List<ProductInheritedAnnotation> inserted = ProductInheritedAnnotation.getData();
+        db.insertAll(inserted);
+
+        List<ProductInheritedAnnotation> retrieved = db.from(table).select();
+
+        for (int j = 0; j < retrieved.size(); j++) {
+            ProductInheritedAnnotation i = inserted.get(j);
+            ProductInheritedAnnotation r = retrieved.get(j);
+            assertEquals(i.category, r.category);
+            assertEquals(i.mappedField, r.mappedField);
+            assertEquals(i.unitsInStock, r.unitsInStock);
+            assertEquals(i.unitPrice, r.unitPrice);
+            assertEquals(i.name(), r.name());
+            assertEquals(i.id(), r.id());
+        }
+    }
+
+    @Test
+    public void testCreateTableIfRequiredAnnotation() {
+        // tests IQTable.createTableIfRequired=false
+        try {
+            db.insertAll(ProductNoCreateTable.getList());
+        } catch (IciqlException e) {
+            assertEquals(IciqlException.CODE_OBJECT_NOT_FOUND, e.getIciqlCode());
+        }
+    }
 
 }
index f5cd5e7d4f2a3a94543603911b84fdd0af3ff681..3744204c3d34bd29e15c0d370a50c39a1e0ef2b5 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.util.List;\r
-\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.test.models.BooleanModel;\r
 import com.iciql.test.models.BooleanModel.BooleanAsIntModel;\r
 import com.iciql.test.models.BooleanModel.BooleanAsPrimitiveShortModel;\r
+import org.junit.Test;\r
+\r
+import java.util.List;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * Tests interchangeable mapping of INT columns with Booleans and BOOL columns\r
@@ -39,135 +38,135 @@ import com.iciql.test.models.BooleanModel.BooleanAsPrimitiveShortModel;
  */\r
 public class BooleanModelTest {\r
 \r
-       @Test\r
-       public void testBooleanColumn() {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(BooleanModel.getList());\r
-               BooleanAsIntModel b = new BooleanAsIntModel();\r
-               List<BooleanAsIntModel> models = db.from(b).select();\r
-               int count = 0;\r
-               for (BooleanAsIntModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are true\r
-                               assertTrue(model.mybool > 0);\r
-                       } else {\r
-                               // assert that even ids are false\r
-                               assertTrue(model.mybool == 0);\r
-                       }\r
-\r
-                       // count true values\r
-                       if (model.mybool > 0) {\r
-                               count++;\r
-                       }\r
-               }\r
-               assertEquals(2, count);\r
-\r
-               // invert boolean values and update\r
-               for (BooleanAsIntModel model : models) {\r
-                       model.mybool = model.mybool > 0 ? 0 : 1;\r
-               }\r
-               db.updateAll(models);\r
-\r
-               // check even ids are true\r
-               models = db.from(b).select();\r
-               for (BooleanAsIntModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are false\r
-                               assertTrue(model.mybool == 0);\r
-                       } else {\r
-                               // assert that even ids are true\r
-                               assertTrue(model.mybool > 0);\r
-                       }\r
-               }\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testIntColumn() {\r
-               Db db = IciqlSuite.openNewDb();\r
-               // insert INT column\r
-               db.insertAll(BooleanAsIntModel.getList());\r
-\r
-               // select all rows with INT column and map to Boolean\r
-               BooleanModel b = new BooleanModel();\r
-               List<BooleanModel> models = db.from(b).select();\r
-               int count = 0;\r
-               for (BooleanModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are true\r
-                               assertTrue(model.mybool);\r
-                       } else {\r
-                               // assert that even ids are false\r
-                               assertTrue(!model.mybool);\r
-                       }\r
-\r
-                       // count true values\r
-                       if (model.mybool) {\r
-                               count++;\r
-                       }\r
-               }\r
-               assertEquals(2, count);\r
-\r
-               // invert boolean values and update\r
-               for (BooleanModel model : models) {\r
-                       model.mybool = !model.mybool;\r
-               }\r
-               db.updateAll(models);\r
-\r
-               // check even ids are true\r
-               models = db.from(b).select();\r
-               for (BooleanModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are false\r
-                               assertTrue(!model.mybool);\r
-                       } else {\r
-                               // assert that even ids are true\r
-                               assertTrue(model.mybool);\r
-                       }\r
-               }\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testPrimitiveShortBooleanColumn() {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(BooleanModel.getList());\r
-               BooleanAsPrimitiveShortModel b = new BooleanAsPrimitiveShortModel();\r
-               List<BooleanAsPrimitiveShortModel> models = db.from(b).select();\r
-               int count = 0;\r
-               for (BooleanAsPrimitiveShortModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are true\r
-                               assertTrue(model.mybool > 0);\r
-                       } else {\r
-                               // assert that even ids are false\r
-                               assertTrue(model.mybool == 0);\r
-                       }\r
-\r
-                       // count true values\r
-                       if (model.mybool > 0) {\r
-                               count++;\r
-                       }\r
-               }\r
-               assertEquals(2, count);\r
-\r
-               // invert boolean values and update\r
-               for (BooleanAsPrimitiveShortModel model : models) {\r
-                       model.mybool = (short) (model.mybool > 0 ? 0 : 1);\r
-               }\r
-               db.updateAll(models);\r
-\r
-               // check even ids are true\r
-               models = db.from(b).select();\r
-               for (BooleanAsPrimitiveShortModel model : models) {\r
-                       if ((model.id % 2) == 1) {\r
-                               // assert that odd ids are false\r
-                               assertTrue(model.mybool == 0);\r
-                       } else {\r
-                               // assert that even ids are true\r
-                               assertTrue(model.mybool > 0);\r
-                       }\r
-               }\r
-               db.close();\r
-       }\r
+    @Test\r
+    public void testBooleanColumn() {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(BooleanModel.getList());\r
+        BooleanAsIntModel b = new BooleanAsIntModel();\r
+        List<BooleanAsIntModel> models = db.from(b).select();\r
+        int count = 0;\r
+        for (BooleanAsIntModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are true\r
+                assertTrue(model.mybool > 0);\r
+            } else {\r
+                // assert that even ids are false\r
+                assertTrue(model.mybool == 0);\r
+            }\r
+\r
+            // count true values\r
+            if (model.mybool > 0) {\r
+                count++;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+\r
+        // invert boolean values and update\r
+        for (BooleanAsIntModel model : models) {\r
+            model.mybool = model.mybool > 0 ? 0 : 1;\r
+        }\r
+        db.updateAll(models);\r
+\r
+        // check even ids are true\r
+        models = db.from(b).select();\r
+        for (BooleanAsIntModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are false\r
+                assertTrue(model.mybool == 0);\r
+            } else {\r
+                // assert that even ids are true\r
+                assertTrue(model.mybool > 0);\r
+            }\r
+        }\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testIntColumn() {\r
+        Db db = IciqlSuite.openNewDb();\r
+        // insert INT column\r
+        db.insertAll(BooleanAsIntModel.getList());\r
+\r
+        // select all rows with INT column and map to Boolean\r
+        BooleanModel b = new BooleanModel();\r
+        List<BooleanModel> models = db.from(b).select();\r
+        int count = 0;\r
+        for (BooleanModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are true\r
+                assertTrue(model.mybool);\r
+            } else {\r
+                // assert that even ids are false\r
+                assertTrue(!model.mybool);\r
+            }\r
+\r
+            // count true values\r
+            if (model.mybool) {\r
+                count++;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+\r
+        // invert boolean values and update\r
+        for (BooleanModel model : models) {\r
+            model.mybool = !model.mybool;\r
+        }\r
+        db.updateAll(models);\r
+\r
+        // check even ids are true\r
+        models = db.from(b).select();\r
+        for (BooleanModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are false\r
+                assertTrue(!model.mybool);\r
+            } else {\r
+                // assert that even ids are true\r
+                assertTrue(model.mybool);\r
+            }\r
+        }\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testPrimitiveShortBooleanColumn() {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(BooleanModel.getList());\r
+        BooleanAsPrimitiveShortModel b = new BooleanAsPrimitiveShortModel();\r
+        List<BooleanAsPrimitiveShortModel> models = db.from(b).select();\r
+        int count = 0;\r
+        for (BooleanAsPrimitiveShortModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are true\r
+                assertTrue(model.mybool > 0);\r
+            } else {\r
+                // assert that even ids are false\r
+                assertTrue(model.mybool == 0);\r
+            }\r
+\r
+            // count true values\r
+            if (model.mybool > 0) {\r
+                count++;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+\r
+        // invert boolean values and update\r
+        for (BooleanAsPrimitiveShortModel model : models) {\r
+            model.mybool = (short) (model.mybool > 0 ? 0 : 1);\r
+        }\r
+        db.updateAll(models);\r
+\r
+        // check even ids are true\r
+        models = db.from(b).select();\r
+        for (BooleanAsPrimitiveShortModel model : models) {\r
+            if ((model.id % 2) == 1) {\r
+                // assert that odd ids are false\r
+                assertTrue(model.mybool == 0);\r
+            } else {\r
+                // assert that even ids are true\r
+                assertTrue(model.mybool > 0);\r
+            }\r
+        }\r
+        db.close();\r
+    }\r
 }\r
index 49cee7273a3c6bbd55a36d0053b9c688c3df5e14..89e21cd72d65254faf7b63d5a3275bb990747a0c 100644 (file)
 
 package com.iciql.test;
 
-import static com.iciql.Define.primaryKey;
-import static com.iciql.Define.tableName;
-import static org.junit.Assert.assertEquals;
+import com.iciql.Db;
+import com.iciql.Iciql;
+import org.junit.Test;
 
 import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.List;
 
-import org.junit.Test;
-
-import com.iciql.Db;
-import com.iciql.Iciql;
+import static com.iciql.Define.primaryKey;
+import static com.iciql.Define.tableName;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests if converting a CLOB to a String works.
  */
 public class ClobTest {
 
-       @Test
-       public void testClob() throws Exception {
-               String create = "CREATE TABLE CLOB_TEST(ID INT PRIMARY KEY, WORDS {0})";
-               Db db = IciqlSuite.openNewDb();
-               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, 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();
-       }
-
-       private void testSimpleUpdate(Db db, String failureMsg) {
-               String newWords = "I changed the words";
-               StringRecord r = new StringRecord();
-               StringRecord originalRecord = db.from(r).where(r.id).is(2).selectFirst();
-               String oldWords = originalRecord.words;
-               originalRecord.words = newWords;
-               db.update(originalRecord);
-
-               StringRecord r2 = new StringRecord();
-               StringRecord revisedRecord = db.from(r2).where(r2.id).is(2).selectFirst();
-               assertEquals(failureMsg, newWords, revisedRecord.words);
-
-               // undo update
-               originalRecord.words = oldWords;
-               db.update(originalRecord);
-       }
-
-       /**
-        * A simple class used in this test.
-        */
-       public static class StringRecord implements Iciql {
-
-               public Integer id;
-               public String words;
-
-               public StringRecord() {
-                       // public constructor
-               }
-
-               private StringRecord(int id, String words) {
-                       this.id = id;
-                       this.words = words;
-               }
-
-               public void defineIQ() {
-                       tableName("CLOB_TEST");
-                       primaryKey(id);
-               }
-
-               private static StringRecord create(int id, String words) {
-                       return new StringRecord(id, words);
-               }
-
-               public static List<StringRecord> getList() {
-                       StringRecord[] list = {
-                                       create(1, "Once upon a midnight dreary, while I pondered weak and weary,"),
-                                       create(2, "Over many a quaint and curious volume of forgotten lore,"),
-                                       create(3, "While I nodded, nearly napping, suddenly there came a tapping,"),
-                                       create(4, "As of some one gently rapping, rapping at my chamber door."),
-                                       create(5, "`'Tis some visitor,' I muttered, `tapping at my chamber door -"),
-                                       create(6, "Only this, and nothing more.'") };
-
-                       return Arrays.asList(list);
-               }
-
-               public String toString() {
-                       return id + ": " + words;
-               }
-       }
+    @Test
+    public void testClob() throws Exception {
+        String create = "CREATE TABLE CLOB_TEST(ID INT PRIMARY KEY, WORDS {0})";
+        Db db = IciqlSuite.openNewDb();
+        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, 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();
+    }
+
+    private void testSimpleUpdate(Db db, String failureMsg) {
+        String newWords = "I changed the words";
+        StringRecord r = new StringRecord();
+        StringRecord originalRecord = db.from(r).where(r.id).is(2).selectFirst();
+        String oldWords = originalRecord.words;
+        originalRecord.words = newWords;
+        db.update(originalRecord);
+
+        StringRecord r2 = new StringRecord();
+        StringRecord revisedRecord = db.from(r2).where(r2.id).is(2).selectFirst();
+        assertEquals(failureMsg, newWords, revisedRecord.words);
+
+        // undo update
+        originalRecord.words = oldWords;
+        db.update(originalRecord);
+    }
+
+    /**
+     * A simple class used in this test.
+     */
+    public static class StringRecord implements Iciql {
+
+        public Integer id;
+        public String words;
+
+        public StringRecord() {
+            // public constructor
+        }
+
+        private StringRecord(int id, String words) {
+            this.id = id;
+            this.words = words;
+        }
+
+        public void defineIQ() {
+            tableName("CLOB_TEST");
+            primaryKey(id);
+        }
+
+        private static StringRecord create(int id, String words) {
+            return new StringRecord(id, words);
+        }
+
+        public static List<StringRecord> getList() {
+            StringRecord[] list = {
+                    create(1, "Once upon a midnight dreary, while I pondered weak and weary,"),
+                    create(2, "Over many a quaint and curious volume of forgotten lore,"),
+                    create(3, "While I nodded, nearly napping, suddenly there came a tapping,"),
+                    create(4, "As of some one gently rapping, rapping at my chamber door."),
+                    create(5, "`'Tis some visitor,' I muttered, `tapping at my chamber door -"),
+                    create(6, "Only this, and nothing more.'")};
+
+            return Arrays.asList(list);
+        }
+
+        public String toString() {
+            return id + ": " + words;
+        }
+    }
 }
index e2482655de95aac2c4dddddd6d18a249cbfa67b5..e7297f1b4f48ed7f31877b5c99563d791e8e87c6 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.IciqlException;
 import com.iciql.Query;
 import com.iciql.test.models.Product;
 import com.iciql.util.Utils;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests concurrency and alias instance sharing.
  */
 public class ConcurrencyTest {
 
-       private int numberOfTests = 800;
-
-       @Before
-       public void setUp() {
-               Db db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
-       }
-
-       @Test
-       public void testAliasSharing() throws Exception {
-               Db db = IciqlSuite.openCurrentDb();
-               try {
-                       // Single-threaded example of why aliases can NOT be shared.
-                       Product p = new Product();
-                       Query<Product> query1 = db.from(p);
-                       Query<Product> query2 = db.from(p);
-
-                       // if you could share alias instances both counts should be equal
-                       long count1 = 0;
-                       try {
-                               count1 = query1.where(p.category).is("Beverages").selectCount();
-                       } catch (IciqlException e) {
-                               assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
-                       }
-                       long count2 = query2.where(p.category).is("Beverages").selectCount();
-
-                       // but they aren't
-                       assertEquals(0, count1);
-                       assertEquals(2, count2);
-                       assertTrue(count1 != count2);
-               } finally {
-                       db.close();
-               }
-       }
-
-       @Test
-       @Ignore
-       public void testConcurrencyFinal() throws Exception {
-               // Multi-threaded example of why aliases can NOT be shared.
-               //
-               // This test looks like it _could_ work and you may find that it _can_
-               // work, but you should also find that it _will_ fail.
-
-               List<Thread> threads = Utils.newArrayList();
-               final AtomicInteger failures = new AtomicInteger(0);
-               final Product p = new Product();
-               for (int i = 0; i < numberOfTests; i++) {
-                       final int testNumber = i;
-                       Thread t = new Thread(new Runnable() {
-                               public void run() {
-                                       try {
-                                               int testCase = testNumber % 10;
-                                               test(testCase, p);
-                                       } catch (AssertionError e) {
-                                               failures.incrementAndGet();
-                                       } catch (IciqlException e) {
-                                               failures.incrementAndGet();
-                                               if (e.getIciqlCode() != IciqlException.CODE_UNMAPPED_FIELD) {
-                                                       System.err.println("UNEXPECTED ERROR in testConcurrencyFinal()");
-                                                       e.printStackTrace();
-                                               }
-                                       }
-                               }
-                       }, "ICIQL-" + i);
-                       t.start();
-                       threads.add(t);
-               }
-
-               // wait till all threads complete
-               for (Thread t : threads) {
-                       t.join();
-               }
-
-               assertTrue("This should fail. Try running a few more times.", failures.get() > 0);
-       }
-
-       @Test
-       @Ignore
-       public void testConcurrencyThreadLocal() throws Exception {
-               List<Thread> threads = Utils.newArrayList();
-               final AtomicInteger failures = new AtomicInteger(0);
-               final ThreadLocal<Product> tl = Utils.newThreadLocal(Product.class);
-               for (int i = 0; i < numberOfTests; i++) {
-                       final int testNumber = i;
-                       Thread t = new Thread(new Runnable() {
-                               public void run() {
-                                       try {
-                                               int testCase = testNumber % 10;
-                                               test(testCase, tl.get());
-                                       } catch (AssertionError e) {
-                                               failures.incrementAndGet();
-                                       } catch (IciqlException e) {
-                                               failures.incrementAndGet();
-                                               if (e.getIciqlCode() != IciqlException.CODE_UNMAPPED_FIELD) {
-                                                       System.err.println("UNEXPECTED ERROR in testConcurrencyThreadLocal()");
-                                                       e.printStackTrace();
-                                               }
-                                       }
-                               }
-                       }, "ICIQL-" + i);
-                       t.start();
-                       threads.add(t);
-               }
-
-               // wait till all threads complete
-               for (Thread t : threads) {
-                       t.join();
-               }
-
-               assertEquals("ThreadLocal should never fail!", 0, failures.get());
-       }
-
-       private void test(int testCase, Product p) throws AssertionError {
-               Db db = IciqlSuite.openCurrentDb();
-               try {
-                       List<Product> list;
-                       switch (testCase) {
-                       case 0:
-                               list = db.from(p).where(p.productName).is("Chai").select();
-                               assertEquals(1, list.size());
-                               assertEquals("Chai", list.get(0).productName);
-                               break;
-                       case 1:
-                               list = db.from(p).where(p.category).is("Condiments").select();
-                               assertEquals(5, list.size());
-                               break;
-                       case 3:
-                               list = db.from(p).where(p.productName).is("Aniseed Syrup").select();
-                               assertEquals(1, list.size());
-                               assertEquals("Aniseed Syrup", list.get(0).productName);
-                               break;
-                       case 4:
-                               list = db.from(p).where(p.productName).like("Chef%").select();
-                               assertEquals(2, list.size());
-                               assertTrue(list.get(0).productName.startsWith("Chef"));
-                               assertTrue(list.get(1).productName.startsWith("Chef"));
-                               break;
-                       case 6:
-                               list = db.from(p).where(p.unitsInStock).exceeds(0).select();
-                               assertEquals(9, list.size());
-                               break;
-                       case 7:
-                               list = db.from(p).where(p.unitsInStock).is(0).select();
-                               assertEquals(1, list.size());
-                               assertEquals("Chef Anton's Gumbo Mix", list.get(0).productName);
-                               break;
-                       case 9:
-                               list = db.from(p).where(p.productId).is(7).select();
-                               assertEquals(1, list.size());
-                               assertTrue(7 == list.get(0).productId);
-                               break;
-                       default:
-                               list = db.from(p).select();
-                               assertEquals(10, list.size());
-                       }
-               } finally {
-                       db.close();
-               }
-       }
+    private int numberOfTests = 800;
+
+    @Before
+    public void setUp() {
+        Db db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
+    }
+
+    @Test
+    public void testAliasSharing() throws Exception {
+        Db db = IciqlSuite.openCurrentDb();
+        try {
+            // Single-threaded example of why aliases can NOT be shared.
+            Product p = new Product();
+            Query<Product> query1 = db.from(p);
+            Query<Product> query2 = db.from(p);
+
+            // if you could share alias instances both counts should be equal
+            long count1 = 0;
+            try {
+                count1 = query1.where(p.category).is("Beverages").selectCount();
+            } catch (IciqlException e) {
+                assertEquals(IciqlException.CODE_UNMAPPED_FIELD, e.getIciqlCode());
+            }
+            long count2 = query2.where(p.category).is("Beverages").selectCount();
+
+            // but they aren't
+            assertEquals(0, count1);
+            assertEquals(2, count2);
+            assertTrue(count1 != count2);
+        } finally {
+            db.close();
+        }
+    }
+
+    @Test
+    @Ignore
+    public void testConcurrencyFinal() throws Exception {
+        // Multi-threaded example of why aliases can NOT be shared.
+        //
+        // This test looks like it _could_ work and you may find that it _can_
+        // work, but you should also find that it _will_ fail.
+
+        List<Thread> threads = Utils.newArrayList();
+        final AtomicInteger failures = new AtomicInteger(0);
+        final Product p = new Product();
+        for (int i = 0; i < numberOfTests; i++) {
+            final int testNumber = i;
+            Thread t = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        int testCase = testNumber % 10;
+                        test(testCase, p);
+                    } catch (AssertionError e) {
+                        failures.incrementAndGet();
+                    } catch (IciqlException e) {
+                        failures.incrementAndGet();
+                        if (e.getIciqlCode() != IciqlException.CODE_UNMAPPED_FIELD) {
+                            System.err.println("UNEXPECTED ERROR in testConcurrencyFinal()");
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }, "ICIQL-" + i);
+            t.start();
+            threads.add(t);
+        }
+
+        // wait till all threads complete
+        for (Thread t : threads) {
+            t.join();
+        }
+
+        assertTrue("This should fail. Try running a few more times.", failures.get() > 0);
+    }
+
+    @Test
+    @Ignore
+    public void testConcurrencyThreadLocal() throws Exception {
+        List<Thread> threads = Utils.newArrayList();
+        final AtomicInteger failures = new AtomicInteger(0);
+        final ThreadLocal<Product> tl = Utils.newThreadLocal(Product.class);
+        for (int i = 0; i < numberOfTests; i++) {
+            final int testNumber = i;
+            Thread t = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        int testCase = testNumber % 10;
+                        test(testCase, tl.get());
+                    } catch (AssertionError e) {
+                        failures.incrementAndGet();
+                    } catch (IciqlException e) {
+                        failures.incrementAndGet();
+                        if (e.getIciqlCode() != IciqlException.CODE_UNMAPPED_FIELD) {
+                            System.err.println("UNEXPECTED ERROR in testConcurrencyThreadLocal()");
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }, "ICIQL-" + i);
+            t.start();
+            threads.add(t);
+        }
+
+        // wait till all threads complete
+        for (Thread t : threads) {
+            t.join();
+        }
+
+        assertEquals("ThreadLocal should never fail!", 0, failures.get());
+    }
+
+    private void test(int testCase, Product p) throws AssertionError {
+        Db db = IciqlSuite.openCurrentDb();
+        try {
+            List<Product> list;
+            switch (testCase) {
+                case 0:
+                    list = db.from(p).where(p.productName).is("Chai").select();
+                    assertEquals(1, list.size());
+                    assertEquals("Chai", list.get(0).productName);
+                    break;
+                case 1:
+                    list = db.from(p).where(p.category).is("Condiments").select();
+                    assertEquals(5, list.size());
+                    break;
+                case 3:
+                    list = db.from(p).where(p.productName).is("Aniseed Syrup").select();
+                    assertEquals(1, list.size());
+                    assertEquals("Aniseed Syrup", list.get(0).productName);
+                    break;
+                case 4:
+                    list = db.from(p).where(p.productName).like("Chef%").select();
+                    assertEquals(2, list.size());
+                    assertTrue(list.get(0).productName.startsWith("Chef"));
+                    assertTrue(list.get(1).productName.startsWith("Chef"));
+                    break;
+                case 6:
+                    list = db.from(p).where(p.unitsInStock).exceeds(0).select();
+                    assertEquals(9, list.size());
+                    break;
+                case 7:
+                    list = db.from(p).where(p.unitsInStock).is(0).select();
+                    assertEquals(1, list.size());
+                    assertEquals("Chef Anton's Gumbo Mix", list.get(0).productName);
+                    break;
+                case 9:
+                    list = db.from(p).where(p.productId).is(7).select();
+                    assertEquals(1, list.size());
+                    assertTrue(7 == list.get(0).productId);
+                    break;
+                default:
+                    list = db.from(p).select();
+                    assertEquals(10, list.size());
+            }
+        } finally {
+            db.close();
+        }
+    }
 }
index 4d2350c779030bb9b587c5dfb75c8ac27d624d06..72de7941d6b0c92dad4b9ceb9b3ab1ab8669f27a 100644 (file)
 
 package com.iciql.test;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.Date;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQTable;
 import com.iciql.Iciql.TypeAdapter;
 import com.iciql.adapter.JavaSerializationTypeAdapter;
 import com.iciql.test.models.SupportedTypes;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Date;
 
 /**
  * Tests insertion and retrieval of a custom data type that is automatically transformed
@@ -40,66 +39,66 @@ import com.iciql.test.models.SupportedTypes;
  */
 public class DataTypeAdapterTest extends Assert {
 
-       private Db db;
+    private Db db;
 
 
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-       }
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+    }
 
-       @After
-       public void tearDown() {
-               db.close();
-       }
+    @After
+    public void tearDown() {
+        db.close();
+    }
 
-       @Test
-       public void testSerializedObjectDataType() {
+    @Test
+    public void testSerializedObjectDataType() {
 
-               SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
-               row.received = new Date();
-               row.obj = SupportedTypes.createList().get(1);
-               db.insert(row);
+        SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
+        row.received = new Date();
+        row.obj = SupportedTypes.createList().get(1);
+        db.insert(row);
 
-               SerializedObjectTypeAdapterTest table = new SerializedObjectTypeAdapterTest();
-               SerializedObjectTypeAdapterTest q1 = db.from(table).selectFirst();
+        SerializedObjectTypeAdapterTest table = new SerializedObjectTypeAdapterTest();
+        SerializedObjectTypeAdapterTest q1 = db.from(table).selectFirst();
 
-               assertNotNull(q1);
-               assertTrue(row.obj.equivalentTo(q1.obj));
+        assertNotNull(q1);
+        assertTrue(row.obj.equivalentTo(q1.obj));
 
-       }
+    }
 
-       @IQTable(name="dataTypeAdapters")
-       public static class SerializedObjectTypeAdapterTest {
+    @IQTable(name = "dataTypeAdapters")
+    public static class SerializedObjectTypeAdapterTest {
 
-               @IQColumn(autoIncrement = true, primaryKey = true)
-               public long id;
+        @IQColumn(autoIncrement = true, primaryKey = true)
+        public long id;
 
-               @IQColumn
-               public java.util.Date received;
+        @IQColumn
+        public java.util.Date received;
 
-               @IQColumn
-               @SupportedTypesAdapter
-               public SupportedTypes obj;
+        @IQColumn
+        @SupportedTypesAdapter
+        public SupportedTypes obj;
 
-       }
+    }
 
-       /**
-        * Maps a SupportedType instance to a BLOB using Java Object serialization.
-        *
-        */
-       public static class SupportedTypesAdapterImpl extends JavaSerializationTypeAdapter<SupportedTypes> {
+    /**
+     * Maps a SupportedType instance to a BLOB using Java Object serialization.
+     */
+    public static class SupportedTypesAdapterImpl extends JavaSerializationTypeAdapter<SupportedTypes> {
 
-               @Override
-               public Class<SupportedTypes> getJavaType() {
-                       return SupportedTypes.class;
-               }
+        @Override
+        public Class<SupportedTypes> getJavaType() {
+            return SupportedTypes.class;
+        }
 
-       }
+    }
 
-       @Retention(RetentionPolicy.RUNTIME)
-       @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
-       @TypeAdapter(SupportedTypesAdapterImpl.class)
-       public @interface SupportedTypesAdapter { }
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
+    @TypeAdapter(SupportedTypesAdapterImpl.class)
+    public @interface SupportedTypesAdapter {
+    }
 
 }
index 1374379e48e527f9b86121ec9044cc75754e64f1..e1b75a3a292aef1fd1cebecff179c2e21d36cd5e 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.util.List;\r
-\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.DbInspector;\r
 import com.iciql.ValidationRemark;\r
 import com.iciql.test.models.DefaultValuesModel;\r
+import org.junit.Test;\r
+\r
+import java.util.List;\r
+\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * Tests default object values.\r
  */\r
 public class DefaultValuesTest {\r
 \r
-       @Test\r
-       public void testDefaultObjectValues() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               // insert random model\r
-               DefaultValuesModel model = new DefaultValuesModel();\r
-               db.insert(model);\r
-\r
-               DefaultValuesModel v = new DefaultValuesModel();\r
-\r
-               // retrieve model and compare\r
-               DefaultValuesModel retrievedModel = db.from(v).selectFirst();\r
-               assertTrue(model.myInteger.equals(retrievedModel.myInteger));\r
-               assertTrue(model.myDate.equals(retrievedModel.myDate));\r
-               assertTrue(model.myEnumIdTree.equals(retrievedModel.myEnumIdTree));\r
-               assertTrue(model.myNameTree.equals(retrievedModel.myNameTree));\r
-               assertTrue(model.myOrdinalTree.equals(retrievedModel.myOrdinalTree));\r
-               assertTrue(retrievedModel.myNullTree == null);\r
-\r
-               DbInspector inspector = new DbInspector(db);\r
-               List<ValidationRemark> remarks = inspector.validateModel(model, false);\r
-               db.close();\r
-               for (ValidationRemark remark : remarks) {\r
-                       System.out.println(remark.toString());\r
-               }\r
-       }\r
+    @Test\r
+    public void testDefaultObjectValues() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        // insert random model\r
+        DefaultValuesModel model = new DefaultValuesModel();\r
+        db.insert(model);\r
+\r
+        DefaultValuesModel v = new DefaultValuesModel();\r
+\r
+        // retrieve model and compare\r
+        DefaultValuesModel retrievedModel = db.from(v).selectFirst();\r
+        assertTrue(model.myInteger.equals(retrievedModel.myInteger));\r
+        assertTrue(model.myDate.equals(retrievedModel.myDate));\r
+        assertTrue(model.myEnumIdTree.equals(retrievedModel.myEnumIdTree));\r
+        assertTrue(model.myNameTree.equals(retrievedModel.myNameTree));\r
+        assertTrue(model.myOrdinalTree.equals(retrievedModel.myOrdinalTree));\r
+        assertTrue(retrievedModel.myNullTree == null);\r
+\r
+        DbInspector inspector = new DbInspector(db);\r
+        List<ValidationRemark> remarks = inspector.validateModel(model, false);\r
+        db.close();\r
+        for (ValidationRemark remark : remarks) {\r
+            System.out.println(remark.toString());\r
+        }\r
+    }\r
 }\r
index 8e1f90e29eab0354bc454048f12ed1369eed63bc..e0f307d1f4a6394e95d93c153a673636bb84e41f 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.util.List;\r
-\r
-import org.junit.After;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.IciqlException;\r
 import com.iciql.test.models.EnumModels;\r
@@ -33,123 +24,131 @@ import com.iciql.test.models.EnumModels.EnumOrdinalModel;
 import com.iciql.test.models.EnumModels.EnumStringModel;\r
 import com.iciql.test.models.EnumModels.Genus;\r
 import com.iciql.test.models.EnumModels.Tree;\r
+import org.junit.After;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+\r
+import java.util.List;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * Tests enum support.\r
  */\r
 public class EnumsTest {\r
 \r
-       private Db db;\r
-\r
-       @Before\r
-       public void setUp() {\r
-               db = IciqlSuite.openNewDb();\r
-               db.insertAll(EnumIdModel.createList());\r
-               db.insertAll(EnumOrdinalModel.createList());\r
-               db.insertAll(EnumStringModel.createList());\r
-       }\r
-\r
-       @After\r
-       public void tearDown() {\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testEnumQueries() {\r
-               testIntEnums(new EnumIdModel());\r
-               testIntEnums(new EnumOrdinalModel());\r
-               testStringEnums(new EnumStringModel());\r
-               testStringEnumIds(new EnumStringModel());\r
-       }\r
-\r
-       private void testIntEnums(EnumModels e) {\r
-               // ensure all records inserted\r
-               long count = db.from(e).selectCount();\r
-               assertEquals(5, count);\r
-\r
-               // special case:\r
-               // value is first enum constant which is also the alias object.\r
-               // the first enum constant is used as the alias because we can not\r
-               // instantiate an enum reflectively.\r
-               EnumModels firstEnumValue = db.from(e).where(e.tree()).is(Tree.PINE).selectFirst();\r
-               assertEquals(Tree.PINE, firstEnumValue.tree());\r
-\r
-               EnumModels model = db.from(e).where(e.tree()).is(Tree.WALNUT).selectFirst();\r
-\r
-               assertEquals(400, model.id.intValue());\r
-               assertEquals(Tree.WALNUT, model.tree());\r
-\r
-               List<EnumModels> list = db.from(e).where(e.tree()).atLeast(Tree.BIRCH).select();\r
-               assertEquals(3, list.size());\r
-\r
-               // between is an int compare\r
-               list = db.from(e).where(e.tree()).between(Tree.BIRCH).and(Tree.WALNUT).select();\r
-               assertEquals(2, list.size());\r
-\r
-       }\r
-\r
-       private void testStringEnums(EnumModels e) {\r
-               // ensure all records inserted\r
-               long count = db.from(e).selectCount();\r
-               assertEquals(5, count);\r
-\r
-               // special case:\r
-               // value is first enum constant which is also the alias object.\r
-               // the first enum constant is used as the alias because we can not\r
-               // instantiate an enum reflectively.\r
-               EnumModels firstEnumValue = db.from(e).where(e.tree()).is(Tree.PINE).selectFirst();\r
-               assertEquals(Tree.PINE, firstEnumValue.tree());\r
-\r
-               EnumModels model = db.from(e).where(e.tree()).is(Tree.WALNUT).selectFirst();\r
-\r
-               assertEquals(400, model.id.intValue());\r
-               assertEquals(Tree.WALNUT, model.tree());\r
-\r
-               List<EnumModels> list = db.from(e).where(e.tree()).isNot(Tree.BIRCH).select();\r
-               assertEquals(count - 1, list.size());\r
-\r
-               // between is a string compare\r
-               list = db.from(e).where(e.tree()).between(Tree.MAPLE).and(Tree.PINE).select();\r
-               assertEquals(3, list.size());\r
-       }\r
-\r
-       private void testStringEnumIds(EnumModels e) {\r
-               // ensure all records inserted\r
-               long count = db.from(e).selectCount();\r
-               assertEquals(5, count);\r
-\r
-               // special case:\r
-               // value is first enum constant which is also the alias object.\r
-               // the first enum constant is used as the alias because we can not\r
-               // instantiate an enum reflectively.\r
-               EnumModels firstEnumValue = db.from(e).where(e.genus()).is(Genus.PINUS).selectFirst();\r
-               assertEquals(Tree.PINE, firstEnumValue.tree());\r
-               assertEquals(Genus.PINUS, firstEnumValue.genus());\r
-\r
-               EnumModels model = db.from(e).where(e.genus()).is(Genus.JUGLANS).selectFirst();\r
-\r
-               assertEquals(400, model.id.intValue());\r
-               assertEquals(Tree.WALNUT, model.tree());\r
-               assertEquals(Genus.JUGLANS, model.genus());\r
-\r
-               List<EnumModels> list = db.from(e).where(e.genus()).isNot(Genus.BETULA).select();\r
-               assertEquals(count - 1, list.size());\r
-\r
-       }\r
-\r
-       @Test\r
-       public void testMultipleEnumInstances() {\r
-               BadEnums b = new BadEnums();\r
-               try {\r
-                       db.from(b).where(b.tree1).is(Tree.BIRCH).and (b.tree2).is(Tree.MAPLE).getSQL();\r
-                       assertTrue("Failed to detect multiple Tree fields?!", false);\r
-               } catch (IciqlException e) {\r
-                       assertTrue(e.getMessage(), e.getMessage().startsWith("Can not explicitly reference Tree"));\r
-               }\r
-       }\r
-\r
-       public static class BadEnums {\r
-               Tree tree1 = Tree.BIRCH;\r
-               Tree tree2 = Tree.MAPLE;\r
-       }\r
+    private Db db;\r
+\r
+    @Before\r
+    public void setUp() {\r
+        db = IciqlSuite.openNewDb();\r
+        db.insertAll(EnumIdModel.createList());\r
+        db.insertAll(EnumOrdinalModel.createList());\r
+        db.insertAll(EnumStringModel.createList());\r
+    }\r
+\r
+    @After\r
+    public void tearDown() {\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testEnumQueries() {\r
+        testIntEnums(new EnumIdModel());\r
+        testIntEnums(new EnumOrdinalModel());\r
+        testStringEnums(new EnumStringModel());\r
+        testStringEnumIds(new EnumStringModel());\r
+    }\r
+\r
+    private void testIntEnums(EnumModels e) {\r
+        // ensure all records inserted\r
+        long count = db.from(e).selectCount();\r
+        assertEquals(5, count);\r
+\r
+        // special case:\r
+        // value is first enum constant which is also the alias object.\r
+        // the first enum constant is used as the alias because we can not\r
+        // instantiate an enum reflectively.\r
+        EnumModels firstEnumValue = db.from(e).where(e.tree()).is(Tree.PINE).selectFirst();\r
+        assertEquals(Tree.PINE, firstEnumValue.tree());\r
+\r
+        EnumModels model = db.from(e).where(e.tree()).is(Tree.WALNUT).selectFirst();\r
+\r
+        assertEquals(400, model.id.intValue());\r
+        assertEquals(Tree.WALNUT, model.tree());\r
+\r
+        List<EnumModels> list = db.from(e).where(e.tree()).atLeast(Tree.BIRCH).select();\r
+        assertEquals(3, list.size());\r
+\r
+        // between is an int compare\r
+        list = db.from(e).where(e.tree()).between(Tree.BIRCH).and(Tree.WALNUT).select();\r
+        assertEquals(2, list.size());\r
+\r
+    }\r
+\r
+    private void testStringEnums(EnumModels e) {\r
+        // ensure all records inserted\r
+        long count = db.from(e).selectCount();\r
+        assertEquals(5, count);\r
+\r
+        // special case:\r
+        // value is first enum constant which is also the alias object.\r
+        // the first enum constant is used as the alias because we can not\r
+        // instantiate an enum reflectively.\r
+        EnumModels firstEnumValue = db.from(e).where(e.tree()).is(Tree.PINE).selectFirst();\r
+        assertEquals(Tree.PINE, firstEnumValue.tree());\r
+\r
+        EnumModels model = db.from(e).where(e.tree()).is(Tree.WALNUT).selectFirst();\r
+\r
+        assertEquals(400, model.id.intValue());\r
+        assertEquals(Tree.WALNUT, model.tree());\r
+\r
+        List<EnumModels> list = db.from(e).where(e.tree()).isNot(Tree.BIRCH).select();\r
+        assertEquals(count - 1, list.size());\r
+\r
+        // between is a string compare\r
+        list = db.from(e).where(e.tree()).between(Tree.MAPLE).and(Tree.PINE).select();\r
+        assertEquals(3, list.size());\r
+    }\r
+\r
+    private void testStringEnumIds(EnumModels e) {\r
+        // ensure all records inserted\r
+        long count = db.from(e).selectCount();\r
+        assertEquals(5, count);\r
+\r
+        // special case:\r
+        // value is first enum constant which is also the alias object.\r
+        // the first enum constant is used as the alias because we can not\r
+        // instantiate an enum reflectively.\r
+        EnumModels firstEnumValue = db.from(e).where(e.genus()).is(Genus.PINUS).selectFirst();\r
+        assertEquals(Tree.PINE, firstEnumValue.tree());\r
+        assertEquals(Genus.PINUS, firstEnumValue.genus());\r
+\r
+        EnumModels model = db.from(e).where(e.genus()).is(Genus.JUGLANS).selectFirst();\r
+\r
+        assertEquals(400, model.id.intValue());\r
+        assertEquals(Tree.WALNUT, model.tree());\r
+        assertEquals(Genus.JUGLANS, model.genus());\r
+\r
+        List<EnumModels> list = db.from(e).where(e.genus()).isNot(Genus.BETULA).select();\r
+        assertEquals(count - 1, list.size());\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testMultipleEnumInstances() {\r
+        BadEnums b = new BadEnums();\r
+        try {\r
+            db.from(b).where(b.tree1).is(Tree.BIRCH).and(b.tree2).is(Tree.MAPLE).getSQL();\r
+            assertTrue("Failed to detect multiple Tree fields?!", false);\r
+        } catch (IciqlException e) {\r
+            assertTrue(e.getMessage(), e.getMessage().startsWith("Can not explicitly reference Tree"));\r
+        }\r
+    }\r
+\r
+    public static class BadEnums {\r
+        Tree tree1 = Tree.BIRCH;\r
+        Tree tree2 = Tree.MAPLE;\r
+    }\r
 }\r
index 12d2a07611bc327f9527112966c5414183f1ec59..e1c8ffa26348ac2d51a1b697e9def84a342d74eb 100644 (file)
  */\r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertTrue;\r
-\r
+import com.iciql.Db;\r
+import com.iciql.IciqlException;\r
+import com.iciql.test.models.CategoryAnnotationOnly;\r
+import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey;\r
 import org.junit.After;\r
 import org.junit.Before;\r
 import org.junit.Ignore;\r
 import org.junit.Test;\r
 \r
-import com.iciql.Db;\r
-import com.iciql.IciqlException;\r
-import com.iciql.test.models.CategoryAnnotationOnly;\r
-import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * Tests of Foreign Keys.\r
  */\r
 public class ForeignKeyTest {\r
 \r
-       /**\r
-        * This object represents a database (actually a connection to the\r
-        * database).\r
-        */\r
+    /**\r
+     * This object represents a database (actually a connection to the\r
+     * database).\r
+     */\r
+\r
+    private Db db;\r
+\r
+    @Before\r
+    public void setUp() {\r
+        db = IciqlSuite.openNewDb();\r
+        db.insertAll(CategoryAnnotationOnly.getList());\r
+        db.insertAll(ProductAnnotationOnlyWithForeignKey.getList());\r
+    }\r
+\r
+    @After\r
+    public void tearDown() {\r
+        db.dropTable(ProductAnnotationOnlyWithForeignKey.class);\r
+        db.dropTable(CategoryAnnotationOnly.class);\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testForeignKeyWithOnDeleteCascade() {\r
+        ProductAnnotationOnlyWithForeignKey p = new ProductAnnotationOnlyWithForeignKey();\r
+        long count1 = db.from(p).selectCount();\r
 \r
-       private Db db;\r
+        // should remove 2 associated products\r
+        CategoryAnnotationOnly c = new CategoryAnnotationOnly();\r
+        db.from(c).where(c.categoryId).is(1L).delete();\r
 \r
-       @Before\r
-       public void setUp() {\r
-               db = IciqlSuite.openNewDb();\r
-               db.insertAll(CategoryAnnotationOnly.getList());\r
-               db.insertAll(ProductAnnotationOnlyWithForeignKey.getList());\r
-       }\r
+        long count2 = db.from(p).selectCount();\r
 \r
-       @After\r
-       public void tearDown() {\r
-               db.dropTable(ProductAnnotationOnlyWithForeignKey.class);\r
-               db.dropTable(CategoryAnnotationOnly.class);\r
-               db.close();\r
-       }\r
+        assertEquals(count1, count2 + 2L);\r
+    }\r
 \r
-       @Test\r
-       public void testForeignKeyWithOnDeleteCascade() {\r
-               ProductAnnotationOnlyWithForeignKey p = new ProductAnnotationOnlyWithForeignKey();\r
-               long count1 = db.from(p).selectCount();\r
-               \r
-               // should remove 2 associated products\r
-               CategoryAnnotationOnly c = new CategoryAnnotationOnly();\r
-               db.from(c).where(c.categoryId).is(1L).delete();\r
-               \r
-               long count2 = db.from(p).selectCount();\r
-               \r
-               assertEquals(count1, count2 + 2L);\r
-       }\r
-       \r
-       @Test\r
-       @Ignore\r
-       public void testForeignKeyDropReferenceTable() {\r
-               try {\r
-                       db.dropTable(CategoryAnnotationOnly.class);\r
-                       assertTrue("Should not be able to drop reference table!", false);\r
-               } catch (IciqlException e) {\r
-                       assertEquals(e.getMessage(), IciqlException.CODE_CONSTRAINT_VIOLATION, e.getIciqlCode());\r
-               }\r
-       }\r
+    @Test\r
+    @Ignore\r
+    public void testForeignKeyDropReferenceTable() {\r
+        try {\r
+            db.dropTable(CategoryAnnotationOnly.class);\r
+            assertTrue("Should not be able to drop reference table!", false);\r
+        } catch (IciqlException e) {\r
+            assertEquals(e.getMessage(), IciqlException.CODE_CONSTRAINT_VIOLATION, e.getIciqlCode());\r
+        }\r
+    }\r
 \r
 }\r
index 37c534ce853e5bfbf16d9949ab45ddf7caaea10b..df5e4d668f767d4971595d486b426da13733df7c 100644 (file)
  */
 package com.iciql.test;
 
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.sql.SQLException;
-import java.text.DecimalFormat;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.dbcp.ConnectionFactory;
-import org.apache.commons.dbcp.DriverManagerConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDataSource;
-import org.apache.commons.pool.impl.GenericObjectPool;
-import org.apache.derby.drda.NetworkServerControl;
-import org.hsqldb.persist.HsqlProperties;
-import org.junit.Assert;
-import org.junit.runner.JUnitCore;
-import org.junit.runner.Result;
-import org.junit.runner.RunWith;
-import org.junit.runner.notification.Failure;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
 import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.ParameterException;
@@ -77,10 +50,36 @@ import com.iciql.util.IciqlLogger.IciqlListener;
 import com.iciql.util.IciqlLogger.StatementType;
 import com.iciql.util.StringUtils;
 import com.iciql.util.Utils;
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.derby.drda.NetworkServerControl;
+import org.hsqldb.persist.HsqlProperties;
+import org.junit.Assert;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.Failure;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.sql.SQLException;
+import java.text.DecimalFormat;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 
 /**
  * JUnit 4 iciql test suite.
- *
+ * <p>
  * By default this test suite will run against the H2 database. You can change
  * this by switching the DEFAULT_TEST_DB value.
  * <p>
@@ -90,614 +89,613 @@ import com.iciql.util.Utils;
  * NOTE: If you want to test against MySQL or PostgreSQL you must create an
  * "iciql" database and allow user "sa" password "sa" complete control of that
  * database.
- *
  */
 @RunWith(Suite.class)
-@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
-               ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class, OneOfTest.class,
-               RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UpgradesTest.class, JoinTest.class,
-               UUIDTest.class, ViewsTest.class, ForeignKeyTest.class, TransactionTest.class, NestedConditionsTest.class,
-               DataTypeAdapterTest.class, ProductDaoTest.class })
+@SuiteClasses({AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
+        ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class, OneOfTest.class,
+        RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UpgradesTest.class, JoinTest.class,
+        UUIDTest.class, ViewsTest.class, ForeignKeyTest.class, TransactionTest.class, NestedConditionsTest.class,
+        DataTypeAdapterTest.class, ProductDaoTest.class})
 public class IciqlSuite {
-       private final static File baseFolder = new File(System.getProperty("user.dir"), "/testdbs");
-       private static final TestDb[] TEST_DBS = {
-                       new TestDb("H2", "memory", "jdbc:h2:mem:iciql"),
-                       new TestDb("H2", "file", "jdbc:h2:file:"
-                                       + new File(baseFolder, "/h2/iciql").getAbsolutePath()),
-                       new TestDb("H2", "tcp", "jdbc:h2:tcp://localhost/"
-                                       + new File(baseFolder, "/h2tcp/iciql").getAbsolutePath()),
-                       new TestDb("HSQL", "memory", "jdbc:hsqldb:mem:iciql"),
-                       new TestDb("HSQL", "file", "jdbc:hsqldb:file:testdbs/hsql/iciql"),
-                       new TestDb("HSQL", "tcp", "jdbc:hsqldb:hsql://localhost/iciql"),
-                       new TestDb("Derby", "memory", "jdbc:derby:memory:iciql;create=true"),
-                       new TestDb("Derby", "file", "jdbc:derby:directory:testdbs/derby/iciql;create=true"),
-                       new TestDb("Derby", "tcp", "jdbc:derby://localhost:1527/testdbs/derby/iciql;create=true", "sa", "sa"),
-                       new TestDb("MySQL", "tcp", "jdbc:mysql://localhost:3306/iciql", "sa", "sa"),
-                       new TestDb("PostgreSQL", "tcp", "jdbc:postgresql://localhost:5432/iciql", "sa", "sa"),
-
-                       //
-                       // SQLite Memory
-                       //
-                       new TestDb("SQLite", "memory", "jdbc:sqlite:file::memory:?cache=shared&foreign_keys=ON"),
-
-                       //
-                       // SQLite DELETE rollback journal (default)
-                       //
-                       new TestDb("SQLite", "delete,full_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=DELETE&synchronous=FULL"),
-
-                       new TestDb("SQLite", "delete,norm_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=DELETE&synchronous=NORMAL"),
-
-                       new TestDb("SQLite", "delete,no_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=DELETE&synchronous=OFF"),
-
-                       //
-                       // SQLite WAL
-                       //
-                       new TestDb("SQLite", "wal,full_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=WAL&synchronous=FULL"),
-
-                       new TestDb("SQLite", "wal,norm_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=WAL&synchronous=NORMAL"),
-
-                       new TestDb("SQLite", "wal,no_sync", "jdbc:sqlite:"
-                                       + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
-                                       + "?foreign_keys=ON&journal_mode=WAL&synchronous=OFF"),
-
-                       };
-
-       private static final TestDb DEFAULT_TEST_DB = TEST_DBS[3];
-
-       private static final PrintStream ERR = System.err;
-
-       private static PrintStream out = System.out;
-
-       private static Map<String, PoolableConnectionFactory> connectionFactories = Utils
-                       .newSynchronizedHashMap();
-
-       private static Map<String, PoolingDataSource> dataSources = Utils.newSynchronizedHashMap();
-
-       public static void assertStartsWith(String value, String startsWith) {
-               Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", startsWith, value),
-                               value.startsWith(startsWith));
-       }
-
-       public static void assertEqualsIgnoreCase(String expected, String actual) {
-               Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", expected, actual),
-                               expected.equalsIgnoreCase(actual));
-       }
-
-       public static boolean equivalentTo(double expected, double actual) {
-               if (Double.compare(expected, actual) == 0) {
-                       return true;
-               }
-               return Math.abs(expected - actual) <= 0.000001d;
-       }
-
-       public static Db openNewDb() {
-               return openNewDb(Mode.PROD);
-       }
-
-       /**
-        * Open a new Db object. All connections are cached and re-used to eliminate
-        * embedded database startup costs.
-        *
-        * @param mode
-        * @return a fresh Db object
-        */
-       public static Db openNewDb(Mode mode) {
-               String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
-               String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
-               String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
-
-               Db db = null;
-               PoolingDataSource dataSource = dataSources.get(testUrl);
-               if (dataSource == null) {
-                       ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(testUrl, testUser,
-                                       testPassword);
-                       GenericObjectPool pool = new GenericObjectPool();
-                       pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
-                       PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, pool, null,
-                                       null, false, true);
-                       dataSource = new PoolingDataSource(pool);
-                       dataSources.put(testUrl, dataSource);
-                       connectionFactories.put(testUrl, factory);
-               }
-               db = Db.open(dataSource, mode);
-
-               // drop views
-               db.dropView(ProductView.class);
-               db.dropView(ProductViewInherited.class);
-               db.dropView(ProductViewFromQuery.class);
-               db.dropView(ProductViewInheritedComplex.class);
-
-               // 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);
-               db.dropTable(JoinTest.UserId.class);
-               db.dropTable(JoinTest.UserNote.class);
-               db.dropTable(EnumsTest.BadEnums.class);
-               db.dropTable(MultipleBoolsModel.class);
-               db.dropTable(ProductAnnotationOnlyWithForeignKey.class);
-               db.dropTable(CategoryAnnotationOnly.class);
-               db.dropTable(SerializedObjectTypeAdapterTest.class);
-
-               return db;
-       }
-
-       /**
-        * Open the current database.
-        *
-        * @return the current database
-        */
-       public static Db openCurrentDb() {
-               String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
-               String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
-               String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
-               return Db.open(testUrl, testUser, testPassword);
-       }
-
-       /**
-        * Returns the name of the underlying database engine for the Db object.
-        *
-        * @param db
-        * @return the database engine name
-        */
-       public static String getDatabaseEngineName(Db db) {
-               String database = "";
-               try {
-                       database = db.getConnection().getMetaData().getDatabaseProductName();
-               } catch (SQLException s) {
-               }
-               return database;
-       }
-
-       /**
-        * Returns true if the underlying database engine is Derby.
-        *
-        * @param db
-        * @return true if underlying database engine is Derby
-        */
-       public static boolean isDerby(Db db) {
-               return IciqlSuite.getDatabaseEngineName(db).equals("Apache Derby");
-       }
-
-       /**
-        * Returns true if the underlying database engine is H2.
-        *
-        * @param db
-        * @return true if underlying database engine is H2
-        */
-       public static boolean isH2(Db db) {
-               return IciqlSuite.getDatabaseEngineName(db).equals("H2");
-       }
-
-       /**
-        * 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");
-       }
-
-       /**
-        * Returns true if the underlying database engine is SQLite.
-        *
-        * @param db
-        * @return true if underlying database engine is SQLite
-        */
-       public static boolean isSQLite(Db db) {
-               return IciqlSuite.getDatabaseEngineName(db).equals("SQLite");
-       }
-
-       /**
-        * Gets the default schema of the underlying database engine.
-        *
-        * @param db
-        * @return the default schema
-        */
-       public static String getDefaultSchema(Db db) {
-               if (isDerby(db)) {
-                       // Derby sets default schema name to username
-                       return "SA";
-               } else if (isMySQL(db)) {
-                       // MySQL does not have schemas
-                       return null;
-               } else if (isSQLite(db)) {
-                       // SQLite does not have schemas
-                       return null;
-               }
-
-               return "PUBLIC";
-       }
-
-       /**
-        * Main entry point for the test suite. Executing this method will run the
-        * test suite on all registered databases.
-        *
-        * @param args
-        * @throws Exception
-        */
-       public static void main(String... args) throws Exception {
-               Params params = new Params();
-               JCommander jc = new JCommander(params);
-               try {
-                       jc.parse(args);
-               } catch (ParameterException t) {
-                       usage(jc, t);
-               }
-
-               // Replace System.out with a file
-               if (!StringUtils.isNullOrEmpty(params.dbPerformanceFile)) {
-                       out = new PrintStream(params.dbPerformanceFile);
-                       System.setErr(out);
-               }
-
-               deleteRecursively(baseFolder);
-               new File(baseFolder, "/sqlite").mkdirs();
-
-               // Start the HSQL, H2, and Derby servers in-process
-               org.hsqldb.Server hsql = startHSQL();
-               org.h2.tools.Server h2 = startH2();
-               NetworkServerControl derby = startDerby();
-
-               // Statement logging
-               final FileWriter statementWriter;
-               if (StringUtils.isNullOrEmpty(params.sqlStatementsFile)) {
-                       statementWriter = null;
-               } else {
-                       statementWriter = new FileWriter(params.sqlStatementsFile);
-               }
-               IciqlListener statementListener = new IciqlListener() {
-                       @Override
-                       public void logIciql(StatementType type, String statement) {
-                               if (statementWriter == null) {
-                                       return;
-                               }
-                               try {
-                                       statementWriter.append(statement);
-                                       statementWriter.append('\n');
-                               } catch (IOException e) {
-                                       e.printStackTrace();
-                               }
-                       }
-               };
-               IciqlLogger.registerListener(statementListener);
-
-               SuiteClasses suiteClasses = IciqlSuite.class.getAnnotation(SuiteClasses.class);
-               long quickestDatabase = Long.MAX_VALUE;
-               String dividerMajor = buildDivider('*', 79);
-               String dividerMinor = buildDivider('-', 79);
-
-               // Header
-               out.println(dividerMajor);
-               out.println(MessageFormat.format("{0} {1} ({2}) testing {3} database configurations", Constants.NAME,
-                               Constants.getVersion(), Constants.getBuildDate(), TEST_DBS.length));
-               out.println(dividerMajor);
-               out.println();
-
-               showProperty("java.vendor");
-               showProperty("java.runtime.version");
-               showProperty("java.vm.name");
-               showProperty("os.name");
-               showProperty("os.version");
-               showProperty("os.arch");
-               showProperty("available processors", "" + Runtime.getRuntime().availableProcessors());
-               showProperty(
-                               "available memory",
-                               MessageFormat.format("{0,number,0.0} GB", ((double) Runtime.getRuntime().maxMemory())
-                                               / (1024 * 1024)));
-               out.println();
-
-               // Test a database
-               long lastCount = 0;
-               for (TestDb testDb : TEST_DBS) {
-                       out.println(dividerMinor);
-                       out.println("Testing " + testDb.describeDatabase());
-                       out.println("        " + testDb.url);
-                       out.println(dividerMinor);
-
-                       // inject a database section delimiter in the statement log
-                       if (statementWriter != null) {
-                               statementWriter.append("\n\n");
-                               statementWriter.append("# ").append(dividerMinor).append('\n');
-                               statementWriter.append("# ").append("Testing " + testDb.describeDatabase()).append('\n');
-                               statementWriter.append("# ").append(dividerMinor).append('\n');
-                               statementWriter.append("\n\n");
-                       }
-
-                       if (testDb.getVersion().equals("OFFLINE")) {
-                               // Database not available
-                               out.println("Skipping.  Could not find " + testDb.url);
-                               out.println();
-                       } else {
-                               // Setup system properties
-                               System.setProperty("iciql.url", testDb.url);
-                               System.setProperty("iciql.user", testDb.username);
-                               System.setProperty("iciql.password", testDb.password);
-
-                               // Test database
-                               Result result = JUnitCore.runClasses(suiteClasses.value());
-
-                               // Report results
-                               testDb.runtime = result.getRunTime();
-                               if (testDb.runtime < quickestDatabase) {
-                                       quickestDatabase = testDb.runtime;
-                               }
-                               testDb.statements = IciqlLogger.getTotalCount() - lastCount;
-                               // reset total count for next database
-                               lastCount = IciqlLogger.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.getVersion(), Constants.getBuildDate()));
-
-               StringBuilder compressedSystem = new StringBuilder();
-               compressedSystem.append("      on ");
-               compressedSystem.append(System.getProperty("java.vendor"));
-               compressedSystem.append(' ');
-               compressedSystem.append(System.getProperty("java.runtime.version"));
-               compressedSystem.append(", ");
-               compressedSystem.append(System.getProperty("os.name"));
-               compressedSystem.append(' ');
-               compressedSystem.append(System.getProperty("os.version"));
-               compressedSystem.append(", ");
-               compressedSystem.append(System.getProperty("os.arch"));
-               out.println(compressedSystem.toString());
-
-               out.println(dividerMajor);
-               List<TestDb> dbs = Arrays.asList(TEST_DBS);
-               Collections.sort(dbs);
-
-               out.println(MessageFormat.format("{0} {1} {2} {3} {4}",
-                               StringUtils.pad("Name", 11, " ", true),
-                               StringUtils.pad("Config", 16, " ", true),
-                               StringUtils.pad("Version", 25, " ", true),
-                               StringUtils.pad("Stats/sec", 10, " ", true),
-                               "Runtime"));
-               out.println(dividerMinor);
-               for (TestDb testDb : dbs) {
-                       DecimalFormat df = new DecimalFormat("0.0");
-                       out.println(MessageFormat.format("{0} {1} {2} {3} {4}s  ({5,number,0.0}x)",
-                                       StringUtils.pad(testDb.name, 11, " ", true),
-                                       StringUtils.pad(testDb.config, 16, " ", true),
-                                       StringUtils.pad(testDb.getVersion(), 23, " ", true),
-                                       StringUtils.pad("" + testDb.getStatementRate(), 7, " ", false),
-                                       StringUtils.pad(df.format(testDb.getRuntime()), 8, " ", false),
-                                       ((double) testDb.runtime) / quickestDatabase));
-               }
-               out.println(dividerMinor);
-
-               // cleanup
-               for (PoolableConnectionFactory factory : connectionFactories.values()) {
-                       factory.getPool().close();
-               }
-               IciqlLogger.unregisterListener(statementListener);
-               out.close();
-               System.setErr(ERR);
-               if (statementWriter != null) {
-                       statementWriter.close();
-               }
-               hsql.stop();
-               h2.stop();
-               derby.shutdown();
-               System.exit(0);
-       }
-
-       private static void showProperty(String name) {
-               showProperty(name, System.getProperty(name));
-       }
-
-       private static void showProperty(String name, String value) {
-               out.print(' ');
-               out.print(StringUtils.pad(name, 25, " ", true));
-               out.println(value);
-       }
-
-       private static void usage(JCommander jc, ParameterException t) {
-               System.out.println(Constants.NAME + " test suite v" + Constants.getVersion());
-               System.out.println();
-               if (t != null) {
-                       System.out.println(t.getMessage());
-                       System.out.println();
-               }
-               if (jc != null) {
-                       jc.usage();
-               }
-               System.exit(0);
-       }
-
-       private static String buildDivider(char c, int length) {
-               StringBuilder sb = new StringBuilder();
-               for (int i = 0; i < length; i++) {
-                       sb.append(c);
-               }
-               return sb.toString();
-       }
-
-       private static void deleteRecursively(File f) {
-               if (f.isDirectory()) {
-                       for (File file : f.listFiles()) {
-                               if (file.isDirectory()) {
-                                       deleteRecursively(file);
-                               }
-                               file.delete();
-                       }
-               }
-               f.delete();
-       }
-
-       /**
-        * Start an HSQL tcp server.
-        *
-        * @return an HSQL server instance
-        * @throws Exception
-        */
-       private static org.hsqldb.Server startHSQL() throws Exception {
-               HsqlProperties p = new HsqlProperties();
-               String db = new File(System.getProperty("user.dir")).getAbsolutePath() + "/testdbs/hsqltcp/iciql";
-               p.setProperty("server.database.0", "file:" + db);
-               p.setProperty("server.dbname.0", "iciql");
-               // set up the rest of properties
-
-               // alternative to the above is
-               org.hsqldb.Server server = new org.hsqldb.Server();
-               server.setProperties(p);
-               server.setLogWriter(null);
-               server.setErrWriter(null);
-               server.start();
-               return server;
-       }
-
-       /**
-        * Start the H2 tcp server.
-        *
-        * @return an H2 server instance
-        * @throws Exception
-        */
-       private static org.h2.tools.Server startH2() throws Exception {
-               org.h2.tools.Server server = org.h2.tools.Server.createTcpServer();
-               server.start();
-               return server;
-       }
-
-       /**
-        * Start the Derby tcp server.
-        *
-        * @return an Derby server instance
-        * @throws Exception
-        */
-       private static NetworkServerControl startDerby() throws Exception {
-               NetworkServerControl serverControl = new NetworkServerControl();
-               serverControl.start(null);
-               return serverControl;
-       }
-
-       /**
-        * Represents a test database url.
-        */
-       private static class TestDb implements Comparable<TestDb> {
-               final String name;
-               final String config;
-               final String url;
-               final String username;
-               final String password;
-               String version;
-               long runtime;
-               long statements;
-
-               TestDb(String name, String config, String url) {
-                       this(name, config, url, "sa", "");
-               }
-
-               TestDb(String name, String config, String url, String username, String password) {
-                       this.name = name;
-                       this.config = config;
-                       this.url = url;
-                       this.username = username;
-                       this.password = password;
-               }
-
-               double getRuntime() {
-                       return runtime / 1000d;
-               }
-
-               int getStatementRate() {
-                       return Double.valueOf((statements) / (runtime / 1000d)).intValue();
-               }
-
-               String describeDatabase() {
-                       StringBuilder sb = new StringBuilder(name);
-                       sb.append(" ");
-                       sb.append(getVersion());
-                       return sb.toString();
-               }
-
-               String getVersion() {
-                       if (version == null) {
-                               try {
-                                       Db db = Db.open(url, username, password);
-                                       version = db.getConnection().getMetaData().getDatabaseProductVersion();
-                                       db.close();
-                                       return version;
-                               } catch (Throwable t) {
-                                       version = "OFFLINE";
-                               }
-                       }
-                       return version;
-               }
-
-               @Override
-               public int compareTo(TestDb o) {
-                       if (runtime == 0) {
-                               return 1;
-                       }
-                       if (o.runtime == 0) {
-                               return -1;
-                       }
-                       int r1 = getStatementRate();
-                       int r2 = o.getStatementRate();
-                       if (r1 == r2) {
-                               return 0;
-                       }
-                       if (r1 < r2) {
-                               return 1;
-                       }
-                       return -1;
-               }
-       }
-
-       /**
-        * Command-line parameters for TestSuite.
-        */
-       @Parameters(separators = " ")
-       private static class Params {
-
-               @Parameter(names = { "--dbFile" }, description = "Database performance results text file", required = false)
-               public String dbPerformanceFile;
-
-               @Parameter(names = { "--sqlFile" }, description = "SQL statements log file", required = false)
-               public String sqlStatementsFile;
-       }
+    private final static File baseFolder = new File(System.getProperty("user.dir"), "/testdbs");
+    private static final TestDb[] TEST_DBS = {
+            new TestDb("H2", "memory", "jdbc:h2:mem:iciql"),
+            new TestDb("H2", "file", "jdbc:h2:file:"
+                    + new File(baseFolder, "/h2/iciql").getAbsolutePath()),
+            new TestDb("H2", "tcp", "jdbc:h2:tcp://localhost/"
+                    + new File(baseFolder, "/h2tcp/iciql").getAbsolutePath()),
+            new TestDb("HSQL", "memory", "jdbc:hsqldb:mem:iciql"),
+            new TestDb("HSQL", "file", "jdbc:hsqldb:file:testdbs/hsql/iciql"),
+            new TestDb("HSQL", "tcp", "jdbc:hsqldb:hsql://localhost/iciql"),
+            new TestDb("Derby", "memory", "jdbc:derby:memory:iciql;create=true"),
+            new TestDb("Derby", "file", "jdbc:derby:directory:testdbs/derby/iciql;create=true"),
+            new TestDb("Derby", "tcp", "jdbc:derby://localhost:1527/testdbs/derby/iciql;create=true", "sa", "sa"),
+            new TestDb("MySQL", "tcp", "jdbc:mysql://localhost:3306/iciql", "sa", "sa"),
+            new TestDb("PostgreSQL", "tcp", "jdbc:postgresql://localhost:5432/iciql", "sa", "sa"),
+
+            //
+            // SQLite Memory
+            //
+            new TestDb("SQLite", "memory", "jdbc:sqlite:file::memory:?cache=shared&foreign_keys=ON"),
+
+            //
+            // SQLite DELETE rollback journal (default)
+            //
+            new TestDb("SQLite", "delete,full_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=DELETE&synchronous=FULL"),
+
+            new TestDb("SQLite", "delete,norm_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=DELETE&synchronous=NORMAL"),
+
+            new TestDb("SQLite", "delete,no_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=DELETE&synchronous=OFF"),
+
+            //
+            // SQLite WAL
+            //
+            new TestDb("SQLite", "wal,full_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=WAL&synchronous=FULL"),
+
+            new TestDb("SQLite", "wal,norm_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=WAL&synchronous=NORMAL"),
+
+            new TestDb("SQLite", "wal,no_sync", "jdbc:sqlite:"
+                    + new File(baseFolder, "/sqlite/iciql.db").getAbsolutePath()
+                    + "?foreign_keys=ON&journal_mode=WAL&synchronous=OFF"),
+
+    };
+
+    private static final TestDb DEFAULT_TEST_DB = TEST_DBS[3];
+
+    private static final PrintStream ERR = System.err;
+
+    private static PrintStream out = System.out;
+
+    private static Map<String, PoolableConnectionFactory> connectionFactories = Utils
+            .newSynchronizedHashMap();
+
+    private static Map<String, PoolingDataSource> dataSources = Utils.newSynchronizedHashMap();
+
+    public static void assertStartsWith(String value, String startsWith) {
+        Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", startsWith, value),
+                value.startsWith(startsWith));
+    }
+
+    public static void assertEqualsIgnoreCase(String expected, String actual) {
+        Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", expected, actual),
+                expected.equalsIgnoreCase(actual));
+    }
+
+    public static boolean equivalentTo(double expected, double actual) {
+        if (Double.compare(expected, actual) == 0) {
+            return true;
+        }
+        return Math.abs(expected - actual) <= 0.000001d;
+    }
+
+    public static Db openNewDb() {
+        return openNewDb(Mode.PROD);
+    }
+
+    /**
+     * Open a new Db object. All connections are cached and re-used to eliminate
+     * embedded database startup costs.
+     *
+     * @param mode
+     * @return a fresh Db object
+     */
+    public static Db openNewDb(Mode mode) {
+        String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
+        String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
+        String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
+
+        Db db = null;
+        PoolingDataSource dataSource = dataSources.get(testUrl);
+        if (dataSource == null) {
+            ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(testUrl, testUser,
+                    testPassword);
+            GenericObjectPool pool = new GenericObjectPool();
+            pool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW);
+            PoolableConnectionFactory factory = new PoolableConnectionFactory(connectionFactory, pool, null,
+                    null, false, true);
+            dataSource = new PoolingDataSource(pool);
+            dataSources.put(testUrl, dataSource);
+            connectionFactories.put(testUrl, factory);
+        }
+        db = Db.open(dataSource, mode);
+
+        // drop views
+        db.dropView(ProductView.class);
+        db.dropView(ProductViewInherited.class);
+        db.dropView(ProductViewFromQuery.class);
+        db.dropView(ProductViewInheritedComplex.class);
+
+        // 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);
+        db.dropTable(JoinTest.UserId.class);
+        db.dropTable(JoinTest.UserNote.class);
+        db.dropTable(EnumsTest.BadEnums.class);
+        db.dropTable(MultipleBoolsModel.class);
+        db.dropTable(ProductAnnotationOnlyWithForeignKey.class);
+        db.dropTable(CategoryAnnotationOnly.class);
+        db.dropTable(SerializedObjectTypeAdapterTest.class);
+
+        return db;
+    }
+
+    /**
+     * Open the current database.
+     *
+     * @return the current database
+     */
+    public static Db openCurrentDb() {
+        String testUrl = System.getProperty("iciql.url", DEFAULT_TEST_DB.url);
+        String testUser = System.getProperty("iciql.user", DEFAULT_TEST_DB.username);
+        String testPassword = System.getProperty("iciql.password", DEFAULT_TEST_DB.password);
+        return Db.open(testUrl, testUser, testPassword);
+    }
+
+    /**
+     * Returns the name of the underlying database engine for the Db object.
+     *
+     * @param db
+     * @return the database engine name
+     */
+    public static String getDatabaseEngineName(Db db) {
+        String database = "";
+        try {
+            database = db.getConnection().getMetaData().getDatabaseProductName();
+        } catch (SQLException s) {
+        }
+        return database;
+    }
+
+    /**
+     * Returns true if the underlying database engine is Derby.
+     *
+     * @param db
+     * @return true if underlying database engine is Derby
+     */
+    public static boolean isDerby(Db db) {
+        return IciqlSuite.getDatabaseEngineName(db).equals("Apache Derby");
+    }
+
+    /**
+     * Returns true if the underlying database engine is H2.
+     *
+     * @param db
+     * @return true if underlying database engine is H2
+     */
+    public static boolean isH2(Db db) {
+        return IciqlSuite.getDatabaseEngineName(db).equals("H2");
+    }
+
+    /**
+     * 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");
+    }
+
+    /**
+     * Returns true if the underlying database engine is SQLite.
+     *
+     * @param db
+     * @return true if underlying database engine is SQLite
+     */
+    public static boolean isSQLite(Db db) {
+        return IciqlSuite.getDatabaseEngineName(db).equals("SQLite");
+    }
+
+    /**
+     * Gets the default schema of the underlying database engine.
+     *
+     * @param db
+     * @return the default schema
+     */
+    public static String getDefaultSchema(Db db) {
+        if (isDerby(db)) {
+            // Derby sets default schema name to username
+            return "SA";
+        } else if (isMySQL(db)) {
+            // MySQL does not have schemas
+            return null;
+        } else if (isSQLite(db)) {
+            // SQLite does not have schemas
+            return null;
+        }
+
+        return "PUBLIC";
+    }
+
+    /**
+     * Main entry point for the test suite. Executing this method will run the
+     * test suite on all registered databases.
+     *
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String... args) throws Exception {
+        Params params = new Params();
+        JCommander jc = new JCommander(params);
+        try {
+            jc.parse(args);
+        } catch (ParameterException t) {
+            usage(jc, t);
+        }
+
+        // Replace System.out with a file
+        if (!StringUtils.isNullOrEmpty(params.dbPerformanceFile)) {
+            out = new PrintStream(params.dbPerformanceFile);
+            System.setErr(out);
+        }
+
+        deleteRecursively(baseFolder);
+        new File(baseFolder, "/sqlite").mkdirs();
+
+        // Start the HSQL, H2, and Derby servers in-process
+        org.hsqldb.Server hsql = startHSQL();
+        org.h2.tools.Server h2 = startH2();
+        NetworkServerControl derby = startDerby();
+
+        // Statement logging
+        final FileWriter statementWriter;
+        if (StringUtils.isNullOrEmpty(params.sqlStatementsFile)) {
+            statementWriter = null;
+        } else {
+            statementWriter = new FileWriter(params.sqlStatementsFile);
+        }
+        IciqlListener statementListener = new IciqlListener() {
+            @Override
+            public void logIciql(StatementType type, String statement) {
+                if (statementWriter == null) {
+                    return;
+                }
+                try {
+                    statementWriter.append(statement);
+                    statementWriter.append('\n');
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        };
+        IciqlLogger.registerListener(statementListener);
+
+        SuiteClasses suiteClasses = IciqlSuite.class.getAnnotation(SuiteClasses.class);
+        long quickestDatabase = Long.MAX_VALUE;
+        String dividerMajor = buildDivider('*', 79);
+        String dividerMinor = buildDivider('-', 79);
+
+        // Header
+        out.println(dividerMajor);
+        out.println(MessageFormat.format("{0} {1} ({2}) testing {3} database configurations", Constants.NAME,
+                Constants.getVersion(), Constants.getBuildDate(), TEST_DBS.length));
+        out.println(dividerMajor);
+        out.println();
+
+        showProperty("java.vendor");
+        showProperty("java.runtime.version");
+        showProperty("java.vm.name");
+        showProperty("os.name");
+        showProperty("os.version");
+        showProperty("os.arch");
+        showProperty("available processors", "" + Runtime.getRuntime().availableProcessors());
+        showProperty(
+                "available memory",
+                MessageFormat.format("{0,number,0.0} GB", ((double) Runtime.getRuntime().maxMemory())
+                        / (1024 * 1024)));
+        out.println();
+
+        // Test a database
+        long lastCount = 0;
+        for (TestDb testDb : TEST_DBS) {
+            out.println(dividerMinor);
+            out.println("Testing " + testDb.describeDatabase());
+            out.println("        " + testDb.url);
+            out.println(dividerMinor);
+
+            // inject a database section delimiter in the statement log
+            if (statementWriter != null) {
+                statementWriter.append("\n\n");
+                statementWriter.append("# ").append(dividerMinor).append('\n');
+                statementWriter.append("# ").append("Testing " + testDb.describeDatabase()).append('\n');
+                statementWriter.append("# ").append(dividerMinor).append('\n');
+                statementWriter.append("\n\n");
+            }
+
+            if (testDb.getVersion().equals("OFFLINE")) {
+                // Database not available
+                out.println("Skipping.  Could not find " + testDb.url);
+                out.println();
+            } else {
+                // Setup system properties
+                System.setProperty("iciql.url", testDb.url);
+                System.setProperty("iciql.user", testDb.username);
+                System.setProperty("iciql.password", testDb.password);
+
+                // Test database
+                Result result = JUnitCore.runClasses(suiteClasses.value());
+
+                // Report results
+                testDb.runtime = result.getRunTime();
+                if (testDb.runtime < quickestDatabase) {
+                    quickestDatabase = testDb.runtime;
+                }
+                testDb.statements = IciqlLogger.getTotalCount() - lastCount;
+                // reset total count for next database
+                lastCount = IciqlLogger.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.getVersion(), Constants.getBuildDate()));
+
+        StringBuilder compressedSystem = new StringBuilder();
+        compressedSystem.append("      on ");
+        compressedSystem.append(System.getProperty("java.vendor"));
+        compressedSystem.append(' ');
+        compressedSystem.append(System.getProperty("java.runtime.version"));
+        compressedSystem.append(", ");
+        compressedSystem.append(System.getProperty("os.name"));
+        compressedSystem.append(' ');
+        compressedSystem.append(System.getProperty("os.version"));
+        compressedSystem.append(", ");
+        compressedSystem.append(System.getProperty("os.arch"));
+        out.println(compressedSystem.toString());
+
+        out.println(dividerMajor);
+        List<TestDb> dbs = Arrays.asList(TEST_DBS);
+        Collections.sort(dbs);
+
+        out.println(MessageFormat.format("{0} {1} {2} {3} {4}",
+                StringUtils.pad("Name", 11, " ", true),
+                StringUtils.pad("Config", 16, " ", true),
+                StringUtils.pad("Version", 25, " ", true),
+                StringUtils.pad("Stats/sec", 10, " ", true),
+                "Runtime"));
+        out.println(dividerMinor);
+        for (TestDb testDb : dbs) {
+            DecimalFormat df = new DecimalFormat("0.0");
+            out.println(MessageFormat.format("{0} {1} {2} {3} {4}s  ({5,number,0.0}x)",
+                    StringUtils.pad(testDb.name, 11, " ", true),
+                    StringUtils.pad(testDb.config, 16, " ", true),
+                    StringUtils.pad(testDb.getVersion(), 23, " ", true),
+                    StringUtils.pad("" + testDb.getStatementRate(), 7, " ", false),
+                    StringUtils.pad(df.format(testDb.getRuntime()), 8, " ", false),
+                    ((double) testDb.runtime) / quickestDatabase));
+        }
+        out.println(dividerMinor);
+
+        // cleanup
+        for (PoolableConnectionFactory factory : connectionFactories.values()) {
+            factory.getPool().close();
+        }
+        IciqlLogger.unregisterListener(statementListener);
+        out.close();
+        System.setErr(ERR);
+        if (statementWriter != null) {
+            statementWriter.close();
+        }
+        hsql.stop();
+        h2.stop();
+        derby.shutdown();
+        System.exit(0);
+    }
+
+    private static void showProperty(String name) {
+        showProperty(name, System.getProperty(name));
+    }
+
+    private static void showProperty(String name, String value) {
+        out.print(' ');
+        out.print(StringUtils.pad(name, 25, " ", true));
+        out.println(value);
+    }
+
+    private static void usage(JCommander jc, ParameterException t) {
+        System.out.println(Constants.NAME + " test suite v" + Constants.getVersion());
+        System.out.println();
+        if (t != null) {
+            System.out.println(t.getMessage());
+            System.out.println();
+        }
+        if (jc != null) {
+            jc.usage();
+        }
+        System.exit(0);
+    }
+
+    private static String buildDivider(char c, int length) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    private static void deleteRecursively(File f) {
+        if (f.isDirectory()) {
+            for (File file : f.listFiles()) {
+                if (file.isDirectory()) {
+                    deleteRecursively(file);
+                }
+                file.delete();
+            }
+        }
+        f.delete();
+    }
+
+    /**
+     * Start an HSQL tcp server.
+     *
+     * @return an HSQL server instance
+     * @throws Exception
+     */
+    private static org.hsqldb.Server startHSQL() throws Exception {
+        HsqlProperties p = new HsqlProperties();
+        String db = new File(System.getProperty("user.dir")).getAbsolutePath() + "/testdbs/hsqltcp/iciql";
+        p.setProperty("server.database.0", "file:" + db);
+        p.setProperty("server.dbname.0", "iciql");
+        // set up the rest of properties
+
+        // alternative to the above is
+        org.hsqldb.Server server = new org.hsqldb.Server();
+        server.setProperties(p);
+        server.setLogWriter(null);
+        server.setErrWriter(null);
+        server.start();
+        return server;
+    }
+
+    /**
+     * Start the H2 tcp server.
+     *
+     * @return an H2 server instance
+     * @throws Exception
+     */
+    private static org.h2.tools.Server startH2() throws Exception {
+        org.h2.tools.Server server = org.h2.tools.Server.createTcpServer();
+        server.start();
+        return server;
+    }
+
+    /**
+     * Start the Derby tcp server.
+     *
+     * @return an Derby server instance
+     * @throws Exception
+     */
+    private static NetworkServerControl startDerby() throws Exception {
+        NetworkServerControl serverControl = new NetworkServerControl();
+        serverControl.start(null);
+        return serverControl;
+    }
+
+    /**
+     * Represents a test database url.
+     */
+    private static class TestDb implements Comparable<TestDb> {
+        final String name;
+        final String config;
+        final String url;
+        final String username;
+        final String password;
+        String version;
+        long runtime;
+        long statements;
+
+        TestDb(String name, String config, String url) {
+            this(name, config, url, "sa", "");
+        }
+
+        TestDb(String name, String config, String url, String username, String password) {
+            this.name = name;
+            this.config = config;
+            this.url = url;
+            this.username = username;
+            this.password = password;
+        }
+
+        double getRuntime() {
+            return runtime / 1000d;
+        }
+
+        int getStatementRate() {
+            return Double.valueOf((statements) / (runtime / 1000d)).intValue();
+        }
+
+        String describeDatabase() {
+            StringBuilder sb = new StringBuilder(name);
+            sb.append(" ");
+            sb.append(getVersion());
+            return sb.toString();
+        }
+
+        String getVersion() {
+            if (version == null) {
+                try {
+                    Db db = Db.open(url, username, password);
+                    version = db.getConnection().getMetaData().getDatabaseProductVersion();
+                    db.close();
+                    return version;
+                } catch (Throwable t) {
+                    version = "OFFLINE";
+                }
+            }
+            return version;
+        }
+
+        @Override
+        public int compareTo(TestDb o) {
+            if (runtime == 0) {
+                return 1;
+            }
+            if (o.runtime == 0) {
+                return -1;
+            }
+            int r1 = getStatementRate();
+            int r2 = o.getStatementRate();
+            if (r1 == r2) {
+                return 0;
+            }
+            if (r1 < r2) {
+                return 1;
+            }
+            return -1;
+        }
+    }
+
+    /**
+     * Command-line parameters for TestSuite.
+     */
+    @Parameters(separators = " ")
+    private static class Params {
+
+        @Parameter(names = {"--dbFile"}, description = "Database performance results text file", required = false)
+        public String dbPerformanceFile;
+
+        @Parameter(names = {"--sqlFile"}, description = "SQL statements log file", required = false)
+        public String sqlStatementsFile;
+    }
 }
\ No newline at end of file
index 0e5e39d46214dd5b539d6c019dd2fe3133244483..e3370b1dea3a7ab384ee49c9fcfb30a59bf064a2 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQTable;
 import com.iciql.QueryWhere;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests of Joins.
  */
 public class JoinTest {
 
-       Db db;
-
-       @Before
-       public void setup() {
-               db = IciqlSuite.openNewDb();
-
-               db.insertAll(UserId.getList());
-               db.insertAll(UserNote.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testPrimitiveJoin() throws Exception {
-               final UserId u = new UserId();
-               final UserNote n = new UserNote();
-
-               List<UserNote> notes = db.from(u).innerJoin(n).on(u.id).is(n.userId).where(u.id).is(2)
-                               .select(new UserNote() {
-                                       {
-                                               userId = n.userId;
-                                               noteId = n.noteId;
-                                               text = n.text;
-                                       }
-                               });
-               assertEquals(3, notes.size());
-       }
-
-       @Test
-       public void testJoin() throws Exception {
-               final UserId u = new UserId();
-               final UserNote n = new UserNote();
-
-               // this query returns 1 UserId if the user has a note
-               // it's purpose is to confirm fluency/type-safety on a very simple
-               // join case where the main table is filtered/reduced by hits in a
-               // related table
-
-               List<UserId> users = db.from(u).innerJoin(n).on(u.id).is(n.userId).where(u.id).is(2).selectDistinct();
-
-               assertEquals(1, users.size());
-               assertEquals(2, users.get(0).id);
-       }
+    Db db;
+
+    @Before
+    public void setup() {
+        db = IciqlSuite.openNewDb();
+
+        db.insertAll(UserId.getList());
+        db.insertAll(UserNote.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testPrimitiveJoin() throws Exception {
+        final UserId u = new UserId();
+        final UserNote n = new UserNote();
+
+        List<UserNote> notes = db.from(u).innerJoin(n).on(u.id).is(n.userId).where(u.id).is(2)
+                .select(new UserNote() {
+                    {
+                        userId = n.userId;
+                        noteId = n.noteId;
+                        text = n.text;
+                    }
+                });
+        assertEquals(3, notes.size());
+    }
+
+    @Test
+    public void testJoin() throws Exception {
+        final UserId u = new UserId();
+        final UserNote n = new UserNote();
+
+        // this query returns 1 UserId if the user has a note
+        // it's purpose is to confirm fluency/type-safety on a very simple
+        // join case where the main table is filtered/reduced by hits in a
+        // related table
+
+        List<UserId> users = db.from(u).innerJoin(n).on(u.id).is(n.userId).where(u.id).is(2).selectDistinct();
+
+        assertEquals(1, users.size());
+        assertEquals(2, users.get(0).id);
+    }
 
     @Test
     public void testLeftJoin() throws Exception {
@@ -103,71 +101,71 @@ public class JoinTest {
         assertEquals(3, notes.size());
 
         // do not test MySQL on this statement because the databases
-               if (IciqlSuite.isMySQL(db)) {
-                       assertEquals("SELECT * FROM UserId WHERE `id` in (SELECT `userId` FROM UserNote WHERE `userId` > 0 )", q.toSQL());
-               } else {
-                       assertEquals("SELECT * FROM UserId WHERE id in (SELECT userId FROM UserNote WHERE userId > 0 )", q.toSQL());
-               }
+        if (IciqlSuite.isMySQL(db)) {
+            assertEquals("SELECT * FROM UserId WHERE `id` in (SELECT `userId` FROM UserNote WHERE `userId` > 0 )", q.toSQL());
+        } else {
+            assertEquals("SELECT * FROM UserId WHERE id in (SELECT userId FROM UserNote WHERE userId > 0 )", q.toSQL());
+        }
+    }
+
+    @IQTable
+    public static class UserId {
+
+        @IQColumn(primaryKey = true)
+        public int id;
+
+        @IQColumn(length = 10)
+        public String name;
+
+        public UserId() {
+            // public constructor
+        }
+
+        public UserId(int id, String name) {
+            this.id = id;
+            this.name = name;
+        }
+
+        public String toString() {
+            return name + " (" + id + ")";
+        }
+
+        public static List<UserId> getList() {
+            UserId[] list = {new UserId(1, "Tom"), new UserId(2, "Dick"), new UserId(3, "Harry"), new UserId(4, "Jack")};
+            return Arrays.asList(list);
+        }
+    }
+
+    @IQTable
+    public static class UserNote {
+
+        @IQColumn(autoIncrement = true, primaryKey = true)
+        public int noteId;
+
+        @IQColumn
+        public int userId;
+
+        @IQColumn(length = 10)
+        public String text;
+
+        public UserNote() {
+            // public constructor
+        }
+
+        public UserNote(int userId, String text) {
+            this.userId = userId;
+            this.text = text;
+        }
+
+        public String toString() {
+            return text;
+        }
+
+        public static List<UserNote> getList() {
+            UserNote[] list = {new UserNote(1, "A"), new UserNote(2, "B"), new UserNote(3, "C"),
+                    new UserNote(1, "D"), new UserNote(2, "E"), new UserNote(3, "F"), new UserNote(1, "G"),
+                    new UserNote(2, "H"), new UserNote(3, "I"),};
+            return Arrays.asList(list);
+        }
     }
-    
-       @IQTable
-       public static class UserId {
-
-               @IQColumn(primaryKey = true)
-               public int id;
-
-               @IQColumn(length = 10)
-               public String name;
-
-               public UserId() {
-                       // public constructor
-               }
-
-               public UserId(int id, String name) {
-                       this.id = id;
-                       this.name = name;
-               }
-
-               public String toString() {
-                       return name + " (" + id + ")";
-               }
-
-               public static List<UserId> getList() {
-                       UserId[] list = { new UserId(1, "Tom"), new UserId(2, "Dick"), new UserId(3, "Harry"), new UserId(4, "Jack") };
-                       return Arrays.asList(list);
-               }
-       }
-
-       @IQTable
-       public static class UserNote {
-
-               @IQColumn(autoIncrement = true, primaryKey = true)
-               public int noteId;
-
-               @IQColumn
-               public int userId;
-
-               @IQColumn(length = 10)
-               public String text;
-
-               public UserNote() {
-                       // public constructor
-               }
-
-               public UserNote(int userId, String text) {
-                       this.userId = userId;
-                       this.text = text;
-               }
-
-               public String toString() {
-                       return text;
-               }
-
-               public static List<UserNote> getList() {
-                       UserNote[] list = { new UserNote(1, "A"), new UserNote(2, "B"), new UserNote(3, "C"),
-                                       new UserNote(1, "D"), new UserNote(2, "E"), new UserNote(3, "F"), new UserNote(1, "G"),
-                                       new UserNote(2, "H"), new UserNote(3, "I"), };
-                       return Arrays.asList(list);
-               }
-       }
 }
index 0b43c570d1f3cea7a243a08801f2f75efc4e7df3..742ed536c291c4b57c48aa33e9346720fa9f15e3 100644 (file)
 
 package com.iciql.test;
 
-import static com.iciql.test.IciqlSuite.assertEqualsIgnoreCase;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.SQLException;
-import java.text.MessageFormat;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ErrorCollector;
-
 import com.iciql.Db;
 import com.iciql.DbInspector;
 import com.iciql.ValidationRemark;
@@ -39,140 +25,153 @@ import com.iciql.test.models.ProductAnnotationOnly;
 import com.iciql.test.models.ProductMixedAnnotation;
 import com.iciql.test.models.SupportedTypes;
 import com.iciql.util.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+
+import java.sql.SQLException;
+import java.text.MessageFormat;
+import java.util.List;
+
+import static com.iciql.test.IciqlSuite.assertEqualsIgnoreCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test that the mapping between classes and tables is done correctly.
  */
 public class ModelsTest {
 
-       /*
-        * The ErrorCollector Rule allows execution of a test to continue after the
-        * first problem is found and report them all at once
-        */
-       @Rule
-       public ErrorCollector errorCollector = new ErrorCollector();
-
-       private Db db;
-
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
-               db.insertAll(ProductAnnotationOnly.getList());
-               db.insertAll(ProductMixedAnnotation.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testValidateModels() {
-               // SQLite metadata mapping in the JDBC driver needs improvement
-               String schemaName = IciqlSuite.getDefaultSchema(db);
-               DbInspector inspector = new DbInspector(db);
-               validateModel(inspector, schemaName, new ProductAnnotationOnly(), IciqlSuite.isSQLite(db) ? 5 : 2);
-               validateModel(inspector, schemaName, new ProductMixedAnnotation(), IciqlSuite.isSQLite(db) ? 6 : 4);
-       }
-
-       private void validateModel(DbInspector inspector, String schemaName, Object o, int expected) {
-               List<ValidationRemark> remarks = inspector.validateModel(o, false);
-               assertTrue("validation remarks are null for " + o.getClass().getName(), remarks != null);
-               StringBuilder sb = new StringBuilder();
-               sb.append("validation remarks for " + o.getClass().getName());
-               sb.append('\n');
-               for (ValidationRemark remark : remarks) {
-                       sb.append(remark.toString());
-                       sb.append('\n');
-                       if (remark.isError()) {
-                               errorCollector.addError(new SQLException(remark.toString()));
-                       }
-               }
-
-               if (IciqlSuite.isSQLite(db)) {
-                       assertEquals(sb.toString(), expected, remarks.size());
-               } else  if (StringUtils.isNullOrEmpty(schemaName)) {
-                       // no schema expected
-                       assertEquals(sb.toString(), expected - 1, remarks.size());
-               } else {
-                       assertEquals(sb.toString(), expected, remarks.size());
-                       assertEqualsIgnoreCase(MessageFormat.format("@IQSchema(\"{0}\")", schemaName),
-                                       remarks.get(0).message);
-               }
-       }
-
-       @Test
-       public void testSupportedTypes() {
-               List<SupportedTypes> original = SupportedTypes.createList();
-               db.insertAll(original);
-               List<SupportedTypes> retrieved = db.from(SupportedTypes.SAMPLE).select();
-               assertEquals(original.size(), retrieved.size());
-               for (int i = 0; i < original.size(); i++) {
-                       SupportedTypes o = original.get(i);
-                       SupportedTypes r = retrieved.get(i);
-                       assertTrue(o.equivalentTo(r));
-               }
-       }
-
-       @Test
-       public void testModelGeneration() {
-               List<SupportedTypes> original = SupportedTypes.createList();
-               db.insertAll(original);
-               DbInspector inspector = new DbInspector(db);
-               List<String> models = inspector.generateModel(null, "SupportedTypes", "com.iciql.test.models", true,
-                               true);
-               assertEquals(1, models.size());
-               // a poor test, but a start
-               String dbName = IciqlSuite.getDatabaseEngineName(db);
-               if (dbName.equals("H2")) {
-                       assertEquals(1587, models.get(0).length());
-               } else if (dbName.startsWith("HSQL")) {
-                       // HSQL uses Double instead of Float
-                       assertEquals(1591, models.get(0).length());
-               } else if (dbName.equals("Apache Derby")) {
-                       // Derby uses java.sql.Timestamp not java.util.Date
-                       // Derby uses username as schema name
-                       assertEquals(1601, models.get(0).length());
-               } else if (dbName.equals("PostgreSQL")) {
-                       assertEquals(1643, models.get(0).length());
-               } else if (dbName.equals("MySQL")) {
-                       // MySQL uses timestamp default values like
-                       // 0000-00-00 00:00:00 and CURRENT_TIMESTAMP
-                       assertEquals(1673, models.get(0).length());
-               } else if (dbName.equals("SQLite")) {
-                       assertEquals(1566, models.get(0).length());
-               } else {
-                       // unknown database
-                       assertEquals(0, models.get(0).length());
-               }
-       }
-
-       @Test
-       public void testDiscreteUpdateStringTrimming() {
-               List<SupportedTypes> original = SupportedTypes.createList();
-               db.insertAll(original);
-               SupportedTypes s1 = db.from(SupportedTypes.SAMPLE).where(SupportedTypes.SAMPLE.id).is(1).selectFirst();
-               db.from(SupportedTypes.SAMPLE)
-                               .set(SupportedTypes.SAMPLE.myString)
-                               .to(s1.myString + s1.myString + s1.myString + s1.myString)
-                               .update();
-               SupportedTypes s2 = db.from(SupportedTypes.SAMPLE).where(SupportedTypes.SAMPLE.id).is(1).selectFirst();
-               assertEquals(40, s2.myString.length());
-       }
-
-       @Test
-       public void testColumnSelection() {
-               List<SupportedTypes> original = SupportedTypes.createList();
-               db.insertAll(original);
-               List<String> myStrings = db.from(SupportedTypes.SAMPLE)
-                               .select(SupportedTypes.SAMPLE.myString);
-               assertEquals(10, myStrings.size());
-
-               List<Integer> ids = db.from(SupportedTypes.SAMPLE)
-                               .orderByDesc(SupportedTypes.SAMPLE.myInteger)
-                               .selectDistinct(SupportedTypes.SAMPLE.myInteger);
-               assertEquals(10, ids.size());
-               assertEquals("[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]", ids.toString());
-       }
+    /*
+     * The ErrorCollector Rule allows execution of a test to continue after the
+     * first problem is found and report them all at once
+     */
+    @Rule
+    public ErrorCollector errorCollector = new ErrorCollector();
+
+    private Db db;
+
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
+        db.insertAll(ProductAnnotationOnly.getList());
+        db.insertAll(ProductMixedAnnotation.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testValidateModels() {
+        // SQLite metadata mapping in the JDBC driver needs improvement
+        String schemaName = IciqlSuite.getDefaultSchema(db);
+        DbInspector inspector = new DbInspector(db);
+        validateModel(inspector, schemaName, new ProductAnnotationOnly(), IciqlSuite.isSQLite(db) ? 5 : 2);
+        validateModel(inspector, schemaName, new ProductMixedAnnotation(), IciqlSuite.isSQLite(db) ? 6 : 4);
+    }
+
+    private void validateModel(DbInspector inspector, String schemaName, Object o, int expected) {
+        List<ValidationRemark> remarks = inspector.validateModel(o, false);
+        assertTrue("validation remarks are null for " + o.getClass().getName(), remarks != null);
+        StringBuilder sb = new StringBuilder();
+        sb.append("validation remarks for " + o.getClass().getName());
+        sb.append('\n');
+        for (ValidationRemark remark : remarks) {
+            sb.append(remark.toString());
+            sb.append('\n');
+            if (remark.isError()) {
+                errorCollector.addError(new SQLException(remark.toString()));
+            }
+        }
+
+        if (IciqlSuite.isSQLite(db)) {
+            assertEquals(sb.toString(), expected, remarks.size());
+        } else if (StringUtils.isNullOrEmpty(schemaName)) {
+            // no schema expected
+            assertEquals(sb.toString(), expected - 1, remarks.size());
+        } else {
+            assertEquals(sb.toString(), expected, remarks.size());
+            assertEqualsIgnoreCase(MessageFormat.format("@IQSchema(\"{0}\")", schemaName),
+                    remarks.get(0).message);
+        }
+    }
+
+    @Test
+    public void testSupportedTypes() {
+        List<SupportedTypes> original = SupportedTypes.createList();
+        db.insertAll(original);
+        List<SupportedTypes> retrieved = db.from(SupportedTypes.SAMPLE).select();
+        assertEquals(original.size(), retrieved.size());
+        for (int i = 0; i < original.size(); i++) {
+            SupportedTypes o = original.get(i);
+            SupportedTypes r = retrieved.get(i);
+            assertTrue(o.equivalentTo(r));
+        }
+    }
+
+    @Test
+    public void testModelGeneration() {
+        List<SupportedTypes> original = SupportedTypes.createList();
+        db.insertAll(original);
+        DbInspector inspector = new DbInspector(db);
+        List<String> models = inspector.generateModel(null, "SupportedTypes", "com.iciql.test.models", true,
+                true);
+        assertEquals(1, models.size());
+        // a poor test, but a start
+        String dbName = IciqlSuite.getDatabaseEngineName(db);
+        if (dbName.equals("H2")) {
+            assertEquals(1587, models.get(0).length());
+        } else if (dbName.startsWith("HSQL")) {
+            // HSQL uses Double instead of Float
+            assertEquals(1591, models.get(0).length());
+        } else if (dbName.equals("Apache Derby")) {
+            // Derby uses java.sql.Timestamp not java.util.Date
+            // Derby uses username as schema name
+            assertEquals(1601, models.get(0).length());
+        } else if (dbName.equals("PostgreSQL")) {
+            assertEquals(1643, models.get(0).length());
+        } else if (dbName.equals("MySQL")) {
+            // MySQL uses timestamp default values like
+            // 0000-00-00 00:00:00 and CURRENT_TIMESTAMP
+            assertEquals(1673, models.get(0).length());
+        } else if (dbName.equals("SQLite")) {
+            assertEquals(1566, models.get(0).length());
+        } else {
+            // unknown database
+            assertEquals(0, models.get(0).length());
+        }
+    }
+
+    @Test
+    public void testDiscreteUpdateStringTrimming() {
+        List<SupportedTypes> original = SupportedTypes.createList();
+        db.insertAll(original);
+        SupportedTypes s1 = db.from(SupportedTypes.SAMPLE).where(SupportedTypes.SAMPLE.id).is(1).selectFirst();
+        db.from(SupportedTypes.SAMPLE)
+                .set(SupportedTypes.SAMPLE.myString)
+                .to(s1.myString + s1.myString + s1.myString + s1.myString)
+                .update();
+        SupportedTypes s2 = db.from(SupportedTypes.SAMPLE).where(SupportedTypes.SAMPLE.id).is(1).selectFirst();
+        assertEquals(40, s2.myString.length());
+    }
+
+    @Test
+    public void testColumnSelection() {
+        List<SupportedTypes> original = SupportedTypes.createList();
+        db.insertAll(original);
+        List<String> myStrings = db.from(SupportedTypes.SAMPLE)
+                .select(SupportedTypes.SAMPLE.myString);
+        assertEquals(10, myStrings.size());
+
+        List<Integer> ids = db.from(SupportedTypes.SAMPLE)
+                .orderByDesc(SupportedTypes.SAMPLE.myInteger)
+                .selectDistinct(SupportedTypes.SAMPLE.myInteger);
+        assertEquals(10, ids.size());
+        assertEquals("[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]", ids.toString());
+    }
 }
index 6676c9ee09798b3a615580566e2076b1961bf01b..008a8eb962b4e85a091fab53cf478f28e65d37af 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.IciqlException;
 import com.iciql.NestedConditions.And;
 import com.iciql.NestedConditions.Or;
 import com.iciql.QueryWhere;
 import com.iciql.test.models.Customer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class NestedConditionsTest {
 
-       enum Region {
-               JP, FR
-       }
-
-       private Db db;
-
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Customer.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       private String search(Region region, String... customerIds) {
-               Customer model;
-               QueryWhere<Customer> query;
-
-               model = new Customer();
-               query = db.from(model).whereTrue();
-
-               if (customerIds != null && customerIds.length > 0) {
-                       query.andOpen();
-                       for (String value : customerIds) {
-                               query.or(model.customerId).is(value);
-                       }
-                       query.close();
-               }
-
-               if (region != null) {
-                       query.and(model.region).is(region.name());
-               }
-               return query.toSQL();
-       }
-
-       @Test
-       public void andOrSyntaxTest() {
-               String Customer = db.getDialect().prepareTableName(null,  "Customer");
-               String customerId = db.getDialect().prepareColumnName("customerId");
-               String region = db.getDialect().prepareColumnName("region");
-               String trueValue = db.getDialect().prepareStringParameter(true);
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s)", Customer, trueValue),
-                               search(null, (String[]) null));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s)", Customer, trueValue),
-                               search(null, new String[0]));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' )",
-                                               Customer, trueValue, customerId),
-                               search(null, "0001"));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' OR %s = '0002' )",
-                                               Customer, trueValue, customerId, customerId),
-                               search(null, "0001", "0002"));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND %s = 'JP'",
-                                               Customer, trueValue, region),
-                               search(Region.JP, (String[]) null));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND %s = 'JP'",
-                                               Customer, trueValue, region),
-                               search(Region.JP, new String[0]));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' ) AND %s = 'JP'",
-                                               Customer, trueValue, customerId, region),
-                               search(Region.JP, "0001"));
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' OR %s = '0002' ) AND %s = 'JP'",
-                                               Customer, trueValue, customerId, customerId, region),
-                               search(Region.JP, "0001", "0002"));
-       }
-
-       @Test
-       public void errorTest() {
-               Customer model;
-
-               model = new Customer();
-               try {
-                       db.from(model)
-                                       .where(model.customerId).is("0001")
-                                       .andOpen()
-                                                       .or(model.region).is("FR")
-                                                       .or(model.region).is("JP")
-                                       .close()
-                                       .toSQL();
-                       assertTrue(true);
-               }
-               catch (IciqlException error) {
-                       assertTrue(false);
-               }
-
-               try {
-                       db.from(model)
-                                       .where(model.customerId).is("0001")
-                                       .andOpen()
-                                                       .or(model.region).is("FR")
-                                                       .or(model.region).is("JP")
-                                                       .toSQL();
-                       assertTrue(false);
-               }
-               catch (IciqlException error) {
-                       assertTrue(true);
-               }
-
-               try {
-                       db.from(model)
-                                       .where(model.customerId).is("0001")
-                                       .andOpen()
-                                                       .or(model.region).is("FR")
-                                                       .or(model.region).is("JP")
-                                       .close()
-                       .close();
-                       assertTrue(false);
-               }
-               catch (IciqlException error) {
-                       assertTrue(true);
-               }
-       }
-
-       @Test
-       public void fluentSyntaxTest() {
-               String Customer = db.getDialect().prepareTableName(null,  "Customer");
-               String customerId = db.getDialect().prepareColumnName("customerId");
-               String region = db.getDialect().prepareColumnName("region");
-               String trueValue = db.getDialect().prepareStringParameter(true);
-               String falseValue = db.getDialect().prepareStringParameter(false);
-
-               final Customer model = new Customer();
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) AND %s = '0001' AND ( %s = 'CA' OR %s = 'LA' )",
-                                               Customer, trueValue, customerId, region, region),
-
-                               db.from(model).where(new And<Customer>(db, model) {{
-
-                                       and(model.customerId).is("0001");
-                                       and(new Or<Customer>(db, model) {{
-                                               or(model.region).is("CA");
-                                               or(model.region).is("LA");
-                                       }});
-
-                               }})
-
-                               .toSQL());
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) OR %s = '0001' OR ( %s = '0002' AND %s = 'LA' )",
-                                               Customer, falseValue, customerId, customerId, region),
-
-                               db.from(model).where(new Or<Customer>(db, model) {{
-
-                                       or(model.customerId).is("0001");
-
-                                       or(new And<Customer>(db, model) {{
-                                               and(model.customerId).is("0002");
-                                               and(model.region).is("LA");
-                                       }});
-
-                               }})
-
-                               .toSQL());
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE (%s) OR ( %s = '0001' AND %s = 'WA' ) OR ( %s = '0002' AND %s = 'LA' )",
-                                               Customer, falseValue, customerId, region, customerId, region),
-
-                               db.from(model).where(new Or<Customer>(db, model) {{
-
-                                       or(new And<Customer>(db, model) {{
-                                               and(model.customerId).is("0001");
-                                               and(model.region).is("WA");
-                                       }});
-
-                                       or(new And<Customer>(db, model) {{
-                                               and(model.customerId).is("0002");
-                                               and(model.region).is("LA");
-                                       }});
-
-                               }})
-
-                               .toSQL());
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s = '0001' OR ( %s = '0002' AND %s = 'LA' )",
-                                               Customer, customerId, customerId, region),
-
-                               db.from(model).where(model.customerId).is("0001")
-
-                                       .or(new And<Customer>(db, model) {{
-                                               and(model.customerId).is("0002");
-                                               and(model.region).is("LA");
-                                       }})
-
-                                       .toSQL());
-
-
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s IS NOT NULL AND ( %s = 'LA' OR %s = 'CA' OR %s = 'WA' )",
-                                               Customer, customerId, region, region, region),
-                               db.from(model)
-                                               .where(model.customerId).isNotNull()
+    enum Region {
+        JP, FR
+    }
+
+    private Db db;
+
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Customer.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    private String search(Region region, String... customerIds) {
+        Customer model;
+        QueryWhere<Customer> query;
+
+        model = new Customer();
+        query = db.from(model).whereTrue();
+
+        if (customerIds != null && customerIds.length > 0) {
+            query.andOpen();
+            for (String value : customerIds) {
+                query.or(model.customerId).is(value);
+            }
+            query.close();
+        }
+
+        if (region != null) {
+            query.and(model.region).is(region.name());
+        }
+        return query.toSQL();
+    }
+
+    @Test
+    public void andOrSyntaxTest() {
+        String Customer = db.getDialect().prepareTableName(null, "Customer");
+        String customerId = db.getDialect().prepareColumnName("customerId");
+        String region = db.getDialect().prepareColumnName("region");
+        String trueValue = db.getDialect().prepareStringParameter(true);
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s)", Customer, trueValue),
+                search(null, (String[]) null));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s)", Customer, trueValue),
+                search(null, new String[0]));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' )",
+                        Customer, trueValue, customerId),
+                search(null, "0001"));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' OR %s = '0002' )",
+                        Customer, trueValue, customerId, customerId),
+                search(null, "0001", "0002"));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND %s = 'JP'",
+                        Customer, trueValue, region),
+                search(Region.JP, (String[]) null));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND %s = 'JP'",
+                        Customer, trueValue, region),
+                search(Region.JP, new String[0]));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' ) AND %s = 'JP'",
+                        Customer, trueValue, customerId, region),
+                search(Region.JP, "0001"));
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND ( %s = '0001' OR %s = '0002' ) AND %s = 'JP'",
+                        Customer, trueValue, customerId, customerId, region),
+                search(Region.JP, "0001", "0002"));
+    }
+
+    @Test
+    public void errorTest() {
+        Customer model;
+
+        model = new Customer();
+        try {
+            db.from(model)
+                    .where(model.customerId).is("0001")
+                    .andOpen()
+                    .or(model.region).is("FR")
+                    .or(model.region).is("JP")
+                    .close()
+                    .toSQL();
+            assertTrue(true);
+        } catch (IciqlException error) {
+            assertTrue(false);
+        }
+
+        try {
+            db.from(model)
+                    .where(model.customerId).is("0001")
+                    .andOpen()
+                    .or(model.region).is("FR")
+                    .or(model.region).is("JP")
+                    .toSQL();
+            assertTrue(false);
+        } catch (IciqlException error) {
+            assertTrue(true);
+        }
+
+        try {
+            db.from(model)
+                    .where(model.customerId).is("0001")
+                    .andOpen()
+                    .or(model.region).is("FR")
+                    .or(model.region).is("JP")
+                    .close()
+                    .close();
+            assertTrue(false);
+        } catch (IciqlException error) {
+            assertTrue(true);
+        }
+    }
+
+    @Test
+    public void fluentSyntaxTest() {
+        String Customer = db.getDialect().prepareTableName(null, "Customer");
+        String customerId = db.getDialect().prepareColumnName("customerId");
+        String region = db.getDialect().prepareColumnName("region");
+        String trueValue = db.getDialect().prepareStringParameter(true);
+        String falseValue = db.getDialect().prepareStringParameter(false);
+
+        final Customer model = new Customer();
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) AND %s = '0001' AND ( %s = 'CA' OR %s = 'LA' )",
+                        Customer, trueValue, customerId, region, region),
+
+                db.from(model).where(new And<Customer>(db, model) {{
+
+                    and(model.customerId).is("0001");
+                    and(new Or<Customer>(db, model) {{
+                        or(model.region).is("CA");
+                        or(model.region).is("LA");
+                    }});
+
+                }})
+
+                        .toSQL());
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) OR %s = '0001' OR ( %s = '0002' AND %s = 'LA' )",
+                        Customer, falseValue, customerId, customerId, region),
+
+                db.from(model).where(new Or<Customer>(db, model) {{
+
+                    or(model.customerId).is("0001");
+
+                    or(new And<Customer>(db, model) {{
+                        and(model.customerId).is("0002");
+                        and(model.region).is("LA");
+                    }});
+
+                }})
+
+                        .toSQL());
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE (%s) OR ( %s = '0001' AND %s = 'WA' ) OR ( %s = '0002' AND %s = 'LA' )",
+                        Customer, falseValue, customerId, region, customerId, region),
+
+                db.from(model).where(new Or<Customer>(db, model) {{
+
+                    or(new And<Customer>(db, model) {{
+                        and(model.customerId).is("0001");
+                        and(model.region).is("WA");
+                    }});
+
+                    or(new And<Customer>(db, model) {{
+                        and(model.customerId).is("0002");
+                        and(model.region).is("LA");
+                    }});
+
+                }})
+
+                        .toSQL());
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s = '0001' OR ( %s = '0002' AND %s = 'LA' )",
+                        Customer, customerId, customerId, region),
+
+                db.from(model).where(model.customerId).is("0001")
+
+                        .or(new And<Customer>(db, model) {{
+                            and(model.customerId).is("0002");
+                            and(model.region).is("LA");
+                        }})
+
+                        .toSQL());
+
+
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s IS NOT NULL AND ( %s = 'LA' OR %s = 'CA' OR %s = 'WA' )",
+                        Customer, customerId, region, region, region),
+                db.from(model)
+                        .where(model.customerId).isNotNull()
 
-                                               .and(new Or<Customer>(db, model) {{
-                                                       or(model.region).is("LA");
-                                                       or(model.region).is("CA");
-                                                       or(model.region).is("WA");
-                                               }})
+                        .and(new Or<Customer>(db, model) {{
+                            or(model.region).is("LA");
+                            or(model.region).is("CA");
+                            or(model.region).is("WA");
+                        }})
 
-                                               .toSQL());
-       }
+                        .toSQL());
+    }
 
-       @Test
-       public void compoundConditionsTest() {
-               final Customer c = new Customer();
-               List<Customer> matches = db.from(c)
-                               .where(c.customerId).like("A%")
-                               .and(c.region).isNotNull()
-                               .and(new Or<Customer>(db, c) {{
-                                       or(c.region).is("LA");
-                                       or(c.region).is("CA");
-                               }}).select();
+    @Test
+    public void compoundConditionsTest() {
+        final Customer c = new Customer();
+        List<Customer> matches = db.from(c)
+                .where(c.customerId).like("A%")
+                .and(c.region).isNotNull()
+                .and(new Or<Customer>(db, c) {{
+                    or(c.region).is("LA");
+                    or(c.region).is("CA");
+                }}).select();
 
-               assertEquals(2, matches.size());
+        assertEquals(2, matches.size());
 
-               Set<String> ids = new TreeSet<String>();
-               for (Customer customer : matches) {
-                       ids.add(customer.customerId);
-               }
-               assertEquals("[ANTON, ASLAN]", ids.toString());
+        Set<String> ids = new TreeSet<String>();
+        for (Customer customer : matches) {
+            ids.add(customer.customerId);
+        }
+        assertEquals("[ANTON, ASLAN]", ids.toString());
 
-       }
+    }
 
 }
index c4aa90bf2220f355fa82b94e68f86fabe11d9423..c5d92f9da4bcb69901726f2a4e4bcaa747620562 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
+import com.iciql.Db;
+import com.iciql.test.models.Customer;
+import com.iciql.test.models.PrimitivesModel;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.iciql.Db;
-import com.iciql.test.models.Customer;
-import com.iciql.test.models.PrimitivesModel;
+import static org.junit.Assert.assertEquals;
 
 public class OneOfTest {
 
-       private Db db;
-
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Customer.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @SuppressWarnings("serial")
-       @Test
-       public void oneOfSyntaxTest() {
-               String PrimitivesTest = db.getDialect().prepareTableName(null, "PrimitivesTest");
-               String Customer = db.getDialect().prepareTableName(null, "Customer");
-               String myInteger = db.getDialect().prepareColumnName("myInteger");
-               String customerId = db.getDialect().prepareColumnName("customerId");
-
-               PrimitivesModel p = new PrimitivesModel();
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s IN(0)", PrimitivesTest, myInteger),
-                               db.from(p)
-                                               .where(p.myInteger).oneOf(0)
-                                               .toSQL());
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s IN(0, 1)", PrimitivesTest, myInteger),
-                               db.from(p)
-                                               .where(p.myInteger).oneOf(0, 1)
-                                               .toSQL());
-               Customer c = new Customer();
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s IN('a')", Customer, customerId),
-                               db.from(c)
-                                               .where(c.customerId).oneOf(new ArrayList<String>() {{
-                                                       this.add("a");
-                                               }})
-                                               .toSQL());
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s IN('a', 'b')", Customer, customerId),
-                               db.from(c)
-                                               .where(c.customerId).oneOf(new ArrayList<String>() {{
-                                                       this.add("a");
-                                                       this.add("b");
-                                               }})
-                                               .toSQL());
-       }
-
-       @SuppressWarnings("serial")
-       @Test
-       public void noneOfSyntaxTest() {
-               String PrimitivesTest = db.getDialect().prepareTableName(null, "PrimitivesTest");
-               String Customer = db.getDialect().prepareTableName(null, "Customer");
-               String myInteger = db.getDialect().prepareColumnName("myInteger");
-               String customerId = db.getDialect().prepareColumnName("customerId");
-
-               PrimitivesModel p = new PrimitivesModel();
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s NOT IN(0)", PrimitivesTest, myInteger),
-                               db.from(p)
-                                               .where(p.myInteger).noneOf(0)
-                                               .toSQL());
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s NOT IN(0, 1)", PrimitivesTest, myInteger),
-                               db.from(p)
-                                               .where(p.myInteger).noneOf(0, 1)
-                                               .toSQL());
-               Customer c = new Customer();
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s NOT IN('a')", Customer, customerId),
-                               db.from(c)
-                                               .where(c.customerId).noneOf(new ArrayList<String>() {{
-                                                       this.add("a");
-                                               }})
-                                               .toSQL());
-               assertEquals(
-                               String.format("SELECT * FROM %s WHERE %s NOT IN('a', 'b')", Customer, customerId),
-                               db.from(c)
-                                               .where(c.customerId).noneOf(new ArrayList<String>() {{
-                                                       this.add("a");
-                                                       this.add("b");
-                                               }})
-                                               .toSQL());
-       }
-
-       public void noneOfTest() {
-               Customer c = new Customer();
-               List<Customer> meAndny = db.from(c).where(c.region).noneOf("WA", "CA", "LA").select();
-               assertEquals(2, meAndny.size());
-
-               Set<String> regions = new TreeSet<String>();
-               for (Customer customer : meAndny) {
-                       regions.add(customer.region);
-               }
-               assertEquals("[ME, NY]", regions.toString());
-       }
-
-       public void oneOfTest() {
-               Customer c = new Customer();
-               List<Customer> meAndny = db.from(c).where(c.region).oneOf("ME", "NY").select();
-               assertEquals(2, meAndny.size());
-
-               Set<String> regions = new TreeSet<String>();
-               for (Customer customer : meAndny) {
-                       regions.add(customer.region);
-               }
-               assertEquals("[ME, NY]", regions.toString());
-       }
+    private Db db;
+
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Customer.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @SuppressWarnings("serial")
+    @Test
+    public void oneOfSyntaxTest() {
+        String PrimitivesTest = db.getDialect().prepareTableName(null, "PrimitivesTest");
+        String Customer = db.getDialect().prepareTableName(null, "Customer");
+        String myInteger = db.getDialect().prepareColumnName("myInteger");
+        String customerId = db.getDialect().prepareColumnName("customerId");
+
+        PrimitivesModel p = new PrimitivesModel();
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s IN(0)", PrimitivesTest, myInteger),
+                db.from(p)
+                        .where(p.myInteger).oneOf(0)
+                        .toSQL());
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s IN(0, 1)", PrimitivesTest, myInteger),
+                db.from(p)
+                        .where(p.myInteger).oneOf(0, 1)
+                        .toSQL());
+        Customer c = new Customer();
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s IN('a')", Customer, customerId),
+                db.from(c)
+                        .where(c.customerId).oneOf(new ArrayList<String>() {{
+                    this.add("a");
+                }})
+                        .toSQL());
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s IN('a', 'b')", Customer, customerId),
+                db.from(c)
+                        .where(c.customerId).oneOf(new ArrayList<String>() {{
+                    this.add("a");
+                    this.add("b");
+                }})
+                        .toSQL());
+    }
+
+    @SuppressWarnings("serial")
+    @Test
+    public void noneOfSyntaxTest() {
+        String PrimitivesTest = db.getDialect().prepareTableName(null, "PrimitivesTest");
+        String Customer = db.getDialect().prepareTableName(null, "Customer");
+        String myInteger = db.getDialect().prepareColumnName("myInteger");
+        String customerId = db.getDialect().prepareColumnName("customerId");
+
+        PrimitivesModel p = new PrimitivesModel();
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s NOT IN(0)", PrimitivesTest, myInteger),
+                db.from(p)
+                        .where(p.myInteger).noneOf(0)
+                        .toSQL());
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s NOT IN(0, 1)", PrimitivesTest, myInteger),
+                db.from(p)
+                        .where(p.myInteger).noneOf(0, 1)
+                        .toSQL());
+        Customer c = new Customer();
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s NOT IN('a')", Customer, customerId),
+                db.from(c)
+                        .where(c.customerId).noneOf(new ArrayList<String>() {{
+                    this.add("a");
+                }})
+                        .toSQL());
+        assertEquals(
+                String.format("SELECT * FROM %s WHERE %s NOT IN('a', 'b')", Customer, customerId),
+                db.from(c)
+                        .where(c.customerId).noneOf(new ArrayList<String>() {{
+                    this.add("a");
+                    this.add("b");
+                }})
+                        .toSQL());
+    }
+
+    public void noneOfTest() {
+        Customer c = new Customer();
+        List<Customer> meAndny = db.from(c).where(c.region).noneOf("WA", "CA", "LA").select();
+        assertEquals(2, meAndny.size());
+
+        Set<String> regions = new TreeSet<String>();
+        for (Customer customer : meAndny) {
+            regions.add(customer.region);
+        }
+        assertEquals("[ME, NY]", regions.toString());
+    }
+
+    public void oneOfTest() {
+        Customer c = new Customer();
+        List<Customer> meAndny = db.from(c).where(c.region).oneOf("ME", "NY").select();
+        assertEquals(2, meAndny.size());
+
+        Set<String> regions = new TreeSet<String>();
+        for (Customer customer : meAndny) {
+            regions.add(customer.region);
+        }
+        assertEquals("[ME, NY]", regions.toString());
+    }
 
 }
index 625064918f591b8338587df379841322517acbd7..49595a209b8dfb35b38a289221b7763777c7319e 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.util.Collections;\r
-import java.util.List;\r
-\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.IciqlException;\r
 import com.iciql.test.models.MultipleBoolsModel;\r
 import com.iciql.test.models.PrimitivesModel;\r
+import org.junit.Test;\r
+\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * Tests primitives with autoboxing within the framework.\r
  */\r
 public class PrimitivesTest {\r
 \r
-       @Test\r
-       public void testPrimitives() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               // insert random models in reverse order\r
-               List<PrimitivesModel> models = PrimitivesModel.getList();\r
-               PrimitivesModel model = models.get(0);\r
-               Collections.reverse(models);\r
-               // insert them in reverse order\r
-               db.insertAll(models);\r
-\r
-               PrimitivesModel p = new PrimitivesModel();\r
-\r
-               // retrieve model and compare\r
-               PrimitivesModel retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
-               assertTrue(model.equivalentTo(retrievedModel));\r
-\r
-               retrievedModel = db.from(p).where("mylong = ? and myinteger = ?", model.myLong, model.myInteger)\r
-                               .selectFirst();\r
-               assertTrue(model.equivalentTo(retrievedModel));\r
-\r
-               // retrieve with conditions and compare\r
-               retrievedModel = db.from(p).where(p.myLong).is(model.myLong).and(p.myInteger).is(model.myInteger)\r
-                               .selectFirst();\r
-               assertTrue(model.equivalentTo(retrievedModel));\r
-\r
-               // set myInteger & myDouble\r
-               db.from(p).set(p.myInteger).to(10).set(p.myDouble).to(3.0d).where(p.myLong).is(model.myLong).update();\r
-               retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
-\r
-               assertEquals(10, retrievedModel.myInteger);\r
-               assertEquals(3d, retrievedModel.myDouble, 0.001d);\r
-\r
-               // increment my double by pi\r
-               db.from(p).increment(p.myDouble).by(3.14d).update();\r
-               retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
-               assertEquals(6.14d, retrievedModel.myDouble, 0.001d);\r
-\r
-               // test order by\r
-               List<PrimitivesModel> list = db.from(p).orderBy(p.myLong).select();\r
-               assertEquals(models.size(), list.size());\r
-               assertEquals("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", list.toString());\r
-\r
-               // test model update\r
-               retrievedModel.myInteger = 1337;\r
-               assertTrue(db.update(retrievedModel));\r
-               assertTrue(db.delete(retrievedModel));\r
-\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testMultipleBooleans() {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(MultipleBoolsModel.getList());\r
-\r
-               MultipleBoolsModel m = new MultipleBoolsModel();\r
-               try {\r
-                       db.from(m).where(m.a).is(true).select();\r
-                       assertTrue(false);\r
-               } catch (IciqlException e) {\r
-                       assertTrue(true);\r
-               }\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testPrimitiveColumnSelection() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               // insert random models in reverse order\r
-               List<PrimitivesModel> models = PrimitivesModel.getList();\r
-               Collections.reverse(models);\r
-               // insert them in reverse order\r
-               db.insertAll(models);\r
-\r
-               PrimitivesModel p = new PrimitivesModel();\r
-               List<Long> list = db.from(p).orderByDesc(p.myLong).select(p.myLong);\r
-               assertEquals(models.size(), list.size());\r
-               assertEquals("[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]", list.toString());\r
-       }\r
+    @Test\r
+    public void testPrimitives() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        // insert random models in reverse order\r
+        List<PrimitivesModel> models = PrimitivesModel.getList();\r
+        PrimitivesModel model = models.get(0);\r
+        Collections.reverse(models);\r
+        // insert them in reverse order\r
+        db.insertAll(models);\r
+\r
+        PrimitivesModel p = new PrimitivesModel();\r
+\r
+        // retrieve model and compare\r
+        PrimitivesModel retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
+        assertTrue(model.equivalentTo(retrievedModel));\r
+\r
+        retrievedModel = db.from(p).where("mylong = ? and myinteger = ?", model.myLong, model.myInteger)\r
+                .selectFirst();\r
+        assertTrue(model.equivalentTo(retrievedModel));\r
+\r
+        // retrieve with conditions and compare\r
+        retrievedModel = db.from(p).where(p.myLong).is(model.myLong).and(p.myInteger).is(model.myInteger)\r
+                .selectFirst();\r
+        assertTrue(model.equivalentTo(retrievedModel));\r
+\r
+        // set myInteger & myDouble\r
+        db.from(p).set(p.myInteger).to(10).set(p.myDouble).to(3.0d).where(p.myLong).is(model.myLong).update();\r
+        retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
+\r
+        assertEquals(10, retrievedModel.myInteger);\r
+        assertEquals(3d, retrievedModel.myDouble, 0.001d);\r
+\r
+        // increment my double by pi\r
+        db.from(p).increment(p.myDouble).by(3.14d).update();\r
+        retrievedModel = db.from(p).orderBy(p.myLong).selectFirst();\r
+        assertEquals(6.14d, retrievedModel.myDouble, 0.001d);\r
+\r
+        // test order by\r
+        List<PrimitivesModel> list = db.from(p).orderBy(p.myLong).select();\r
+        assertEquals(models.size(), list.size());\r
+        assertEquals("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", list.toString());\r
+\r
+        // test model update\r
+        retrievedModel.myInteger = 1337;\r
+        assertTrue(db.update(retrievedModel));\r
+        assertTrue(db.delete(retrievedModel));\r
+\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testMultipleBooleans() {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(MultipleBoolsModel.getList());\r
+\r
+        MultipleBoolsModel m = new MultipleBoolsModel();\r
+        try {\r
+            db.from(m).where(m.a).is(true).select();\r
+            assertTrue(false);\r
+        } catch (IciqlException e) {\r
+            assertTrue(true);\r
+        }\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testPrimitiveColumnSelection() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        // insert random models in reverse order\r
+        List<PrimitivesModel> models = PrimitivesModel.getList();\r
+        Collections.reverse(models);\r
+        // insert them in reverse order\r
+        db.insertAll(models);\r
+\r
+        PrimitivesModel p = new PrimitivesModel();\r
+        List<Long> list = db.from(p).orderByDesc(p.myLong).select(p.myLong);\r
+        assertEquals(models.size(), list.size());\r
+        assertEquals("[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]", list.toString());\r
+    }\r
 }\r
index d8eac72f9a1db9ea8aafd379ed0f93334d61b6b3..301753ac3231765ebf4465bfe497287123bf7493 100644 (file)
 
 package com.iciql.test;
 
-import java.sql.Date;
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Dao;
 import com.iciql.DaoClasspathStatementProvider;
 import com.iciql.Db;
@@ -35,6 +26,14 @@ import com.iciql.test.DataTypeAdapterTest.SupportedTypesAdapter;
 import com.iciql.test.models.Order;
 import com.iciql.test.models.Product;
 import com.iciql.test.models.SupportedTypes;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.sql.Date;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Tests DAO dynamic proxy mechanism.
@@ -43,373 +42,373 @@ import com.iciql.test.models.SupportedTypes;
  */
 public class ProductDaoTest extends Assert {
 
-       private Db db;
+    private Db db;
 
-       @Before
-       public void setUp() throws Exception {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
-               db.insertAll(Order.getList());
-               db.setDaoStatementProvider(new DaoClasspathStatementProvider());
-       }
+    @Before
+    public void setUp() throws Exception {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
+        db.insertAll(Order.getList());
+        db.setDaoStatementProvider(new DaoClasspathStatementProvider());
+    }
 
-       @After
-       public void tearDown() {
-               db.close();
-       }
+    @After
+    public void tearDown() {
+        db.close();
+    }
 
-       @Test
-       public void testQueryVoidReturnType() {
+    @Test
+    public void testQueryVoidReturnType() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               try {
-                       dao.getWithIllegalVoid();
-                       assertTrue("void return type on a query should fail", false);
-               } catch (IciqlException e) {
-                       assertTrue(true);
-               }
-       }
+        try {
+            dao.getWithIllegalVoid();
+            assertTrue("void return type on a query should fail", false);
+        } catch (IciqlException e) {
+            assertTrue(true);
+        }
+    }
 
-       @Test
-       public void testQueryCollectionReturnType() {
+    @Test
+    public void testQueryCollectionReturnType() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               try {
-                       dao.getWithIllegalCollection();
-                       assertTrue("collection return types on a query should fail", false);
-               } catch (IciqlException e) {
-                       assertTrue(true);
-               }
-       }
+        try {
+            dao.getWithIllegalCollection();
+            assertTrue("collection return types on a query should fail", false);
+        } catch (IciqlException e) {
+            assertTrue(true);
+        }
+    }
 
-       @Test
-       public void testQueryIgnoreDoubleDelimiter() {
+    @Test
+    public void testQueryIgnoreDoubleDelimiter() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               try {
-                       dao.getWithDoubleDelimiter();
-                       assertTrue("the double delimiter should have been ignored", false);
-               } catch (IciqlException e) {
-                       assertTrue(true);
-               }
+        try {
+            dao.getWithDoubleDelimiter();
+            assertTrue("the double delimiter should have been ignored", false);
+        } catch (IciqlException e) {
+            assertTrue(true);
+        }
 
-       }
+    }
 
-       @Test
-       public void testQueryReturnModels() {
+    @Test
+    public void testQueryReturnModels() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product[] products = dao.getAllProducts();
-               assertEquals(10, products.length);
-       }
+        Product[] products = dao.getAllProducts();
+        assertEquals(10, products.length);
+    }
 
-       @Test
-       public void testQueryNamedOrIndexedParameterBinding() {
+    @Test
+    public void testQueryNamedOrIndexedParameterBinding() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product p2 = dao.getProduct(2);
-               assertEquals("Chang", p2.productName);
+        Product p2 = dao.getProduct(2);
+        assertEquals("Chang", p2.productName);
 
-               Product p3 = dao.getProductWithUnusedBoundParameters(true, 3, "test");
-               assertEquals("Aniseed Syrup", p3.productName);
+        Product p3 = dao.getProductWithUnusedBoundParameters(true, 3, "test");
+        assertEquals("Aniseed Syrup", p3.productName);
 
-               Product p4 = dao.getProductWithUnboundParameters(true, 4, "test");
-               assertEquals("Chef Anton's Cajun Seasoning", p4.productName);
+        Product p4 = dao.getProductWithUnboundParameters(true, 4, "test");
+        assertEquals("Chef Anton's Cajun Seasoning", p4.productName);
 
-               Product p5 = dao.getProductWithUnboundParameters(true, 5, "test");
-               assertEquals("Chef Anton's Gumbo Mix", p5.productName);
+        Product p5 = dao.getProductWithUnboundParameters(true, 5, "test");
+        assertEquals("Chef Anton's Gumbo Mix", p5.productName);
 
-               // test re-use of IndexedSql (manual check with debugger)
-               Product p6 = dao.getProduct(6);
-               assertEquals("Grandma's Boysenberry Spread", p6.productName);
+        // test re-use of IndexedSql (manual check with debugger)
+        Product p6 = dao.getProduct(6);
+        assertEquals("Grandma's Boysenberry Spread", p6.productName);
 
-       }
+    }
 
-       @Test
-       public void testJDBCPlaceholderParameterBinding() {
+    @Test
+    public void testJDBCPlaceholderParameterBinding() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product p2 = dao.getProductWithJDBCPlaceholders(2);
-               assertEquals("Chang", p2.productName);
+        Product p2 = dao.getProductWithJDBCPlaceholders(2);
+        assertEquals("Chang", p2.productName);
 
-       }
+    }
 
-       @Test
-       public void testQueryBeanBinding() {
+    @Test
+    public void testQueryBeanBinding() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product p4 = dao.getProduct(4);
+        Product p4 = dao.getProduct(4);
 
-               long [] products = dao.getSimilarInStockItemIds(p4);
+        long[] products = dao.getSimilarInStockItemIds(p4);
 
-               assertEquals("[6]", Arrays.toString(products));
+        assertEquals("[6]", Arrays.toString(products));
 
-       }
+    }
 
-       @Test
-       public void testQueryReturnField() {
+    @Test
+    public void testQueryReturnField() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               String n5 = dao.getProductName(5);
-               assertEquals("Chef Anton's Gumbo Mix", n5);
+        String n5 = dao.getProductName(5);
+        assertEquals("Chef Anton's Gumbo Mix", n5);
 
-               int u4 = dao.getUnitsInStock(4);
-               assertEquals(53, u4);
+        int u4 = dao.getUnitsInStock(4);
+        assertEquals(53, u4);
 
-       }
+    }
 
-       @Test
-       public void testQueryReturnFields() {
+    @Test
+    public void testQueryReturnFields() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               long [] ids = dao.getProductIdsForCategory("Condiments");
-               assertEquals("[3, 4, 5, 6, 8]", Arrays.toString(ids));
+        long[] ids = dao.getProductIdsForCategory("Condiments");
+        assertEquals("[3, 4, 5, 6, 8]", Arrays.toString(ids));
 
-               Date date = dao.getMostRecentOrder();
-               assertEquals("2007-04-11", date.toString());
+        Date date = dao.getMostRecentOrder();
+        assertEquals("2007-04-11", date.toString());
 
-       }
+    }
 
-       @Test
-       public void testUpdateIllegalReturnType() {
+    @Test
+    public void testUpdateIllegalReturnType() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               try {
-                       dao.setWithIllegalReturnType();
-                       assertTrue("this should have been an illegal return type", false);
-               } catch (IciqlException e) {
-                       assertTrue(true);
-               }
+        try {
+            dao.setWithIllegalReturnType();
+            assertTrue("this should have been an illegal return type", false);
+        } catch (IciqlException e) {
+            assertTrue(true);
+        }
 
-       }
+    }
 
-       @Test
-       public void testUpdateStatements() {
+    @Test
+    public void testUpdateStatements() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product p1 = dao.getProduct(1);
-               assertEquals("Chai", p1.productName);
+        Product p1 = dao.getProduct(1);
+        assertEquals("Chai", p1.productName);
 
-               String name = "Tea";
-               dao.setProductName(1, name);
+        String name = "Tea";
+        dao.setProductName(1, name);
 
-               Product p2 = dao.getProduct(1);
+        Product p2 = dao.getProduct(1);
 
-               assertEquals(name, p2.productName);
+        assertEquals(name, p2.productName);
 
-       }
+    }
 
-       @Test
-       public void testUpdateStatementsReturnsSuccess() {
+    @Test
+    public void testUpdateStatementsReturnsSuccess() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               boolean success = dao.setProductNameReturnsSuccess(1, "Tea");
-               assertTrue(success);
+        boolean success = dao.setProductNameReturnsSuccess(1, "Tea");
+        assertTrue(success);
 
-       }
+    }
 
-       @Test
-       public void testUpdateStatementsReturnsCount() {
+    @Test
+    public void testUpdateStatementsReturnsCount() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               int rows = dao.renameProductCategoryReturnsCount("Condiments", "Garnishes");
-               assertEquals(5, rows);
+        int rows = dao.renameProductCategoryReturnsCount("Condiments", "Garnishes");
+        assertEquals(5, rows);
 
-       }
+    }
 
-       @Test
-       public void testQueryWithDataTypeAdapter() {
+    @Test
+    public void testQueryWithDataTypeAdapter() {
 
-               final SupportedTypes obj0 = SupportedTypes.createList().get(1);
+        final SupportedTypes obj0 = SupportedTypes.createList().get(1);
 
-               // insert our custom serialized object
-               SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
-               row.received = new java.util.Date();
-               row.obj = obj0;
-               final long id = db.insertAndGetKey(row);
+        // insert our custom serialized object
+        SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
+        row.received = new java.util.Date();
+        row.obj = obj0;
+        final long id = db.insertAndGetKey(row);
 
-               SerializedObjectTypeAdapterTest row1 = db.from(row).selectFirst();
+        SerializedObjectTypeAdapterTest row1 = db.from(row).selectFirst();
 
-               // validate retrieved object
-               final SupportedTypes obj1a = row1.obj;
-               assertNotNull(obj1a);
-               assertTrue(obj0.equivalentTo(obj1a));
+        // validate retrieved object
+        final SupportedTypes obj1a = row1.obj;
+        assertNotNull(obj1a);
+        assertTrue(obj0.equivalentTo(obj1a));
 
-               // validate the primary keys match
-               assertEquals("The returned primary key should match the object primary key", id, row1.id);
+        // validate the primary keys match
+        assertEquals("The returned primary key should match the object primary key", id, row1.id);
 
-               // retrieve our object with automatic data type conversion
-               ProductDao dao = db.open(ProductDao.class);
-               final SupportedTypes obj1 = dao.getCustomDataType(id);
-               assertNotNull(obj1);
-               assertTrue(obj0.equivalentTo(obj1));
-       }
+        // retrieve our object with automatic data type conversion
+        ProductDao dao = db.open(ProductDao.class);
+        final SupportedTypes obj1 = dao.getCustomDataType(id);
+        assertNotNull(obj1);
+        assertTrue(obj0.equivalentTo(obj1));
+    }
 
-       @Test
-       public void testUpdateWithDataTypeAdapter() {
+    @Test
+    public void testUpdateWithDataTypeAdapter() {
 
-               final SupportedTypes obj0 = SupportedTypes.createList().get(1);
+        final SupportedTypes obj0 = SupportedTypes.createList().get(1);
 
-               // insert our custom serialized object
-               SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
-               row.received = new java.util.Date();
-               row.obj = obj0;
+        // insert our custom serialized object
+        SerializedObjectTypeAdapterTest row = new SerializedObjectTypeAdapterTest();
+        row.received = new java.util.Date();
+        row.obj = obj0;
 
-               final long id = db.insertAndGetKey(row);
+        final long id = db.insertAndGetKey(row);
 
-               SerializedObjectTypeAdapterTest row1 = db.from(row).selectFirst();
+        SerializedObjectTypeAdapterTest row1 = db.from(row).selectFirst();
 
-               // validate retrieved object
-               final SupportedTypes obj1a = row1.obj;
-               assertNotNull(obj1a);
-               assertTrue(obj0.equivalentTo(obj1a));
+        // validate retrieved object
+        final SupportedTypes obj1a = row1.obj;
+        assertNotNull(obj1a);
+        assertTrue(obj0.equivalentTo(obj1a));
 
-               // validate the primary keys match
-               assertEquals("The returned primary key should match the object primary key", id, row1.id);
+        // validate the primary keys match
+        assertEquals("The returned primary key should match the object primary key", id, row1.id);
 
-               // validate the alternate retrieved object is equivalent
-               ProductDao dao = db.open(ProductDao.class);
-               final SupportedTypes obj1b = dao.getCustomDataType(id);
-               assertNotNull(obj1b);
-               assertTrue(obj1a.equivalentTo(obj1b));
+        // validate the alternate retrieved object is equivalent
+        ProductDao dao = db.open(ProductDao.class);
+        final SupportedTypes obj1b = dao.getCustomDataType(id);
+        assertNotNull(obj1b);
+        assertTrue(obj1a.equivalentTo(obj1b));
 
-               // update the stored object
-               obj1b.myString = "dta update successful";
-               dao.setSupportedTypes(id, obj1b);
+        // update the stored object
+        obj1b.myString = "dta update successful";
+        dao.setSupportedTypes(id, obj1b);
 
-               // confirm the update took place
-               final SupportedTypes obj2 = dao.getCustomDataType(id);
-               assertNotNull(obj2);
-               assertEquals("dta update successful", obj2.myString);
-               assertTrue(obj1b.equivalentTo(obj2));
-       }
+        // confirm the update took place
+        final SupportedTypes obj2 = dao.getCustomDataType(id);
+        assertNotNull(obj2);
+        assertEquals("dta update successful", obj2.myString);
+        assertTrue(obj1b.equivalentTo(obj2));
+    }
 
-       @Test
-       public void testDefaultProdResourceQueryReturnModels() {
+    @Test
+    public void testDefaultProdResourceQueryReturnModels() {
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product[] products = dao.getProductsFromResourceQuery();
-               assertEquals(10, products.length);
-       }
+        Product[] products = dao.getProductsFromResourceQuery();
+        assertEquals(10, products.length);
+    }
 
-       @Test
-       public void testDevResourceQueryReturnModels() {
+    @Test
+    public void testDevResourceQueryReturnModels() {
 
-               Db db = IciqlSuite.openNewDb(Mode.DEV);
-               db.insertAll(Product.getList());
-               db.insertAll(Order.getList());
-               db.setDaoStatementProvider(new DaoClasspathStatementProvider());
+        Db db = IciqlSuite.openNewDb(Mode.DEV);
+        db.insertAll(Product.getList());
+        db.insertAll(Order.getList());
+        db.setDaoStatementProvider(new DaoClasspathStatementProvider());
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product[] products = dao.getProductsFromResourceQuery();
-               assertEquals(5, products.length);
+        Product[] products = dao.getProductsFromResourceQuery();
+        assertEquals(5, products.length);
 
-               db.close();
-       }
+        db.close();
+    }
 
-       @Test
-       public void testTestResourceQueryReturnModels() {
+    @Test
+    public void testTestResourceQueryReturnModels() {
 
-               Db db = IciqlSuite.openNewDb(Mode.TEST);
-               db.insertAll(Product.getList());
-               db.insertAll(Order.getList());
-               db.setDaoStatementProvider(new DaoClasspathStatementProvider());
+        Db db = IciqlSuite.openNewDb(Mode.TEST);
+        db.insertAll(Product.getList());
+        db.insertAll(Order.getList());
+        db.setDaoStatementProvider(new DaoClasspathStatementProvider());
 
-               ProductDao dao = db.open(ProductDao.class);
+        ProductDao dao = db.open(ProductDao.class);
 
-               Product[] products = dao.getProductsFromResourceQuery();
-               assertEquals(2, products.length);
+        Product[] products = dao.getProductsFromResourceQuery();
+        assertEquals(2, products.length);
 
-               db.close();
-       }
+        db.close();
+    }
 
-       /**
-        * Define the Product DAO interface.
-        */
-       public interface ProductDao extends Dao {
+    /**
+     * Define the Product DAO interface.
+     */
+    public interface ProductDao extends Dao {
 
-               @SqlQuery("select * from Product")
-               void getWithIllegalVoid();
+        @SqlQuery("select * from Product")
+        void getWithIllegalVoid();
 
-               @SqlQuery("select * from Product")
-               List<Product> getWithIllegalCollection();
+        @SqlQuery("select * from Product")
+        List<Product> getWithIllegalCollection();
 
-               @SqlQuery("select * from Product where ::id = 1")
-               Product getWithDoubleDelimiter();
+        @SqlQuery("select * from Product where ::id = 1")
+        Product getWithDoubleDelimiter();
 
-               @SqlQuery("select * from Product")
-               Product[] getAllProducts();
+        @SqlQuery("select * from Product")
+        Product[] getAllProducts();
 
-               @SqlQuery("select * from Product where productId = :id")
-               Product getProduct(@Bind("id") long id);
+        @SqlQuery("select * from Product where productId = :id")
+        Product getProduct(@Bind("id") long id);
 
-               @SqlQuery("select * from Product where productId = :id")
-               Product getProductWithUnusedBoundParameters(
-                               @Bind("irrelevant") boolean whocares,
-                               @Bind("id") long id,
-                               @Bind("dontmatter") String something);
+        @SqlQuery("select * from Product where productId = :id")
+        Product getProductWithUnusedBoundParameters(
+                @Bind("irrelevant") boolean whocares,
+                @Bind("id") long id,
+                @Bind("dontmatter") String something);
 
-               @SqlQuery("select * from Product where productId = :arg1")
-               Product getProductWithUnboundParameters(
-                               boolean whocares,
-                               long id,
-                               String something);
+        @SqlQuery("select * from Product where productId = :arg1")
+        Product getProductWithUnboundParameters(
+                boolean whocares,
+                long id,
+                String something);
 
-               @SqlQuery("select * from Product where productId = :?")
-               Product getProductWithJDBCPlaceholders(long id);
+        @SqlQuery("select * from Product where productId = :?")
+        Product getProductWithJDBCPlaceholders(long id);
 
-               @SqlQuery("select productId from Product where unitsInStock > :p.unitsInStock and category = :p.category")
-               long[] getSimilarInStockItemIds(@BindBean("p") Product p);
+        @SqlQuery("select productId from Product where unitsInStock > :p.unitsInStock and category = :p.category")
+        long[] getSimilarInStockItemIds(@BindBean("p") Product p);
 
-               @SqlQuery("select productName from Product where productId = :?")
-               String getProductName(long id);
+        @SqlQuery("select productName from Product where productId = :?")
+        String getProductName(long id);
 
-               @SqlQuery("select unitsInStock from Product where productId = :?")
-               int getUnitsInStock(long id);
+        @SqlQuery("select unitsInStock from Product where productId = :?")
+        int getUnitsInStock(long id);
 
-               @SqlQuery("select productId from Product where category = :category")
-               long[] getProductIdsForCategory(@Bind("category") String cat);
+        @SqlQuery("select productId from Product where category = :category")
+        long[] getProductIdsForCategory(@Bind("category") String cat);
 
-               // will break ResultSet iteration after retrieving first value
-               @SqlQuery("select orderDate from Orders order by orderDate desc")
-               Date getMostRecentOrder();
+        // will break ResultSet iteration after retrieving first value
+        @SqlQuery("select orderDate from Orders order by orderDate desc")
+        Date getMostRecentOrder();
 
-               @SqlStatement("update Product set productName = 'test' where productId = 1")
-               String setWithIllegalReturnType();
+        @SqlStatement("update Product set productName = 'test' where productId = 1")
+        String setWithIllegalReturnType();
 
-               @SqlStatement("update Product set productName = :name where productId = :id")
-               void setProductName(@Bind("id") long id, @Bind("name") String name);
+        @SqlStatement("update Product set productName = :name where productId = :id")
+        void setProductName(@Bind("id") long id, @Bind("name") String name);
 
-               @SqlStatement("update Product set productName = :name where productId = :id")
-               boolean setProductNameReturnsSuccess(@Bind("id") long id, @Bind("name") String name);
+        @SqlStatement("update Product set productName = :name where productId = :id")
+        boolean setProductNameReturnsSuccess(@Bind("id") long id, @Bind("name") String name);
 
-               @SqlStatement("update Product set category = :newCategory where category = :oldCategory")
-               int renameProductCategoryReturnsCount(@Bind("oldCategory") String oldCategory, @Bind("newCategory") String newCategory);
+        @SqlStatement("update Product set category = :newCategory where category = :oldCategory")
+        int renameProductCategoryReturnsCount(@Bind("oldCategory") String oldCategory, @Bind("newCategory") String newCategory);
 
-               @SqlQuery("select obj from dataTypeAdapters where id=:1")
-               @SupportedTypesAdapter
-               SupportedTypes getCustomDataType(long id);
+        @SqlQuery("select obj from dataTypeAdapters where id=:1")
+        @SupportedTypesAdapter
+        SupportedTypes getCustomDataType(long id);
 
-               @SqlStatement("update dataTypeAdapters set obj=:2 where id=:1")
-               boolean setSupportedTypes(long id, @SupportedTypesAdapter SupportedTypes obj);
+        @SqlStatement("update dataTypeAdapters set obj=:2 where id=:1")
+        boolean setSupportedTypes(long id, @SupportedTypesAdapter SupportedTypes obj);
 
-               @SqlQuery("get.products")
-               Product[] getProductsFromResourceQuery();
+        @SqlQuery("get.products")
+        Product[] getProductsFromResourceQuery();
 
-       }
+    }
 }
index 8220d7fccda066a9cff31850ff5e73f27e7cfb0b..8a5bc5b3bd90c4a54823c6972f929a1964ea64bd 100644 (file)
  */\r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.text.MessageFormat;\r
-import java.text.SimpleDateFormat;\r
-import java.util.List;\r
-\r
-import org.junit.Assume;\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.QueryWhere;\r
 import com.iciql.test.models.EnumModels.Tree;\r
@@ -33,182 +22,192 @@ import com.iciql.test.models.Product;
 import com.iciql.test.models.StaticQueries;\r
 import com.iciql.util.JdbcUtils;\r
 import com.iciql.util.Utils;\r
+import org.junit.Assume;\r
+import org.junit.Test;\r
+\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.text.MessageFormat;\r
+import java.text.SimpleDateFormat;\r
+import java.util.List;\r
+\r
+import static org.junit.Assert.assertEquals;\r
 \r
 /**\r
  * Tests the runtime dynamic query function.\r
  */\r
 public class RuntimeQueryTest {\r
 \r
-       @Test\r
-       public void testParameters() {\r
-               Db db = IciqlSuite.openNewDb();\r
+    @Test\r
+    public void testParameters() {\r
+        Db db = IciqlSuite.openNewDb();\r
 \r
-               // do not test non-H2 databases because dialects will get in the way\r
-               // e.g. column quoting, etc\r
-               Assume.assumeTrue(IciqlSuite.isH2(db));\r
+        // do not test non-H2 databases because dialects will get in the way\r
+        // e.g. column quoting, etc\r
+        Assume.assumeTrue(IciqlSuite.isH2(db));\r
 \r
-               Product p = new Product();\r
-               String q1 = db.from(p).where(p.unitsInStock).isParameter().and(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
-               String q2 = db.from(p).where(p.unitsInStock).lessThan(100).and(p.productName).like("test").or(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
+        Product p = new Product();\r
+        String q1 = db.from(p).where(p.unitsInStock).isParameter().and(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
+        String q2 = db.from(p).where(p.unitsInStock).lessThan(100).and(p.productName).like("test").or(p.productName).likeParameter().orderBy(p.productId).toSQL();\r
 \r
-               StaticQueries.StaticModel1 m1 = new StaticQueries.StaticModel1();\r
-               String q3 = db.from(m1).where(m1.myTree).is(Tree.MAPLE).and(m1.myTree).isParameter().toSQL();\r
+        StaticQueries.StaticModel1 m1 = new StaticQueries.StaticModel1();\r
+        String q3 = db.from(m1).where(m1.myTree).is(Tree.MAPLE).and(m1.myTree).isParameter().toSQL();\r
 \r
-               StaticQueries.StaticModel2 m2 = new StaticQueries.StaticModel2();\r
-               String q4 = db.from(m2).where(m2.myTree).is(Tree.MAPLE).and(m2.myTree).isParameter().toSQL();\r
+        StaticQueries.StaticModel2 m2 = new StaticQueries.StaticModel2();\r
+        String q4 = db.from(m2).where(m2.myTree).is(Tree.MAPLE).and(m2.myTree).isParameter().toSQL();\r
 \r
-               StaticQueries.StaticModel3 m3 = new StaticQueries.StaticModel3();\r
-               String q5 = db.from(m3).where(m3.myTree).is(Tree.MAPLE).and(m3.myTree).isParameter().toSQL();\r
+        StaticQueries.StaticModel3 m3 = new StaticQueries.StaticModel3();\r
+        String q5 = db.from(m3).where(m3.myTree).is(Tree.MAPLE).and(m3.myTree).isParameter().toSQL();\r
 \r
-               long now = System.currentTimeMillis();\r
-               java.sql.Date aDate = new java.sql.Date(now);\r
-               java.sql.Time aTime = new java.sql.Time(now);\r
-               java.sql.Timestamp aTimestamp = new java.sql.Timestamp(now);\r
+        long now = System.currentTimeMillis();\r
+        java.sql.Date aDate = new java.sql.Date(now);\r
+        java.sql.Time aTime = new java.sql.Time(now);\r
+        java.sql.Timestamp aTimestamp = new java.sql.Timestamp(now);\r
 \r
-               String q6 = db.from(m1).where(m1.myDate).is(aDate).and(m1.myDate).isParameter().toSQL();\r
-               String q7 = db.from(m1).where(m1.myTime).is(aTime).and(m1.myTime).isParameter().toSQL();\r
-               String q8 = db.from(m1).where(m1.myTimestamp).is(aTimestamp).and(m1.myTimestamp).isParameter().toSQL();\r
+        String q6 = db.from(m1).where(m1.myDate).is(aDate).and(m1.myDate).isParameter().toSQL();\r
+        String q7 = db.from(m1).where(m1.myTime).is(aTime).and(m1.myTime).isParameter().toSQL();\r
+        String q8 = db.from(m1).where(m1.myTimestamp).is(aTimestamp).and(m1.myTimestamp).isParameter().toSQL();\r
 \r
-               db.close();\r
-               assertEquals("SELECT * FROM Product WHERE unitsInStock = ? AND productName LIKE ?  ORDER BY productId", q1);\r
-               assertEquals("SELECT * FROM Product WHERE unitsInStock < 100 AND productName LIKE 'test' OR productName LIKE ?  ORDER BY productId", q2);\r
+        db.close();\r
+        assertEquals("SELECT * FROM Product WHERE unitsInStock = ? AND productName LIKE ?  ORDER BY productId", q1);\r
+        assertEquals("SELECT * FROM Product WHERE unitsInStock < 100 AND productName LIKE 'test' OR productName LIKE ?  ORDER BY productId", q2);\r
 \r
-               assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTree = 'MAPLE' AND myTree = ?", q3);\r
-               assertEquals("SELECT * FROM StaticQueryTest2 WHERE myTree = 50 AND myTree = ?", q4);\r
-               assertEquals("SELECT * FROM StaticQueryTest3 WHERE myTree = 4 AND myTree = ?", q5);\r
+        assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTree = 'MAPLE' AND myTree = ?", q3);\r
+        assertEquals("SELECT * FROM StaticQueryTest2 WHERE myTree = 50 AND myTree = ?", q4);\r
+        assertEquals("SELECT * FROM StaticQueryTest3 WHERE myTree = 4 AND myTree = ?", q5);\r
 \r
-               java.util.Date refDate = new java.util.Date(now);\r
-               assertEquals("SELECT * FROM StaticQueryTest1 WHERE myDate = '" + new SimpleDateFormat("yyyy-MM-dd").format(refDate) + "' AND myDate = ?", q6);\r
-               assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTime = '" + new SimpleDateFormat("HH:mm:ss").format(refDate) + "' AND myTime = ?", q7);\r
-               assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTimestamp = '" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(refDate) + "' AND myTimestamp = ?", q8);\r
-       }\r
+        java.util.Date refDate = new java.util.Date(now);\r
+        assertEquals("SELECT * FROM StaticQueryTest1 WHERE myDate = '" + new SimpleDateFormat("yyyy-MM-dd").format(refDate) + "' AND myDate = ?", q6);\r
+        assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTime = '" + new SimpleDateFormat("HH:mm:ss").format(refDate) + "' AND myTime = ?", q7);\r
+        assertEquals("SELECT * FROM StaticQueryTest1 WHERE myTimestamp = '" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(refDate) + "' AND myTimestamp = ?", q8);\r
+    }\r
 \r
-       @Test\r
-       public void testRuntimeSet() {\r
-               Db db = IciqlSuite.openNewDb();\r
+    @Test\r
+    public void testRuntimeSet() {\r
+        Db db = IciqlSuite.openNewDb();\r
 \r
-               // do not test non-H2 databases because dialects will get in the way\r
-               // e.g. column quoting, etc\r
-               Assume.assumeTrue(IciqlSuite.isH2(db));\r
+        // do not test non-H2 databases because dialects will get in the way\r
+        // e.g. column quoting, etc\r
+        Assume.assumeTrue(IciqlSuite.isH2(db));\r
 \r
-               StaticQueries.StaticModel1 m = new StaticQueries.StaticModel1();\r
-               String q = db.from(m).set(m.myTimestamp).toParameter().where(m.id).isParameter().toSQL();\r
-               db.close();\r
+        StaticQueries.StaticModel1 m = new StaticQueries.StaticModel1();\r
+        String q = db.from(m).set(m.myTimestamp).toParameter().where(m.id).isParameter().toSQL();\r
+        db.close();\r
 \r
-               assertEquals("UPDATE StaticQueryTest1 SET myTimestamp = ? WHERE id = ?", q);\r
-       }\r
+        assertEquals("UPDATE StaticQueryTest1 SET myTimestamp = ? WHERE id = ?", q);\r
+    }\r
 \r
-       @Test\r
-       public void testRuntimeSelectWildcards() {\r
-               Db db = IciqlSuite.openNewDb();\r
+    @Test\r
+    public void testRuntimeSelectWildcards() {\r
+        Db db = IciqlSuite.openNewDb();\r
 \r
-               // do not test non-H2 databases because dialects will get in the way\r
-               // e.g. column quoting, etc\r
-               Assume.assumeTrue(IciqlSuite.isH2(db));\r
+        // do not test non-H2 databases because dialects will get in the way\r
+        // e.g. column quoting, etc\r
+        Assume.assumeTrue(IciqlSuite.isH2(db));\r
 \r
-               StaticQueries.StaticModel1 m1 = new StaticQueries.StaticModel1();\r
-               StaticQueries.StaticModel2 m2 = new StaticQueries.StaticModel2();\r
-               StaticQueries.StaticModel2 m3 = new StaticQueries.StaticModel2();\r
+        StaticQueries.StaticModel1 m1 = new StaticQueries.StaticModel1();\r
+        StaticQueries.StaticModel2 m2 = new StaticQueries.StaticModel2();\r
+        StaticQueries.StaticModel2 m3 = new StaticQueries.StaticModel2();\r
 \r
-               int t0 = Utils.AS_COUNTER.get() + 1;\r
-               int t1 = t0 + 1;\r
+        int t0 = Utils.AS_COUNTER.get() + 1;\r
+        int t1 = t0 + 1;\r
 \r
-               QueryWhere<?> where = db.from(m1).innerJoin(m2).on(m1.id).is(m2.id).where(m2.myTree).is(Tree.MAPLE);\r
-               String q1 = where.toSQL(false);\r
-               String q2 = where.toSQL(true);\r
-               String q3 = where.toSQL(false, m1);\r
-               String q4 = where.toSQL(true, m1);\r
-               String q5 = where.toSQL(false, m2);\r
-               String q6 = where.toSQL(true, m2);\r
+        QueryWhere<?> where = db.from(m1).innerJoin(m2).on(m1.id).is(m2.id).where(m2.myTree).is(Tree.MAPLE);\r
+        String q1 = where.toSQL(false);\r
+        String q2 = where.toSQL(true);\r
+        String q3 = where.toSQL(false, m1);\r
+        String q4 = where.toSQL(true, m1);\r
+        String q5 = where.toSQL(false, m2);\r
+        String q6 = where.toSQL(true, m2);\r
 \r
-               // test unused alias\r
-               String q7 = where.toSQL(true, m3);\r
+        // test unused alias\r
+        String q7 = where.toSQL(true, m3);\r
 \r
-               db.close();\r
+        db.close();\r
 \r
-               assertEquals(MessageFormat.format("SELECT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q1);\r
-               assertEquals(MessageFormat.format("SELECT DISTINCT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q2);\r
+        assertEquals(MessageFormat.format("SELECT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q1);\r
+        assertEquals(MessageFormat.format("SELECT DISTINCT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q2);\r
 \r
-               assertEquals(MessageFormat.format("SELECT T{0,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q3);\r
-               assertEquals(MessageFormat.format("SELECT DISTINCT T{0,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q4);\r
+        assertEquals(MessageFormat.format("SELECT T{0,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q3);\r
+        assertEquals(MessageFormat.format("SELECT DISTINCT T{0,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q4);\r
 \r
-               assertEquals(MessageFormat.format("SELECT T{1,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q5);\r
-               assertEquals(MessageFormat.format("SELECT DISTINCT T{1,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q6);\r
+        assertEquals(MessageFormat.format("SELECT T{1,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q5);\r
+        assertEquals(MessageFormat.format("SELECT DISTINCT T{1,number,0}.* FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q6);\r
 \r
-               assertEquals(MessageFormat.format("SELECT DISTINCT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q7);\r
-       }\r
+        assertEquals(MessageFormat.format("SELECT DISTINCT * FROM StaticQueryTest1 AS T{0,number,0} INNER JOIN StaticQueryTest2 AS T{1,number,0} ON T{0,number,0}.id = T{1,number,0}.id  WHERE T{1,number,0}.myTree = 50", t0, t1), q7);\r
+    }\r
 \r
-       @Test\r
-       public void testRuntimeQuery() {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(Product.getList());\r
+    @Test\r
+    public void testRuntimeQuery() {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(Product.getList());\r
 \r
-               String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
-               String productName = db.getDialect().prepareColumnName("productName");\r
-               String productId = db.getDialect().prepareColumnName("productId");\r
+        String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
+        String productName = db.getDialect().prepareColumnName("productName");\r
+        String productId = db.getDialect().prepareColumnName("productId");\r
 \r
-               Product p = new Product();\r
-               List<Product> products = db.from(p).where(unitsInStock + "=?", 120).orderBy(p.productId).select();\r
-               assertEquals(1, products.size());\r
+        Product p = new Product();\r
+        List<Product> products = db.from(p).where(unitsInStock + "=?", 120).orderBy(p.productId).select();\r
+        assertEquals(1, products.size());\r
 \r
-               products = db.from(p).where(String.format("%s=? and productName like ? order by productId",\r
-                               unitsInStock, productName, productId), 0, "Chef%")\r
-                               .select();\r
-               assertEquals(1, products.size());\r
-\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testExecuteQuery() throws SQLException {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(Product.getList());\r
-\r
-               String product = db.getDialect().prepareTableName(null, "Product");\r
-               String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
-\r
-               // test plain statement\r
-               List<Product> products = db.executeQuery(Product.class,\r
-                               String.format("select * from %s where %s=120",\r
-                                               product, unitsInStock));\r
-               assertEquals(1, products.size());\r
-               assertEquals("Condiments", products.get(0).category);\r
-\r
-               // test prepared statement\r
-               products = db.executeQuery(Product.class, String.format("select * from %s where %s=?",\r
-                               product, unitsInStock), 120);\r
-               assertEquals(1, products.size());\r
-               assertEquals("Condiments", products.get(0).category);\r
-\r
-               db.close();\r
-       }\r
+        products = db.from(p).where(String.format("%s=? and productName like ? order by productId",\r
+                unitsInStock, productName, productId), 0, "Chef%")\r
+                .select();\r
+        assertEquals(1, products.size());\r
+\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testExecuteQuery() throws SQLException {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(Product.getList());\r
+\r
+        String product = db.getDialect().prepareTableName(null, "Product");\r
+        String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
+\r
+        // test plain statement\r
+        List<Product> products = db.executeQuery(Product.class,\r
+                String.format("select * from %s where %s=120",\r
+                        product, unitsInStock));\r
+        assertEquals(1, products.size());\r
+        assertEquals("Condiments", products.get(0).category);\r
+\r
+        // test prepared statement\r
+        products = db.executeQuery(Product.class, String.format("select * from %s where %s=?",\r
+                product, unitsInStock), 120);\r
+        assertEquals(1, products.size());\r
+        assertEquals("Condiments", products.get(0).category);\r
+\r
+        db.close();\r
+    }\r
 \r
-       @Test\r
-       public void testBuildObjects() throws SQLException {\r
-               Db db = IciqlSuite.openNewDb();\r
-               db.insertAll(Product.getList());\r
-\r
-               String product = db.getDialect().prepareTableName(null, "Product");\r
-               String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
+    @Test\r
+    public void testBuildObjects() throws SQLException {\r
+        Db db = IciqlSuite.openNewDb();\r
+        db.insertAll(Product.getList());\r
+\r
+        String product = db.getDialect().prepareTableName(null, "Product");\r
+        String unitsInStock = db.getDialect().prepareColumnName("unitsInStock");\r
 \r
-               // test plain statement\r
-               ResultSet rs = db.executeQuery(String.format("select * from %s where %s=120",\r
-                               product, unitsInStock));\r
-               List<Product> products = db.buildObjects(Product.class, rs);\r
-               JdbcUtils.closeSilently(rs, true);\r
+        // test plain statement\r
+        ResultSet rs = db.executeQuery(String.format("select * from %s where %s=120",\r
+                product, unitsInStock));\r
+        List<Product> products = db.buildObjects(Product.class, rs);\r
+        JdbcUtils.closeSilently(rs, true);\r
 \r
-               assertEquals(1, products.size());\r
-               assertEquals("Condiments", products.get(0).category);\r
-\r
-               // test prepared statement\r
-               rs = db.executeQuery(String.format("select * from %s where %s=?",\r
-                               product, unitsInStock), 120);\r
-               products = db.buildObjects(Product.class, rs);\r
-               JdbcUtils.closeSilently(rs, true);\r
+        assertEquals(1, products.size());\r
+        assertEquals("Condiments", products.get(0).category);\r
+\r
+        // test prepared statement\r
+        rs = db.executeQuery(String.format("select * from %s where %s=?",\r
+                product, unitsInStock), 120);\r
+        products = db.buildObjects(Product.class, rs);\r
+        JdbcUtils.closeSilently(rs, true);\r
 \r
-               assertEquals(1, products.size());\r
-               assertEquals("Condiments", products.get(0).category);\r
+        assertEquals(1, products.size());\r
+        assertEquals("Condiments", products.get(0).category);\r
 \r
-               db.close();\r
-       }\r
+        db.close();\r
+    }\r
 }\r
index dbbf97fa2061b6586ff3f48c0e04ede74b6500bf..e3b3ea5b7008facc998f4661bd21f899757e3555 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static com.iciql.Function.count;\r
-import static com.iciql.Function.isNull;\r
-import static com.iciql.Function.length;\r
-import static com.iciql.Function.max;\r
-import static com.iciql.Function.min;\r
-import static com.iciql.Function.not;\r
-import static com.iciql.Function.sum;\r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertTrue;\r
-\r
-import java.math.BigDecimal;\r
-import java.text.DecimalFormat;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-import org.junit.After;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.Filter;\r
 import com.iciql.Iciql.IQColumn;\r
@@ -47,6 +26,20 @@ import com.iciql.test.models.Customer;
 import com.iciql.test.models.Order;\r
 import com.iciql.test.models.Product;\r
 import com.iciql.test.models.SupportedTypes;\r
+import org.junit.After;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+\r
+import java.math.BigDecimal;\r
+import java.text.DecimalFormat;\r
+import java.util.Collections;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import static com.iciql.Function.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 /**\r
  * This is the implementation of the 101 LINQ Samples as described in\r
@@ -54,399 +47,399 @@ import com.iciql.test.models.SupportedTypes;
  */\r
 public class SamplesTest {\r
 \r
-       /**\r
-        * This object represents a database (actually a connection to the\r
-        * database).\r
-        */\r
-\r
-       Db db;\r
-\r
-       @Before\r
-       public void setUp() {\r
-               db = IciqlSuite.openNewDb();\r
-               db.insertAll(Product.getList());\r
-               db.insertAll(Customer.getList());\r
-               db.insertAll(Order.getList());\r
-               db.insertAll(ComplexObject.getList());\r
-       }\r
-\r
-       @After\r
-       public void tearDown() {\r
-               db.close();\r
-       }\r
-\r
-       /**\r
-        * A simple test table. The columns are in a different order than in the\r
-        * database.\r
-        */\r
-       public static class TestReverse {\r
-               public String name;\r
-               public Integer id;\r
-       }\r
-\r
-       @Test\r
-       public void testReverseColumns() {\r
-               try {\r
-                       db.executeUpdate("DROP TABLE TestReverse");\r
-               } catch (IciqlException e) {\r
-               }\r
-               db.executeUpdate("create table TestReverse(id int, name varchar(10), additional varchar(10))");\r
-               TestReverse t = new TestReverse();\r
-               t.id = 10;\r
-               t.name = "Hello";\r
-               db.insert(t);\r
-               TestReverse check = db.from(new TestReverse()).selectFirst();\r
-               assertEquals(t.name, check.name);\r
-               assertEquals(t.id, check.id);\r
-               db.executeUpdate("DROP TABLE TestReverse");\r
-       }\r
-\r
-       @Test\r
-       public void testWhereSimple2() {\r
-\r
-               // var soldOutProducts =\r
-               // from p in products\r
-               // where p.UnitsInStock == 0\r
-               // select p;\r
-\r
-               Product p = new Product();\r
-               List<Product> soldOutProducts = db.from(p).where(p.unitsInStock).is(0).orderBy(p.productId).select();\r
-               List<Product> soldOutProducts2 = db.from(p).where(p.unitsInStock).is(0).orderBy(p.productId).select(p);\r
-\r
-               assertEquals("[Chef Anton's Gumbo Mix: 0]", soldOutProducts.toString());\r
-               assertEquals(soldOutProducts.toString(), soldOutProducts2.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testWhereSimple3() {\r
-\r
-               // var expensiveInStockProducts =\r
-               // from p in products\r
-               // where p.UnitsInStock > 0\r
-               // && p.UnitPrice > 3.00M\r
-               // select p;\r
-\r
-               Product p = new Product();\r
-               List<Product> expensiveInStockProducts = db.from(p).where(p.unitsInStock).exceeds(0).and(p.unitPrice)\r
-                               .exceeds(30.0).orderBy(p.productId).select();\r
-\r
-               assertEquals("[Northwoods Cranberry Sauce: 6, Mishi Kobe Niku: 29, Ikura: 31]",\r
-                               expensiveInStockProducts.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testWhereSimple4() {\r
-\r
-               // var waCustomers =\r
-               // from c in customers\r
-               // where c.Region == "WA"\r
-               // select c;\r
-\r
-               Customer c = new Customer();\r
-               List<Customer> waCustomers = db.from(c).where(c.region).is("WA").select();\r
-\r
-               assertEquals("[ALFKI, ANATR]", waCustomers.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testSelectSimple2() {\r
-\r
-               // var productNames =\r
-               // from p in products\r
-               // select p.ProductName;\r
-\r
-               Product p = new Product();\r
-               List<String> productNames = db.from(p).orderBy(p.productId).select(p.productName);\r
-\r
-               List<Product> products = Product.getList();\r
-               for (int i = 0; i < products.size(); i++) {\r
-                       assertEquals(products.get(i).productName, productNames.get(i));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * A result set class containing the product name and price.\r
-        */\r
-       public static class ProductPrice {\r
-               public String productName;\r
-               public String category;\r
-               @IQColumn(name = "unitPrice")\r
-               public Double price;\r
-       }\r
-\r
-       @Test\r
-       public void testAnonymousTypes3() {\r
-\r
-               // var productInfos =\r
-               // from p in products\r
-               // select new {\r
-               // p.ProductName,\r
-               // p.Category,\r
-               // Price = p.UnitPrice\r
-               // };\r
-\r
-               final Product p = new Product();\r
-               List<ProductPrice> productInfos = db.from(p).orderBy(p.productId).select(new ProductPrice() {\r
-                       {\r
-                               productName = p.productName;\r
-                               category = p.category;\r
-                               price = p.unitPrice;\r
-                       }\r
-               });\r
-\r
-               List<Product> products = Product.getList();\r
-               assertEquals(products.size(), productInfos.size());\r
-               for (int i = 0; i < products.size(); i++) {\r
-                       ProductPrice pr = productInfos.get(i);\r
-                       Product p2 = products.get(i);\r
-                       assertEquals(p2.productName, pr.productName);\r
-                       assertEquals(p2.category, pr.category);\r
-                       assertEquals(p2.unitPrice, pr.price);\r
-               }\r
-       }\r
-\r
-       /**\r
-        * A result set class containing customer data and the order total.\r
-        */\r
-       public static class CustOrder {\r
-               public String customerId;\r
-               public Integer orderId;\r
-               public BigDecimal total;\r
-\r
-               @Override\r
-               public String toString() {\r
-                       return customerId + ":" + orderId + ":" + new DecimalFormat("##.00").format(total);\r
-               }\r
-       }\r
-\r
-       @Test\r
-       public void testSelectManyCompoundFrom2() {\r
-\r
-               // var orders =\r
-               // from c in customers,\r
-               // o in c.Orders\r
-               // where o.Total < 500.00M\r
-               // select new {\r
-               // c.CustomerID,\r
-               // o.OrderID,\r
-               // o.Total\r
-               // };\r
-\r
-               final Customer c = new Customer();\r
-               final Order o = new Order();\r
-               List<CustOrder> orders = db.from(c).innerJoin(o).on(c.customerId).is(o.customerId).where(o.total)\r
-                               .lessThan(new BigDecimal("100.00")).orderBy(c.customerId).select(new CustOrder() {\r
-                                       {\r
-                                               customerId = c.customerId;\r
-                                               orderId = o.orderId;\r
-                                               total = o.total;\r
-                                       }\r
-                               });\r
-\r
-               assertEquals("[ANATR:10308:88.80]", orders.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testIsNull() {\r
-               Product p = new Product();\r
-               String sql = db.from(p).whereTrue(isNull(p.productName)).getSQL();\r
-               assertEquals("SELECT * FROM Product WHERE (" + db.getDialect().prepareColumnName("productName")\r
-                               + " IS NULL)", sql);\r
-       }\r
-\r
-       @Test\r
-       public void testDelete() {\r
-               Product p = new Product();\r
-               int deleted = db.from(p).where(p.productName).like("A%").delete();\r
-               assertEquals(1, deleted);\r
-               deleted = db.from(p).delete();\r
-               assertEquals(9, deleted);\r
-               db.insertAll(Product.getList());\r
-               db.deleteAll(Product.getList());\r
-               assertEquals(0, db.from(p).selectCount());\r
-               db.insertAll(Product.getList());\r
-       }\r
-\r
-       @Test\r
-       public void testOrAndNot() {\r
-               Product p = new Product();\r
-               String sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();\r
-               String productName = db.getDialect().prepareColumnName("productName");\r
-               assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);\r
-               sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();\r
-               assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);\r
-               sql = db.from(p).whereTrue(db.test(p.productId).is(1)).getSQL();\r
-               String productId = db.getDialect().prepareColumnName("productId");\r
-               assertEquals("SELECT * FROM Product WHERE ((" + productId + " = ?))", sql);\r
-       }\r
-\r
-       @Test\r
-       public void testLength() {\r
-               Product p = new Product();\r
-               List<Integer> lengths = db.from(p).where(length(p.productName)).lessThan(10)\r
-                               .selectDistinct(length(p.productName));\r
-               // Formerly used orderBy(1) here, but that is not portable across DBs\r
-               Collections.sort(lengths);\r
-               assertEquals("[4, 5]", lengths.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testSum() {\r
-               Product p = new Product();\r
-               Number sum = db.from(p).selectFirst(sum(p.unitsInStock));\r
-               assertEquals(323, sum.intValue());\r
-               Double sumPrice = db.from(p).selectFirst(sum(p.unitPrice));\r
-               assertEquals(313.35, sumPrice.doubleValue(), 0.001);\r
-       }\r
-\r
-       @Test\r
-       public void testMinMax() {\r
-               Product p = new Product();\r
-               Integer min = db.from(p).selectFirst(min(p.unitsInStock));\r
-               assertEquals(0, min.intValue());\r
-               String minName = db.from(p).selectFirst(min(p.productName));\r
-               assertEquals("Aniseed Syrup", minName);\r
-               Double max = db.from(p).selectFirst(max(p.unitPrice));\r
-               assertEquals(97.0, max.doubleValue(), 0.001);\r
-       }\r
-\r
-       @Test\r
-       public void testLike() {\r
-               Product p = new Product();\r
-               List<Product> aList = db.from(p).where(p.productName).like("Cha%").orderBy(p.productName).select();\r
-               assertEquals("[Chai: 39, Chang: 17]", aList.toString());\r
-       }\r
-\r
-       @Test\r
-       public void testCount() {\r
-               long count = db.from(new Product()).selectCount();\r
-               assertEquals(10, count);\r
-       }\r
-\r
-       @Test\r
-       public void testComplexObject() {\r
-               ComplexObject co = new ComplexObject();\r
-               String sql = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday)\r
-                               .lessThan(new java.util.Date()).and(co.created)\r
-                               .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello")\r
-                               .and(co.time).lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value)\r
-                               .is(new BigDecimal("1")).getSQL();\r
-\r
-               StringBuilder sb = new StringBuilder();\r
-               sb.append("SELECT * FROM ComplexObject WHERE ");\r
-               sb.append(db.getDialect().prepareColumnName("id"));\r
-               sb.append(" = ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("amount"));\r
-               sb.append(" = ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("birthday"));\r
-               sb.append(" < ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("created"));\r
-               sb.append(" < ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("name"));\r
-               sb.append(" = ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("time"));\r
-               sb.append(" < ? AND ");\r
-               sb.append(db.getDialect().prepareColumnName("value"));\r
-               sb.append(" = ?");\r
-               assertEquals(sb.toString(), sql);\r
-\r
-               long count = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday)\r
-                               .lessThan(new java.util.Date()).and(co.created)\r
-                               .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello")\r
-                               .and(co.time).lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value)\r
-                               .is(new BigDecimal("1")).selectCount();\r
-               assertEquals(1, count);\r
-       }\r
-\r
-       @Test\r
-       public void testComplexObject2() {\r
-               testComplexObject2(1, "hello");\r
-       }\r
-\r
-       private void testComplexObject2(final int x, final String name) {\r
-               final ComplexObject co = new ComplexObject();\r
-\r
-               String sql = db.from(co).where(new Filter() {\r
-                       @Override\r
-                       public boolean where() {\r
-                               return co.id == x && co.name.equals(name) && co.name.equals("hello");\r
-                       }\r
-               }).getSQL();\r
-               StringBuilder sb = new StringBuilder();\r
-               sb.append("SELECT * FROM ComplexObject WHERE ");\r
-               sb.append(db.getDialect().prepareColumnName("id"));\r
-               sb.append("=? AND ?=");\r
-               sb.append(db.getDialect().prepareColumnName("name"));\r
-               sb.append(" AND 'hello'=");\r
-               sb.append(db.getDialect().prepareColumnName("name"));\r
-               assertEquals(sb.toString(), sql);\r
-\r
-               long count = db.from(co).where(new Filter() {\r
-                       @Override\r
-                       public boolean where() {\r
-                               return co.id == x && co.name.equals(name) && co.name.equals("hello");\r
-                       }\r
-               }).selectCount();\r
-\r
-               assertEquals(1, count);\r
-       }\r
-\r
-       @Test\r
-       public void testLimitOffset() {\r
-               Set<Integer> ids = new HashSet<Integer>();\r
-               Product p = new Product();\r
-               for (int i = 0; i < 5; i++) {\r
-                       List<Product> products = db.from(p).limit(2).offset(2 * i).select();\r
-                       assertTrue(products.size() == 2);\r
-                       for (Product prod : products) {\r
-                               assertTrue("Failed to add product id.  Duplicate?", ids.add(prod.productId));\r
-                       }\r
-               }\r
-       }\r
-\r
-       @Test\r
-       public void testKeyRetrieval() {\r
-               List<SupportedTypes> list = SupportedTypes.createList();\r
-               List<Long> keys = db.insertAllAndGetKeys(list);\r
-               Set<Long> uniqueKeys = new HashSet<Long>();\r
-               for (Long l : keys) {\r
-                       assertTrue("Failed to add key.  Duplicate?", uniqueKeys.add(l));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * A result set class containing product groups.\r
-        */\r
-       public static class ProductGroup {\r
-               public String category;\r
-               public Long productCount;\r
-\r
-               @Override\r
-               public String toString() {\r
-                       return category + ":" + productCount;\r
-               }\r
-       }\r
-\r
-       @Test\r
-       public void testGroup() {\r
-\r
-               // var orderGroups =\r
-               // from p in products\r
-               // group p by p.Category into g\r
-               // select new {\r
-               // Category = g.Key,\r
-               // Products = g\r
-               // };\r
-\r
-               final Product p = new Product();\r
-               List<ProductGroup> list = db.from(p).groupBy(p.category).orderBy(p.category)\r
-                               .select(new ProductGroup() {\r
-                                       {\r
-                                               category = p.category;\r
-                                               productCount = count();\r
-                                       }\r
-                               });\r
-               assertEquals("[Beverages:2, Condiments:5, Meat/Poultry:1, Produce:1, Seafood:1]", list.toString());\r
-       }\r
+    /**\r
+     * This object represents a database (actually a connection to the\r
+     * database).\r
+     */\r
+\r
+    Db db;\r
+\r
+    @Before\r
+    public void setUp() {\r
+        db = IciqlSuite.openNewDb();\r
+        db.insertAll(Product.getList());\r
+        db.insertAll(Customer.getList());\r
+        db.insertAll(Order.getList());\r
+        db.insertAll(ComplexObject.getList());\r
+    }\r
+\r
+    @After\r
+    public void tearDown() {\r
+        db.close();\r
+    }\r
+\r
+    /**\r
+     * A simple test table. The columns are in a different order than in the\r
+     * database.\r
+     */\r
+    public static class TestReverse {\r
+        public String name;\r
+        public Integer id;\r
+    }\r
+\r
+    @Test\r
+    public void testReverseColumns() {\r
+        try {\r
+            db.executeUpdate("DROP TABLE TestReverse");\r
+        } catch (IciqlException e) {\r
+        }\r
+        db.executeUpdate("create table TestReverse(id int, name varchar(10), additional varchar(10))");\r
+        TestReverse t = new TestReverse();\r
+        t.id = 10;\r
+        t.name = "Hello";\r
+        db.insert(t);\r
+        TestReverse check = db.from(new TestReverse()).selectFirst();\r
+        assertEquals(t.name, check.name);\r
+        assertEquals(t.id, check.id);\r
+        db.executeUpdate("DROP TABLE TestReverse");\r
+    }\r
+\r
+    @Test\r
+    public void testWhereSimple2() {\r
+\r
+        // var soldOutProducts =\r
+        // from p in products\r
+        // where p.UnitsInStock == 0\r
+        // select p;\r
+\r
+        Product p = new Product();\r
+        List<Product> soldOutProducts = db.from(p).where(p.unitsInStock).is(0).orderBy(p.productId).select();\r
+        List<Product> soldOutProducts2 = db.from(p).where(p.unitsInStock).is(0).orderBy(p.productId).select(p);\r
+\r
+        assertEquals("[Chef Anton's Gumbo Mix: 0]", soldOutProducts.toString());\r
+        assertEquals(soldOutProducts.toString(), soldOutProducts2.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testWhereSimple3() {\r
+\r
+        // var expensiveInStockProducts =\r
+        // from p in products\r
+        // where p.UnitsInStock > 0\r
+        // && p.UnitPrice > 3.00M\r
+        // select p;\r
+\r
+        Product p = new Product();\r
+        List<Product> expensiveInStockProducts = db.from(p).where(p.unitsInStock).exceeds(0).and(p.unitPrice)\r
+                .exceeds(30.0).orderBy(p.productId).select();\r
+\r
+        assertEquals("[Northwoods Cranberry Sauce: 6, Mishi Kobe Niku: 29, Ikura: 31]",\r
+                expensiveInStockProducts.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testWhereSimple4() {\r
+\r
+        // var waCustomers =\r
+        // from c in customers\r
+        // where c.Region == "WA"\r
+        // select c;\r
+\r
+        Customer c = new Customer();\r
+        List<Customer> waCustomers = db.from(c).where(c.region).is("WA").select();\r
+\r
+        assertEquals("[ALFKI, ANATR]", waCustomers.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testSelectSimple2() {\r
+\r
+        // var productNames =\r
+        // from p in products\r
+        // select p.ProductName;\r
+\r
+        Product p = new Product();\r
+        List<String> productNames = db.from(p).orderBy(p.productId).select(p.productName);\r
+\r
+        List<Product> products = Product.getList();\r
+        for (int i = 0; i < products.size(); i++) {\r
+            assertEquals(products.get(i).productName, productNames.get(i));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A result set class containing the product name and price.\r
+     */\r
+    public static class ProductPrice {\r
+        public String productName;\r
+        public String category;\r
+        @IQColumn(name = "unitPrice")\r
+        public Double price;\r
+    }\r
+\r
+    @Test\r
+    public void testAnonymousTypes3() {\r
+\r
+        // var productInfos =\r
+        // from p in products\r
+        // select new {\r
+        // p.ProductName,\r
+        // p.Category,\r
+        // Price = p.UnitPrice\r
+        // };\r
+\r
+        final Product p = new Product();\r
+        List<ProductPrice> productInfos = db.from(p).orderBy(p.productId).select(new ProductPrice() {\r
+            {\r
+                productName = p.productName;\r
+                category = p.category;\r
+                price = p.unitPrice;\r
+            }\r
+        });\r
+\r
+        List<Product> products = Product.getList();\r
+        assertEquals(products.size(), productInfos.size());\r
+        for (int i = 0; i < products.size(); i++) {\r
+            ProductPrice pr = productInfos.get(i);\r
+            Product p2 = products.get(i);\r
+            assertEquals(p2.productName, pr.productName);\r
+            assertEquals(p2.category, pr.category);\r
+            assertEquals(p2.unitPrice, pr.price);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A result set class containing customer data and the order total.\r
+     */\r
+    public static class CustOrder {\r
+        public String customerId;\r
+        public Integer orderId;\r
+        public BigDecimal total;\r
+\r
+        @Override\r
+        public String toString() {\r
+            return customerId + ":" + orderId + ":" + new DecimalFormat("##.00").format(total);\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testSelectManyCompoundFrom2() {\r
+\r
+        // var orders =\r
+        // from c in customers,\r
+        // o in c.Orders\r
+        // where o.Total < 500.00M\r
+        // select new {\r
+        // c.CustomerID,\r
+        // o.OrderID,\r
+        // o.Total\r
+        // };\r
+\r
+        final Customer c = new Customer();\r
+        final Order o = new Order();\r
+        List<CustOrder> orders = db.from(c).innerJoin(o).on(c.customerId).is(o.customerId).where(o.total)\r
+                .lessThan(new BigDecimal("100.00")).orderBy(c.customerId).select(new CustOrder() {\r
+                    {\r
+                        customerId = c.customerId;\r
+                        orderId = o.orderId;\r
+                        total = o.total;\r
+                    }\r
+                });\r
+\r
+        assertEquals("[ANATR:10308:88.80]", orders.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testIsNull() {\r
+        Product p = new Product();\r
+        String sql = db.from(p).whereTrue(isNull(p.productName)).getSQL();\r
+        assertEquals("SELECT * FROM Product WHERE (" + db.getDialect().prepareColumnName("productName")\r
+                + " IS NULL)", sql);\r
+    }\r
+\r
+    @Test\r
+    public void testDelete() {\r
+        Product p = new Product();\r
+        int deleted = db.from(p).where(p.productName).like("A%").delete();\r
+        assertEquals(1, deleted);\r
+        deleted = db.from(p).delete();\r
+        assertEquals(9, deleted);\r
+        db.insertAll(Product.getList());\r
+        db.deleteAll(Product.getList());\r
+        assertEquals(0, db.from(p).selectCount());\r
+        db.insertAll(Product.getList());\r
+    }\r
+\r
+    @Test\r
+    public void testOrAndNot() {\r
+        Product p = new Product();\r
+        String sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();\r
+        String productName = db.getDialect().prepareColumnName("productName");\r
+        assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);\r
+        sql = db.from(p).whereTrue(not(isNull(p.productName))).getSQL();\r
+        assertEquals("SELECT * FROM Product WHERE (NOT " + productName + " IS NULL)", sql);\r
+        sql = db.from(p).whereTrue(db.test(p.productId).is(1)).getSQL();\r
+        String productId = db.getDialect().prepareColumnName("productId");\r
+        assertEquals("SELECT * FROM Product WHERE ((" + productId + " = ?))", sql);\r
+    }\r
+\r
+    @Test\r
+    public void testLength() {\r
+        Product p = new Product();\r
+        List<Integer> lengths = db.from(p).where(length(p.productName)).lessThan(10)\r
+                .selectDistinct(length(p.productName));\r
+        // Formerly used orderBy(1) here, but that is not portable across DBs\r
+        Collections.sort(lengths);\r
+        assertEquals("[4, 5]", lengths.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testSum() {\r
+        Product p = new Product();\r
+        Number sum = db.from(p).selectFirst(sum(p.unitsInStock));\r
+        assertEquals(323, sum.intValue());\r
+        Double sumPrice = db.from(p).selectFirst(sum(p.unitPrice));\r
+        assertEquals(313.35, sumPrice.doubleValue(), 0.001);\r
+    }\r
+\r
+    @Test\r
+    public void testMinMax() {\r
+        Product p = new Product();\r
+        Integer min = db.from(p).selectFirst(min(p.unitsInStock));\r
+        assertEquals(0, min.intValue());\r
+        String minName = db.from(p).selectFirst(min(p.productName));\r
+        assertEquals("Aniseed Syrup", minName);\r
+        Double max = db.from(p).selectFirst(max(p.unitPrice));\r
+        assertEquals(97.0, max.doubleValue(), 0.001);\r
+    }\r
+\r
+    @Test\r
+    public void testLike() {\r
+        Product p = new Product();\r
+        List<Product> aList = db.from(p).where(p.productName).like("Cha%").orderBy(p.productName).select();\r
+        assertEquals("[Chai: 39, Chang: 17]", aList.toString());\r
+    }\r
+\r
+    @Test\r
+    public void testCount() {\r
+        long count = db.from(new Product()).selectCount();\r
+        assertEquals(10, count);\r
+    }\r
+\r
+    @Test\r
+    public void testComplexObject() {\r
+        ComplexObject co = new ComplexObject();\r
+        String sql = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday)\r
+                .lessThan(new java.util.Date()).and(co.created)\r
+                .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello")\r
+                .and(co.time).lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value)\r
+                .is(new BigDecimal("1")).getSQL();\r
+\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("SELECT * FROM ComplexObject WHERE ");\r
+        sb.append(db.getDialect().prepareColumnName("id"));\r
+        sb.append(" = ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("amount"));\r
+        sb.append(" = ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("birthday"));\r
+        sb.append(" < ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("created"));\r
+        sb.append(" < ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("name"));\r
+        sb.append(" = ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("time"));\r
+        sb.append(" < ? AND ");\r
+        sb.append(db.getDialect().prepareColumnName("value"));\r
+        sb.append(" = ?");\r
+        assertEquals(sb.toString(), sql);\r
+\r
+        long count = db.from(co).where(co.id).is(1).and(co.amount).is(1L).and(co.birthday)\r
+                .lessThan(new java.util.Date()).and(co.created)\r
+                .lessThan(java.sql.Timestamp.valueOf("2005-05-05 05:05:05")).and(co.name).is("hello")\r
+                .and(co.time).lessThan(java.sql.Time.valueOf("23:23:23")).and(co.value)\r
+                .is(new BigDecimal("1")).selectCount();\r
+        assertEquals(1, count);\r
+    }\r
+\r
+    @Test\r
+    public void testComplexObject2() {\r
+        testComplexObject2(1, "hello");\r
+    }\r
+\r
+    private void testComplexObject2(final int x, final String name) {\r
+        final ComplexObject co = new ComplexObject();\r
+\r
+        String sql = db.from(co).where(new Filter() {\r
+            @Override\r
+            public boolean where() {\r
+                return co.id == x && co.name.equals(name) && co.name.equals("hello");\r
+            }\r
+        }).getSQL();\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("SELECT * FROM ComplexObject WHERE ");\r
+        sb.append(db.getDialect().prepareColumnName("id"));\r
+        sb.append("=? AND ?=");\r
+        sb.append(db.getDialect().prepareColumnName("name"));\r
+        sb.append(" AND 'hello'=");\r
+        sb.append(db.getDialect().prepareColumnName("name"));\r
+        assertEquals(sb.toString(), sql);\r
+\r
+        long count = db.from(co).where(new Filter() {\r
+            @Override\r
+            public boolean where() {\r
+                return co.id == x && co.name.equals(name) && co.name.equals("hello");\r
+            }\r
+        }).selectCount();\r
+\r
+        assertEquals(1, count);\r
+    }\r
+\r
+    @Test\r
+    public void testLimitOffset() {\r
+        Set<Integer> ids = new HashSet<Integer>();\r
+        Product p = new Product();\r
+        for (int i = 0; i < 5; i++) {\r
+            List<Product> products = db.from(p).limit(2).offset(2 * i).select();\r
+            assertTrue(products.size() == 2);\r
+            for (Product prod : products) {\r
+                assertTrue("Failed to add product id.  Duplicate?", ids.add(prod.productId));\r
+            }\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testKeyRetrieval() {\r
+        List<SupportedTypes> list = SupportedTypes.createList();\r
+        List<Long> keys = db.insertAllAndGetKeys(list);\r
+        Set<Long> uniqueKeys = new HashSet<Long>();\r
+        for (Long l : keys) {\r
+            assertTrue("Failed to add key.  Duplicate?", uniqueKeys.add(l));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A result set class containing product groups.\r
+     */\r
+    public static class ProductGroup {\r
+        public String category;\r
+        public Long productCount;\r
+\r
+        @Override\r
+        public String toString() {\r
+            return category + ":" + productCount;\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void testGroup() {\r
+\r
+        // var orderGroups =\r
+        // from p in products\r
+        // group p by p.Category into g\r
+        // select new {\r
+        // Category = g.Key,\r
+        // Products = g\r
+        // };\r
+\r
+        final Product p = new Product();\r
+        List<ProductGroup> list = db.from(p).groupBy(p.category).orderBy(p.category)\r
+                .select(new ProductGroup() {\r
+                    {\r
+                        category = p.category;\r
+                        productCount = count();\r
+                    }\r
+                });\r
+        assertEquals("[Beverages:2, Condiments:5, Meat/Poultry:1, Produce:1, Seafood:1]", list.toString());\r
+    }\r
 \r
 }\r
index 026366e51d855aadc6b92bb523003072b8415c7a..5c84072e8f4195fff7046b76592d590e2be7b7ce 100644 (file)
  */\r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-\r
-import java.sql.SQLException;\r
-\r
-import org.junit.After;\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.IciqlException;\r
 import com.iciql.test.models.CategoryAnnotationOnly;\r
 import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey;\r
+import org.junit.After;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+\r
+import java.sql.SQLException;\r
+\r
+import static org.junit.Assert.assertEquals;\r
 \r
 /**\r
  * Tests of transactions.\r
  */\r
 public class TransactionTest {\r
 \r
-       /**\r
-        * This object represents a database (actually a connection to the\r
-        * database).\r
-        */\r
-\r
-       private Db db;\r
-\r
-       @Before\r
-       public void setUp() {\r
-               db = IciqlSuite.openNewDb();\r
-               \r
-               // tables creation\r
-               db.from(new CategoryAnnotationOnly());\r
-               db.from(new ProductAnnotationOnlyWithForeignKey());\r
-               \r
-               startTransactionMode();\r
-       }\r
-\r
-       @After\r
-       public void tearDown() {\r
-               \r
-               endTransactionMode();\r
-               \r
-               db.dropTable(ProductAnnotationOnlyWithForeignKey.class);\r
-               db.dropTable(CategoryAnnotationOnly.class);\r
-               db.close();\r
-       }\r
-\r
-       @Test\r
-       public void testTransaction() {\r
-               \r
-               // insert in 2 tables inside a transaction\r
-               \r
-               // insertAll don't use save point in this transaction\r
-               db.insertAll(CategoryAnnotationOnly.getList());\r
-               db.insertAll(ProductAnnotationOnlyWithForeignKey.getList());\r
-\r
-               // don't commit changes\r
-               try {\r
-                       db.getConnection().rollback();\r
-               } catch (SQLException e) {\r
-                       throw new IciqlException(e, "Can't rollback");\r
-               }\r
-               \r
-               ProductAnnotationOnlyWithForeignKey p = new ProductAnnotationOnlyWithForeignKey();\r
-               long count1 = db.from(p).selectCount();\r
-               \r
-               CategoryAnnotationOnly c = new CategoryAnnotationOnly();\r
-               long count2 = db.from(c).selectCount();\r
-               \r
-               // verify changes aren't committed\r
-               assertEquals(count1, 0L);\r
-               assertEquals(count2, 0L);\r
-       }\r
-\r
-       /**\r
-        * Helper to set transaction mode\r
-        */\r
-       private void startTransactionMode() {\r
-               db.setSkipCreate(true);\r
-               db.setAutoSavePoint(false);\r
-               \r
-               try {\r
-                       db.getConnection().setAutoCommit(false);\r
-               } catch (SQLException e) {\r
-                       throw new IciqlException(e, "Could not change auto-commit mode");\r
-               }\r
-       }\r
-       \r
-       /**\r
-        * Helper to return to initial mode\r
-        */\r
-       private void endTransactionMode() {\r
-               try {\r
-                       db.getConnection().setAutoCommit(true);\r
-               } catch (SQLException e) {\r
-                       throw new IciqlException(e, "Could not change auto-commit mode");\r
-               }\r
-               // returns to initial states\r
-               db.setSkipCreate(false);\r
-               db.setAutoSavePoint(true);\r
-       }\r
-       \r
+    /**\r
+     * This object represents a database (actually a connection to the\r
+     * database).\r
+     */\r
+\r
+    private Db db;\r
+\r
+    @Before\r
+    public void setUp() {\r
+        db = IciqlSuite.openNewDb();\r
+\r
+        // tables creation\r
+        db.from(new CategoryAnnotationOnly());\r
+        db.from(new ProductAnnotationOnlyWithForeignKey());\r
+\r
+        startTransactionMode();\r
+    }\r
+\r
+    @After\r
+    public void tearDown() {\r
+\r
+        endTransactionMode();\r
+\r
+        db.dropTable(ProductAnnotationOnlyWithForeignKey.class);\r
+        db.dropTable(CategoryAnnotationOnly.class);\r
+        db.close();\r
+    }\r
+\r
+    @Test\r
+    public void testTransaction() {\r
+\r
+        // insert in 2 tables inside a transaction\r
+\r
+        // insertAll don't use save point in this transaction\r
+        db.insertAll(CategoryAnnotationOnly.getList());\r
+        db.insertAll(ProductAnnotationOnlyWithForeignKey.getList());\r
+\r
+        // don't commit changes\r
+        try {\r
+            db.getConnection().rollback();\r
+        } catch (SQLException e) {\r
+            throw new IciqlException(e, "Can't rollback");\r
+        }\r
+\r
+        ProductAnnotationOnlyWithForeignKey p = new ProductAnnotationOnlyWithForeignKey();\r
+        long count1 = db.from(p).selectCount();\r
+\r
+        CategoryAnnotationOnly c = new CategoryAnnotationOnly();\r
+        long count2 = db.from(c).selectCount();\r
+\r
+        // verify changes aren't committed\r
+        assertEquals(count1, 0L);\r
+        assertEquals(count2, 0L);\r
+    }\r
+\r
+    /**\r
+     * Helper to set transaction mode\r
+     */\r
+    private void startTransactionMode() {\r
+        db.setSkipCreate(true);\r
+        db.setAutoSavePoint(false);\r
+\r
+        try {\r
+            db.getConnection().setAutoCommit(false);\r
+        } catch (SQLException e) {\r
+            throw new IciqlException(e, "Could not change auto-commit mode");\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Helper to return to initial mode\r
+     */\r
+    private void endTransactionMode() {\r
+        try {\r
+            db.getConnection().setAutoCommit(true);\r
+        } catch (SQLException e) {\r
+            throw new IciqlException(e, "Could not change auto-commit mode");\r
+        }\r
+        // returns to initial states\r
+        db.setSkipCreate(false);\r
+        db.setAutoSavePoint(true);\r
+    }\r
+\r
 }\r
index bb09c9fc1d9a551aee327ae067f1a5a2035d6da0..14db69c7f461143cd45d8cf6577ca1b1283f18b5 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
+import com.iciql.Db;
+import com.iciql.Iciql.IQColumn;
+import com.iciql.Iciql.IQTable;
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.iciql.Db;
-import com.iciql.Iciql.IQColumn;
-import com.iciql.Iciql.IQTable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests of UUID type.
@@ -39,77 +38,77 @@ import com.iciql.Iciql.IQTable;
  */
 public class UUIDTest {
 
-       Db db;
-
-       @Before
-       public void setup() {
-               db = IciqlSuite.openNewDb();
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testUUIDs() throws Exception {
-               // do not test non-H2 databases
-               Assume.assumeTrue(IciqlSuite.isH2(db));
-
-               List<UUIDRecord> originals = UUIDRecord.getList();
-               db.insertAll(originals);
-               UUIDRecord u = new UUIDRecord();
-               List<UUIDRecord> retrieved = db.from(u).orderBy(u.id).select();
-               assertEquals(originals.size(), retrieved.size());
-               for (int i = 0; i < originals.size(); i++) {
-                       UUIDRecord a = originals.get(i);
-                       UUIDRecord b = retrieved.get(i);
-                       assertTrue(a.equivalentTo(b));
-               }
-
-               UUIDRecord second = db.from(u).where(u.uuid).is(originals.get(1).uuid).selectFirst();
-               assertTrue(originals.get(1).equivalentTo(second));
-               db.dropTable(UUIDRecord.class);
-       }
-
-       /**
-        * A simple class used in this test.
-        */
-       @IQTable(name = "UUID_TEST")
-       public static class UUIDRecord {
-
-               @IQColumn(primaryKey = true)
-               public Integer id;
-
-               @IQColumn()
-               public UUID uuid;
-
-               public UUIDRecord() {
-                       // public constructor
-               }
-
-               private UUIDRecord(int id) {
-                       this.id = id;
-                       this.uuid = UUID.randomUUID();
-               }
-
-               public boolean equivalentTo(UUIDRecord b) {
-                       boolean same = true;
-                       same &= id == b.id;
-                       same &= uuid.equals(b.uuid);
-                       return same;
-               }
-
-               public String toString() {
-                       return id + ": " + uuid;
-               }
-
-               public static List<UUIDRecord> getList() {
-                       List<UUIDRecord> list = new ArrayList<UUIDRecord>();
-                       for (int i = 0; i < 10; i++) {
-                               list.add(new UUIDRecord(i + 1));
-                       }
-                       return list;
-               }
-       }
+    Db db;
+
+    @Before
+    public void setup() {
+        db = IciqlSuite.openNewDb();
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testUUIDs() throws Exception {
+        // do not test non-H2 databases
+        Assume.assumeTrue(IciqlSuite.isH2(db));
+
+        List<UUIDRecord> originals = UUIDRecord.getList();
+        db.insertAll(originals);
+        UUIDRecord u = new UUIDRecord();
+        List<UUIDRecord> retrieved = db.from(u).orderBy(u.id).select();
+        assertEquals(originals.size(), retrieved.size());
+        for (int i = 0; i < originals.size(); i++) {
+            UUIDRecord a = originals.get(i);
+            UUIDRecord b = retrieved.get(i);
+            assertTrue(a.equivalentTo(b));
+        }
+
+        UUIDRecord second = db.from(u).where(u.uuid).is(originals.get(1).uuid).selectFirst();
+        assertTrue(originals.get(1).equivalentTo(second));
+        db.dropTable(UUIDRecord.class);
+    }
+
+    /**
+     * A simple class used in this test.
+     */
+    @IQTable(name = "UUID_TEST")
+    public static class UUIDRecord {
+
+        @IQColumn(primaryKey = true)
+        public Integer id;
+
+        @IQColumn()
+        public UUID uuid;
+
+        public UUIDRecord() {
+            // public constructor
+        }
+
+        private UUIDRecord(int id) {
+            this.id = id;
+            this.uuid = UUID.randomUUID();
+        }
+
+        public boolean equivalentTo(UUIDRecord b) {
+            boolean same = true;
+            same &= id == b.id;
+            same &= uuid.equals(b.uuid);
+            return same;
+        }
+
+        public String toString() {
+            return id + ": " + uuid;
+        }
+
+        public static List<UUIDRecord> getList() {
+            List<UUIDRecord> list = new ArrayList<UUIDRecord>();
+            for (int i = 0; i < 10; i++) {
+                list.add(new UUIDRecord(i + 1));
+            }
+            return list;
+        }
+    }
 }
index b0981a92093f63d68c8d733ee280f4b2485ca9e4..9f1bf70948daf05d564ba646b40219f7e36c0d67 100644 (file)
 
 package com.iciql.test;
 
-import static java.sql.Date.valueOf;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.test.models.Customer;
 import com.iciql.test.models.Order;
 import com.iciql.test.models.Product;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.sql.Date.valueOf;
+import static org.junit.Assert.*;
 
 /**
  * Tests the Db.update() function.
- * 
+ *
  * @author dmoebius at scoop dash gmbh dot de
  */
 public class UpdateTest {
 
-       private Db db;
-
-       @Before
-       public void setUp() throws Exception {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(Product.getList());
-               db.insertAll(Customer.getList());
-               db.insertAll(Order.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testSimpleUpdate() {
-               Product p = new Product();
-               Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();
-               // update unitPrice from 19.0 to 19.5
-               pChang.unitPrice = 19.5;
-               // update unitsInStock from 17 to 16
-               pChang.unitsInStock = 16;
-               db.update(pChang);
-
-               Product p2 = new Product();
-               Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst();
-               assertEquals(19.5, pChang2.unitPrice.doubleValue(), 0.001);
-               assertEquals(16, pChang2.unitsInStock.intValue());
-
-               // undo update
-               pChang.unitPrice = 19.0;
-               pChang.unitsInStock = 17;
-               db.update(pChang);
-       }
-
-       @Test
-       public void testSimpleUpdateWithCombinedPrimaryKey() {
-               Order o = new Order();
-               Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst();
-               ourOrder.orderDate = valueOf("2007-01-03");
-               db.update(ourOrder);
-
-               Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst();
-               assertTrue("updated order not found", ourUpdatedOrder != null);
-
-               // undo update
-               ourOrder.orderDate = valueOf("2007-01-02");
-               db.update(ourOrder);
-       }
-
-       @Test
-       public void testSimpleMerge() {
-               Product p = new Product();
-               Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();
-               // update unitPrice from 19.0 to 19.5
-               pChang.unitPrice = 19.5;
-               // update unitsInStock from 17 to 16
-               pChang.unitsInStock = 16;
-               db.merge(pChang);
-
-               Product p2 = new Product();
-               Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst();
-               assertEquals(19.5, pChang2.unitPrice, 0.001);
-               assertEquals(16, pChang2.unitsInStock.intValue());
-
-               // undo update
-               pChang.unitPrice = 19.0;
-               pChang.unitsInStock = 17;
-               db.merge(pChang);
-       }
-
-       @Test
-       public void testSimpleMergeWithCombinedPrimaryKey() {
-               Order o = new Order();
-               Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst();
-               ourOrder.orderDate = valueOf("2007-01-03");
-               db.merge(ourOrder);
-
-               Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst();
-               assertTrue("updated order not found", ourUpdatedOrder != null);
-
-               // undo update
-               ourOrder.orderDate = valueOf("2007-01-02");
-               db.merge(ourOrder);
-       }
-
-       @Test
-       public void testSetColumns() {
-               Product p = new Product();
-               Product original = db.from(p).where(p.productId).is(1).selectFirst();
-
-               // update string and double columns
-               db.from(p).set(p.productName).to("updated").increment(p.unitPrice).by(3.14).increment(p.unitsInStock)
-                               .by(2).where(p.productId).is(1).update();
-
-               // confirm the data was properly updated
-               Product revised = db.from(p).where(p.productId).is(1).selectFirst();
-               assertEquals("updated", revised.productName);
-               assertEquals(original.unitPrice + 3.14, revised.unitPrice, 0.001);
-               assertEquals(original.unitsInStock + 2, revised.unitsInStock.intValue());
-
-               // restore the data
-               db.from(p).set(p.productName).to(original.productName).set(p.unitPrice).to(original.unitPrice)
-                               .increment(p.unitsInStock).by(-2).where(p.productId).is(1).update();
-
-               // confirm the data was properly restored
-               Product restored = db.from(p).where(p.productId).is(1).selectFirst();
-               assertEquals(original.productName, restored.productName);
-               assertEquals(original.unitPrice, restored.unitPrice);
-               assertEquals(original.unitsInStock, restored.unitsInStock);
-
-               double unitPriceOld = db.from(p).where(p.productId).is(1).selectFirst().unitPrice;
-               // double the unit price
-               db.from(p).increment(p.unitPrice).by(p.unitPrice).where(p.productId).is(1).update();
-               double unitPriceNew = db.from(p).where(p.productId).is(1).selectFirst().unitPrice;
-               assertEquals(unitPriceOld * 2, unitPriceNew, 0.001);
-
-       }
-
-       @Test
-       public void testSetNull() {
-               Product p = new Product();
-               Product original = db.from(p).where(p.productId).is(1).selectFirst();
-
-               String originalName = original.productName;
-               db.from(p).setNull(p.productName).update();
-
-               // confirm the data was properly updated
-               Product revised = db.from(p).where(p.productId).is(1).selectFirst();
-               assertNull(revised.productName);
-
-               // restore the data
-               db.from(p).set(p.productName).to(originalName).update();
-
-               // confirm the data was properly restored
-               Product restored = db.from(p).where(p.productId).is(1).selectFirst();
-               assertEquals(originalName, restored.productName);
-
-       }
+    private Db db;
+
+    @Before
+    public void setUp() throws Exception {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(Product.getList());
+        db.insertAll(Customer.getList());
+        db.insertAll(Order.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testSimpleUpdate() {
+        Product p = new Product();
+        Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();
+        // update unitPrice from 19.0 to 19.5
+        pChang.unitPrice = 19.5;
+        // update unitsInStock from 17 to 16
+        pChang.unitsInStock = 16;
+        db.update(pChang);
+
+        Product p2 = new Product();
+        Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst();
+        assertEquals(19.5, pChang2.unitPrice.doubleValue(), 0.001);
+        assertEquals(16, pChang2.unitsInStock.intValue());
+
+        // undo update
+        pChang.unitPrice = 19.0;
+        pChang.unitsInStock = 17;
+        db.update(pChang);
+    }
+
+    @Test
+    public void testSimpleUpdateWithCombinedPrimaryKey() {
+        Order o = new Order();
+        Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst();
+        ourOrder.orderDate = valueOf("2007-01-03");
+        db.update(ourOrder);
+
+        Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst();
+        assertTrue("updated order not found", ourUpdatedOrder != null);
+
+        // undo update
+        ourOrder.orderDate = valueOf("2007-01-02");
+        db.update(ourOrder);
+    }
+
+    @Test
+    public void testSimpleMerge() {
+        Product p = new Product();
+        Product pChang = db.from(p).where(p.productName).is("Chang").selectFirst();
+        // update unitPrice from 19.0 to 19.5
+        pChang.unitPrice = 19.5;
+        // update unitsInStock from 17 to 16
+        pChang.unitsInStock = 16;
+        db.merge(pChang);
+
+        Product p2 = new Product();
+        Product pChang2 = db.from(p2).where(p2.productName).is("Chang").selectFirst();
+        assertEquals(19.5, pChang2.unitPrice, 0.001);
+        assertEquals(16, pChang2.unitsInStock.intValue());
+
+        // undo update
+        pChang.unitPrice = 19.0;
+        pChang.unitsInStock = 17;
+        db.merge(pChang);
+    }
+
+    @Test
+    public void testSimpleMergeWithCombinedPrimaryKey() {
+        Order o = new Order();
+        Order ourOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-02")).selectFirst();
+        ourOrder.orderDate = valueOf("2007-01-03");
+        db.merge(ourOrder);
+
+        Order ourUpdatedOrder = db.from(o).where(o.orderDate).is(valueOf("2007-01-03")).selectFirst();
+        assertTrue("updated order not found", ourUpdatedOrder != null);
+
+        // undo update
+        ourOrder.orderDate = valueOf("2007-01-02");
+        db.merge(ourOrder);
+    }
+
+    @Test
+    public void testSetColumns() {
+        Product p = new Product();
+        Product original = db.from(p).where(p.productId).is(1).selectFirst();
+
+        // update string and double columns
+        db.from(p).set(p.productName).to("updated").increment(p.unitPrice).by(3.14).increment(p.unitsInStock)
+                .by(2).where(p.productId).is(1).update();
+
+        // confirm the data was properly updated
+        Product revised = db.from(p).where(p.productId).is(1).selectFirst();
+        assertEquals("updated", revised.productName);
+        assertEquals(original.unitPrice + 3.14, revised.unitPrice, 0.001);
+        assertEquals(original.unitsInStock + 2, revised.unitsInStock.intValue());
+
+        // restore the data
+        db.from(p).set(p.productName).to(original.productName).set(p.unitPrice).to(original.unitPrice)
+                .increment(p.unitsInStock).by(-2).where(p.productId).is(1).update();
+
+        // confirm the data was properly restored
+        Product restored = db.from(p).where(p.productId).is(1).selectFirst();
+        assertEquals(original.productName, restored.productName);
+        assertEquals(original.unitPrice, restored.unitPrice);
+        assertEquals(original.unitsInStock, restored.unitsInStock);
+
+        double unitPriceOld = db.from(p).where(p.productId).is(1).selectFirst().unitPrice;
+        // double the unit price
+        db.from(p).increment(p.unitPrice).by(p.unitPrice).where(p.productId).is(1).update();
+        double unitPriceNew = db.from(p).where(p.productId).is(1).selectFirst().unitPrice;
+        assertEquals(unitPriceOld * 2, unitPriceNew, 0.001);
+
+    }
+
+    @Test
+    public void testSetNull() {
+        Product p = new Product();
+        Product original = db.from(p).where(p.productId).is(1).selectFirst();
+
+        String originalName = original.productName;
+        db.from(p).setNull(p.productName).update();
+
+        // confirm the data was properly updated
+        Product revised = db.from(p).where(p.productId).is(1).selectFirst();
+        assertNull(revised.productName);
+
+        // restore the data
+        db.from(p).set(p.productName).to(originalName).update();
+
+        // confirm the data was properly restored
+        Product restored = db.from(p).where(p.productId).is(1).selectFirst();
+        assertEquals(originalName, restored.productName);
+
+    }
 
 }
index 4ab1ff1e51abb616f03d7be9ef797b6f441dedd5..82ba37262398ef04d917a83eef29697cada37878 100644 (file)
 \r
 package com.iciql.test;\r
 \r
-import static org.junit.Assert.assertEquals;\r
-\r
-import java.util.List;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-\r
-import org.junit.Test;\r
-\r
 import com.iciql.Db;\r
 import com.iciql.DbUpgrader;\r
 import com.iciql.Iciql.IQVersion;\r
 import com.iciql.test.models.Product;\r
 import com.iciql.test.models.SupportedTypes;\r
 import com.iciql.test.models.SupportedTypes.SupportedTypes2;\r
+import org.junit.Test;\r
+\r
+import java.util.List;\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+\r
+import static org.junit.Assert.assertEquals;\r
 \r
 /**\r
  * Tests the database and table upgrade functions.\r
- *\r
  */\r
 public class UpgradesTest {\r
 \r
-       @Test\r
-       public void testDatabaseUpgrade() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               List<Product> products = Product.getList();\r
-\r
-               // set the v1 upgrader and insert a record.\r
-               // this will trigger the upgrade.\r
-               V1DbUpgrader v1 = new V1DbUpgrader();\r
-               db.setDbUpgrader(v1);\r
-               db.insert(products.get(0));\r
-\r
-               // confirm that upgrade occurred\r
-               assertEquals(0, v1.oldVersion.get());\r
-               assertEquals(1, v1.newVersion.get());\r
-\r
-               // open a second connection to the database\r
-               // and then apply the v2 upgrade.\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
-               // set the v2 upgrader and insert a record.\r
-               // this will trigger the upgrade.\r
-               V2DbUpgrader v2 = new V2DbUpgrader();\r
-               db2.setDbUpgrader(v2);\r
-               db2.insert(products.get(1));\r
-\r
-               // confirm that upgrade occurred\r
-               assertEquals(1, v2.oldVersion.get());\r
-               assertEquals(2, v2.newVersion.get());\r
-\r
-               db.executeUpdate("DROP TABLE iq_versions");\r
-               db.close();\r
-               db2.close();\r
-       }\r
-\r
-       @Test\r
-       public void testDatabaseInheritedUpgrade() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               List<Product> products = Product.getList();\r
-\r
-               // set the v1 upgrader and insert a record.\r
-               // this will trigger the upgrade.\r
-               V1DbUpgrader v1 = new V1DbUpgrader();\r
-               db.setDbUpgrader(v1);\r
-               db.insert(products.get(0));\r
-\r
-               // confirm that upgrade occurred\r
-               assertEquals(0, v1.oldVersion.get());\r
-               assertEquals(1, v1.newVersion.get());\r
-\r
-               // open a second connection to the database\r
-               // and then apply the v2 upgrade.\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
-               // set the v2 upgrader and insert a record.\r
-               // this will trigger the upgrade.\r
-               V2DbUpgraderImpl v2 = new V2DbUpgraderImpl();\r
-               db2.setDbUpgrader(v2);\r
-               db2.insert(products.get(1));\r
-\r
-               // confirm that upgrade occurred\r
-               assertEquals(1, v2.oldVersion.get());\r
-               assertEquals(2, v2.newVersion.get());\r
-\r
-               db.executeUpdate("DROP TABLE iq_versions");\r
-               db.close();\r
-               db2.close();\r
-       }\r
-\r
-       @Test\r
-       public void testTableUpgrade() {\r
-               Db db = IciqlSuite.openNewDb();\r
-\r
-               // insert first, this will create version record automatically\r
-               List<SupportedTypes> original = SupportedTypes.createList();\r
-               db.insertAll(original);\r
-\r
-               // reset the dbUpgrader (clears the update check cache)\r
-               V2DbUpgrader dbUpgrader = new V2DbUpgrader();\r
-               db.setDbUpgrader(dbUpgrader);\r
-\r
-               SupportedTypes2 s2 = new SupportedTypes2();\r
-\r
-               List<SupportedTypes2> types = db.from(s2).select();\r
-               assertEquals(10, types.size());\r
-               assertEquals(1, dbUpgrader.oldVersion.get());\r
-               assertEquals(2, dbUpgrader.newVersion.get());\r
-               db.executeUpdate("DROP TABLE iq_versions");\r
-               db.close();\r
-       }\r
-\r
-       /**\r
-        * A sample database upgrader class.\r
-        */\r
-       class BaseDbUpgrader implements DbUpgrader {\r
-               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
-                       newVersion.set(toVersion);\r
-                       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
-                       newVersion.set(toVersion);\r
-                       return true;\r
-               }\r
-       }\r
-\r
-       /**\r
-        * A sample V1 database upgrader class.\r
-        */\r
-       @IQVersion(1)\r
-       class V1DbUpgrader extends BaseDbUpgrader {\r
-       }\r
-\r
-       /**\r
-        * A sample V2 database upgrader class.\r
-        */\r
-       @IQVersion(2)\r
-       class V2DbUpgrader extends BaseDbUpgrader {\r
-       }\r
-\r
-\r
-       /**\r
-        * A sample V2 database upgrader class which inherits its\r
-        * version from the parent class.\r
-        */\r
-       @IQVersion()\r
-       class V2DbUpgraderImpl extends V2DbUpgrader {\r
-       }\r
+    @Test\r
+    public void testDatabaseUpgrade() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        List<Product> products = Product.getList();\r
+\r
+        // set the v1 upgrader and insert a record.\r
+        // this will trigger the upgrade.\r
+        V1DbUpgrader v1 = new V1DbUpgrader();\r
+        db.setDbUpgrader(v1);\r
+        db.insert(products.get(0));\r
+\r
+        // confirm that upgrade occurred\r
+        assertEquals(0, v1.oldVersion.get());\r
+        assertEquals(1, v1.newVersion.get());\r
+\r
+        // open a second connection to the database\r
+        // and then apply the v2 upgrade.\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
+        // set the v2 upgrader and insert a record.\r
+        // this will trigger the upgrade.\r
+        V2DbUpgrader v2 = new V2DbUpgrader();\r
+        db2.setDbUpgrader(v2);\r
+        db2.insert(products.get(1));\r
+\r
+        // confirm that upgrade occurred\r
+        assertEquals(1, v2.oldVersion.get());\r
+        assertEquals(2, v2.newVersion.get());\r
+\r
+        db.executeUpdate("DROP TABLE iq_versions");\r
+        db.close();\r
+        db2.close();\r
+    }\r
+\r
+    @Test\r
+    public void testDatabaseInheritedUpgrade() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        List<Product> products = Product.getList();\r
+\r
+        // set the v1 upgrader and insert a record.\r
+        // this will trigger the upgrade.\r
+        V1DbUpgrader v1 = new V1DbUpgrader();\r
+        db.setDbUpgrader(v1);\r
+        db.insert(products.get(0));\r
+\r
+        // confirm that upgrade occurred\r
+        assertEquals(0, v1.oldVersion.get());\r
+        assertEquals(1, v1.newVersion.get());\r
+\r
+        // open a second connection to the database\r
+        // and then apply the v2 upgrade.\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
+        // set the v2 upgrader and insert a record.\r
+        // this will trigger the upgrade.\r
+        V2DbUpgraderImpl v2 = new V2DbUpgraderImpl();\r
+        db2.setDbUpgrader(v2);\r
+        db2.insert(products.get(1));\r
+\r
+        // confirm that upgrade occurred\r
+        assertEquals(1, v2.oldVersion.get());\r
+        assertEquals(2, v2.newVersion.get());\r
+\r
+        db.executeUpdate("DROP TABLE iq_versions");\r
+        db.close();\r
+        db2.close();\r
+    }\r
+\r
+    @Test\r
+    public void testTableUpgrade() {\r
+        Db db = IciqlSuite.openNewDb();\r
+\r
+        // insert first, this will create version record automatically\r
+        List<SupportedTypes> original = SupportedTypes.createList();\r
+        db.insertAll(original);\r
+\r
+        // reset the dbUpgrader (clears the update check cache)\r
+        V2DbUpgrader dbUpgrader = new V2DbUpgrader();\r
+        db.setDbUpgrader(dbUpgrader);\r
+\r
+        SupportedTypes2 s2 = new SupportedTypes2();\r
+\r
+        List<SupportedTypes2> types = db.from(s2).select();\r
+        assertEquals(10, types.size());\r
+        assertEquals(1, dbUpgrader.oldVersion.get());\r
+        assertEquals(2, dbUpgrader.newVersion.get());\r
+        db.executeUpdate("DROP TABLE iq_versions");\r
+        db.close();\r
+    }\r
+\r
+    /**\r
+     * A sample database upgrader class.\r
+     */\r
+    class BaseDbUpgrader implements DbUpgrader {\r
+        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
+            newVersion.set(toVersion);\r
+            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
+            newVersion.set(toVersion);\r
+            return true;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * A sample V1 database upgrader class.\r
+     */\r
+    @IQVersion(1)\r
+    class V1DbUpgrader extends BaseDbUpgrader {\r
+    }\r
+\r
+    /**\r
+     * A sample V2 database upgrader class.\r
+     */\r
+    @IQVersion(2)\r
+    class V2DbUpgrader extends BaseDbUpgrader {\r
+    }\r
+\r
+\r
+    /**\r
+     * A sample V2 database upgrader class which inherits its\r
+     * version from the parent class.\r
+     */\r
+    @IQVersion()\r
+    class V2DbUpgraderImpl extends V2DbUpgrader {\r
+    }\r
 \r
 }\r
index be2e08560721a988016bf909d2c9bb09e44784ae..cf4df7d457bb8b3ec856a42d6bc0f9825ffd3237 100644 (file)
 
 package com.iciql.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
 import com.iciql.Db;
 import com.iciql.test.models.ProductAnnotationOnly;
 import com.iciql.test.models.ProductView;
@@ -32,83 +23,91 @@ import com.iciql.test.models.ProductViewFromQuery;
 import com.iciql.test.models.ProductViewInherited;
 import com.iciql.test.models.ProductViewInheritedComplex;
 import com.mysql.jdbc.StringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Test annotation processing.
  */
 public class ViewsTest {
 
-       /**
-        * This object represents a database (actually a connection to the
-        * database).
-        */
-
-       private Db db;
-
-       @Before
-       public void setUp() {
-               db = IciqlSuite.openNewDb();
-               db.insertAll(ProductAnnotationOnly.getList());
-       }
-
-       @After
-       public void tearDown() {
-               db.close();
-       }
-
-       @Test
-       public void testProductView() {
-               ProductView view = new ProductView();
-               List<ProductView> products = db.from(view).select();
-               assertEquals(5, products.size());
-               for (int i = 0; i < products.size(); i++) {
-                       assertEquals(3 + i, products.get(i).productId.intValue());
-               }
-       }
-
-       @Test
-       public void testProductViewInherited() {
-               ProductViewInherited view = new ProductViewInherited();
-               List<ProductViewInherited> products = db.from(view).select();
-               assertEquals(5, products.size());
-               for (int i = 0; i < products.size(); i++) {
-                       assertEquals(3 + i, products.get(i).productId.intValue());
-               }
-       }
-       
-       @Test
-       public void testComplexInheritance() {
-               ProductViewInheritedComplex view = new ProductViewInheritedComplex();
-               List<ProductViewInheritedComplex> products = db.from(view).select();
-               assertEquals(5, products.size());
-               for (int i = 0; i < products.size(); i++) {
-                       assertEquals(3 + i, products.get(i).productId.intValue());
-                       assertTrue(!StringUtils.isNullOrEmpty(products.get(i).productName));
-               }
-       }
-       
-       @Test
-       public void testCreateViewFromQuery() {
-               // create view from query
-               ProductAnnotationOnly product = new ProductAnnotationOnly();
-               db.from(product).where(product.productId).exceeds(2L).and(product.productId).atMost(7L).createView(ProductViewFromQuery.class);
-               
-               // select from the created view
-               ProductViewFromQuery view = new ProductViewFromQuery();
-               List<ProductViewFromQuery> products = db.from(view).select();
-               assertEquals(5, products.size());
-               for (int i = 0; i < products.size(); i++) {
-                       assertEquals(3 + i, products.get(i).productId.intValue());
-               }
-               
-               // replace the view
-               db.from(product).where(product.productId).exceeds(3L).and(product.productId).atMost(8L).replaceView(ProductViewFromQuery.class);
-               
-               // select from the replaced view
-               products = db.from(view).select();
-               assertEquals(5, products.size());
-               for (int i = 0; i < products.size(); i++) {
-                       assertEquals(4 + i, products.get(i).productId.intValue());
-               }
-       }
+    /**
+     * This object represents a database (actually a connection to the
+     * database).
+     */
+
+    private Db db;
+
+    @Before
+    public void setUp() {
+        db = IciqlSuite.openNewDb();
+        db.insertAll(ProductAnnotationOnly.getList());
+    }
+
+    @After
+    public void tearDown() {
+        db.close();
+    }
+
+    @Test
+    public void testProductView() {
+        ProductView view = new ProductView();
+        List<ProductView> products = db.from(view).select();
+        assertEquals(5, products.size());
+        for (int i = 0; i < products.size(); i++) {
+            assertEquals(3 + i, products.get(i).productId.intValue());
+        }
+    }
+
+    @Test
+    public void testProductViewInherited() {
+        ProductViewInherited view = new ProductViewInherited();
+        List<ProductViewInherited> products = db.from(view).select();
+        assertEquals(5, products.size());
+        for (int i = 0; i < products.size(); i++) {
+            assertEquals(3 + i, products.get(i).productId.intValue());
+        }
+    }
+
+    @Test
+    public void testComplexInheritance() {
+        ProductViewInheritedComplex view = new ProductViewInheritedComplex();
+        List<ProductViewInheritedComplex> products = db.from(view).select();
+        assertEquals(5, products.size());
+        for (int i = 0; i < products.size(); i++) {
+            assertEquals(3 + i, products.get(i).productId.intValue());
+            assertTrue(!StringUtils.isNullOrEmpty(products.get(i).productName));
+        }
+    }
+
+    @Test
+    public void testCreateViewFromQuery() {
+        // create view from query
+        ProductAnnotationOnly product = new ProductAnnotationOnly();
+        db.from(product).where(product.productId).exceeds(2L).and(product.productId).atMost(7L).createView(ProductViewFromQuery.class);
+
+        // select from the created view
+        ProductViewFromQuery view = new ProductViewFromQuery();
+        List<ProductViewFromQuery> products = db.from(view).select();
+        assertEquals(5, products.size());
+        for (int i = 0; i < products.size(); i++) {
+            assertEquals(3 + i, products.get(i).productId.intValue());
+        }
+
+        // replace the view
+        db.from(product).where(product.productId).exceeds(3L).and(product.productId).atMost(8L).replaceView(ProductViewFromQuery.class);
+
+        // select from the replaced view
+        products = db.from(view).select();
+        assertEquals(5, products.size());
+        for (int i = 0; i < products.size(); i++) {
+            assertEquals(4 + i, products.get(i).productId.intValue());
+        }
+    }
 }
index 4d75ad9f736641aac03165c414617541510e1099..8da9c54834a84091d3dffb115da3685fe26e3d8c 100644 (file)
  */\r
 package com.iciql.test.models;\r
 \r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQTable;\r
 \r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
 /**\r
  * Boolean types model.\r
  */\r
 @IQTable(name = "BooleanTest")\r
 public class BooleanModel {\r
 \r
-       @IQColumn(primaryKey = true)\r
-       public Integer id;\r
-\r
-       @IQColumn\r
-       public Boolean mybool;\r
-\r
-       public BooleanModel() {\r
-       }\r
-\r
-       BooleanModel(int id, boolean val) {\r
-               this.id = id;\r
-               this.mybool = val;\r
-       }\r
-\r
-       public static List<BooleanModel> getList() {\r
-               return Arrays.asList(new BooleanModel(1, true), new BooleanModel(2, false),\r
-                               new BooleanModel(3, true), new BooleanModel(4, false));\r
-       }\r
-\r
-       /**\r
-        * Test boolean as Integer\r
-        */\r
-       @IQTable(name = "BooleanTest")\r
-       public static class BooleanAsIntModel {\r
-               @IQColumn(primaryKey = true)\r
-               public Integer id;\r
-\r
-               @IQColumn\r
-               public Integer mybool;\r
-\r
-               public BooleanAsIntModel() {\r
-               }\r
-\r
-               BooleanAsIntModel(int id, boolean val) {\r
-                       this.id = id;\r
-                       this.mybool = val ? 1 : 0;\r
-               }\r
-\r
-               public static List<BooleanAsIntModel> getList() {\r
-                       return Arrays.asList(new BooleanAsIntModel(1, true), new BooleanAsIntModel(2, false),\r
-                                       new BooleanAsIntModel(3, true), new BooleanAsIntModel(4, false));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Test boolean as primitive short\r
-        */\r
-       @IQTable(name = "BooleanTest")\r
-       public static class BooleanAsPrimitiveShortModel {\r
-               @IQColumn(primaryKey = true)\r
-               public Integer id;\r
-\r
-               @IQColumn\r
-               public short mybool;\r
-\r
-               public BooleanAsPrimitiveShortModel() {\r
-               }\r
-\r
-               BooleanAsPrimitiveShortModel(int id, boolean val) {\r
-                       this.id = id;\r
-                       this.mybool = (short) (val ? 1 : 0);\r
-               }\r
-\r
-               public static List<BooleanAsPrimitiveShortModel> getList() {\r
-                       return Arrays.asList(new BooleanAsPrimitiveShortModel(1, true), new BooleanAsPrimitiveShortModel(2, false),\r
-                                       new BooleanAsPrimitiveShortModel(3, true), new BooleanAsPrimitiveShortModel(4, false));\r
-               }\r
-       }\r
+    @IQColumn(primaryKey = true)\r
+    public Integer id;\r
+\r
+    @IQColumn\r
+    public Boolean mybool;\r
+\r
+    public BooleanModel() {\r
+    }\r
+\r
+    BooleanModel(int id, boolean val) {\r
+        this.id = id;\r
+        this.mybool = val;\r
+    }\r
+\r
+    public static List<BooleanModel> getList() {\r
+        return Arrays.asList(new BooleanModel(1, true), new BooleanModel(2, false),\r
+                new BooleanModel(3, true), new BooleanModel(4, false));\r
+    }\r
+\r
+    /**\r
+     * Test boolean as Integer\r
+     */\r
+    @IQTable(name = "BooleanTest")\r
+    public static class BooleanAsIntModel {\r
+        @IQColumn(primaryKey = true)\r
+        public Integer id;\r
+\r
+        @IQColumn\r
+        public Integer mybool;\r
+\r
+        public BooleanAsIntModel() {\r
+        }\r
+\r
+        BooleanAsIntModel(int id, boolean val) {\r
+            this.id = id;\r
+            this.mybool = val ? 1 : 0;\r
+        }\r
+\r
+        public static List<BooleanAsIntModel> getList() {\r
+            return Arrays.asList(new BooleanAsIntModel(1, true), new BooleanAsIntModel(2, false),\r
+                    new BooleanAsIntModel(3, true), new BooleanAsIntModel(4, false));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Test boolean as primitive short\r
+     */\r
+    @IQTable(name = "BooleanTest")\r
+    public static class BooleanAsPrimitiveShortModel {\r
+        @IQColumn(primaryKey = true)\r
+        public Integer id;\r
+\r
+        @IQColumn\r
+        public short mybool;\r
+\r
+        public BooleanAsPrimitiveShortModel() {\r
+        }\r
+\r
+        BooleanAsPrimitiveShortModel(int id, boolean val) {\r
+            this.id = id;\r
+            this.mybool = (short) (val ? 1 : 0);\r
+        }\r
+\r
+        public static List<BooleanAsPrimitiveShortModel> getList() {\r
+            return Arrays.asList(new BooleanAsPrimitiveShortModel(1, true), new BooleanAsPrimitiveShortModel(2, false),\r
+                    new BooleanAsPrimitiveShortModel(3, true), new BooleanAsPrimitiveShortModel(4, false));\r
+        }\r
+    }\r
 }\r
index 2c01afa1ace5362ff366ac2c7f1a01c329fb7fff..8e538226b8e94c859f1e0bac81b04041279e2acf 100644 (file)
 
 package com.iciql.test.models;
 
-import java.util.Arrays;
-import java.util.List;
-
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQContraintUnique;
 import com.iciql.Iciql.IQIndex;
 import com.iciql.Iciql.IQTable;
 import com.iciql.Iciql.IndexType;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * A table containing category data.
  */
 
 @IQTable(name = "AnnotatedCategory", primaryKey = "id")
-@IQIndex(value = "categ", type=IndexType.UNIQUE)
-@IQContraintUnique(uniqueColumns = { "categ" })
+@IQIndex(value = "categ", type = IndexType.UNIQUE)
+@IQContraintUnique(uniqueColumns = {"categ"})
 public class CategoryAnnotationOnly {
 
-       @IQColumn(name = "id", autoIncrement = true)
-       public Long categoryId;
+    @IQColumn(name = "id", autoIncrement = true)
+    public Long categoryId;
 
-       @IQColumn(name = "categ", length = 15, trim = true)
-       public String category;
+    @IQColumn(name = "categ", length = 15, trim = true)
+    public String category;
 
-       public CategoryAnnotationOnly() {
-               // public constructor
-       }
+    public CategoryAnnotationOnly() {
+        // public constructor
+    }
 
-       private CategoryAnnotationOnly(long categoryId, String category) {
-               this.categoryId = categoryId;
-               this.category = category;
-       }
+    private CategoryAnnotationOnly(long categoryId, String category) {
+        this.categoryId = categoryId;
+        this.category = category;
+    }
 
-       private static CategoryAnnotationOnly create(int categoryId, String category) {
-               return new CategoryAnnotationOnly(categoryId, category);
-       }
+    private static CategoryAnnotationOnly create(int categoryId, String category) {
+        return new CategoryAnnotationOnly(categoryId, category);
+    }
 
-       public static List<CategoryAnnotationOnly> getList() {
-               CategoryAnnotationOnly[] list = {
-                               create(1, "Beverages"),
-                               create(2, "Condiments"),
-                               create(3, "Produce"),
-                               create(4, "Meat/Poultry"),
-                               create(5,"Seafood")
-               };
-               return Arrays.asList(list);
-       }
+    public static List<CategoryAnnotationOnly> getList() {
+        CategoryAnnotationOnly[] list = {
+                create(1, "Beverages"),
+                create(2, "Condiments"),
+                create(3, "Produce"),
+                create(4, "Meat/Poultry"),
+                create(5, "Seafood")
+        };
+        return Arrays.asList(list);
+    }
 
-       @Override
-       public String toString() {
-               return category;
-       }
+    @Override
+    public String toString() {
+        return category;
+    }
 
 }
index ce9b9eca5633f2399e37b63e67b7aedde688f3bc..8a851e23067a35dfaca315394e057075d952c32a 100644 (file)
@@ -17,8 +17,7 @@
 
 package com.iciql.test.models;
 
-import static com.iciql.Define.length;
-import static com.iciql.Define.primaryKey;
+import com.iciql.Iciql;
 
 import java.math.BigDecimal;
 import java.sql.Time;
@@ -27,40 +26,41 @@ import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 
-import com.iciql.Iciql;
+import static com.iciql.Define.length;
+import static com.iciql.Define.primaryKey;
 
 /**
  * A table containing all possible data types.
  */
 
 public class ComplexObject implements Iciql {
-       public Integer id;
-       public Long amount;
-       public String name;
-       public BigDecimal value;
-       public Date birthday;
-       public Time time;
-       public Timestamp created;
+    public Integer id;
+    public Long amount;
+    public String name;
+    public BigDecimal value;
+    public Date birthday;
+    public Time time;
+    public Timestamp created;
 
-       static ComplexObject build(Integer id, boolean isNull) {
-               ComplexObject obj = new ComplexObject();
-               obj.id = id;
-               obj.amount = isNull ? null : Long.valueOf(1);
-               obj.name = isNull ? null : "hello";
-               obj.value = isNull ? null : new BigDecimal("1");
-               obj.birthday = isNull ? null : java.sql.Date.valueOf("2001-01-01");
-               obj.time = isNull ? null : Time.valueOf("10:20:30");
-               obj.created = isNull ? null : Timestamp.valueOf("2002-02-02 02:02:02");
-               return obj;
-       }
+    static ComplexObject build(Integer id, boolean isNull) {
+        ComplexObject obj = new ComplexObject();
+        obj.id = id;
+        obj.amount = isNull ? null : Long.valueOf(1);
+        obj.name = isNull ? null : "hello";
+        obj.value = isNull ? null : new BigDecimal("1");
+        obj.birthday = isNull ? null : java.sql.Date.valueOf("2001-01-01");
+        obj.time = isNull ? null : Time.valueOf("10:20:30");
+        obj.created = isNull ? null : Timestamp.valueOf("2002-02-02 02:02:02");
+        return obj;
+    }
 
-       public void defineIQ() {
-               primaryKey(id);
-               length(name, 25);
-       }
+    public void defineIQ() {
+        primaryKey(id);
+        length(name, 25);
+    }
 
-       public static List<ComplexObject> getList() {
-               return Arrays.asList(new ComplexObject[] { build(0, true), build(1, false) });
-       }
+    public static List<ComplexObject> getList() {
+        return Arrays.asList(new ComplexObject[]{build(0, true), build(1, false)});
+    }
 
 }
index 1537c53fa4efdfd49a956788f5ccf912700a15bb..898c5b57176f30c446e1b8fc4b4bcc1a1201fb8a 100644 (file)
 \r
 package com.iciql.test.models;\r
 \r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQTable;\r
 \r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
 /**\r
  * A table containing customer data.\r
  */\r
 @IQTable\r
 public class Customer {\r
 \r
-       @IQColumn(length = 25)\r
-       public String customerId;\r
+    @IQColumn(length = 25)\r
+    public String customerId;\r
 \r
-       @IQColumn(length = 2)\r
-       public String region;\r
+    @IQColumn(length = 2)\r
+    public String region;\r
 \r
-       public Customer() {\r
-               // public constructor\r
-       }\r
+    public Customer() {\r
+        // public constructor\r
+    }\r
 \r
-       public Customer(String customerId, String region) {\r
-               this.customerId = customerId;\r
-               this.region = region;\r
-       }\r
+    public Customer(String customerId, String region) {\r
+        this.customerId = customerId;\r
+        this.region = region;\r
+    }\r
 \r
-       @Override\r
-       public String toString() {\r
-               return customerId;\r
-       }\r
+    @Override\r
+    public String toString() {\r
+        return customerId;\r
+    }\r
 \r
-       public static List<Customer> getList() {\r
-               return Arrays.asList(\r
-                               new Customer("ALFKI", "WA"),\r
-                               new Customer("ANATR", "WA"),\r
-                               new Customer("ASLAN", "CA"),\r
-                               new Customer("ANTON", "CA"),\r
-                               new Customer("BROWN", "LA"),\r
-                               new Customer("SMITH", "NY"),\r
-                               new Customer("JONES", "ME"),\r
-                               new Customer(null, null));\r
-       }\r
+    public static List<Customer> getList() {\r
+        return Arrays.asList(\r
+                new Customer("ALFKI", "WA"),\r
+                new Customer("ANATR", "WA"),\r
+                new Customer("ASLAN", "CA"),\r
+                new Customer("ANTON", "CA"),\r
+                new Customer("BROWN", "LA"),\r
+                new Customer("SMITH", "NY"),\r
+                new Customer("JONES", "ME"),\r
+                new Customer(null, null));\r
+    }\r
 \r
 }\r
index cb3b4210057c6a7098bb42890f30787e34374541..937f2b159e00f548b7a97e0a3a64a4d8e2df9213 100644 (file)
  */\r
 package com.iciql.test.models;\r
 \r
-import java.util.Date;\r
-\r
 import com.iciql.Iciql.EnumType;\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQEnum;\r
 import com.iciql.Iciql.IQTable;\r
 import com.iciql.test.models.EnumModels.Tree;\r
 \r
+import java.util.Date;\r
+\r
 /**\r
  * Default values model.\r
  */\r
 @IQTable(name = "DefaultValuesTest")\r
 public class DefaultValuesModel {\r
 \r
-       @IQColumn(primaryKey = true, autoIncrement = true)\r
-       public Long myLong;\r
+    @IQColumn(primaryKey = true, autoIncrement = true)\r
+    public Long myLong;\r
 \r
-       @SuppressWarnings("deprecation")\r
-       @IQColumn\r
-       public Date myDate = new Date(100, 7, 1);\r
+    @SuppressWarnings("deprecation")\r
+    @IQColumn\r
+    public Date myDate = new Date(100, 7, 1);\r
 \r
-       @IQColumn\r
-       public Integer myInteger = 12345;\r
+    @IQColumn\r
+    public Integer myInteger = 12345;\r
 \r
-       @IQColumn\r
-       public Tree myEnumIdTree = Tree.WALNUT;\r
+    @IQColumn\r
+    public Tree myEnumIdTree = Tree.WALNUT;\r
 \r
-       @IQColumn\r
-       @IQEnum(EnumType.NAME)\r
-       public Tree myNameTree = Tree.MAPLE;\r
+    @IQColumn\r
+    @IQEnum(EnumType.NAME)\r
+    public Tree myNameTree = Tree.MAPLE;\r
 \r
-       @IQColumn\r
-       @IQEnum(EnumType.ORDINAL)\r
-       public Tree myOrdinalTree = Tree.PINE;\r
+    @IQColumn\r
+    @IQEnum(EnumType.ORDINAL)\r
+    public Tree myOrdinalTree = Tree.PINE;\r
 \r
-       @IQColumn(nullable = true)\r
-       public Tree myNullTree;\r
+    @IQColumn(nullable = true)\r
+    public Tree myNullTree;\r
 \r
-       public DefaultValuesModel() {\r
-       }\r
+    public DefaultValuesModel() {\r
+    }\r
 }\r
index 232073477ad2f2afb96b09748c7da92fc01660a9..de22328408cdc1e5eef2d08de2c233c4a1f96b45 100644 (file)
 \r
 package com.iciql.test.models;\r
 \r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
 import com.iciql.Iciql.EnumId;\r
 import com.iciql.Iciql.EnumType;\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQEnum;\r
 import com.iciql.Iciql.IQTable;\r
 \r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
 /**\r
  * Container for reusable enum model classes which exercise the 3 supported\r
  * types.\r
  */\r
 public abstract class EnumModels {\r
 \r
-       /**\r
-        * Test of @IQEnum annotated enumeration. This strategy is the default\r
-        * strategy for all fields of the Tree enum.\r
-        *\r
-        * Individual Tree field declarations can override this strategy by\r
-        * specifying a different @IQEnum annotation.\r
-        *\r
-        * Here ORDINAL specifies that this enum will be mapped to an INT column.\r
-        */\r
-       @IQEnum(EnumType.ENUMID)\r
-       public enum Tree implements EnumId<Integer> {\r
-               PINE(10), OAK(20), BIRCH(30), WALNUT(40), MAPLE(50);\r
-\r
-               private int enumid;\r
-\r
-               Tree(int id) {\r
-                       this.enumid = id;\r
-               }\r
-\r
-               @Override\r
-               public Integer enumId() {\r
-                       return enumid;\r
-               }\r
-\r
-               @Override\r
-               public Class<Integer> enumIdClass() {\r
-                       return Integer.class;\r
-               }\r
-\r
-       }\r
-\r
-       /**\r
-        * Enum for testing custom ENUMID mapping.\r
-        */\r
-       @IQEnum(EnumType.ENUMID)\r
-       public enum Genus implements EnumId<String> {\r
-               PINUS("pinaceae"), QUERCUS("fagaceae"), BETULA("betulaceae"), JUGLANS("juglandaceae"), ACER("aceraceae");\r
-\r
-               private String family;\r
-\r
-               Genus(String id) {\r
-                       this.family = id;\r
-               }\r
-\r
-               @Override\r
-               public String enumId() {\r
-                       return family;\r
-               }\r
-\r
-               @Override\r
-               public Class<String> enumIdClass() {\r
-                       return String.class;\r
-               }\r
-       }\r
-\r
-       @IQColumn(primaryKey = true)\r
-       public Integer id;\r
-\r
-       public abstract Tree tree();\r
-\r
-       public abstract Genus genus();\r
-\r
-       /**\r
-        * Test model for enum-as-enumid.\r
-        */\r
-       @IQTable(inheritColumns = true)\r
-       public static class EnumIdModel extends EnumModels {\r
-\r
-               // no need to specify ENUMID type as the enumeration definition\r
-               // specifies it.\r
-               @IQColumn\r
-               private Tree tree;\r
-\r
-               // no need to specify ENUMID type as the enumeration definition\r
-               // specifies it.\r
-               @IQColumn\r
-               private Genus genus;\r
-\r
-               public EnumIdModel() {\r
-               }\r
-\r
-               public EnumIdModel(int id, Tree tree, Genus genus) {\r
-                       this.id = id;\r
-                       this.tree = tree;\r
-                       this.genus = genus;\r
-               }\r
-\r
-               @Override\r
-               public Tree tree() {\r
-                       return tree;\r
-               }\r
-\r
-               @Override\r
-               public Genus genus() {\r
-                       return genus;\r
-               }\r
-\r
-               public static List<EnumIdModel> createList() {\r
-                       return Arrays.asList(new EnumIdModel(400, Tree.WALNUT, Genus.JUGLANS),\r
-                                       new EnumIdModel(200, Tree.OAK, Genus.QUERCUS),\r
-                                       new EnumIdModel(500, Tree.MAPLE, Genus.ACER),\r
-                                       new EnumIdModel(300, Tree.BIRCH, Genus.BETULA),\r
-                                       new EnumIdModel(100, Tree.PINE, Genus.PINUS));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Test model for enum-as-ordinal.\r
-        */\r
-       @IQTable(inheritColumns = true)\r
-       public static class EnumOrdinalModel extends EnumModels {\r
-\r
-               // override the enumtype to ordinal\r
-               @IQEnum(EnumType.ORDINAL)\r
-               @IQColumn\r
-               private Tree tree;\r
-\r
-               @IQColumn\r
-               private Genus genus;\r
-\r
-               public EnumOrdinalModel() {\r
-               }\r
-\r
-               public EnumOrdinalModel(int id, Tree tree, Genus genus) {\r
-                       this.id = id;\r
-                       this.tree = tree;\r
-               }\r
-\r
-               @Override\r
-               public Tree tree() {\r
-                       return tree;\r
-               }\r
-\r
-               @Override\r
-               public Genus genus() {\r
-                       return genus;\r
-               }\r
-\r
-               public static List<EnumOrdinalModel> createList() {\r
-                       return Arrays.asList(new EnumOrdinalModel(400, Tree.WALNUT, Genus.JUGLANS),\r
-                                       new EnumOrdinalModel(200, Tree.OAK, Genus.QUERCUS),\r
-                                       new EnumOrdinalModel(500, Tree.MAPLE, Genus.ACER),\r
-                                       new EnumOrdinalModel(300, Tree.BIRCH, Genus.BETULA),\r
-                                       new EnumOrdinalModel(100, Tree.PINE, Genus.PINUS));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Test model for enum-as-string.\r
-        */\r
-       @IQTable(inheritColumns = true)\r
-       public static class EnumStringModel extends EnumModels {\r
-\r
-               // override the enumtype to string\r
-               // ensure that we specify a length so that the column is VARCHAR\r
-               @IQEnum(EnumType.NAME)\r
-               @IQColumn(length = 25)\r
-               private Tree tree;\r
-\r
-               @IQColumn(trim = true, length = 25)\r
-               private Genus genus;\r
-\r
-               public EnumStringModel() {\r
-               }\r
-\r
-               public EnumStringModel(int id, Tree tree, Genus genus) {\r
-                       this.id = id;\r
-                       this.tree = tree;\r
-                       this.genus = genus;\r
-               }\r
-\r
-               @Override\r
-               public Tree tree() {\r
-                       return tree;\r
-               }\r
-\r
-               @Override\r
-               public Genus genus() {\r
-                       return genus;\r
-               }\r
-\r
-               public static List<EnumStringModel> createList() {\r
-                       return Arrays.asList(new EnumStringModel(400, Tree.WALNUT, Genus.JUGLANS),\r
-                                       new EnumStringModel(200, Tree.OAK, Genus.QUERCUS),\r
-                                       new EnumStringModel(500, Tree.MAPLE, Genus.ACER),\r
-                                       new EnumStringModel(300, Tree.BIRCH, Genus.BETULA),\r
-                                       new EnumStringModel(100, Tree.PINE, Genus.PINUS));\r
-               }\r
-       }\r
+    /**\r
+     * Test of @IQEnum annotated enumeration. This strategy is the default\r
+     * strategy for all fields of the Tree enum.\r
+     * <p>\r
+     * Individual Tree field declarations can override this strategy by\r
+     * specifying a different @IQEnum annotation.\r
+     * <p>\r
+     * Here ORDINAL specifies that this enum will be mapped to an INT column.\r
+     */\r
+    @IQEnum(EnumType.ENUMID)\r
+    public enum Tree implements EnumId<Integer> {\r
+        PINE(10), OAK(20), BIRCH(30), WALNUT(40), MAPLE(50);\r
+\r
+        private int enumid;\r
+\r
+        Tree(int id) {\r
+            this.enumid = id;\r
+        }\r
+\r
+        @Override\r
+        public Integer enumId() {\r
+            return enumid;\r
+        }\r
+\r
+        @Override\r
+        public Class<Integer> enumIdClass() {\r
+            return Integer.class;\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Enum for testing custom ENUMID mapping.\r
+     */\r
+    @IQEnum(EnumType.ENUMID)\r
+    public enum Genus implements EnumId<String> {\r
+        PINUS("pinaceae"), QUERCUS("fagaceae"), BETULA("betulaceae"), JUGLANS("juglandaceae"), ACER("aceraceae");\r
+\r
+        private String family;\r
+\r
+        Genus(String id) {\r
+            this.family = id;\r
+        }\r
+\r
+        @Override\r
+        public String enumId() {\r
+            return family;\r
+        }\r
+\r
+        @Override\r
+        public Class<String> enumIdClass() {\r
+            return String.class;\r
+        }\r
+    }\r
+\r
+    @IQColumn(primaryKey = true)\r
+    public Integer id;\r
+\r
+    public abstract Tree tree();\r
+\r
+    public abstract Genus genus();\r
+\r
+    /**\r
+     * Test model for enum-as-enumid.\r
+     */\r
+    @IQTable(inheritColumns = true)\r
+    public static class EnumIdModel extends EnumModels {\r
+\r
+        // no need to specify ENUMID type as the enumeration definition\r
+        // specifies it.\r
+        @IQColumn\r
+        private Tree tree;\r
+\r
+        // no need to specify ENUMID type as the enumeration definition\r
+        // specifies it.\r
+        @IQColumn\r
+        private Genus genus;\r
+\r
+        public EnumIdModel() {\r
+        }\r
+\r
+        public EnumIdModel(int id, Tree tree, Genus genus) {\r
+            this.id = id;\r
+            this.tree = tree;\r
+            this.genus = genus;\r
+        }\r
+\r
+        @Override\r
+        public Tree tree() {\r
+            return tree;\r
+        }\r
+\r
+        @Override\r
+        public Genus genus() {\r
+            return genus;\r
+        }\r
+\r
+        public static List<EnumIdModel> createList() {\r
+            return Arrays.asList(new EnumIdModel(400, Tree.WALNUT, Genus.JUGLANS),\r
+                    new EnumIdModel(200, Tree.OAK, Genus.QUERCUS),\r
+                    new EnumIdModel(500, Tree.MAPLE, Genus.ACER),\r
+                    new EnumIdModel(300, Tree.BIRCH, Genus.BETULA),\r
+                    new EnumIdModel(100, Tree.PINE, Genus.PINUS));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Test model for enum-as-ordinal.\r
+     */\r
+    @IQTable(inheritColumns = true)\r
+    public static class EnumOrdinalModel extends EnumModels {\r
+\r
+        // override the enumtype to ordinal\r
+        @IQEnum(EnumType.ORDINAL)\r
+        @IQColumn\r
+        private Tree tree;\r
+\r
+        @IQColumn\r
+        private Genus genus;\r
+\r
+        public EnumOrdinalModel() {\r
+        }\r
+\r
+        public EnumOrdinalModel(int id, Tree tree, Genus genus) {\r
+            this.id = id;\r
+            this.tree = tree;\r
+        }\r
+\r
+        @Override\r
+        public Tree tree() {\r
+            return tree;\r
+        }\r
+\r
+        @Override\r
+        public Genus genus() {\r
+            return genus;\r
+        }\r
+\r
+        public static List<EnumOrdinalModel> createList() {\r
+            return Arrays.asList(new EnumOrdinalModel(400, Tree.WALNUT, Genus.JUGLANS),\r
+                    new EnumOrdinalModel(200, Tree.OAK, Genus.QUERCUS),\r
+                    new EnumOrdinalModel(500, Tree.MAPLE, Genus.ACER),\r
+                    new EnumOrdinalModel(300, Tree.BIRCH, Genus.BETULA),\r
+                    new EnumOrdinalModel(100, Tree.PINE, Genus.PINUS));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Test model for enum-as-string.\r
+     */\r
+    @IQTable(inheritColumns = true)\r
+    public static class EnumStringModel extends EnumModels {\r
+\r
+        // override the enumtype to string\r
+        // ensure that we specify a length so that the column is VARCHAR\r
+        @IQEnum(EnumType.NAME)\r
+        @IQColumn(length = 25)\r
+        private Tree tree;\r
+\r
+        @IQColumn(trim = true, length = 25)\r
+        private Genus genus;\r
+\r
+        public EnumStringModel() {\r
+        }\r
+\r
+        public EnumStringModel(int id, Tree tree, Genus genus) {\r
+            this.id = id;\r
+            this.tree = tree;\r
+            this.genus = genus;\r
+        }\r
+\r
+        @Override\r
+        public Tree tree() {\r
+            return tree;\r
+        }\r
+\r
+        @Override\r
+        public Genus genus() {\r
+            return genus;\r
+        }\r
+\r
+        public static List<EnumStringModel> createList() {\r
+            return Arrays.asList(new EnumStringModel(400, Tree.WALNUT, Genus.JUGLANS),\r
+                    new EnumStringModel(200, Tree.OAK, Genus.QUERCUS),\r
+                    new EnumStringModel(500, Tree.MAPLE, Genus.ACER),\r
+                    new EnumStringModel(300, Tree.BIRCH, Genus.BETULA),\r
+                    new EnumStringModel(100, Tree.PINE, Genus.PINUS));\r
+        }\r
+    }\r
 }\r
index 7bc429cc7917219299024769af8b21392bf10fcb..7bdfd400cf812fb7997244e6da9c5b657f1042c5 100644 (file)
@@ -1,40 +1,39 @@
 package com.iciql.test.models;\r
 \r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQTable;\r
 \r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
 /**\r
  * Model class to test the runtime exception of too many primitive boolean\r
  * fields in the model.\r
- * \r
+ *\r
  * @author James Moger\r
- * \r
  */\r
 @IQTable\r
 public class MultipleBoolsModel {\r
 \r
-       @IQColumn(autoIncrement = true, primaryKey = true)\r
-       public int id;\r
+    @IQColumn(autoIncrement = true, primaryKey = true)\r
+    public int id;\r
 \r
-       @IQColumn\r
-       public boolean a;\r
+    @IQColumn\r
+    public boolean a;\r
 \r
-       @IQColumn\r
-       public boolean b;\r
+    @IQColumn\r
+    public boolean b;\r
 \r
-       public MultipleBoolsModel() {\r
-       }\r
+    public MultipleBoolsModel() {\r
+    }\r
 \r
-       public MultipleBoolsModel(boolean a, boolean b) {\r
-               this.a = a;\r
-               this.b = b;\r
-       }\r
+    public MultipleBoolsModel(boolean a, boolean b) {\r
+        this.a = a;\r
+        this.b = b;\r
+    }\r
 \r
-       public static List<MultipleBoolsModel> getList() {\r
-               return Arrays.asList(new MultipleBoolsModel(true, true), new MultipleBoolsModel(true, false),\r
-                               new MultipleBoolsModel(true, false), new MultipleBoolsModel(false, false));\r
-       }\r
+    public static List<MultipleBoolsModel> getList() {\r
+        return Arrays.asList(new MultipleBoolsModel(true, true), new MultipleBoolsModel(true, false),\r
+                new MultipleBoolsModel(true, false), new MultipleBoolsModel(false, false));\r
+    }\r
 }
\ No newline at end of file
index 1fa9097310aa18a8696420200c12957ba9a84460..d406765393be851dd2ed1249f9dfeff91496de49 100644 (file)
 \r
 package com.iciql.test.models;\r
 \r
-import static com.iciql.Define.length;\r
-import static com.iciql.Define.primaryKey;\r
-import static com.iciql.Define.scale;\r
-import static com.iciql.Define.tableName;\r
+import com.iciql.Iciql;\r
 \r
 import java.math.BigDecimal;\r
 import java.util.Arrays;\r
 import java.util.Date;\r
 import java.util.List;\r
 \r
-import com.iciql.Iciql;\r
+import static com.iciql.Define.*;\r
 \r
 /**\r
  * A table containing order data.\r
  */\r
 \r
 public class Order implements Iciql {\r
-       public String customerId;\r
-       public Integer orderId;\r
-       public Date orderDate;\r
-       public BigDecimal total;\r
+    public String customerId;\r
+    public Integer orderId;\r
+    public Date orderDate;\r
+    public BigDecimal total;\r
 \r
-       public Order(String customerId, Integer orderId, String total, String orderDate) {\r
-               this.customerId = customerId;\r
-               this.orderId = orderId;\r
-               this.total = new BigDecimal(total);\r
-               this.orderDate = java.sql.Date.valueOf(orderDate);\r
-       }\r
+    public Order(String customerId, Integer orderId, String total, String orderDate) {\r
+        this.customerId = customerId;\r
+        this.orderId = orderId;\r
+        this.total = new BigDecimal(total);\r
+        this.orderDate = java.sql.Date.valueOf(orderDate);\r
+    }\r
 \r
-       public Order() {\r
-               // public constructor\r
-       }\r
+    public Order() {\r
+        // public constructor\r
+    }\r
 \r
-       public void defineIQ() {\r
-               tableName("Orders");\r
-               length(customerId, 25);\r
-               length(total, 10);\r
-               scale(total, 2);\r
-               primaryKey(customerId, orderId);\r
-       }\r
+    public void defineIQ() {\r
+        tableName("Orders");\r
+        length(customerId, 25);\r
+        length(total, 10);\r
+        scale(total, 2);\r
+        primaryKey(customerId, orderId);\r
+    }\r
 \r
-       public static List<Order> getList() {\r
-               Order[] list = { new Order("ALFKI", 10702, "330.00", "2007-01-02"),\r
-                               new Order("ALFKI", 10952, "471.20", "2007-02-03"),\r
-                               new Order("ANATR", 10308, "88.80", "2007-01-03"),\r
-                               new Order("ANATR", 10625, "479.75", "2007-03-03"),\r
-                               new Order("ANATR", 10759, "320.00", "2007-04-01"),\r
-                               new Order("ANTON", 10365, "403.20", "2007-02-13"),\r
-                               new Order("ANTON", 10682, "375.50", "2007-03-13"),\r
-                               new Order("ANTON", 10355, "480.00", "2007-04-11") };\r
-               return Arrays.asList(list);\r
-       }\r
+    public static List<Order> getList() {\r
+        Order[] list = {new Order("ALFKI", 10702, "330.00", "2007-01-02"),\r
+                new Order("ALFKI", 10952, "471.20", "2007-02-03"),\r
+                new Order("ANATR", 10308, "88.80", "2007-01-03"),\r
+                new Order("ANATR", 10625, "479.75", "2007-03-03"),\r
+                new Order("ANATR", 10759, "320.00", "2007-04-01"),\r
+                new Order("ANTON", 10365, "403.20", "2007-02-13"),\r
+                new Order("ANTON", 10682, "375.50", "2007-03-13"),\r
+                new Order("ANTON", 10355, "480.00", "2007-04-11")};\r
+        return Arrays.asList(list);\r
+    }\r
 \r
 }\r
index 44e8b9b78e9d4c8a869c69983345abcf60c7c8fc..078b5652d0278d5f37a62fe165f993dbf6e26c0b 100644 (file)
  */\r
 package com.iciql.test.models;\r
 \r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Random;\r
-\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQTable;\r
 import com.iciql.test.IciqlSuite;\r
 \r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Random;\r
+\r
 /**\r
  * Primitive types model.\r
  */\r
 @IQTable(name = "PrimitivesTest")\r
 public class PrimitivesModel {\r
 \r
-       @IQColumn(primaryKey = true)\r
-       public long myLong;\r
+    @IQColumn(primaryKey = true)\r
+    public long myLong;\r
 \r
-       @IQColumn\r
-       public int myInteger;\r
+    @IQColumn\r
+    public int myInteger;\r
 \r
-       @IQColumn\r
-       public short myShort;\r
+    @IQColumn\r
+    public short myShort;\r
 \r
-       @IQColumn\r
-       public byte myByte;\r
+    @IQColumn\r
+    public byte myByte;\r
 \r
-       @IQColumn\r
-       public boolean myBoolean;\r
+    @IQColumn\r
+    public boolean myBoolean;\r
 \r
-       @IQColumn\r
-       public double myDouble;\r
+    @IQColumn\r
+    public double myDouble;\r
 \r
-       @IQColumn\r
-       public float myFloat;\r
+    @IQColumn\r
+    public float myFloat;\r
 \r
-       public PrimitivesModel() {\r
-               Random rand = new Random();\r
-               myLong = rand.nextLong();\r
-               myInteger = rand.nextInt();\r
-               myShort = (short) rand.nextInt(Short.MAX_VALUE);\r
-               myByte = (byte) rand.nextInt(Byte.MAX_VALUE);\r
-               myBoolean = rand.nextInt(1) == 1;\r
-               myDouble = rand.nextDouble();\r
-               myFloat = rand.nextFloat();\r
-       }\r
+    public PrimitivesModel() {\r
+        Random rand = new Random();\r
+        myLong = rand.nextLong();\r
+        myInteger = rand.nextInt();\r
+        myShort = (short) rand.nextInt(Short.MAX_VALUE);\r
+        myByte = (byte) rand.nextInt(Byte.MAX_VALUE);\r
+        myBoolean = rand.nextInt(1) == 1;\r
+        myDouble = rand.nextDouble();\r
+        myFloat = rand.nextFloat();\r
+    }\r
 \r
-       public boolean equivalentTo(PrimitivesModel p) {\r
-               boolean same = true;\r
-               same &= myLong == p.myLong;\r
-               same &= myInteger == p.myInteger;\r
-               same &= myShort == p.myShort;\r
-               same &= myByte == p.myByte;\r
-               same &= myBoolean == p.myBoolean;\r
-               same &= IciqlSuite.equivalentTo(myDouble, p.myDouble);\r
-               same &= IciqlSuite.equivalentTo(myFloat, p.myFloat);\r
-               return same;\r
-       }\r
+    public boolean equivalentTo(PrimitivesModel p) {\r
+        boolean same = true;\r
+        same &= myLong == p.myLong;\r
+        same &= myInteger == p.myInteger;\r
+        same &= myShort == p.myShort;\r
+        same &= myByte == p.myByte;\r
+        same &= myBoolean == p.myBoolean;\r
+        same &= IciqlSuite.equivalentTo(myDouble, p.myDouble);\r
+        same &= IciqlSuite.equivalentTo(myFloat, p.myFloat);\r
+        return same;\r
+    }\r
 \r
-       public static List<PrimitivesModel> getList() {\r
-               List<PrimitivesModel> list = new ArrayList<PrimitivesModel>();\r
-               for (int i = 1; i <= 10; i++) {\r
-                       PrimitivesModel p = new PrimitivesModel();\r
-                       p.myLong = i;\r
-                       list.add(p);\r
-               }\r
-               return list;\r
-       }\r
+    public static List<PrimitivesModel> getList() {\r
+        List<PrimitivesModel> list = new ArrayList<PrimitivesModel>();\r
+        for (int i = 1; i <= 10; i++) {\r
+            PrimitivesModel p = new PrimitivesModel();\r
+            p.myLong = i;\r
+            list.add(p);\r
+        }\r
+        return list;\r
+    }\r
 \r
-       @Override\r
-       public String toString() {\r
-               return String.valueOf(myLong);\r
-       }\r
+    @Override\r
+    public String toString() {\r
+        return String.valueOf(myLong);\r
+    }\r
 }\r
index 7feb99849be422aeb72b4b3c1266b6bca01b73ed..bebc4a963895ca04a49b4a3e3806b54acdec8d3d 100644 (file)
 \r
 package com.iciql.test.models;\r
 \r
-import static com.iciql.Define.index;\r
-import static com.iciql.Define.length;\r
-import static com.iciql.Define.primaryKey;\r
-import static com.iciql.Define.tableName;\r
+import com.iciql.Iciql;\r
 \r
 import java.util.Arrays;\r
 import java.util.List;\r
 \r
-import com.iciql.Iciql;\r
+import static com.iciql.Define.*;\r
 \r
 /**\r
  * A table containing product data.\r
@@ -33,63 +30,63 @@ import com.iciql.Iciql;
 \r
 public class Product implements Iciql {\r
 \r
-       public Integer productId;\r
-       public String productName;\r
-       public String category;\r
-       public Double unitPrice;\r
-       public Integer unitsInStock;\r
-\r
-       public Product() {\r
-               // public constructor\r
-       }\r
-\r
-       private Product(int productId, String productName, String category, double unitPrice, int unitsInStock) {\r
-               this.productId = productId;\r
-               this.productName = productName;\r
-               this.category = category;\r
-               this.unitPrice = unitPrice;\r
-               this.unitsInStock = unitsInStock;\r
-       }\r
-\r
-       public String getName() {\r
-               return productName;\r
-       }\r
-\r
-       public int getId() {\r
-               return productId;\r
-       }\r
-\r
-       @Override\r
-       public void defineIQ() {\r
-               tableName("Product");\r
-               primaryKey(productId);\r
-               length(productName, 255);\r
-               length(category, 255);\r
-               index("MyIndex", IndexType.STANDARD, productName, category);\r
-       }\r
-\r
-       private static Product create(int productId, String productName, String category, double unitPrice,\r
-                       int unitsInStock) {\r
-               return new Product(productId, productName, category, unitPrice, unitsInStock);\r
-       }\r
-\r
-       public static List<Product> getList() {\r
-               Product[] list = { create(1, "Chai", "Beverages", 18, 39), create(2, "Chang", "Beverages", 19.0, 17),\r
-                               create(3, "Aniseed Syrup", "Condiments", 10.0, 13),\r
-                               create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53),\r
-                               create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0),\r
-                               create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120),\r
-                               create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15),\r
-                               create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6),\r
-                               create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29),\r
-                               create(10, "Ikura", "Seafood", 31.0, 31), };\r
-\r
-               return Arrays.asList(list);\r
-       }\r
-\r
-       @Override\r
-       public String toString() {\r
-               return productName + ": " + unitsInStock;\r
-       }\r
+    public Integer productId;\r
+    public String productName;\r
+    public String category;\r
+    public Double unitPrice;\r
+    public Integer unitsInStock;\r
+\r
+    public Product() {\r
+        // public constructor\r
+    }\r
+\r
+    private Product(int productId, String productName, String category, double unitPrice, int unitsInStock) {\r
+        this.productId = productId;\r
+        this.productName = productName;\r
+        this.category = category;\r
+        this.unitPrice = unitPrice;\r
+        this.unitsInStock = unitsInStock;\r
+    }\r
+\r
+    public String getName() {\r
+        return productName;\r
+    }\r
+\r
+    public int getId() {\r
+        return productId;\r
+    }\r
+\r
+    @Override\r
+    public void defineIQ() {\r
+        tableName("Product");\r
+        primaryKey(productId);\r
+        length(productName, 255);\r
+        length(category, 255);\r
+        index("MyIndex", IndexType.STANDARD, productName, category);\r
+    }\r
+\r
+    private static Product create(int productId, String productName, String category, double unitPrice,\r
+                                  int unitsInStock) {\r
+        return new Product(productId, productName, category, unitPrice, unitsInStock);\r
+    }\r
+\r
+    public static List<Product> getList() {\r
+        Product[] list = {create(1, "Chai", "Beverages", 18, 39), create(2, "Chang", "Beverages", 19.0, 17),\r
+                create(3, "Aniseed Syrup", "Condiments", 10.0, 13),\r
+                create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53),\r
+                create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0),\r
+                create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120),\r
+                create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15),\r
+                create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6),\r
+                create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29),\r
+                create(10, "Ikura", "Seafood", 31.0, 31),};\r
+\r
+        return Arrays.asList(list);\r
+    }\r
+\r
+    @Override\r
+    public String toString() {\r
+        return productName + ": " + unitsInStock;\r
+    }\r
 \r
 }\r
index ea5856bf646f650cc6aba13cbec3d38c23b2e738..c091b0e99e45e595aa820c87b16a69c55267eeac 100644 (file)
 
 package com.iciql.test.models;
 
-import java.util.Arrays;
-import java.util.List;
-
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQIndex;
 import com.iciql.Iciql.IQIndexes;
 import com.iciql.Iciql.IQTable;
 import com.iciql.Iciql.IndexType;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * A table containing product data.
  */
 
 @IQTable(name = "AnnotatedProduct")
-@IQIndexes({ @IQIndex({ "name", "cat" }), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name") })
+@IQIndexes({@IQIndex({"name", "cat"}), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name")})
 public class ProductAnnotationOnly {
 
-       public String unmappedField;
-
-       @IQColumn(name = "id", autoIncrement = true, primaryKey = true)
-       public Long productId;
-
-       @IQColumn(name = "cat", length = 15, trim = true)
-       public String category;
-
-       @IQColumn(name = "name", length = 50)
-       public String productName;
-
-       @SuppressWarnings("unused")
-       @IQColumn
-       private Double unitPrice;
-
-       @IQColumn
-       private Integer unitsInStock;
-
-       public ProductAnnotationOnly() {
-               // public constructor
-       }
-
-       private ProductAnnotationOnly(long productId, String productName, String category, double unitPrice,
-                       int unitsInStock, String unmappedField) {
-               this.productId = productId;
-               this.productName = productName;
-               this.category = category;
-               this.unitPrice = unitPrice;
-               this.unitsInStock = unitsInStock;
-               this.unmappedField = unmappedField;
-       }
-
-       private static ProductAnnotationOnly create(int productId, String productName, String category,
-                       double unitPrice, int unitsInStock, String unmappedField) {
-               return new ProductAnnotationOnly(productId, productName, category, unitPrice, unitsInStock,
-                               unmappedField);
-       }
-
-       public static List<ProductAnnotationOnly> getList() {
-               String unmappedField = "unmapped";
-               ProductAnnotationOnly[] list = { create(1, "Chai", "Beverages", 18, 39, unmappedField),
-                               create(2, "Chang", "Beverages", 19.0, 17, unmappedField),
-                               create(3, "Aniseed Syrup", "Condiments", 10.0, 13, unmappedField),
-                               create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, unmappedField),
-                               create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, unmappedField),
-                               create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, unmappedField),
-                               create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, unmappedField),
-                               create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, unmappedField),
-                               create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, unmappedField),
-                               create(10, "Ikura", "Seafood", 31.0, 31, unmappedField), };
-               return Arrays.asList(list);
-       }
-
-       @Override
-       public String toString() {
-               return productName + ": " + unitsInStock;
-       }
+    public String unmappedField;
+
+    @IQColumn(name = "id", autoIncrement = true, primaryKey = true)
+    public Long productId;
+
+    @IQColumn(name = "cat", length = 15, trim = true)
+    public String category;
+
+    @IQColumn(name = "name", length = 50)
+    public String productName;
+
+    @SuppressWarnings("unused")
+    @IQColumn
+    private Double unitPrice;
+
+    @IQColumn
+    private Integer unitsInStock;
+
+    public ProductAnnotationOnly() {
+        // public constructor
+    }
+
+    private ProductAnnotationOnly(long productId, String productName, String category, double unitPrice,
+                                  int unitsInStock, String unmappedField) {
+        this.productId = productId;
+        this.productName = productName;
+        this.category = category;
+        this.unitPrice = unitPrice;
+        this.unitsInStock = unitsInStock;
+        this.unmappedField = unmappedField;
+    }
+
+    private static ProductAnnotationOnly create(int productId, String productName, String category,
+                                                double unitPrice, int unitsInStock, String unmappedField) {
+        return new ProductAnnotationOnly(productId, productName, category, unitPrice, unitsInStock,
+                unmappedField);
+    }
+
+    public static List<ProductAnnotationOnly> getList() {
+        String unmappedField = "unmapped";
+        ProductAnnotationOnly[] list = {create(1, "Chai", "Beverages", 18, 39, unmappedField),
+                create(2, "Chang", "Beverages", 19.0, 17, unmappedField),
+                create(3, "Aniseed Syrup", "Condiments", 10.0, 13, unmappedField),
+                create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, unmappedField),
+                create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, unmappedField),
+                create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, unmappedField),
+                create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, unmappedField),
+                create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, unmappedField),
+                create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, unmappedField),
+                create(10, "Ikura", "Seafood", 31.0, 31, unmappedField),};
+        return Arrays.asList(list);
+    }
+
+    @Override
+    public String toString() {
+        return productName + ": " + unitsInStock;
+    }
 
 }
index 4268a89ba90a570c7f3a678db118c44cd36fcc93..d6edc1a2512e14f15880c1e46465db75f6f668d0 100644 (file)
@@ -17,9 +17,6 @@
 
 package com.iciql.test.models;
 
-import java.util.Arrays;
-import java.util.List;
-
 import com.iciql.Iciql.ConstraintDeleteType;
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQContraintForeignKey;
@@ -28,75 +25,78 @@ import com.iciql.Iciql.IQIndexes;
 import com.iciql.Iciql.IQTable;
 import com.iciql.Iciql.IndexType;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * A table containing product data.
  */
 
 @IQTable(name = "AnnotatedProduct", primaryKey = "id")
-@IQIndexes({ @IQIndex({ "name", "cat" }), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name") })
+@IQIndexes({@IQIndex({"name", "cat"}), @IQIndex(name = "nameidx", type = IndexType.HASH, value = "name")})
 @IQContraintForeignKey(
-               foreignColumns= { "cat" }, 
-               referenceName = "AnnotatedCategory",
-               referenceColumns = { "categ" },
-               deleteType = ConstraintDeleteType.CASCADE
+        foreignColumns = {"cat"},
+        referenceName = "AnnotatedCategory",
+        referenceColumns = {"categ"},
+        deleteType = ConstraintDeleteType.CASCADE
 )
 public class ProductAnnotationOnlyWithForeignKey {
 
-       public String unmappedField;
-
-       @IQColumn(name = "id", autoIncrement = true)
-       public Long productId;
-
-       @IQColumn(name = "cat", length = 15, trim = true)
-       public String category;
-
-       @IQColumn(name = "name", length = 50)
-       public String productName;
-
-       @SuppressWarnings("unused")
-       @IQColumn
-       private Double unitPrice;
-
-       @IQColumn
-       private Integer unitsInStock;
-
-       public ProductAnnotationOnlyWithForeignKey() {
-               // public constructor
-       }
-
-       private ProductAnnotationOnlyWithForeignKey(long productId, String productName, String category, double unitPrice,
-                       int unitsInStock, String unmappedField) {
-               this.productId = productId;
-               this.productName = productName;
-               this.category = category;
-               this.unitPrice = unitPrice;
-               this.unitsInStock = unitsInStock;
-               this.unmappedField = unmappedField;
-       }
-
-       private static ProductAnnotationOnlyWithForeignKey create(int productId, String productName, String category,
-                       double unitPrice, int unitsInStock, String unmappedField) {
-               return new ProductAnnotationOnlyWithForeignKey(productId, productName, category, unitPrice, unitsInStock,
-                               unmappedField);
-       }
-
-       public static List<ProductAnnotationOnlyWithForeignKey> getList() {
-               String unmappedField = "unmapped";
-               ProductAnnotationOnlyWithForeignKey[] list = { create(1, "Chai", "Beverages", 18, 39, unmappedField),
-                               create(2, "Chang", "Beverages", 19.0, 17, unmappedField),
-                               create(3, "Aniseed Syrup", "Condiments", 10.0, 13, unmappedField),
-                               create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, unmappedField),
-                               create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, unmappedField),
-                               create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, unmappedField),
-                               create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, unmappedField),
-                               create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, unmappedField),
-                               create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, unmappedField),
-                               create(10, "Ikura", "Seafood", 31.0, 31, unmappedField), };
-               return Arrays.asList(list);
-       }
-
-       public String toString() {
-               return productName + ": " + unitsInStock;
-       }
+    public String unmappedField;
+
+    @IQColumn(name = "id", autoIncrement = true)
+    public Long productId;
+
+    @IQColumn(name = "cat", length = 15, trim = true)
+    public String category;
+
+    @IQColumn(name = "name", length = 50)
+    public String productName;
+
+    @SuppressWarnings("unused")
+    @IQColumn
+    private Double unitPrice;
+
+    @IQColumn
+    private Integer unitsInStock;
+
+    public ProductAnnotationOnlyWithForeignKey() {
+        // public constructor
+    }
+
+    private ProductAnnotationOnlyWithForeignKey(long productId, String productName, String category, double unitPrice,
+                                                int unitsInStock, String unmappedField) {
+        this.productId = productId;
+        this.productName = productName;
+        this.category = category;
+        this.unitPrice = unitPrice;
+        this.unitsInStock = unitsInStock;
+        this.unmappedField = unmappedField;
+    }
+
+    private static ProductAnnotationOnlyWithForeignKey create(int productId, String productName, String category,
+                                                              double unitPrice, int unitsInStock, String unmappedField) {
+        return new ProductAnnotationOnlyWithForeignKey(productId, productName, category, unitPrice, unitsInStock,
+                unmappedField);
+    }
+
+    public static List<ProductAnnotationOnlyWithForeignKey> getList() {
+        String unmappedField = "unmapped";
+        ProductAnnotationOnlyWithForeignKey[] list = {create(1, "Chai", "Beverages", 18, 39, unmappedField),
+                create(2, "Chang", "Beverages", 19.0, 17, unmappedField),
+                create(3, "Aniseed Syrup", "Condiments", 10.0, 13, unmappedField),
+                create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, unmappedField),
+                create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, unmappedField),
+                create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, unmappedField),
+                create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, unmappedField),
+                create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, unmappedField),
+                create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, unmappedField),
+                create(10, "Ikura", "Seafood", 31.0, 31, unmappedField),};
+        return Arrays.asList(list);
+    }
+
+    public String toString() {
+        return productName + ": " + unitsInStock;
+    }
 
 }
index 112f4ef93c4631d850909bc4dd967b4dc088f719..c41a3f0f2245ce90983d4a5467a71844f6ead49f 100644 (file)
 
 package com.iciql.test.models;
 
+import com.iciql.Iciql.IQTable;
+
 import java.util.Arrays;
 import java.util.List;
 
-import com.iciql.Iciql.IQTable;
-
 /**
  * This class inherits all its fields from a parent class which has annotated
  * columns. The IQTable annotation of the parent class is ignored and only the
@@ -31,34 +31,34 @@ import com.iciql.Iciql.IQTable;
 @IQTable(inheritColumns = true, annotationsOnly = false)
 public class ProductInheritedAnnotation extends ProductMixedAnnotation {
 
-       public ProductInheritedAnnotation() {
-               // public constructor
-       }
+    public ProductInheritedAnnotation() {
+        // public constructor
+    }
 
-       private ProductInheritedAnnotation(int productId, String productName, String category, double unitPrice,
-                       int unitsInStock, String mappedField) {
-               super(productId, productName, category, unitPrice, unitsInStock, mappedField);
-       }
+    private ProductInheritedAnnotation(int productId, String productName, String category, double unitPrice,
+                                       int unitsInStock, String mappedField) {
+        super(productId, productName, category, unitPrice, unitsInStock, mappedField);
+    }
 
-       private static ProductInheritedAnnotation create(int productId, String productName, String category,
-                       double unitPrice, int unitsInStock, String mappedField) {
-               return new ProductInheritedAnnotation(productId, productName, category, unitPrice, unitsInStock,
-                               mappedField);
-       }
+    private static ProductInheritedAnnotation create(int productId, String productName, String category,
+                                                     double unitPrice, int unitsInStock, String mappedField) {
+        return new ProductInheritedAnnotation(productId, productName, category, unitPrice, unitsInStock,
+                mappedField);
+    }
 
-       public static List<ProductInheritedAnnotation> getData() {
-               String mappedField = "mapped";
-               ProductInheritedAnnotation[] list = { create(1, "Chai", "Beverages", 18, 39, mappedField),
-                               create(2, "Chang", "Beverages", 19.0, 17, mappedField),
-                               create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
-                               create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
-                               create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
-                               create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
-                               create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
-                               create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
-                               create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
-                               create(10, "Ikura", "Seafood", 31.0, 31, mappedField), };
-               return Arrays.asList(list);
-       }
+    public static List<ProductInheritedAnnotation> getData() {
+        String mappedField = "mapped";
+        ProductInheritedAnnotation[] list = {create(1, "Chai", "Beverages", 18, 39, mappedField),
+                create(2, "Chang", "Beverages", 19.0, 17, mappedField),
+                create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
+                create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
+                create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
+                create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
+                create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
+                create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
+                create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
+                create(10, "Ikura", "Seafood", 31.0, 31, mappedField),};
+        return Arrays.asList(list);
+    }
 
 }
index a893a6965354dfbcf27dea3f6b984ea3e1f489cb..7fcf1d559711867888e9a0b4c97e54f19259fbf1 100644 (file)
 
 package com.iciql.test.models;
 
-import java.util.Arrays;
-import java.util.List;
-
 import com.iciql.Define;
 import com.iciql.Iciql;
 import com.iciql.Iciql.IQIndex;
 import com.iciql.Iciql.IQTable;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * A table containing product data.
  */
 
 @IQTable(annotationsOnly = false)
-@IQIndex({ "name", "cat" })
+@IQIndex({"name", "cat"})
 public class ProductMixedAnnotation implements Iciql {
 
-       public Double unitPrice;
-       public Integer unitsInStock;
-       public String mappedField;
-
-       @IQIgnore
-       public String productDescription;
-
-       @IQColumn(name = "cat", length = 255)
-       public String category;
-
-       @IQColumn(name = "id", primaryKey = true)
-       private Integer productId;
-
-       @IQColumn(name = "name", length = 255)
-       private String productName;
-       
-       public ProductMixedAnnotation() {
-               // public constructor
-       }
-
-       protected ProductMixedAnnotation(int productId, String productName, String category, double unitPrice,
-                       int unitsInStock, String mappedField) {
-               this.productId = productId;
-               this.productName = productName;
-               this.category = category;
-               this.unitPrice = unitPrice;
-               this.unitsInStock = unitsInStock;
-               this.mappedField = mappedField;
-               this.productDescription = category + ": " + productName;
-       }
-
-       private static ProductMixedAnnotation create(int productId, String productName, String category,
-                       double unitPrice, int unitsInStock, String mappedField) {
-               return new ProductMixedAnnotation(productId, productName, category, unitPrice, unitsInStock,
-                               mappedField);
-       }
-
-       public static List<ProductMixedAnnotation> getList() {
-               String mappedField = "mapped";
-               ProductMixedAnnotation[] list = { create(1, "Chai", "Beverages", 18, 39, mappedField),
-                               create(2, "Chang", "Beverages", 19.0, 17, mappedField),
-                               create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
-                               create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
-                               create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
-                               create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
-                               create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
-                               create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
-                               create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
-                               create(10, "Ikura", "Seafood", 31.0, 31, mappedField), };
-               return Arrays.asList(list);
-       }
-
-       public String toString() {
-               return productName + ": " + unitsInStock;
-       }
-
-       public int id() {
-               return productId;
-       }
-
-       public String name() {
-               return productName;
-       }
-
-       @Override
-       public void defineIQ() {
-               Define.length(mappedField, 25);
-       }
+    public Double unitPrice;
+    public Integer unitsInStock;
+    public String mappedField;
+
+    @IQIgnore
+    public String productDescription;
+
+    @IQColumn(name = "cat", length = 255)
+    public String category;
+
+    @IQColumn(name = "id", primaryKey = true)
+    private Integer productId;
+
+    @IQColumn(name = "name", length = 255)
+    private String productName;
+
+    public ProductMixedAnnotation() {
+        // public constructor
+    }
+
+    protected ProductMixedAnnotation(int productId, String productName, String category, double unitPrice,
+                                     int unitsInStock, String mappedField) {
+        this.productId = productId;
+        this.productName = productName;
+        this.category = category;
+        this.unitPrice = unitPrice;
+        this.unitsInStock = unitsInStock;
+        this.mappedField = mappedField;
+        this.productDescription = category + ": " + productName;
+    }
+
+    private static ProductMixedAnnotation create(int productId, String productName, String category,
+                                                 double unitPrice, int unitsInStock, String mappedField) {
+        return new ProductMixedAnnotation(productId, productName, category, unitPrice, unitsInStock,
+                mappedField);
+    }
+
+    public static List<ProductMixedAnnotation> getList() {
+        String mappedField = "mapped";
+        ProductMixedAnnotation[] list = {create(1, "Chai", "Beverages", 18, 39, mappedField),
+                create(2, "Chang", "Beverages", 19.0, 17, mappedField),
+                create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
+                create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
+                create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
+                create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
+                create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
+                create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
+                create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
+                create(10, "Ikura", "Seafood", 31.0, 31, mappedField),};
+        return Arrays.asList(list);
+    }
+
+    public String toString() {
+        return productName + ": " + unitsInStock;
+    }
+
+    public int id() {
+        return productId;
+    }
+
+    public String name() {
+        return productName;
+    }
+
+    @Override
+    public void defineIQ() {
+        Define.length(mappedField, 25);
+    }
 }
index cbf96e9ee6a9aed194d2eca7ff0b5d2ab667492d..9c75ba55d19e1c5edc80ccea131163f644467d6b 100644 (file)
 
 package com.iciql.test.models;
 
-import java.util.Arrays;
-import java.util.List;
-
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQTable;
 
+import java.util.Arrays;
+import java.util.List;
+
 /**
  * A table containing product data.
  */
@@ -30,30 +30,30 @@ import com.iciql.Iciql.IQTable;
 @IQTable(create = false)
 public class ProductNoCreateTable {
 
-       @SuppressWarnings("unused")
-       @IQColumn(name = "id")
-       private Integer productId;
+    @SuppressWarnings("unused")
+    @IQColumn(name = "id")
+    private Integer productId;
 
-       @SuppressWarnings("unused")
-       @IQColumn(name = "name")
-       private String productName;
+    @SuppressWarnings("unused")
+    @IQColumn(name = "name")
+    private String productName;
 
-       public ProductNoCreateTable() {
-               // public constructor
-       }
+    public ProductNoCreateTable() {
+        // public constructor
+    }
 
-       private ProductNoCreateTable(int productId, String productName) {
-               this.productId = productId;
-               this.productName = productName;
-       }
+    private ProductNoCreateTable(int productId, String productName) {
+        this.productId = productId;
+        this.productName = productName;
+    }
 
-       private static ProductNoCreateTable create(int productId, String productName) {
-               return new ProductNoCreateTable(productId, productName);
-       }
+    private static ProductNoCreateTable create(int productId, String productName) {
+        return new ProductNoCreateTable(productId, productName);
+    }
 
-       public static List<ProductNoCreateTable> getList() {
-               ProductNoCreateTable[] list = { create(1, "Chai"), create(2, "Chang") };
-               return Arrays.asList(list);
-       }
+    public static List<ProductNoCreateTable> getList() {
+        ProductNoCreateTable[] list = {create(1, "Chai"), create(2, "Chang")};
+        return Arrays.asList(list);
+    }
 
 }
index 2efe9eb53c610e4b54a35b0db003b562ea55f54d..17390043185782c28451c2f75e99dd9ea630e96c 100644 (file)
@@ -27,21 +27,21 @@ import com.iciql.Iciql.IQView;
 @IQView(name = "AnnotatedProductView", tableName = "AnnotatedProduct")
 public class ProductView {
 
-       public String unmappedField;
+    public String unmappedField;
 
-       @IQColumn(name = "id", autoIncrement = true)
-       @IQConstraint("this <= 7 AND this > 2")
-       public Long productId;
+    @IQColumn(name = "id", autoIncrement = true)
+    @IQConstraint("this <= 7 AND this > 2")
+    public Long productId;
 
-       @IQColumn(name = "name")
-       public String productName;
+    @IQColumn(name = "name")
+    public String productName;
 
-       public ProductView() {
-               // public constructor
-       }
+    public ProductView() {
+        // public constructor
+    }
 
-       public String toString() {
-               return productName + " (" + productId + ")";
-       }
+    public String toString() {
+        return productName + " (" + productId + ")";
+    }
 
 }
index 2f2f194f35b9b1682b3464138f430937a3e5fedc..0a0595d0ec6a0142f5842bc2fe1840f6c067edcb 100644 (file)
@@ -24,19 +24,19 @@ import com.iciql.Iciql.IQView;
  */
 
 @IQView(name = "AnnotatedProductViewInherited", inheritColumns = true)
-public class ProductViewFromQuery  extends ProductAnnotationOnly {
+public class ProductViewFromQuery extends ProductAnnotationOnly {
 
-       public String unmappedField;
+    public String unmappedField;
 
-       @IQColumn(name = "id")
-       public Long productId;
+    @IQColumn(name = "id")
+    public Long productId;
 
-       public ProductViewFromQuery() {
-               // public constructor
-       }
+    public ProductViewFromQuery() {
+        // public constructor
+    }
 
-       public String toString() {
-               return productName + " (" + productId + ")";
-       }
+    public String toString() {
+        return productName + " (" + productId + ")";
+    }
 
 }
index e9c274b5605553ebdae1676fa9b87d1c09d9a063..48137ed8bde362821329618df8d43ec0467c9620 100644 (file)
@@ -27,18 +27,18 @@ import com.iciql.Iciql.IQView;
 @IQView(name = "AnnotatedProductViewInherited", inheritColumns = true)
 public class ProductViewInherited extends ProductAnnotationOnly {
 
-       public String unmappedField;
+    public String unmappedField;
 
-       @IQColumn(name = "id", autoIncrement = true)
-       @IQConstraint("this <= 7 AND this > 2")
-       public Long productId;
+    @IQColumn(name = "id", autoIncrement = true)
+    @IQConstraint("this <= 7 AND this > 2")
+    public Long productId;
 
-       public ProductViewInherited() {
-               // public constructor
-       }
+    public ProductViewInherited() {
+        // public constructor
+    }
 
-       public String toString() {
-               return productName + " (" + productId + ")";
-       }
+    public String toString() {
+        return productName + " (" + productId + ")";
+    }
 
 }
index 55e7ba864529f563c8e2cca7f77d7acdb594d609..a37325157b4200fae27e4ece563d8b4aa2af2dee 100644 (file)
@@ -23,6 +23,6 @@ import com.iciql.Iciql.IQView;
  */
 
 @IQView(inheritColumns = true)
-public class ProductViewInheritedComplex  extends ProductViewInherited {
+public class ProductViewInheritedComplex extends ProductViewInherited {
 
 }
index 09f84e6a16341348aa2717a32229bc041f088a83..b78be571beef01d1a08af94e47f53d147082e9f8 100644 (file)
  */\r
 package com.iciql.test.models;\r
 \r
-import java.sql.Timestamp;\r
-\r
 import com.iciql.Iciql.EnumType;\r
 import com.iciql.Iciql.IQColumn;\r
 import com.iciql.Iciql.IQEnum;\r
 import com.iciql.Iciql.IQTable;\r
 import com.iciql.test.models.EnumModels.Tree;\r
 \r
+import java.sql.Timestamp;\r
+\r
 /**\r
  * Static query models.\r
  */\r
 public class StaticQueries {\r
 \r
-       @IQTable(name = "StaticQueryTest1")\r
-       public static class StaticModel1 {\r
+    @IQTable(name = "StaticQueryTest1")\r
+    public static class StaticModel1 {\r
 \r
-               @IQColumn(primaryKey = true, autoIncrement = true)\r
-               public Integer id;\r
+        @IQColumn(primaryKey = true, autoIncrement = true)\r
+        public Integer id;\r
 \r
-               @IQColumn\r
-               @IQEnum(EnumType.NAME)\r
-               public Tree myTree;\r
+        @IQColumn\r
+        @IQEnum(EnumType.NAME)\r
+        public Tree myTree;\r
 \r
-               @IQColumn\r
-               public String myString;\r
+        @IQColumn\r
+        public String myString;\r
 \r
-               @IQColumn\r
-               public Boolean myBool;\r
+        @IQColumn\r
+        public Boolean myBool;\r
 \r
-               @IQColumn\r
-               public Timestamp myTimestamp;\r
+        @IQColumn\r
+        public Timestamp myTimestamp;\r
 \r
-               @IQColumn\r
-               public java.sql.Date myDate;\r
+        @IQColumn\r
+        public java.sql.Date myDate;\r
 \r
-               @IQColumn\r
-               public java.sql.Time myTime;\r
+        @IQColumn\r
+        public java.sql.Time myTime;\r
 \r
-               public StaticModel1() {\r
-               }\r
-       }\r
+        public StaticModel1() {\r
+        }\r
+    }\r
 \r
-       @IQTable(name = "StaticQueryTest2")\r
-       public static class StaticModel2 {\r
+    @IQTable(name = "StaticQueryTest2")\r
+    public static class StaticModel2 {\r
 \r
-               @IQColumn(primaryKey = true, autoIncrement = true)\r
-               public Integer id;\r
+        @IQColumn(primaryKey = true, autoIncrement = true)\r
+        public Integer id;\r
 \r
-               @IQColumn\r
-               @IQEnum(EnumType.ENUMID)\r
-               public Tree myTree;\r
+        @IQColumn\r
+        @IQEnum(EnumType.ENUMID)\r
+        public Tree myTree;\r
 \r
-               public StaticModel2() {\r
-               }\r
-       }\r
+        public StaticModel2() {\r
+        }\r
+    }\r
 \r
-       @IQTable(name = "StaticQueryTest3")\r
-       public static class StaticModel3 {\r
+    @IQTable(name = "StaticQueryTest3")\r
+    public static class StaticModel3 {\r
 \r
-               @IQColumn(primaryKey = true, autoIncrement = true)\r
-               public Integer id;\r
+        @IQColumn(primaryKey = true, autoIncrement = true)\r
+        public Integer id;\r
 \r
-               @IQColumn\r
-               @IQEnum(EnumType.ORDINAL)\r
-               public Tree myTree;\r
+        @IQColumn\r
+        @IQEnum(EnumType.ORDINAL)\r
+        public Tree myTree;\r
 \r
-               public StaticModel3() {\r
-               }\r
-       }\r
+        public StaticModel3() {\r
+        }\r
+    }\r
 }\r
index e04a3abc060d96ae166876549017635b9ae959de..8640c27a1acf1912ae3ab2451a5dc2ca894e7430 100644 (file)
 
 package com.iciql.test.models;
 
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Random;
-
 import com.iciql.Iciql.EnumType;
 import com.iciql.Iciql.IQColumn;
 import com.iciql.Iciql.IQEnum;
@@ -40,182 +30,192 @@ import com.iciql.test.IciqlSuite;
 import com.iciql.test.models.EnumModels.Tree;
 import com.iciql.util.Utils;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Random;
+
 /**
  * A data class that contains a column for each data type.
  */
 @IQTable
-@IQIndexes({ @IQIndex({ "myLong", "myInteger" }), @IQIndex(type = IndexType.HASH, value = "myString") })
+@IQIndexes({@IQIndex({"myLong", "myInteger"}), @IQIndex(type = IndexType.HASH, value = "myString")})
 @IQVersion(1)
 public class SupportedTypes implements Serializable {
 
-       private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
-       public static final SupportedTypes SAMPLE = new SupportedTypes();
+    public static final SupportedTypes SAMPLE = new SupportedTypes();
 
-       /**
-        * Test of plain enumeration.
-        *
-        * Each field declaraton of this enum must specify a mapping strategy.
-        */
-       public enum Flower {
-               ROSE, TULIP, MUM, PETUNIA, MARIGOLD, DAFFODIL;
-       }
-
-       @IQColumn(primaryKey = true, autoIncrement = true)
-       public Integer id;
-
-       @IQColumn
-       private Boolean myBool;
-
-       @IQColumn
-       private Byte myByte;
-
-       @IQColumn
-       private Short myShort;
-
-       @IQColumn
-       public Integer myInteger;
-
-       @IQColumn
-       private Long myLong;
-
-       @IQColumn
-       private Float myFloat;
-
-       @IQColumn
-       private Double myDouble;
-
-       // scale change must match the test value scale
-       @IQColumn(length = 10, scale = 5)
-       private BigDecimal myBigDecimal;
-
-       @IQColumn(length = 40, trim = true)
-       public String myString;
-
-       @IQColumn
-       private java.util.Date myUtilDate;
-
-       @IQColumn
-       private java.sql.Date mySqlDate;
-
-       @IQColumn
-       private java.sql.Time mySqlTime;
-
-       @IQColumn
-       private java.sql.Timestamp mySqlTimestamp;
-
-       @IQColumn
-       private byte[] myBlob;
-
-       // test default enum type NAME
-       @IQColumn(trim = true, length = 25)
-       private Flower myDefaultFlower;
-
-       @IQEnum(EnumType.NAME)
-       @IQColumn(trim = true, length = 25)
-       private Flower myFavoriteFlower;
-
-       @IQEnum(EnumType.ORDINAL)
-       @IQColumn
-       private Flower myOtherFavoriteFlower;
-
-       @IQEnum(EnumType.ORDINAL)
-       @IQColumn
-       // override the default enum strategy and use the ordinal value
-       private Tree myFavoriteTree;
-
-       // @IQEnum is set on the enumeration definition and is shared
-       // by all uses of Tree as an @IQColumn
-       @IQColumn
-       private Tree myOtherFavoriteTree;
-
-       public static List<SupportedTypes> createList() {
-               List<SupportedTypes> list = Utils.newArrayList();
-               Calendar c = Calendar.getInstance();
-               c.setTimeInMillis(System.currentTimeMillis());
-               c.set(Calendar.MILLISECOND, 0);
-               long now = c.getTimeInMillis();
-
-               long oneday = 24 * 60 * 60 * 1000L;
-               for (int i = 0; i < 10; i++) {
-                       SupportedTypes s = randomValue(now - (i * oneday));
-                       s.myInteger = i + 1;
-                       list.add(s);
-               }
-               return list;
-       }
-
-       static SupportedTypes randomValue(long time) {
-               Random rand = new Random();
-               SupportedTypes s = new SupportedTypes();
-               s.myBool = new Boolean(rand.nextBoolean());
-               s.myByte = new Byte((byte) rand.nextInt(Byte.MAX_VALUE));
-               s.myShort = new Short((short) rand.nextInt(Short.MAX_VALUE));
-               s.myLong = new Long(rand.nextLong());
-               s.myFloat = new Float(rand.nextFloat());
-               s.myDouble = new Double(rand.nextDouble());
-               s.myBigDecimal = new BigDecimal(rand.nextDouble());
-               // scale must match annotation
-               s.myBigDecimal = s.myBigDecimal.setScale(5, RoundingMode.UP);
-               s.myString = Long.toHexString(rand.nextLong());
-               s.myUtilDate = new java.util.Date(time);
-               s.mySqlDate = new java.sql.Date(time);
-               s.mySqlTime = new java.sql.Time(time);
-               s.mySqlTimestamp = new java.sql.Timestamp(time);
-               s.myBlob = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
-               s.myDefaultFlower = Flower.DAFFODIL;
-               s.myFavoriteFlower = Flower.MUM;
-               s.myOtherFavoriteFlower = Flower.MARIGOLD;
-               s.myFavoriteTree = Tree.BIRCH;
-               s.myOtherFavoriteTree = Tree.WALNUT;
-               return s;
-       }
-
-       public boolean equivalentTo(SupportedTypes s) {
-               boolean same = true;
-               same &= same("myBool", myBool.equals(s.myBool));
-               same &= same("myByte", myByte.equals(s.myByte));
-               same &= same("myShort", myShort.equals(s.myShort));
-               same &= same("myInteger", myInteger.equals(s.myInteger));
-               same &= same("myLong", myLong.equals(s.myLong));
-               same &= same("myFloat", IciqlSuite.equivalentTo(myFloat, s.myFloat));
-               same &= same("myDouble", IciqlSuite.equivalentTo(myDouble, s.myDouble));
-
-               BigDecimal bda = myBigDecimal.round(MathContext.DECIMAL32);
-               BigDecimal bdb = s.myBigDecimal.round(MathContext.DECIMAL32);
-               same &= same("myBigDecimal", bda.compareTo(bdb) == 0);
-
-               SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-               same &= same("myUtilDate", df.format(myUtilDate).equals(df.format(s.myUtilDate)));
-               same &= same("mySqlTimestamp", df.format(mySqlTimestamp).equals(df.format(s.mySqlTimestamp)));
-               same &= same("mySqlDate", mySqlDate.toString().equals(s.mySqlDate.toString()));
-               same &= same("mySqlTime", mySqlTime.toString().equals(s.mySqlTime.toString()));
-               same &= same("myString", myString.equals(s.myString));
-               same &= same("myBlob", Arrays.equals(myBlob, s.myBlob));
-               same &= same("myDefaultFlower", myDefaultFlower.equals(s.myDefaultFlower));
-               same &= same("myFavoriteFlower", myFavoriteFlower.equals(s.myFavoriteFlower));
-               same &= same("myOtherFavoriteFlower", myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower));
-               same &= same("myFavoriteTree", myFavoriteTree.equals(s.myFavoriteTree));
-               same &= same("myOtherFavoriteTree", myOtherFavoriteTree.equals(s.myOtherFavoriteTree));
-               return same;
-       }
-
-       private boolean same(String field, boolean same) {
-               if (!same) {
-                       throw new IciqlException("{0} is not the same",  field);
-               }
-               return same;
-       }
-
-       /**
-        * This class demonstrates the table upgrade.
-        */
-       @IQTable(name = "SupportedTypes", inheritColumns = true)
-       @IQVersion(2)
-       public static class SupportedTypes2 extends SupportedTypes {
-
-               public SupportedTypes2() {
-                       // nothing to do
-               }
-       }
+    /**
+     * Test of plain enumeration.
+     * <p>
+     * Each field declaraton of this enum must specify a mapping strategy.
+     */
+    public enum Flower {
+        ROSE, TULIP, MUM, PETUNIA, MARIGOLD, DAFFODIL;
+    }
+
+    @IQColumn(primaryKey = true, autoIncrement = true)
+    public Integer id;
+
+    @IQColumn
+    private Boolean myBool;
+
+    @IQColumn
+    private Byte myByte;
+
+    @IQColumn
+    private Short myShort;
+
+    @IQColumn
+    public Integer myInteger;
+
+    @IQColumn
+    private Long myLong;
+
+    @IQColumn
+    private Float myFloat;
+
+    @IQColumn
+    private Double myDouble;
+
+    // scale change must match the test value scale
+    @IQColumn(length = 10, scale = 5)
+    private BigDecimal myBigDecimal;
+
+    @IQColumn(length = 40, trim = true)
+    public String myString;
+
+    @IQColumn
+    private java.util.Date myUtilDate;
+
+    @IQColumn
+    private java.sql.Date mySqlDate;
+
+    @IQColumn
+    private java.sql.Time mySqlTime;
+
+    @IQColumn
+    private java.sql.Timestamp mySqlTimestamp;
+
+    @IQColumn
+    private byte[] myBlob;
+
+    // test default enum type NAME
+    @IQColumn(trim = true, length = 25)
+    private Flower myDefaultFlower;
+
+    @IQEnum(EnumType.NAME)
+    @IQColumn(trim = true, length = 25)
+    private Flower myFavoriteFlower;
+
+    @IQEnum(EnumType.ORDINAL)
+    @IQColumn
+    private Flower myOtherFavoriteFlower;
+
+    @IQEnum(EnumType.ORDINAL)
+    @IQColumn
+    // override the default enum strategy and use the ordinal value
+    private Tree myFavoriteTree;
+
+    // @IQEnum is set on the enumeration definition and is shared
+    // by all uses of Tree as an @IQColumn
+    @IQColumn
+    private Tree myOtherFavoriteTree;
+
+    public static List<SupportedTypes> createList() {
+        List<SupportedTypes> list = Utils.newArrayList();
+        Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(System.currentTimeMillis());
+        c.set(Calendar.MILLISECOND, 0);
+        long now = c.getTimeInMillis();
+
+        long oneday = 24 * 60 * 60 * 1000L;
+        for (int i = 0; i < 10; i++) {
+            SupportedTypes s = randomValue(now - (i * oneday));
+            s.myInteger = i + 1;
+            list.add(s);
+        }
+        return list;
+    }
+
+    static SupportedTypes randomValue(long time) {
+        Random rand = new Random();
+        SupportedTypes s = new SupportedTypes();
+        s.myBool = new Boolean(rand.nextBoolean());
+        s.myByte = new Byte((byte) rand.nextInt(Byte.MAX_VALUE));
+        s.myShort = new Short((short) rand.nextInt(Short.MAX_VALUE));
+        s.myLong = new Long(rand.nextLong());
+        s.myFloat = new Float(rand.nextFloat());
+        s.myDouble = new Double(rand.nextDouble());
+        s.myBigDecimal = new BigDecimal(rand.nextDouble());
+        // scale must match annotation
+        s.myBigDecimal = s.myBigDecimal.setScale(5, RoundingMode.UP);
+        s.myString = Long.toHexString(rand.nextLong());
+        s.myUtilDate = new java.util.Date(time);
+        s.mySqlDate = new java.sql.Date(time);
+        s.mySqlTime = new java.sql.Time(time);
+        s.mySqlTimestamp = new java.sql.Timestamp(time);
+        s.myBlob = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        s.myDefaultFlower = Flower.DAFFODIL;
+        s.myFavoriteFlower = Flower.MUM;
+        s.myOtherFavoriteFlower = Flower.MARIGOLD;
+        s.myFavoriteTree = Tree.BIRCH;
+        s.myOtherFavoriteTree = Tree.WALNUT;
+        return s;
+    }
+
+    public boolean equivalentTo(SupportedTypes s) {
+        boolean same = true;
+        same &= same("myBool", myBool.equals(s.myBool));
+        same &= same("myByte", myByte.equals(s.myByte));
+        same &= same("myShort", myShort.equals(s.myShort));
+        same &= same("myInteger", myInteger.equals(s.myInteger));
+        same &= same("myLong", myLong.equals(s.myLong));
+        same &= same("myFloat", IciqlSuite.equivalentTo(myFloat, s.myFloat));
+        same &= same("myDouble", IciqlSuite.equivalentTo(myDouble, s.myDouble));
+
+        BigDecimal bda = myBigDecimal.round(MathContext.DECIMAL32);
+        BigDecimal bdb = s.myBigDecimal.round(MathContext.DECIMAL32);
+        same &= same("myBigDecimal", bda.compareTo(bdb) == 0);
+
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        same &= same("myUtilDate", df.format(myUtilDate).equals(df.format(s.myUtilDate)));
+        same &= same("mySqlTimestamp", df.format(mySqlTimestamp).equals(df.format(s.mySqlTimestamp)));
+        same &= same("mySqlDate", mySqlDate.toString().equals(s.mySqlDate.toString()));
+        same &= same("mySqlTime", mySqlTime.toString().equals(s.mySqlTime.toString()));
+        same &= same("myString", myString.equals(s.myString));
+        same &= same("myBlob", Arrays.equals(myBlob, s.myBlob));
+        same &= same("myDefaultFlower", myDefaultFlower.equals(s.myDefaultFlower));
+        same &= same("myFavoriteFlower", myFavoriteFlower.equals(s.myFavoriteFlower));
+        same &= same("myOtherFavoriteFlower", myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower));
+        same &= same("myFavoriteTree", myFavoriteTree.equals(s.myFavoriteTree));
+        same &= same("myOtherFavoriteTree", myOtherFavoriteTree.equals(s.myOtherFavoriteTree));
+        return same;
+    }
+
+    private boolean same(String field, boolean same) {
+        if (!same) {
+            throw new IciqlException("{0} is not the same", field);
+        }
+        return same;
+    }
+
+    /**
+     * This class demonstrates the table upgrade.
+     */
+    @IQTable(name = "SupportedTypes", inheritColumns = true)
+    @IQVersion(2)
+    public static class SupportedTypes2 extends SupportedTypes {
+
+        public SupportedTypes2() {
+            // nothing to do
+        }
+    }
 }
index cecb056f0493aa96857dc8a322d6b4ec60d6babb..d79d318c57388239925078b1fddb8a17097c94be 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Example resource file for DaoClasspathStatementProvider
 #
-
-get.products = select * from Product
-%test.get.products = select * from Product where category = 'Beverages'
-%dev.get.products = select * from Product where category = 'Condiments'
+get.products=select * from Product
+%test.get.products=select * from Product where category = 'Beverages'
+%dev.get.products=select * from Product where category = 'Condiments'