diff options
author | James Moger <james.moger@gmail.com> | 2011-08-12 14:05:54 -0400 |
---|---|---|
committer | James Moger <james.moger@gmail.com> | 2011-08-12 14:05:54 -0400 |
commit | 27ccb36e11953d1bbe8eadef68e99b5ca3e09cab (patch) | |
tree | 7810515e0d29620dfa44c9fa6b2deb82680f6ddf | |
parent | 78d9f3ecbd9203a5ad63138037960e265509efba (diff) | |
download | iciql-27ccb36e11953d1bbe8eadef68e99b5ca3e09cab.tar.gz iciql-27ccb36e11953d1bbe8eadef68e99b5ca3e09cab.zip |
Primitive default: NOT NULL. Autoincrement primitive = 0 skip on insert.
-rw-r--r-- | docs/01_model_classes.mkd | 21 | ||||
-rw-r--r-- | docs/02_usage.mkd | 2 | ||||
-rw-r--r-- | docs/05_releases.mkd | 1 | ||||
-rw-r--r-- | src/com/iciql/TableDefinition.java | 32 |
4 files changed, 43 insertions, 13 deletions
diff --git a/docs/01_model_classes.mkd b/docs/01_model_classes.mkd index 1b370d8..7e050bb 100644 --- a/docs/01_model_classes.mkd +++ b/docs/01_model_classes.mkd @@ -8,8 +8,8 @@ Alternatively, model classes can be automatically generated by iciql using the m ### Configuration Requirements and Limitations
1. Your model class **must** provide a public default constructor.
-2. All **Object** columns are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)*.
-3. All **Primitive** columns are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)*.
+2. All **Object** fields are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)*.
+3. All **Primitive** fields are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)*.
4. Only the specified types are supported. Any other types are not supported.
5. Triggers, views, and other advanced database features are not supported.
@@ -110,14 +110,27 @@ You may specify default values for an @IQColumn by either: @IQColumn(defaultValue="'2000-01-01 00:00:00'")
Date myDate;
%ENDCODE%
-2. setting a default object on the field<br/>
+2. setting a default value on the field<br/>
+**NOTE:**<br/>
+Primitive types have an implicit default value of *0* or *false*.
%BEGINCODE%
@IQColumn
Date myDate = new Date(100, 0, 1);
+
+@IQColumn
+int myId;
%ENDCODE%
If you want to specify a database-specific variable or function as your default value (e.g. CURRENT_TIMESTAMP) you must do that within the annotation. Also note that the IQColumn.defaultValue must be a well-formatted SQL DEFAULT expression whereas object defaults will be automatically converted to an SQL DEFAULT expression.
-
+
+### Special Case: primitive autoincrement fields and 0
+%BEGINCODE%
+@IQColumn(autoIncrement = true)
+int myId;
+%ENDCODE%
+
+Because primitive types have implicit default values, this field will be excluded from an INSERT statement if its value is 0. Iciql can not differentiate an implicit/uninitialized 0 from a explicitly assigned 0.
+
### Example Annotated Model
%BEGINCODE%
import com.iciql.Iciql.EnumType;
diff --git a/docs/02_usage.mkd b/docs/02_usage.mkd index 4cca129..4f823b5 100644 --- a/docs/02_usage.mkd +++ b/docs/02_usage.mkd @@ -113,7 +113,7 @@ The Product model class instance named **p** is an *alias* object. An *alias* i 1. *Alias* instances are **NOT** thread-safe and must not be used concurrently.
2. *Alias* instances have no other purpose than to provide a compile-time/runtime map of your table.
-3. If you inspected an *alias* instance after using one you would find that it's fields have been assigned numeric values.<br/>These values have no meaning. They are assigned from a static counter in `com.iciql.Utils.newObject()` during execution of the *db.from()* method.
+3. If you inspected an *alias* instance after using one you would find that it's fields have been assigned numeric values.<br/>These values are assigned from a static counter in `com.iciql.Utils.newObject()` during execution of the *db.from()* method.<p>For *Object* fields, these values are meaningless since objects are mapped by reference. These values do matter for *primitive* fields where they are mapped by value.
If your statement is a query, like in the above example, iciql will generate new instances of your *alias* model class and return them as a list where each entry of the list represents a row from the JDBC `ResultSet`.
diff --git a/docs/05_releases.mkd b/docs/05_releases.mkd index 22ebb2e..3266ba9 100644 --- a/docs/05_releases.mkd +++ b/docs/05_releases.mkd @@ -7,6 +7,7 @@ **%VERSION%** ([zip](http://code.google.com/p/iciql/downloads/detail?name=%ZIP%)|[jar](http://code.google.com/p/iciql/downloads/detail?name=%JAR%)) *released %BUILDDATE%*
- api change release (API v4)
+- don't INSERT primitive autoIncrement primaryKey fields, let database assign value
- full support for primitives in all clauses
- DECIMAL(length, scale) support
- unspecified length String fields are now CLOB instead of TEXT. dialects can intercept this and convert to another type. e.g. MySQL dialect can change CLOB to TEXT.
diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java index 687ba53..729cb90 100644 --- a/src/com/iciql/TableDefinition.java +++ b/src/com/iciql/TableDefinition.java @@ -129,12 +129,11 @@ public class TableDefinition<T> { int tableVersion;
List<String> primaryKeyColumnNames;
boolean memoryTable;
-
- private boolean createTableIfRequired = true;
+
+ private boolean createTableIfRequired = true;
private Class<T> clazz;
private IdentityHashMap<Object, FieldDefinition> fieldMap = Utils.newIdentityHashMap();
private ArrayList<IndexDefinition> indexes = Utils.newArrayList();
-
TableDefinition(Class<T> clazz) {
this.clazz = clazz;
@@ -251,7 +250,7 @@ public class TableDefinition<T> { def.length = length;
}
}
-
+
public void setScale(Object column, int scale) {
FieldDefinition def = fieldMap.get(column);
if (def != null) {
@@ -286,7 +285,7 @@ public class TableDefinition<T> { int length = 0;
int scale = 0;
boolean trim = false;
- boolean nullable = true;
+ boolean nullable = !f.getType().isPrimitive();
EnumType enumType = null;
String defaultValue = "";
// configure Java -> SQL enum mapping
@@ -402,7 +401,7 @@ public class TableDefinition<T> { return enumid.enumId();
}
}
-
+
if (field.trim && field.length > 0) {
if (value instanceof String) {
// clip strings
@@ -423,12 +422,18 @@ public class TableDefinition<T> { 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);
@@ -443,6 +448,17 @@ public class TableDefinition<T> { return stat.executeUpdate();
}
+ private boolean skipInsertField(FieldDefinition field, Object obj) {
+ // skip uninitialized primitive autoincrement values
+ if (field.isAutoIncrement && field.isPrimitive) {
+ Object value = getValue(obj, field);
+ if (value.toString().equals("0")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void merge(Db db, Object obj) {
if (primaryKeyColumnNames == null || primaryKeyColumnNames.size() == 0) {
throw new IllegalStateException("No primary key columns defined " + "for table " + obj.getClass()
@@ -530,14 +546,14 @@ public class TableDefinition<T> { return this;
}
SQLStatement stat = new SQLStatement(db);
- db.getDialect().prepareCreateTable(stat, this);
+ db.getDialect().prepareCreateTable(stat, this);
StatementLogger.create(stat.getSQL());
stat.executeUpdate();
// create indexes
for (IndexDefinition index : indexes) {
stat = new SQLStatement(db);
- db.getDialect().prepareCreateIndex(stat, schemaName, tableName, index);
+ db.getDialect().prepareCreateIndex(stat, schemaName, tableName, index);
StatementLogger.create(stat.getSQL());
try {
stat.executeUpdate();
|