]> source.dussan.org Git - iciql.git/commitdiff
Documentation. EnumType default is NAME.
authorJames Moger <james.moger@gmail.com>
Mon, 8 Aug 2011 15:12:50 +0000 (11:12 -0400)
committerJames Moger <james.moger@gmail.com>
Mon, 8 Aug 2011 15:12:50 +0000 (11:12 -0400)
12 files changed:
docs/01_model_classes.mkd
docs/02_table_versioning.mkd
docs/02_usage.mkd
docs/05_releases.mkd
src/com/iciql/Iciql.java
src/com/iciql/ModelUtils.java
src/com/iciql/TableDefinition.java
src/com/iciql/util/Utils.java
tests/com/iciql/test/ModelsTest.java
tests/com/iciql/test/PrimitivesTest.java
tests/com/iciql/test/models/EnumModels.java
tests/com/iciql/test/models/SupportedTypes.java

index 6e58f0a79d1299e29e8a1c49ad7fb87fc2c8fda4..846ef6c2b4dabfc11db6c75e2be7b680b1827aa8 100644 (file)
@@ -5,9 +5,16 @@ Models can be manually written using one of two approaches: *annotation configur
 \r
 Alternatively, model classes can be automatically generated by iciql using the model generation tool.  Please see the [tools](tools.html) page for details.\r
 \r
-### Supported Data Types\r
-<table>\r
+### Configuration Requirements and Limitations\r
+\r
+1. Your model class **must** provide a public default constructor.\r
+2. Only the specified types are supported.  Other types such as arrays and custom types are not supported.\r
+3. Triggers, views, and other advanced database features are not supported.\r
 \r
+### Fully Supported Data Types\r
+The following data types can be used for all iciql expressions.\r
+<table>\r
+<tr><th colspan="2">All Databases</th></tr>\r
 <tr><td>java.lang.String</td>\r
 <td>VARCHAR *(length > 0)* or TEXT *(length == 0)*</td></tr>\r
        \r
@@ -47,11 +54,8 @@ Alternatively, model classes can be automatically generated by iciql using the m
 <tr><td>java.util.Date</td>\r
 <td>TIMESTAMP</td></tr>\r
 \r
-<tr><td>byte []</td>\r
-<td>BLOB</td></tr>\r
-\r
-<tr><td>java.lang.Enum.name()</td>\r
-<td>VARCHAR *(length > 0)* or TEXT *(length == 0)*<br/>*EnumType.STRING*</td></tr>\r
+<tr><td>java.lang.Enum.name()<br/>*default type*</td>\r
+<td>VARCHAR *(length > 0)* or TEXT *(length == 0)*<br/>*EnumType.NAME*</td></tr>\r
 \r
 <tr><td>java.lang.Enum.ordinal()</td>\r
 <td>INT<br/>*EnumType.ORDINAL*</td></tr>\r
@@ -59,23 +63,79 @@ Alternatively, model classes can be automatically generated by iciql using the m
 <tr><td>java.lang.Enum implements<br/>*com.iciql.Iciql.EnumId.enumId()*</td>\r
 <td>INT<br/>*EnumType.ENUMID*</td></tr>\r
 \r
+<tr><th colspan="2">H2 Databases</th></tr>\r
+<tr><td>java.util.UUID</td>\r
+<td>UUID</td><tr/>\r
+\r
 </table>\r
 \r
 **NOTE:**<br/>\r
 The reverse lookup used for model generation, SQL type -> Java type, contains more mappings.<br/>\r
 Please consult the `com.iciql.ModelUtils` class for details. \r
 \r
-### Unsupported Types\r
-- Java primitives (use their object counterparts instead)\r
-- array types\r
-- custom types\r
+### Partially Supported Data Types\r
+The following data types can be mapped to columns for all general statements <u>BUT</u> these field types may **not** be used to specify **compile-time** *clauses or constraints*.\r
+\r
+<table>\r
+<tr><td>byte []</td>\r
+<td>BLOB</td></tr>\r
+\r
+<tr><td>boolean</td>\r
+<td>BIT</td></tr>\r
+       \r
+<tr><td>byte</td>\r
+<td>TINYINT</td></tr>\r
+       \r
+<tr><td>short</td>\r
+<td>SMALLINT</td></tr>\r
+       \r
+<tr><td>int</td>\r
+<td>INT</td></tr>\r
+       \r
+<tr><td>long</td>\r
+<td>BIGINT</td></tr>\r
+       \r
+<tr><td>float</td>\r
+<td>REAL</td></tr>\r
+       \r
+<tr><td>double</td>\r
+<td>DOUBLE</td></tr>\r
+\r
+</table>\r
 \r
