Eclipse Public License, Version 1.0.\r
\r
http://code.google.com/p/h2database\r
+ \r
+---------------------------------------------------------------------------\r
+HSQL Database\r
+---------------------------------------------------------------------------\r
+ hsqldb, released under the\r
+ BSD.\r
+ \r
+ http://hsqldb.org \r
\r
---------------------------------------------------------------------------\r
MarkdownPapers\r
### Configuration Requirements and Limitations\r
\r
1. Your model class **must** provide a public default constructor.\r
-2. All columns are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)*. \r
-3. Only the specified types are supported. Other types such as arrays and custom types are not supported.\r
-4. Triggers, views, and other advanced database features are not supported.\r
+2. All **Object** columns are assumed NULLABLE unless explicitly set *@IQColumn(nullable = false)*.\r
+3. All **Primitive** columns are assumed NOT NULLABLE unless explicitly set *@IQColumn(nullable = true)*.\r
+4. Only the specified types are supported. Any other types are not supported.\r
+5. 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
+### Supported Data Types\r
<table>\r
-<tr><th colspan="2">Standard SQL Types</th></tr>\r
-<tr><td>java.lang.String</td>\r
+<tr><td colspan="3"><b>Fully Supported Types</b><br/>\r
+can be used for all iciql expressions\r
+</tr>\r
+<tr><th>Object</th><th>Primitive</th><th>SQL Type</th></tr>\r
+<tr><td>java.lang.String</td><td></td>\r
<td>VARCHAR *(length > 0)* or CLOB *(length == 0)*</td></tr>\r
\r
-<tr><td>java.lang.Boolean</td>\r
-<td>BIT</td></tr>\r
+<tr><td>java.lang.Boolean</td><td>boolean</td>\r
+<td>BOOLEAN</td></tr>\r
\r
-<tr><td>java.lang.Byte</td>\r
+<tr><td>java.lang.Byte</td><td>byte</td>\r
<td>TINYINT</td></tr>\r
\r
-<tr><td>java.lang.Short</td>\r
+<tr><td>java.lang.Short</td><td>short</td>\r
<td>SMALLINT</td></tr>\r
\r
-<tr><td>java.lang.Integer</td>\r
+<tr><td>java.lang.Integer</td><td>int</td>\r
<td>INT</td></tr>\r
\r
-<tr><td>java.lang.Long</td>\r
+<tr><td>java.lang.Long</td><td>long</td>\r
<td>BIGINT</td></tr>\r
\r
-<tr><td>java.lang.Float</td>\r
+<tr><td>java.lang.Float</td><td>float</td>\r
<td>REAL</td></tr>\r
\r
-<tr><td>java.lang.Double</td>\r
+<tr><td>java.lang.Double</td><td>double</td>\r
<td>DOUBLE</td></tr>\r
\r
-<tr><td>java.math.BigDecimal</td>\r
+<tr><td>java.math.BigDecimal</td><td></td>\r
<td>DECIMAL *(length == 0)* or DECIMAL(length,scale) *(length > 0)*</td></tr>\r
\r
-<tr><td>java.sql.Date</td>\r
+<tr><td>java.sql.Date</td><td></td>\r
<td>DATE</td></tr>\r
\r
-<tr><td>java.sql.Time</td>\r
+<tr><td>java.sql.Time</td><td></td>\r
<td>TIME</td></tr>\r
\r
-<tr><td>java.sql.Timestamp</td>\r
+<tr><td>java.sql.Timestamp</td><td></td>\r
<td>TIMESTAMP</td></tr>\r
\r
-<tr><td>java.util.Date</td>\r
+<tr><td>java.util.Date</td><td></td>\r
<td>TIMESTAMP</td></tr>\r
\r
-<tr><td>java.lang.Enum.name()<br/>*default type*</td>\r
+<tr><td>java.lang.Enum.name()<br/>*default type*</td><td></td>\r
<td>VARCHAR *(length > 0)* or CLOB *(length == 0)*<br/>*EnumType.NAME*</td></tr>\r
\r
-<tr><td>java.lang.Enum.ordinal()</td>\r
+<tr><td>java.lang.Enum.ordinal()</td><td></td>\r
<td>INT<br/>*EnumType.ORDINAL*</td></tr>\r
\r
-<tr><td>java.lang.Enum implements<br/>*com.iciql.Iciql.EnumId.enumId()*</td>\r
+<tr><td>java.lang.Enum implements<br/>*com.iciql.Iciql.EnumId.enumId()*</td><td></td>\r
<td>INT<br/>*EnumType.ENUMID*</td></tr>\r
\r
-<tr><th colspan="2">H2 Database Types</th></tr>\r
-<tr><td>java.util.UUID</td>\r
+<tr><td colspan="3"><b>Partially Supported Types</b><br/>\r
+can not be directly referenced in an expression</td></tr>\r
+<tr><td>byte []</td><td></td>\r
+<td>BLOB</td><tr/>\r
+\r
+<tr><td colspan="3"><b>H2 Database Types</b><br/>\r
+fully supported when paired with an H2 database \r
+</td></tr>\r
+<tr><td>java.util.UUID</td><td></td>\r
<td>UUID</td><tr/>\r
\r
</table>\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
-### 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
-#### 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
-\r
## Annotation Configuration\r
The recommended approach to setup a model class is to annotate the class and field declarations.\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%)) *released %BUILDDATE%*\r
\r
- api change release (API v4)\r
+- full support for primitives in all clauses\r
- DECIMAL(length, scale) support\r
- 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.\r
- Boolean now maps to BOOLEAN instead of BIT\r
- moved dialects back to main package\r
- improved automatic dialect determination on pooled connections\r
- moved create table and create index statement generation into dialects\r
-- added HSQL dialect. HSQL fails 4 out of 49 unit tests: 2 failures are unimplemented merge, 1 has been filed as a bug in HSQL.\r
+- added HSQL dialect. HSQL fails 4 out of 49 unit tests: 2 failures are unimplemented merge, and 1 has been filed as a [bug in HSQL](https://sourceforge.net/tracker/?func=detail&aid=3390047&group_id=23316&atid=378131).\r
- added MySQL dialect. untested.\r
- renamed <b>_ iq_versions</b> table to *iq_versions* since leading _ character is troublesome for some databases.\r
- @IQColumn(allowNull=true) -> @IQColumn(nullable=true)\r
import java.sql.ResultSet;\r
import java.sql.SQLException;\r
import java.util.ArrayList;\r
+import java.util.Arrays;\r
import java.util.HashMap;\r
import java.util.IdentityHashMap;\r
import java.util.List;\r
private ArrayList<SelectTable<T>> joins = Utils.newArrayList();\r
private final IdentityHashMap<Object, SelectColumn<T>> aliasMap = Utils.newIdentityHashMap();\r
private ArrayList<OrderExpression<T>> orderByList = Utils.newArrayList();\r
- private Object[] groupByExpressions;\r
+ private ArrayList<Object> groupByExpressions = Utils.newArrayList();\r
private long limit;\r
private long offset;\r
\r
return new UpdateColumnSet<T, A>(this, field);\r
}\r
\r
+ public UpdateColumnSet<T, Boolean> set(boolean field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Byte> set(byte field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Short> set(short field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Integer> set(int field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Long> set(long field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Float> set(float field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnSet<T, Double> set(double field) {\r
+ return setPrimitive(field);\r
+ }\r
+\r
+ private <A> UpdateColumnSet<T, A> setPrimitive(A field) {\r
+ A alias = getPrimitiveAliasByValue(field);\r
+ if (alias == null) {\r
+ // this will result in an unmapped field exception\r
+ return set(field);\r
+ }\r
+ return set(alias);\r
+ }\r
+\r
public <A> UpdateColumnIncrement<T, A> increment(A field) {\r
return new UpdateColumnIncrement<T, A>(this, field);\r
}\r
\r
+ public UpdateColumnIncrement<T, Byte> increment(byte field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+ \r
+ public UpdateColumnIncrement<T, Short> increment(short field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnIncrement<T, Integer> increment(int field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnIncrement<T, Long> increment(long field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnIncrement<T, Float> increment(float field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+\r
+ public UpdateColumnIncrement<T, Double> increment(double field) {\r
+ return incrementPrimitive(field);\r
+ }\r
+\r
+ private <A> UpdateColumnIncrement<T, A> incrementPrimitive(A field) {\r
+ A alias = getPrimitiveAliasByValue(field);\r
+ if (alias == null) {\r
+ // this will result in an unmapped field exception\r
+ return increment(field);\r
+ }\r
+ return increment(alias);\r
+ }\r
+\r
public int update() {\r
if (updateColumnDeclarations.size() == 0) {\r
throw new IciqlException("Missing set or increment call.");\r
return stat;\r
}\r
\r
+ /**\r
+ * Begin a primitive boolean field condition clause.\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> where(boolean x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive short field condition clause.\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, Byte> where(byte x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive short field condition clause.\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> where(short x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive int field condition clause.\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> where(int x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive long field condition clause.\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> where(long x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive float field condition clause.\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> where(float x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begin a primitive double field condition clause.\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> where(double x) {\r
+ return wherePrimitive(x);\r
+ }\r
+\r
+ /**\r
+ * Begins a primitive field condition clause.\r
+ * \r
+ * @param value\r
+ * @return a query condition to continue building the condition\r
+ */\r
+ private <A> QueryCondition<T, A> wherePrimitive(A value) {\r
+ A alias = getPrimitiveAliasByValue(value);\r
+ if (alias == null) {\r
+ // this will result in an unmapped field exception\r
+ return where(value);\r
+ }\r
+ return where(alias);\r
+ }\r
+\r
+ /**\r
+ * Begin an Object field condition clause.\r
+ * \r
+ * @param x\r
+ * the mapped object to query\r
+ * @return a query condition to continue building the condition\r
+ */\r
public <A> QueryCondition<T, A> where(A x) {\r
return new QueryCondition<T, A>(this, x);\r
}\r
return this;\r
}\r
\r
+ public Query<T> orderBy(boolean field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(byte field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(short field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(int field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(long field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(float field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> orderBy(double field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ Query<T> orderByPrimitive(Object field) {\r
+ Object alias = getPrimitiveAliasByValue(field);\r
+ if (alias == null) {\r
+ return orderBy(field);\r
+ }\r
+ return orderBy(alias);\r
+ }\r
+ \r
+ public Query<T> orderBy(Object expr) {\r
+ OrderExpression<T> e = new OrderExpression<T>(this, expr, false, false, false);\r
+ addOrderBy(e);\r
+ return this;\r
+ }\r
+ \r
/**\r
* Order by a number of columns.\r
* \r
return this;\r
}\r
\r
+ public Query<T> groupBy(boolean field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(byte field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(short field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(int field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(long field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(float field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ public Query<T> groupBy(double field) {\r
+ return orderByPrimitive(field);\r
+ }\r
+\r
+ Query<T> groupByPrimitive(Object field) {\r
+ Object alias = getPrimitiveAliasByValue(field);\r
+ if (alias == null) {\r
+ return groupBy(field);\r
+ }\r
+ return groupBy(alias);\r
+ }\r
+ \r
+ public Query<T> groupBy(Object expr) {\r
+ groupByExpressions.add(expr);\r
+ return this;\r
+ }\r
+ \r
public Query<T> groupBy(Object... groupBy) {\r
- this.groupByExpressions = groupBy;\r
+ this.groupByExpressions.addAll(Arrays.asList(groupBy));\r
return this;\r
}\r
\r
addParameter(stat, alias, value);\r
return;\r
}\r
- SelectColumn<T> col = aliasMap.get(value);\r
+ SelectColumn<T> col = getColumnByReference(value);\r
if (col != null) {\r
col.appendSQL(stat);\r
return;\r
\r
private void addParameter(SQLStatement stat, Object alias, Object value) {\r
if (alias != null && value.getClass().isEnum()) {\r
- SelectColumn<T> col = aliasMap.get(alias);\r
+ SelectColumn<T> col = getColumnByReference(alias);\r
EnumType type = col.getFieldDefinition().enumType;\r
Enum<?> anEnum = (Enum<?>) value;\r
Object y = Utils.convertEnum(anEnum, type);\r
join.appendSQLAsJoin(stat, this);\r
}\r
appendWhere(stat);\r
- if (groupByExpressions != null) {\r
+ if (!groupByExpressions.isEmpty()) {\r
stat.appendSQL(" GROUP BY ");\r
int i = 0;\r
for (Object obj : groupByExpressions) {\r
return !joins.isEmpty();\r
}\r
\r
- SelectColumn<T> getSelectColumn(Object obj) {\r
- return aliasMap.get(obj);\r
+ /**\r
+ * This method returns a mapped Object field by its reference.\r
+ * \r
+ * @param obj\r
+ * @return\r
+ */\r
+ private SelectColumn<T> getColumnByReference(Object obj) {\r
+ SelectColumn<T> col = aliasMap.get(obj);\r
+ return col;\r
+ }\r
+\r
+ /**\r
+ * This method returns the alias of a mapped primitive field by its value.\r
+ * \r
+ * @param obj\r
+ * @return\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ <A> A getPrimitiveAliasByValue(A obj) {\r
+ for (Object alias : aliasMap.keySet()) {\r
+ if (alias.equals(obj)) {\r
+ SelectColumn<T> match = aliasMap.get(alias);\r
+ if (match.getFieldDefinition().isPrimitive) {\r
+ return (A) alias;\r
+ }\r
+ }\r
+ }\r
+ return null;\r
}\r
\r
void addOrderBy(OrderExpression<T> expr) {\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
+ 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.addConditionToken(ConditionAndOr.AND);\r
return new QueryCondition<T, A>(query, x);\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
+ 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.addConditionToken(ConditionAndOr.OR);\r
return new QueryCondition<T, A>(query, x);\r
}\r
\r
/**\r
- * Order by a number of columns.\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
+ 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.orderBy(field);\r
+ return this;\r
+ }\r
+ /**\r
+ * Order by a number of Object columns.\r
* \r
* @param expressions\r
* the order by expressions\r
*/\r
\r
public QueryWhere<T> orderBy(Object... expressions) {\r
- for (Object expr : expressions) {\r
- OrderExpression<T> e = new OrderExpression<T>(query, expr, false, false, false);\r
- query.addOrderBy(e);\r
- }\r
+ query.orderBy(expressions);\r
return this;\r
}\r
\r
boolean nullable;\r
String defaultValue;\r
EnumType enumType;\r
+ boolean isPrimitive;\r
\r
Object getValue(Object obj) {\r
try {\r
boolean reflectiveMatch = isPublic && !byAnnotationsOnly;\r
if (reflectiveMatch || hasAnnotation) {\r
FieldDefinition fieldDef = new FieldDefinition();\r
+ fieldDef.isPrimitive = f.getType().isPrimitive();\r
fieldDef.field = f;\r
fieldDef.columnName = columnName;\r
fieldDef.isAutoIncrement = isAutoIncrement;\r
query.appendSQL(stat, x, obj);\r
}\r
}\r
-\r
- <Y, X> void copyAttributeValues(Query<Y> query, X to, X map) {\r
- for (FieldDefinition def : fields) {\r
- Object obj = def.getValue(map);\r
- SelectColumn<Y> col = query.getSelectColumn(obj);\r
- Object value = col.getCurrentValue();\r
- def.setValue(to, value);\r
- }\r
- }\r
-\r
}\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 == 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
}\r
try {\r
package com.iciql.test;
import static org.junit.Assert.assertEquals;
-
-import java.util.List;
+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;
/**
- * 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
+ * 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 testAliasMapping() throws Exception {
+ public void testObjectAliasMapping() throws Exception {
Db db = IciqlSuite.openDb();
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;
+
Product p = new Product();
- List<Product> products = db.from(p).where(p.unitsInStock).is(9).orderBy(p.productId).select();
+ // 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());
+ }
+
+ db.close();
+ }
+
+ /**
+ * Confirms that primitive aliases ARE mapped by value.
+ */
+ @Test
+ public void testPrimitiveAliasMapping() throws Exception {
+ Db db = IciqlSuite.openDb();
+ PrimitivesModel model = new PrimitivesModel();
+ model.myLong = 100L;
+ db.insert(model);
+ model.myLong = 200L;
+ db.insert(model);
- assertEquals("[]", products.toString());
+ // 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();
}
}
\ No newline at end of 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
public void testPrimitives() {\r
Db db = IciqlSuite.openDb();\r
\r
- // insert random model\r
- PrimitivesModel model = new PrimitivesModel();\r
- db.insert(model);\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).selectFirst();\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
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
+ 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
db.close();\r
}\r
*/\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
same &= 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
+ \r
+ @Override\r
+ public String toString() {\r
+ return String.valueOf(myLong);\r
+ }\r
}\r