From: James Moger Date: Tue, 13 Dec 2011 20:24:43 +0000 (-0500) Subject: Corrected performance regression. Tweaked dynamic query results. X-Git-Tag: v0.7.5^0 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8e7ccd33d586bdea3fea1f606874deeaf7b9884f;p=iciql.git Corrected performance regression. Tweaked dynamic query results. --- diff --git a/api/v10.xml b/api/v10.xml new file mode 100644 index 0000000..13f5663 --- /dev/null +++ b/api/v10.xml @@ -0,0 +1,6184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/04_examples.mkd b/docs/04_examples.mkd index a1273be..eaaa579 100644 --- a/docs/04_examples.mkd +++ b/docs/04_examples.mkd @@ -11,7 +11,6 @@ List<Customer> waCustomers = db.from(c). where(c.region).is("WA").select() public static class ProductPrice { public String productName; public String category; - @IQColumn(name = "unitPrice") public Double price; } diff --git a/docs/05_releases.mkd b/docs/05_releases.mkd index d4aa8f2..ebc1fae 100644 --- a/docs/05_releases.mkd +++ b/docs/05_releases.mkd @@ -6,29 +6,18 @@ **%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%* +- Iciql now identifies wildcard queries and builds a dynamic column lookup. Otherwise, the original field-position-based approach is used. This corrects the performance regression released in 0.7.4 while still fixing the wildcard statement column mapping problem. + +**0.7.4**   *released 2011-12-06* + - Disallow **declaring and explicitly referencing** multiple primitive booleans in a single model.
A runtime exception will be thrown if an attempt to use where/set/on/and/or/groupBy/orderBy(boolean) and your model has multiple mapped primitive boolean fields. - Added list alternatives to the varargs methods because it was too easy to forget list.toArray()
*Db.executeQuery(Class<? extends T> modelClass, String sql, List<?> args)*
*Db.executeQuery(String sql, List<?> args)*
*Query.where(String fragment, List<?> args)*
- Fixed inherited JaQu bug related to model classes and wildcard queries (select *).

-Iciql maps resultset columns by the index of the model class field from a list. This assumes that *all* columns in the resultset have a corresponding model field definition. This works fine for most queries because iciql explicitly selects columns from the table (*select alpha, beta...*) when you execute *select()*. The problem is when iciql issues a join or a custom wildcard query and your model does not represent all columns in the resultset: columns and fields fail to correctly line-up.

-The fix for this (building a column index from the resultset by column name lookup) breaks selecting into *some* anonymous inner classes. At issue is that the inner class field names must now match the column names or the fields must be explicitly annotated with the column names.