-### Configuration Rules\r
-1. field mappings must be Objects not primitives\r
-2. the model class must have a default public constructor\r
+#### Partially Supported Data Types Example\r
+%BEGINCODE%\r
+class Primitives {\r
+    @IQColumn(primaryKey = true)\r
+    int id;\r
+        \r
+    @IQColumn\r
+    String name;\r
+        \r
+    public Primitives() {\r
+    }\r
+    \r
+    public Primitives(int id, String name) {\r
+        this.id = id;\r
+        this.name = name;\r
+    }    \r
+}\r
+    \r
+Primitives p = new Primitives();\r
+\r
+// the following expressions compile, but will throw iciql runtime exceptions\r
+db.from(p).where(p.id).is(100).selectFirst();\r
+db.from(p).where(p.id).atLeast(10).select();\r
+\r
+// the following expressions will work as expected\r
+db.from(p).select();\r
+db.from(p).where("id = ?", 100).selectFirst();\r
+db.from(p).where("id >= ?", 10).select();\r
+db.insert(new Primitives(150, "test"));\r
+db.update(new Primitives(150, "modified"));\r
+db.delete(new Primitives(150, "test"));\r
+%ENDCODE%\r
 \r
-### Configuration Limitations\r
-Triggers, views, and other advanced database features are unimplemented.\r
 \r
 ## Annotation Configuration\r
 The recommended approach to setup a model class is to annotate the class and field declarations.\r
index 4650f74eb2910401387dccaec6336c56fe6e8f03..12cdf6cf6e3f41b1d9c1fb16e8e5ee6aba501c25 100644 (file)
@@ -10,7 +10,7 @@ Your `com.iciql.DbUpgrader` implementation must specify the `IQVersion(version)`
 ### How does it work?\r
 If you choose to use versioning, iciql will maintain a table within your database named *_iq_versions* which is defined as:\r
 \r
-    CREATE TABLE _IQ_VERSIONS(SCHEMANAME TEXT NOT NULL, TABLENAME TEXT NOT NULL, VERSION INT NOT NULL)\r
+    CREATE TABLE _IQ_VERSIONS(SCHEMANAME VARCHAR(255) NOT NULL, TABLENAME VARCHAR(255) NOT NULL, VERSION INT NOT NULL)\r
     \r
 This database table is automatically created if and only if at least one of your model classes specifies a *version* > 0.\r
 \r
