Browse Source

Simplified annotations. Interchangeable int-boolean runtime mapping.

tags/v0.6.0
James Moger 13 years ago
parent
commit
b865898879

+ 6
- 6
docs/01_model_classes.mkd View File

@@ -9,7 +9,7 @@ Alternatively, model classes can be automatically generated by iciql using the m
<table>
<tr><td>java.lang.String</td>
<td>VARCHAR *(maxLength > 0)* or TEXT *(maxLength == 0)*</td></tr>
<td>VARCHAR *(length > 0)* or TEXT *(length == 0)*</td></tr>
<tr><td>java.lang.Boolean</td>
<td>BIT</td></tr>
@@ -51,7 +51,7 @@ Alternatively, model classes can be automatically generated by iciql using the m
<td>BLOB</td></tr>
<tr><td>java.lang.Enum.name()</td>
<td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td></tr>
<td>VARCHAR (length > 0) or TEXT (length == 0)<br/>EnumType.STRING</td></tr>
<tr><td>java.lang.Enum.ordinal()</td>
<td>INT<br/>EnumType.ORDINAL</td></tr>
@@ -115,10 +115,10 @@ public class Product {
@IQColumn(primaryKey = true)
public Integer productId;
@IQColumn(maxLength = 200, trimString = true)
@IQColumn(length = 200, trim = true)
public String productName;
@IQColumn(maxLength = 50, trimString = true)
@IQColumn(length = 50, trim = true)
public String category;
@IQColumn
@@ -185,8 +185,8 @@ public class Product implements Iciql {
public void defineIQ() {
com.iciql.Define.primaryKey(productId);
com.iciql.Define.columnName(unitsInStock, "units");
com.iciql.Define.maxLength(productName, 200);
com.iciql.Define.maxLength(category, 50);
com.iciql.Define.length(productName, 200);
com.iciql.Define.length(category, 50);
com.iciql.Define.index(productName, category);
}
}

+ 5
- 1
docs/05_releases.mkd View File

@@ -3,9 +3,11 @@
### Current Release
**%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%*
- api change release (API v2)
- added BLOB support (issue 1)
- added java.lang.Enum support (issue 2)
- api change release (API v2)
- allow runtime flexible mapping of BOOL columns to Integer fields
- allow runtime flexible mapping of INT columns to Boolean fields
- annotations overhaul to reduce verbosity
- @IQSchema(name="public") -> @IQSchema("public")
- @IQDatabase(version=2) -> @IQVersion(2)
@@ -15,6 +17,8 @@
%BEGINCODE%
@IQIndexes({ @IQIndex("name"), @IQIndex(name="myindexname" value={"name", "nickname"}) })
%ENDCODE%
- @IQColumn(maxLength=20) -> @IQColumn(length=20)
- @IQColumn(trimString=true) -> @IQColumn(trim=true)
### Older Releases

+ 1
- 1
src/com/iciql/Define.java View File

@@ -59,7 +59,7 @@ public class Define {
currentTableDefinition.setColumnName(column, columnName);
}
public static void maxLength(Object column, int length) {
public static void length(Object column, int length) {
checkInDefine();
currentTableDefinition.setMaxLength(column, length);
}

+ 18
- 13
src/com/iciql/Iciql.java View File

@@ -37,7 +37,7 @@ import java.lang.annotation.Target;
* <table>
* <tr>
* <td>java.lang.String</td>
* <td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)</td>
* <td>VARCHAR (length > 0) or TEXT (length == 0)</td>
* </tr>
* <tr>
* <td>java.lang.Boolean</td>
@@ -93,15 +93,19 @@ import java.lang.annotation.Target;
* </tr>
* <tr>
* <td>java.lang.Enum.name()</td>
* <td>VARCHAR (maxLength > 0) or TEXT (maxLength == 0)<br/>EnumType.STRING</td>
* <td>VARCHAR (length > 0) or TEXT (length == 0)<br/>
* EnumType.STRING</td>
* </tr>
* <tr>
* <td>java.lang.Enum.ordinal()</td>
* <td>INT<br/>EnumType.ORDINAL</td>
* <td>INT<br/>
* EnumType.ORDINAL</td>
* </tr>
* <tr>
* <td>java.lang.Enum implements<br/>com.iciql.Iciql.EnumID.enumId()</td>
* <td>INT<br/>EnumType.ENUMID</td>
* <td>java.lang.Enum implements<br/>
* com.iciql.Iciql.EnumID.enumId()</td>
* <td>INT<br/>
* EnumType.ENUMID</td>
* </tr>
* </tr>
* </table>
@@ -346,18 +350,18 @@ public interface Iciql {
/**
* If larger than zero, it is used during the CREATE TABLE phase. It may
* also be used to prevent database exceptions on INSERT and UPDATE
* statements (see trimString).
* statements (see trim).
* <p>
* Any maxLength set in define() may override this annotation setting if
* Any length set in define() may override this annotation setting if
* the model class is not annotated with IQTable. Default: 0.
*/
int maxLength() default 0;
int length() default 0;
/**
* If true, iciql will automatically trim the string if it exceeds
* maxLength (value.substring(0, maxLength)). Default: false.
* length (value.substring(0, length)). Default: false.
*/
boolean trimString() default false;
boolean trim() default false;
/**
* If false, iciql will set the column NOT NULL during the CREATE TABLE
@@ -403,7 +407,8 @@ public interface Iciql {
* <li>ORDINAL - ordinal() : int
* <li>ENUMID - enumId() : int
* </ul>
* @see com.iciql.Iciql.EnumId interface
*
* @see com.iciql.Iciql.EnumId interface
*/
public enum EnumType {
STRING, ORDINAL, ENUMID;
@@ -428,8 +433,8 @@ public interface Iciql {
* IQEnum(EnumType.STRING)
* </pre>
*
* A string mapping will generate either a VARCHAR, if IQColumn.maxLength >
* 0 or a TEXT column if IQColumn.maxLength == 0
* A string mapping will generate either a VARCHAR, if IQColumn.length >
* 0 or a TEXT column if IQColumn.length == 0
*
*/
@Retention(RetentionPolicy.RUNTIME)

+ 1
- 0
src/com/iciql/Query.java View File

@@ -222,6 +222,7 @@ public class Query<T> {
try {
X value;
Object o = rs.getObject(1);
// Convert CLOB and BLOB now because we close the resultset
if (Clob.class.isAssignableFrom(o.getClass())) {
value = (X) Utils.convert(o, String.class);
} else if (Blob.class.isAssignableFrom(o.getClass())) {

+ 2
- 2
src/com/iciql/TableDefinition.java View File

@@ -285,8 +285,8 @@ class TableDefinition<T> {
}
isAutoIncrement = col.autoIncrement();
isPrimaryKey = col.primaryKey();
maxLength = col.maxLength();
trimString = col.trimString();
maxLength = col.length();
trimString = col.trim();
allowNull = col.allowNull();
defaultValue = col.defaultValue();
}

+ 4
- 4
src/com/iciql/TableInspector.java View File

@@ -346,13 +346,13 @@ public class TableInspector {
ap.addParameter("primaryKey=true");
}

// IQColumn.maxLength
// IQColumn.length
if ((clazz == String.class) && (col.size > 0) && (col.size < Integer.MAX_VALUE)) {
ap.addParameter("maxLength", col.size);
ap.addParameter("length", col.size);

// IQColumn.trimStrings
// IQColumn.trim
if (trimStrings) {
ap.addParameter("trimString=true");
ap.addParameter("trim=true");
}
} else {
// IQColumn.AutoIncrement

+ 16
- 0
src/com/iciql/util/Utils.java View File

@@ -226,6 +226,22 @@ public class Utils {
return o.toString();
}
// convert from number to boolean
if (Boolean.class.isAssignableFrom(targetType)) {
if (Number.class.isAssignableFrom(currentType)) {
Number n = (Number) o;
return n.intValue() > 0;
}
}
// convert from boolean to number
if (Boolean.class.isAssignableFrom(currentType)) {
if (Number.class.isAssignableFrom(targetType)) {
Boolean b = (Boolean) o;
return b ? 1 : 0;
}
}
// convert from number to number
if (Number.class.isAssignableFrom(currentType)) {
Number n = (Number) o;

+ 128
- 0
tests/com/iciql/test/BooleanModelTest.java View File

@@ -0,0 +1,128 @@
/*
* Copyright 2011 James Moger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.iciql.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Test;
import com.iciql.Db;
import com.iciql.test.models.BooleanModel;
import com.iciql.test.models.BooleanModel.BooleanAsIntModel;
/**
* Tests interchangeable mapping of INT columns with Booleans and BOOL columns
* with Integers.
* <ul>
* <li>mapping a BIT/BOOLEAN column as an Integer
* <li>mapping a INT column as a Boolean.
* </ul>
*/
public class BooleanModelTest {
@Test
public void testBooleanColumn() {
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.insertAll(BooleanModel.getList());
BooleanAsIntModel b = new BooleanAsIntModel();
List<BooleanAsIntModel> models = db.from(b).select();
int count = 0;
for (BooleanAsIntModel model : models) {
if ((model.id % 2) == 1) {
// assert that odd ids are true
assertTrue(model.mybool > 0);
} else {
// assert that even ids are false
assertTrue(model.mybool == 0);
}
// count true values
if (model.mybool > 0) {
count++;
}
}
assertEquals(2, count);
// invert boolean values and update
for (BooleanAsIntModel model : models) {
model.mybool = model.mybool > 0 ? 0 : 1;
}
db.updateAll(models);
// check even ids are true
models = db.from(b).select();
for (BooleanAsIntModel model : models) {
if ((model.id % 2) == 1) {
// assert that odd ids are false
assertTrue(model.mybool == 0);
} else {
// assert that even ids are true
assertTrue(model.mybool > 0);
}
}
db.close();
}
@Test
public void testIntColumn() {
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
// insert INT column
db.insertAll(BooleanAsIntModel.getList());
// select all rows with INT column and map to Boolean
BooleanModel b = new BooleanModel();
List<BooleanModel> models = db.from(b).select();
int count = 0;
for (BooleanModel model : models) {
if ((model.id % 2) == 1) {
// assert that odd ids are true
assertTrue(model.mybool);
} else {
// assert that even ids are false
assertTrue(!model.mybool);
}
// count true values
if (model.mybool) {
count++;
}
}
assertEquals(2, count);
// invert boolean values and update
for (BooleanModel model : models) {
model.mybool = !model.mybool;
}
db.updateAll(models);
// check even ids are true
models = db.from(b).select();
for (BooleanModel model : models) {
if ((model.id % 2) == 1) {
// assert that odd ids are false
assertTrue(!model.mybool);
} else {
// assert that even ids are true
assertTrue(model.mybool);
}
}
db.close();
}
}

+ 2
- 2
tests/com/iciql/test/IciqlSuite.java View File

@@ -25,8 +25,8 @@ import org.junit.runners.Suite.SuiteClasses;
*
*/
@RunWith(Suite.class)
@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, ClobTest.class, ConcurrencyTest.class,
ModelsTest.class, SamplesTest.class, UpdateTest.class, RuntimeQueryTest.class,
@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
ConcurrencyTest.class, ModelsTest.class, SamplesTest.class, UpdateTest.class, RuntimeQueryTest.class,
StatementLoggerTest.class })
public class IciqlSuite {

+ 1
- 1
tests/com/iciql/test/ModelsTest.java View File

@@ -115,7 +115,7 @@ public class ModelsTest {
true);
assertEquals(1, models.size());
// a poor test, but a start
assertEquals(1904, models.get(0).length());
assertEquals(1895, models.get(0).length());
}

@Test

+ 73
- 0
tests/com/iciql/test/models/BooleanModel.java View File

@@ -0,0 +1,73 @@
/*
* Copyright 2011 James Moger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.iciql.test.models;
import java.util.Arrays;
import java.util.List;
import com.iciql.Iciql.IQColumn;
import com.iciql.Iciql.IQTable;
/**
* Boolean types model.
*/
@IQTable(name = "BooleanTest")
public class BooleanModel {
@IQColumn(primaryKey = true)
public Integer id;
@IQColumn
public Boolean mybool;
public BooleanModel() {
}
BooleanModel(int id, boolean val) {
this.id = id;
this.mybool = val;
}
public static List<BooleanModel> getList() {
return Arrays.asList(new BooleanModel(1, true), new BooleanModel(2, false),
new BooleanModel(3, true), new BooleanModel(4, false));
}
/**
* Test boolean as int
*/
@IQTable(name = "BooleanTest")
public static class BooleanAsIntModel {
@IQColumn(primaryKey = true)
public Integer id;
@IQColumn
public Integer mybool;
public BooleanAsIntModel() {
}
BooleanAsIntModel(int id, boolean val) {
this.id = id;
this.mybool = val ? 1 : 0;
}
public static List<BooleanAsIntModel> getList() {
return Arrays.asList(new BooleanAsIntModel(1, true), new BooleanAsIntModel(2, false),
new BooleanAsIntModel(3, true), new BooleanAsIntModel(4, false));
}
}
}

+ 2
- 2
tests/com/iciql/test/models/Product.java View File

@@ -18,7 +18,7 @@
package com.iciql.test.models;
import static com.iciql.Define.index;
import static com.iciql.Define.maxLength;
import static com.iciql.Define.length;
import static com.iciql.Define.primaryKey;
import static com.iciql.Define.tableName;
@@ -54,7 +54,7 @@ public class Product implements Iciql {
public void defineIQ() {
tableName("Product");
primaryKey(productId);
maxLength(category, 255);
length(category, 255);
index(productName, category);
}

+ 1
- 1
tests/com/iciql/test/models/ProductAnnotationOnly.java View File

@@ -42,7 +42,7 @@ public class ProductAnnotationOnly {
@IQColumn(name = "id")
public Integer productId;

@IQColumn(name = "cat", maxLength = 15, trimString = true)
@IQColumn(name = "cat", length = 15, trim = true)
public String category;

@IQColumn(name = "name")

+ 1
- 1
tests/com/iciql/test/models/ProductMixedAnnotation.java View File

@@ -36,7 +36,7 @@ public class ProductMixedAnnotation {
public Integer unitsInStock;
public String mappedField;

@IQColumn(name = "cat", maxLength = 255)
@IQColumn(name = "cat", length = 255)
public String category;

@IQColumn(name = "id", primaryKey = true)

+ 5
- 5
tests/com/iciql/test/models/SupportedTypes.java View File

@@ -80,10 +80,10 @@ public class SupportedTypes {
public Integer id;

@IQColumn
private Boolean myBool = false;
private Boolean myBool;

@IQColumn
private Byte myByte = 2;
private Byte myByte;

@IQColumn
private Short myShort;
@@ -95,7 +95,7 @@ public class SupportedTypes {
private Long myLong;

@IQColumn
private Float myFloat = 1.0f;
private Float myFloat;

@IQColumn
private Double myDouble;
@@ -122,14 +122,14 @@ public class SupportedTypes {
private byte[] myBlob;

@IQEnum(EnumType.STRING)
@IQColumn(trimString = true, maxLength = 25)
@IQColumn(trim = true, length = 25)
private Flower myFavoriteFlower;

@IQEnum(EnumType.ORDINAL)
@IQColumn
private Flower myOtherFavoriteFlower;

@IQColumn(maxLength = 25)
@IQColumn(length = 25)
// @IQEnum is set on the enumeration definition and is shared
// by all uses of Tree as an @IQColumn
private Tree myFavoriteTree;

Loading…
Cancel
Save