**Example** (notice *IQColumn* annotation)
-%BEGINCODE% -public static class ProductPrice { - public String productName; - public String category; - @IQColumn(name = "unitPrice") - public Double price; -} - -db....select(new ProductPrice() {{ - productName = p.productName; - category = p.category; - // or unitPrice = p.unitPrice; - price = p.unitPrice; -}} -%ENDCODE% +Iciql maps resultset columns by the index of the model class field from a list. This assumes that *all* columns in the resultset have a corresponding model field definition. This works fine for most queries because iciql explicitly selects columns from the table (*select alpha, beta...*) when you execute *select()*. The problem is when iciql issues a dynamic wildcard query and your model does not represent all columns in the resultset: columns and fields may fail to correctly line-up.

+Iciql now maps all fields by their column name, not by their position. ### Older Releases diff --git a/docs/06_jaqu_comparison.mkd b/docs/06_jaqu_comparison.mkd index 9c0f56c..fcc9fc0 100644 --- a/docs/06_jaqu_comparison.mkd +++ b/docs/06_jaqu_comparison.mkd @@ -10,7 +10,7 @@ This is an overview of the fundamental differences between the original JaQu pro databasesH2, HSQL, Derby, MySQL, and PostreSQLH2 only loggingconsole, SLF4J, or custom loggingconsole logging exceptionsalways includes generated statement in exception, when available-- -column mappingsresult sets built by column nameresult sets built by field index
this can fail for dynamic queries or joins +column mappingswildcard queries index result sets by column nameall result sets built by field index
this can fail for wildcard queries syntax and api dynamic queriesmethods and where clauses for dynamic queries that build iciql objects-- DROPsyntax to drop a table diff --git a/src/com/iciql/Constants.java b/src/com/iciql/Constants.java index 9dab0fb..4034b3b 100644 --- a/src/com/iciql/Constants.java +++ b/src/com/iciql/Constants.java @@ -25,14 +25,14 @@ public class Constants { // The build script extracts this exact line so be careful editing it // and only use A-Z a-z 0-9 .-_ in the string. - public static final String VERSION = "0.7.4"; + public static final String VERSION = "0.7.5"; // The build script extracts this exact line so be careful editing it // and only use A-Z a-z 0-9 .-_ in the string. - public static final String VERSION_DATE = "2011-12-09"; + public static final String VERSION_DATE = "2011-12-12"; // The build script extracts this exact line so be careful editing it // and only use A-Z a-z 0-9 .-_ in the string. - public static final String API_CURRENT = "9"; + public static final String API_CURRENT = "10"; } diff --git a/src/com/iciql/Db.java b/src/com/iciql/Db.java index 4dc0b5e..bfc3c73 100644 --- a/src/com/iciql/Db.java +++ b/src/com/iciql/Db.java @@ -37,8 +37,8 @@ import javax.sql.DataSource; import com.iciql.DbUpgrader.DefaultDbUpgrader; import com.iciql.Iciql.IQTable; import com.iciql.Iciql.IQVersion; -import com.iciql.util.JdbcUtils; 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; @@ -139,20 +139,6 @@ public class Db { } } - /** - * Convenience function to avoid import statements in application code. - */ - public static void activateConsoleLogger() { - IciqlLogger.activateConsoleLogger(); - } - - /** - * Convenience function to avoid import statements in application code. - */ - public static void deactivateConsoleLogger() { - IciqlLogger.deactivateConsoleLogger(); - } - public static Db open(String url) { try { Connection conn = JdbcUtils.getConnection(null, url, null, null); @@ -161,7 +147,7 @@ public class Db { throw new IciqlException(e); } } - + public static Db open(String url, String user, String password) { try { Connection conn = JdbcUtils.getConnection(null, url, user, password); @@ -202,6 +188,20 @@ public class Db { throw new IciqlException(e); } } + + /** + * 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 void insert(T t) { Class clazz = t.getClass(); @@ -282,12 +282,16 @@ public class Db { return rc; } - @SuppressWarnings("unchecked") public List buildObjects(Class modelClass, ResultSet rs) { + return buildObjects(modelClass, false, rs); + } + + @SuppressWarnings("unchecked") + public List buildObjects(Class modelClass, boolean wildcardSelect, ResultSet rs) { List result = new ArrayList(); TableDefinition def = (TableDefinition) define(modelClass); try { - int [] columns = def.mapColumns(rs); + int[] columns = def.mapColumns(wildcardSelect, rs); while (rs.next()) { T item = Utils.newObject(modelClass); def.readRow(item, rs, columns); @@ -463,7 +467,6 @@ public class Db { return (TableDefinition) classMap.get(clazz); } - /** * Run a SQL query directly against the database. * @@ -482,7 +485,7 @@ public class Db { public ResultSet executeQuery(String sql, List args) { return executeQuery(sql, args.toArray()); } - + /** * Run a SQL query directly against the database. * @@ -528,7 +531,7 @@ public class Db { public List executeQuery(Class 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. @@ -552,7 +555,9 @@ public class Db { } rs = stat.executeQuery(); } - return buildObjects(modelClass, rs); + boolean wildcardSelect = sql.toLowerCase().startsWith("select *") + || sql.toLowerCase().startsWith("select distinct *"); + return buildObjects(modelClass, wildcardSelect, rs); } catch (SQLException e) { throw new IciqlException(e); } finally { diff --git a/src/com/iciql/Iciql.java b/src/com/iciql/Iciql.java index b13baf4..eaa256a 100644 --- a/src/com/iciql/Iciql.java +++ b/src/com/iciql/Iciql.java @@ -499,17 +499,6 @@ public interface Iciql { EnumType value() default EnumType.NAME; } - /** - * Annotation to define a field that should contain the result a function. - * This annotation ensures that functions mapped in anonymous inner classes - * can still be referenced in the ResultSet after the switch to dynamic - * column-name mapping from fixed position column mapping. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface IQFunction{ - } - /** * Annotation to define an ignored field. */ diff --git a/src/com/iciql/Query.java b/src/com/iciql/Query.java index 33b6dfa..37987ea 100644 --- a/src/com/iciql/Query.java +++ b/src/com/iciql/Query.java @@ -123,7 +123,7 @@ public class Query { appendFromWhere(stat); ResultSet rs = stat.executeQuery(); try { - int[] columns = def.mapColumns(rs); + int[] columns = def.mapColumns(false, rs); while (rs.next()) { T item = from.newObject(); def.readRow(item, rs, columns); @@ -271,7 +271,7 @@ public class Query { appendFromWhere(stat); ResultSet rs = stat.executeQuery(); try { - int[] columns = def.mapColumns(rs); + int[] columns = def.mapColumns(false, rs); while (rs.next()) { X row = Utils.newObject(clazz); def.readRow(row, rs, columns); diff --git a/src/com/iciql/TableDefinition.java b/src/com/iciql/TableDefinition.java index 1147238..f8238e5 100644 --- a/src/com/iciql/TableDefinition.java +++ b/src/com/iciql/TableDefinition.java @@ -30,7 +30,6 @@ import com.iciql.Iciql.EnumId; import com.iciql.Iciql.EnumType; import com.iciql.Iciql.IQColumn; import com.iciql.Iciql.IQEnum; -import com.iciql.Iciql.IQFunction; import com.iciql.Iciql.IQIgnore; import com.iciql.Iciql.IQIndex; import com.iciql.Iciql.IQIndexes; @@ -74,7 +73,6 @@ public class TableDefinition { String dataType; int length; int scale; - boolean isFunction; boolean isPrimaryKey; boolean isAutoIncrement; boolean trim; @@ -117,10 +115,6 @@ public class TableDefinition { } private Object read(ResultSet rs, int columnIndex) { - if (columnIndex == 0) { - // unmapped column or function field - return null; - } try { return rs.getObject(columnIndex); } catch (SQLException e) { @@ -361,7 +355,6 @@ public class TableDefinition { throw new IciqlException(e, "failed to get default object for {0}", columnName); } - boolean isFunction = f.isAnnotationPresent(IQFunction.class); boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class); if (hasAnnotation) { IQColumn col = f.getAnnotation(IQColumn.class); @@ -393,7 +386,6 @@ public class TableDefinition { fieldDef.scale = scale; fieldDef.trim = trim; fieldDef.nullable = nullable; - fieldDef.isFunction = isFunction; fieldDef.defaultValue = defaultValue; fieldDef.enumType = enumType; fieldDef.dataType = ModelUtils.getDataType(fieldDef); @@ -727,30 +719,35 @@ public class TableDefinition { * 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. + * 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. * - * So iciql maps column names to column index in the result set to properly - * map the results of wildcard queries. + * 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(ResultSet rs) { + int[] mapColumns(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 (def.isFunction) { - // XXX review functions _always_ map after fields? - columnIndex = i + 1; + if (wildcardSelect) { + // select * + // create column index by field name + columnIndex = rs.findColumn(def.columnName); } else { - columnIndex = rs.findColumn(def.columnName); - } + // select alpha, beta, gamma, etc + // explicit select order + columnIndex = i + 1; + } columns[i] = columnIndex; } catch (SQLException s) { throw new IciqlException(s); @@ -761,7 +758,7 @@ public class TableDefinition { void readRow(Object item, ResultSet rs, int[] columns) { for (int i = 0; i < fields.size(); i++) { - FieldDefinition def = fields.get(i); + FieldDefinition def = fields.get(i); int index = columns[i]; Object o = def.read(rs, index); def.setValue(item, o); diff --git a/tests/com/iciql/test/JoinTest.java b/tests/com/iciql/test/JoinTest.java index 3d72ab8..07de098 100644 --- a/tests/com/iciql/test/JoinTest.java +++ b/tests/com/iciql/test/JoinTest.java @@ -39,7 +39,7 @@ public class JoinTest { @Before public void setup() { db = IciqlSuite.openNewDb(); - + db.insertAll(UserId.getList()); db.insertAll(UserNote.getList()); } @@ -64,7 +64,7 @@ public class JoinTest { }); assertEquals(3, notes.size()); } - + @Test public void testJoin() throws Exception { final UserId u = new UserId(); diff --git a/tests/com/iciql/test/SamplesTest.java b/tests/com/iciql/test/SamplesTest.java index 5c7ffc8..5179d79 100644 --- a/tests/com/iciql/test/SamplesTest.java +++ b/tests/com/iciql/test/SamplesTest.java @@ -40,7 +40,6 @@ import org.junit.Test; import com.iciql.Db; import com.iciql.Filter; import com.iciql.Iciql.IQColumn; -import com.iciql.Iciql.IQFunction; import com.iciql.test.models.ComplexObject; import com.iciql.test.models.Customer; import com.iciql.test.models.Order; @@ -409,7 +408,6 @@ public class SamplesTest { */ public static class ProductGroup { public String category; - @IQFunction public Long productCount; public String toString() {