index d872ee0aa6cda996da58cbc15018836d86204bbe..4cca129e54f55103d7b9d56dc39a9d46d004d78a 100644 (file)
@@ -48,7 +48,7 @@ List&lt;Product&gt; restock = db.from(p).where("unitsInStock=? and productName l
 #### Db.executeQuery Approaches\r
 There may be times when the hybrid approach is still too restrictive and you'd prefer to write straight SQL.  You can do that too and use iciql to build objects from your ResultSet, but be careful:\r
 \r
-1. Make sure to _select *_ in your query otherwise db.bindResultSet() will throw a RuntimeException\r
+1. Make sure to _select *_ in your query otherwise db.buildObjects() will throw a RuntimeException\r
 2. There is no model class type checking nor field type checking. \r
 \r
 %BEGINCODE%\r
index eb2c93c12fc00eea33e0310019b32386844d1876..f2f14ccd8238937660934f5a838556a4b7384334 100644 (file)
@@ -1,8 +1,19 @@
 ## Release History\r
 \r
 ### Current Release\r
+\r
 **%VERSION%** ([zip](http://code.google.com/p/iciql/downloads/detail?name=%ZIP%)|[jar](http://code.google.com/p/iciql/downloads/detail?name=%JAR%)) &nbsp; *released %BUILDDATE%*\r
 \r
+- api change release (API v3)\r
+- finished enum support (issue 4)\r
+- added UUID type support (H2 databases only)\r
+- added partial primitives support *(primitives may not be used for compile-time condition clauses)*\r
+- added *between(A y).and(A z)* condition syntax\r
+\r
+### Older Releases\r
+\r
+**0.6.2** &nbsp; *released 2011-08-05*\r
+\r
 - api change release (API v2)\r
 - fix to versioning to support H2 1.3.158+\r
 - added BLOB support (issue 1)\r
 %ENDCODE%\r
     - @IQColumn(maxLength=20) -> @IQColumn(length=20)\r
     - @IQColumn(trimString=true) -> @IQColumn(trim=true)\r
-\r
-### Older Releases\r
-\r
-**0.5.0** ([zip](http://code.google.com/p/iciql/downloads/detail?name=iciql-0.5.0.zip)|[jar](http://code.google.com/p/iciql/downloads/detail?name=iciql-0.5.0.jar)) &nbsp; *released 2011-08-03*\r
+    \r
+**0.5.0** &nbsp; *released 2011-08-03*\r
 \r
 - initial release (API v1)\r
 \r
index 6abe97de97ff66644c9e353851f4f63c85bd7953..64c2158f956c9be0c117426aeebef915f5161ea9 100644 (file)
@@ -33,8 +33,9 @@ import java.lang.annotation.Target;
  * If a class is annotated with IQTable and at the same time implements Table,\r
  * the define() method is not called.\r
  * <p>\r
- * Supported data types:\r
+ * Fully Supported Data Types:\r
  * <table>\r
+ * <tr><th colspan="2">All Databases</th></tr>\r
  * <tr>\r
  * <td>java.lang.String</td>\r
  * <td>VARCHAR (length > 0) or TEXT (length == 0)</td>\r
@@ -88,13 +89,9 @@ import java.lang.annotation.Target;
  * <td>TIMESTAMP</td>\r
  * </tr>\r
  * <tr>\r
- * <td>byte []</td>\r
- * <td>BLOB</td>\r
- * </tr>\r
- * <tr>\r
  * <td>java.lang.Enum.name()</td>\r
  * <td>VARCHAR (length > 0) or TEXT (length == 0)<br/>\r
- * EnumType.STRING</td>\r
+ * EnumType.NAME</td>\r
  * </tr>\r
  * <tr>\r
  * <td>java.lang.Enum.ordinal()</td>\r
@@ -107,10 +104,36 @@ import java.lang.annotation.Target;
  * <td>INT<br/>\r
  * EnumType.ENUMID</td>\r
  * </tr>\r
+ * <tr><th colspan="2">H2 Databases</th></tr>\r
+ * <tr>\r
+ * <td>java.util.UUID</td>\r
+ * <td>UUID</td>\r
  * </tr>\r
  * </table>\r
  * <p>\r
- * Unsupported data types: primitives, Array Types, and custom types.\r
+ * Partially Supported Data Types:\r
+ * <p>\r
+ * The following data types can be mapped to columns for all general statements\r
+ * BUT these field types may not be used to specify compile-time clauses or\r
+ * constraints.\r
+ * <table>\r
+ * <tr><td>byte []</td>\r
+ * <td>BLOB</td></tr>\r
+ * <tr><td>boolean</td>\r
+ * <td>BIT</td></tr>\r
+ * <tr><td>byte</td>\r
+ * <td>TINYINT</td></tr>\r
+ * <tr><td>short</td>\r
+ * <td>SMALLINT</td></tr>\r
+ * <tr><td>int</td>\r
+ * <td>INT</td></tr>\r
+ * <tr><td>long</td>\r
+ * <td>BIGINT</td></tr>\r
+ * <tr><td>float</td>\r
+ * <td>REAL</td></tr>\r
+ * <tr><td>double</td>\r
+ * <td>DOUBLE</td></tr>\r
+ * </table>\r
  * <p>\r
  * Table and field mapping: by default, the mapped table name is the class name\r
  * and the public fields are reflectively mapped, by their name, to columns. As\r
@@ -403,7 +426,7 @@ public interface Iciql {
         * Enumeration representing how to map a java.lang.Enum to a column.\r
         * <p>\r
         * <ul>\r
-        * <li>STRING - name() : string\r
+        * <li>NAME - name() : string\r
         * <li>ORDINAL - ordinal() : int\r
         * <li>ENUMID - enumId() : int\r
         * </ul>\r
@@ -411,7 +434,9 @@ public interface Iciql {
         * @see com.iciql.Iciql.EnumId interface\r
         */\r
        public enum EnumType {\r
-               STRING, ORDINAL, ENUMID;\r
+               NAME, ORDINAL, ENUMID;\r
+               \r
+               public static final EnumType DEFAULT_TYPE = NAME;\r
        }\r
 \r
        /**\r
@@ -427,20 +452,20 @@ public interface Iciql {
         * be overridden for an individual field by specifying the IQEnum\r
         * annotation.\r
         * <p>\r
-        * The default mapping is by STRING.\r
+        * The default mapping is by NAME.\r
         * \r
         * <pre>\r
-        * IQEnum(EnumType.STRING)\r
+        * IQEnum(EnumType.NAME)\r
         * </pre>\r
         * \r
-        * A string mapping will generate either a VARCHAR, if IQColumn.length >\r
-        * or a TEXT column if IQColumn.length == 0\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.STRING;\r
+               EnumType value() default EnumType.NAME;\r
        }\r
 \r
        /**\r
index 51c2d6c00c9dffa7899c9af27c0d7a1f3cdef4fe..4607e3072dd3178afb6282c3cd29f5b995c49db1 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.regex.Pattern;
 
+import com.iciql.Iciql.EnumType;
 import com.iciql.TableDefinition.FieldDefinition;
 import com.iciql.util.StringUtils;
 
@@ -150,18 +151,16 @@ class ModelUtils {
        static String getDataType(FieldDefinition fieldDef, boolean strictTypeMapping) {
                Class<?> fieldClass = fieldDef.field.getType();
                if (fieldClass.isEnum()) {
-                       if (fieldDef.enumType == null) {
-                               throw new IciqlException(fieldDef.field.getName() + " enum field does not specify @IQEnum!");
-                       }
                        switch (fieldDef.enumType) {
-                       case STRING:
+                       case ORDINAL:
+                       case ENUMID:
+                               return "INT";
+                       case NAME:
+                       default:
                                if (fieldDef.maxLength <= 0) {
                                        return "TEXT";
                                }
                                return "VARCHAR";
-                       case ORDINAL:
-                       case ENUMID:
-                               return "INT";
                        }
                }
                if (SUPPORTED_TYPES.containsKey(fieldClass)) {
index f0ee4fafe7ab1a2477691a51d8d429d02f2d5972..f5064844e0cecf4413e93aa7e534c6dca4160f61 100644 (file)
@@ -293,6 +293,7 @@ class TableDefinition<T> {
 \r
                        // configure Java -> SQL enum mapping\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
@@ -343,7 +344,7 @@ class TableDefinition<T> {
                        // convert enumeration to INT or STRING\r
                        Enum<?> iqenum = (Enum<?>) value;\r
                        switch (field.enumType) {\r
-                       case STRING:\r
+                       case NAME:\r
                                if (field.trimString && field.maxLength > 0) {\r
                                        if (iqenum.name().length() > field.maxLength) {\r
                                                return iqenum.name().substring(0, field.maxLength);\r
index 3846c320b65f40986b15c09568bb83d722a622b4..32377423a54adf48996404d392a115e3c8ca8588 100644 (file)
@@ -33,7 +33,6 @@ import java.util.Collections;
 import java.util.HashMap;\r
 import java.util.HashSet;\r
 import java.util.IdentityHashMap;\r
-import java.util.List;\r
 import java.util.Map;\r
 import java.util.UUID;\r
 import java.util.concurrent.atomic.AtomicLong;\r
@@ -162,8 +161,6 @@ public class Utils {
                        return clazz.getEnumConstants()[0];\r
                } else if (clazz == java.util.UUID.class) {\r
                        return (T) UUID.randomUUID();\r
-               } else if (clazz == List.class) {\r
-                       return (T) new ArrayList();\r
                }\r
                try {\r
                        return clazz.newInstance();\r
@@ -282,7 +279,7 @@ public class Utils {
        }\r
 \r
        public static Object convertEnum(Enum<?> o, EnumType type) {\r
-               if (o == null || type == null) {\r
+               if (o == null) {\r
                        return null;\r
                }\r
                switch (type) {\r
@@ -294,7 +291,7 @@ public class Utils {
                        }\r
                        EnumId enumid = (EnumId) o;\r
                        return enumid.enumId();\r
-               case STRING:\r
+               case NAME:\r
                default:\r
                        return o.name();\r
                }\r
@@ -308,7 +305,6 @@ public class Utils {
                if (targetType.isAssignableFrom(currentType)) {\r
                        return o;\r
                }\r
-\r
                // convert from VARCHAR/TEXT/INT to Enum\r
                Enum<?>[] values = (Enum[]) targetType.getEnumConstants();\r
                if (Clob.class.isAssignableFrom(currentType)) {\r
index 75c2073e877cf41d622d172554f0e347947de748..8a933aeef02279613b2f7e6c606a186b83996bec 100644 (file)
@@ -163,7 +163,7 @@ public class ModelsTest {
                                true);
                assertEquals(1, models.size());
                // a poor test, but a start
-               assertEquals(1697, models.get(0).length());
+               assertEquals(1780, models.get(0).length());
        }
 
        @Test
index aee2479c6b4ffbc68fe2454ab19b0853e0981055..2d591c39f48f81bbc4accece51a773d6253e05ca 100644 (file)
@@ -37,22 +37,27 @@ public class PrimitivesTest {
                db.insert(model);\r
 \r
                PrimitivesModel p = new PrimitivesModel();\r
-               \r
+\r
                // retrieve model and compare\r
                PrimitivesModel retrievedModel = db.from(p).selectFirst();\r
                assertTrue(model.equivalentTo(retrievedModel));\r
 \r
-               // retrieve with conditions and compare \r
-//             StatementLogger.activateConsoleLogger();\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
-//             // update myInteger and compare\r
-//             db.from(p).set(p.myInteger).to(10).where(p.myLong).is(model.myLong).update();\r
-//             retrievedModel = db.from(p).selectFirst();\r
-               \r
-//             assertEquals(10, retrievedModel.myInteger);\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
+               // StatementLogger.activateConsoleLogger();\r
+               // retrievedModel =\r
+               // db.from(p).where(p.myLong).is(model.myLong).and(p.myInteger).is(model.myInteger)\r
+               // .selectFirst();\r
+               // assertTrue(model.equivalentTo(retrievedModel));\r
+               //\r
+               // // update myInteger and compare\r
+               // db.from(p).set(p.myInteger).to(10).where(p.myLong).is(model.myLong).update();\r
+               // retrievedModel = db.from(p).selectFirst();\r
+\r
+               // assertEquals(10, retrievedModel.myInteger);\r
 \r
                db.close();\r
        }\r
index bd9d88ad7981e0d6f576209d38c083b9a32e1c88..e5f6f39ee5a9741ddf9dc4ef6030f5c5ac69a8c8 100644 (file)
@@ -127,7 +127,7 @@ public abstract class EnumModels {
 \r
                // override the enumtype to string\r
                // ensure that we specify a length so that the column is VARCHAR\r
-               @IQEnum(EnumType.STRING)\r
+               @IQEnum(EnumType.NAME)\r
                @IQColumn(length = 25)\r
                private Tree tree;\r
 \r
index b8abf2dcc8fd1819bceed169e624450654af0029..49dd9511319ba8c71fef1f19d4612d3855fe7a38 100644 (file)
@@ -96,7 +96,11 @@ public class SupportedTypes {
        @IQColumn
        private byte[] myBlob;
 
-       @IQEnum(EnumType.STRING)
+       // test default enum type NAME
+       @IQColumn(trim = true, length = 25)
+       private Flower myDefaultFlower;
+
+       @IQEnum(EnumType.NAME)
        @IQColumn(trim = true, length = 25)
        private Flower myFavoriteFlower;
 
@@ -139,6 +143,7 @@ public class SupportedTypes {
                s.mySqlTime = new java.sql.Time(rand.nextLong());
                s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong());
                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;
@@ -162,6 +167,7 @@ public class SupportedTypes {
                same &= mySqlTime.toString().equals(s.mySqlTime.toString());
                same &= myString.equals(s.myString);
                same &= compare(myBlob, s.myBlob);
+               same &= myDefaultFlower.equals(s.myDefaultFlower);
                same &= myFavoriteFlower.equals(s.myFavoriteFlower);
                same &= myOtherFavoriteFlower.equals(s.myOtherFavoriteFlower);
                same &= myFavoriteTree.equals(s.myFavoriteTree);