- Version 2.2 - 04/Dec/2010
- Version 2.1 - 28/Feb/2009
- Version 2.0 - 25/Sep/2008
- Version 1.9 - 22/Aug/2007
- Version 1.8 - 30/May/2007
- Version 1.7 - 19/May/2007
- Version 1.6 - 12/May/2007
- Version 1.5 - 06/Mar/2007
- Version 1.4 - 30/Mar/2006
- Version 1.3 - 06/Mar/2006
- Version 1.2 - 26/Jan/2006
- Version 1.1 - 17/Nov/2005

This page details the changes that occurred from version to version and basically constitutes the release notes for JoSQL.
Changes for version 2.2 (04/Dec/2010)
Focus
Version 2.2 focuses on minor new features and bug fixes.New Features
- Automatically wrap a none collection FROM value for a sub-query
If a "FROM" value for a sub-query is not a collection then it is automatically wrapped in a list. This saves having to coerce the value. A side-effect of this change is that the previous error which warned that the FROM value is not a list has been removed. - Marked Miscellaneous function handler as "NotFixedResults"
The MiscellanousFunctions function handler now implements the NotFixedResults interface to prevent caching of values returned from functions where the arguments to the function are invariant. - Allow a custom comparator to be provided per query
A custom comparator can be specified per query object via the setObjectComparator(java.util.Comparator) method. The comparator will be used for grouping, order bys and built in function handlers. - Handle ordering of null values
When using the ORDER BY clause, null values will be pushed to the bottom of the results for ASC ordering and to the top for DESC ordering. - New "get" bean functions
New get(java.lang.String) and get(java.lang.Object,java.lang.String) functions added for accessing old style "bean" properties.
Bug Fixes
- Grammar
Fixed edge case with LIKE expression whereby 'Gary Bentley' LIKE '%y' would return false due to the % not being greedy and finding the final 'y'. - Grammar
Where a function cannot be used in a sub-query. - Code
Where the wrong Query object was being passed to the initialization code for a function used as the FROM for a sub-query. - Code
Ensure that no arg functions can be used. - Code
Changed the SimpleDateFormat instances used for default date conversions to be per instance of ConversionFunctions not static to prevent threading issues. - Code
Modified the getClassLoader() method to have a fallback class loader if there is no context class loader available. - Code
Modified the regexp function wrappers to use the getClassLoader() for class loading the regexp classes. - Code
The RegExpFactory is no longer static and one is created per instance of StringFunctions (this prevents issues with multiple queries and the desire to use different reg exp implementations in each query). It also ensures that the correct class loader is used for each query (useful in environments where the context class loader is different for different queries). - Code
Code modifications as a result of running theFindBugs program.
Changes for version 2.1 (28/Feb/2009)
Focus
Version 2.1 focuses on minor new features.New Features
- Allow a comparator to be set to be used for comparing object values
Bug Fixes
- Grammar
Fix parser grammar error when 2 strings are in the same query.
Changes for version 2.0 (25/Sep/2008)
Focus
Version 2.0 focuses on minor new features.New Features
- Grammar change to allow keywords to be bind variable names
Previously it was not possible to use JoSQL keywords such as select and where as bind variable names. This changes allows all keywords except from to be used. - New static helper method added
Added a static parseAndExec(java.lang.String, java.util.List) method that allows a JoSQL statement to be parsed and executed in a single call. - New variants of Query.execute method added
Add new execute methods to Query to support passing anIterator or a
Collection for processing.
- Grammar change to allow string literals to contain quotes
- Added the save values to the group by save values so that they can be used within the SELECT clause.
- Added new map function variant
Added new function map(java.util.List, org.josql.expressions.Expression, org.josql.expressions.Expression) to allow a map to be created from a list of objects with the expression arguments specifying the key and values for the map. - Modified the build targets
Changed the compile target in build.xml to exclude the contrib directory. To compile those classes use the: compile-contrib target instead.
Bug Fixes
- Corrected resolution of function methods when one or more arguments is null
Modified getExpectedReturnType(org.josql.Query) method to return Object.class when it represents a null value. This ensures that function resolution can occur when a constant null value is passed as an argument to a function. - Correct outputting of method signatures
Modified formatSignature(java.lang.String, java.lang.Class[]) method to take into that the passed in class may be null. - Ensure that setVariable is called for all variables in map
Changed setVariables(java.util.Map) to internally call setVariable(java.lang.String, java.lang.Object) for each item in the map.
Changes for version 1.9 (22/Aug/2007)
Focus
Version 1.9 focuses on new features.New Features
- Added support for an expression list
It is now possible to define a List of expressions in the form:
"[" Expression [ , Expression ] "]"
The list is modelled by org.josql.expressions.ExpressionList. The expression list is also an Expression so nested expression lists are possible. The expression list can be used any place where an expression is valid (basically everywhere).
So it is now possible to define custom functions such as:And then have usage such as:public int findMin (List ints)
JoSQL will then pass a list of expression values to the findMin function.SELECT * FROM MyObject WHERE findMin ([first, second, third])
Note: if your custom function has a signature that uses ExpressionList or Expression then the expression object will be passed instead of a List, and you will have to evaluate each expression yourself.
For users of Java 1.5 this allows you to use a similar mechanism to varargs, thus you would do:// Annoying here because generics don't let you use primitives. // Also, all numbers in JoSQL are represented by Doubles so you need to specify that otherwise a class cast // exception occurs. public double findMin (List<Double> nums) { double min = Double.MAX_VALUE; for (double i : nums) min = (i < min ? i : min); return min; }
- New interface for not fixed function results
A new marker interface: org.josql.functions.NotFixedResults has been added that when implemented on your function handler tells JoSQL that any functions defined by that handler do not return a fixed result, regardless of the arguments to the function.
Changes for version 1.8 (30/May/2007)
Focus
Version 1.8 focuses on bug fixes.Changes
- Code
Modified setVariable(java.lang.String, java.lang.Object) so that a leading : can be used when specifying the name of the bind variable.
Bug Fixes
- Code
Moved evaluation of the LIMIT clause when a GROUP BY clause is used to be after the evaluation of the GROUP BY ORDER and GROUP BY LIMIT clause so that those clauses can make use of the size of the results per group by (which is useful). Note: this arose as a result of changes to 1.6. - Code
Removed unnecessary group by results. This can happen when using a GROUP BY LIMIT clause, GROUP BY results for group bys outside of the limit can remain in the org.josql.QueryResults.getGroupByResults() map. - Code
Modified various functions within the CollectionFunctions and GroupingFunctions function handlers so that the current object :_currobj and :_allobjs special bind variables are setup correctly.
Changes for version 1.7 (19/May/2007)
Focus
Version 1.7 focuses on bug fixes.Bug Fixes
- Code
Modified Query execution to ensure that the SELECT, ORDER BY and LIMIT clauses are evaluated/applied and the EXECUTE ON GROUP_BY_RESULTS clause executed before the GROUP BY ORDER and GROUP BY LIMIT clauses are evaluated. This ensures that save values and the special bind variables are setup correctly and ready for use in those clauses. Note: this bug arose as a result of changes in version 1.6.
Changes for version 1.6 (12/May/2007)
Focus
Version 1.6 focuses on bug fixes.New Features
- Added new class
New Class org.josql.utils.ExpressionEvaluator added, the class allows expressions to be executed against objects more easily than using a query. See the execution evaluator page for more details.
Changes
- Code
Modifiedorg.josql.Query.clearResults()
to be private, does not need to be public or called directly by client code since it will be called at end of execute. - Code
Modified getClassLoader() to use the current thread's classloader instead.
Bug Fixes
- Code
Modifiedorg.josql.Query.clearResults()
to also clear the group by results. - Code
Modified InExpression to handle the LHS beingnull
but RHS isnot null
for a case-insensitive comparison. - Code
Modified query execution so that LIMIT and ORDER BY clauses are applied to group by results when objects, rather than columns are returned.
Changes for version 1.5 (06/Mar/2007)
Focus
Version 1.5 focuses on bug fixes.Changes
- Code
Modified org.josql.Query parse to move some initialization code to init.
Bug Fixes
- Code
Fix to allow a blank string '' to be used as a LIKE expression. - Code
Fix to allow bind variables (named and indexes) to be used in sub-queries. - Code
Modified org.josql.SubQueryExpression to initialize correctly when the FROM is an accessor.
Changes for version 1.4 (30/Mar/2006)
Focus
Version 1.4 focuses on bug fixes.New Features
- Added new function
New function accessor(org.josql.expressions.Expression, org.josql.expressions.Expression) added, allows more flexibility than the Object,String version.
Changes
- Modified function
Modified function accessor(java.lang.Object, java.lang.String). The function now caches the internalGetter
objects created rather than creating them everytime the function is called.
Bug Fixes
- Code
Modified private method:getTotal(List,Expression)
in org.josql.functions.GroupingFunctions to set the current object in the query when iterating over the list. This method is used in various functions to get the total value of a number from the list of numbers passed in. - Grammar
Modified the grammer to allow the use of keywords as identifiers. This corrects bug:1449339
Changes for version 1.3 (06/Mar/2006)
Focus
Focuses on bug fixes and the addition of new methods/functions.New Features
- Added new function
New function: instanceOf(org.josql.expressions.Expression, org.josql.expressions.Expression) added to the miscellaenous function handler. - Added new method
New methodclearException
added to class: org.josql.filters.AbstractJoSQLFilter so that the exception can be cleared after it occurs and the filter re-used. - Added new method
Added new methodgetAccessor
method to org.josql.expressions.BindVariable class.
Changes
- Code
Overridden theequals (Object)
method on the org.josql.expressions.Accessor, org.josql.expressions.BindVariable class. This allows for more accurate comparisons between accessors which is used when determining whether a GROUP BY column is the same as one specified in a GROUP BY ORDER column.
Bug Fixes
- Code
Modified the handling of GROUP BY and GROUP BY ORDER clauses so that it uses the newly implemented Comparable interface for an expression rather than performing atoString
string comparison which led to inaccurate results. - Code
Modified matchLikePattern(java.util.List, java.lang.Object, boolean, boolean) to return the value returned from the match check rather thantrue
. This provides a fix for bug:1437848 LIKE operator broken in 1.2.
- Code
Modified matchLikePattern(java.util.List, java.lang.String) to returnfalse
if the value passed in (String arg) is null. - Code
Modified org.josql.filters.DefaultObjectFilter to set the expected class correctly when an existing query is used in the filter.
Changes for version 1.2 (26/Jan/2006)
Focus
Version 1.2 focuses on providing "sub-queries" for JoSQL, specifically to allow queries to occur on List/Map attributes of Objects. A number of other features to help make sub-queries more useful have also been introduced, including extending the use of the [*] syntax. 3 bug fixes were made and a couple of small functionality changes.New Features
- Sub-Queries
Introduction of "sub-queries" that allows a SELECT statement to be applied to an attribute of an object that is a Collection (note: Maps are handled by calling either: map.keySet or map.values). This allows for "native" queries to be executed on Collection attributes of objects.
Example:In this caseSELECT * FROM MyObject WHERE (SELECT * FROM myList WHERE name LIKE '%thing')
getMyList
would be a method in objectMyObject
that would return a Collection (note: the collection returned is co-erced into a List internally to satisfy JoSQL's execution contract). The type of object held in the Collection returned by themyList
accessor is discovered at execution time (the full query is still parsed when parse(java.lang.String) is called but the initialisation of the sub-query components isn't performed until execute(java.util.List) is called).
As such, parse-like exceptions can occur when the execution occurs. For example, given the query above, at execution time the object type to initialise the query with is performed and thus expects to find an attribute name as part of the object returned by themyList
accessor), if the object does not contain that attribute then an exception is thrown detailing the error.
This structure allows for n-level nesting of sub-queries and means that the full object-graph is available to use, for example the following query is now possible:It is possible to use either functions, bind variables, save values or accessors in the FROM clause of a sub-query. Also, the full EXECUTE ON, GROUP BYS, LIMIT et al are available for use.SELECT * FROM MyObject WHERE (SELECT * FROM myList WHERE (SELECT * FROM myMap.values WHERE name = 'thing'))
Sub-queries MUST be enclosed by brackets (for fairly obvious reasons!) and they can be used in expressions for comparisons and anywhere else expressions can be used.
For example, it is possible to use sub-queries in the SELECT list:In this case a new list would be returned for the value from the objects held in the myList Collection (which have aSELECT (SELECT value FROM myList WHERE name = 'thing') FROM MyObject
name = 'thing'
) for each object.
It is also possible to append an accessor on the sub-query (note the accessor must be from thejava.util.List
class.
Thus if you want to know how many values matched a sub-query (as opposed to the values themselves) you can do:Sub-queries are supported in the following contexts:SELECT (SELECT * FROM ?).size FROM MyObject
* WHERE clause - IN expressions RHS, such as:- LIKE expressions LHS, such as:SELECT * FROM MyObject WHERE name IN ((SELECT [*] nameAttribute FROM listVals))
- Equals expressions LHS or RHS, such as:SELECT * FROM MyObject WHERE (SELECT [*] nameAttribute FROM listVals) LIKE '%me%'
- >, <, >=, <= expressions LHS or RHS, such as:SELECT * FROM MyObject WHERE (SELECT [*] nameAttribute FROM listVals) = 'me' AND 'you' != (SELECT [*] nameAttribute FROM listVals)
- BETWEEN expressions LHS or RHS (either value), such as:SELECT * FROM MyObject WHERE (SELECT [*] valueAttribute FROM listVals) >= 10 AND 255 < (SELECT [*] valueAttribute FROM listVals)
or Note: in this case, all values in LHS sub-query must match the BETWEEN clause):SELECT * FROM MyObject WHERE 10 BETWEEN (SELECT [*] valueAttribute FROM listVals) AND (SELECT [*] otherValueAttribute FROM listVals)
* SELECT clause, EXECUTE ON clause, LIMIT clause, GROUP BY clause, ORDER BY clauseSELECT * FROM MyObject WHERE (SELECT [*] valueAttribute FROM listVals) BETWEEN 10 AND 20
- Extended [*] usage
The [*] / [*, key|value] syntax has been extended to be simpler and more flexible.
It is now possible to apply the [*] indicator to ANY column in the SELECT list.
If the [*] is applied to any single column however it MUST be applied to all columns. Thus:In this case the results will consist of a mix of the "value" and "name" values gained from theSELECT [*] value, [*] name FROM MyObject
MyObject
object.
This is most useful when using sub-queries to merge a number of items together. In fact it is now possible to perform merges of items without performing any operations on objects in the main select at all!
Thus:Note: the [*] indicator is used for both the sub-query column AND the outer query column to ensure that the objects are returned in a single list.SELECT [*] (SELECT [*] value FROM ? WHERE value > 10), [*] (SELECT [*] someValue FROM ? WHERE value BETWEEN 10 AND 50) FROM java.lang.Object
In this case you can then just set the variables to lists and have the values merged into a single list for those that match.
The code would look something like:Query q = new Query (); q.parse (queryString); q.setVariable (1, listOfObjects); q.setVariable (2, otherListOfObjects); List l = new ArrayList (); // This ensures that there is at least one iteration of the statement execution. l.add (new Object ()); QueryResults qr = q.execute (l);
- Comparing Collections against values and other Collections
Up to version 1.1 it was not possible to compare (for instance) a single value against all the items in List since because of the type incompatibilities the values would have been converted to strings and then
compared.
Thus:would not work as may have been expected.SELECT * FROM MyObject WHERE 30 >= myListOfValues
It is now possible for that comparison to be made and the correct boolean result returned.
Comparing collections against collections, it is now possible to do:in this case every value in the collection provided by theSELECT * FROM MyObject WHERE :myValues >= myListOfValues
myValues
bind variable must be >= to ALL values in the collection provided by themyListOfValues
accessor.
Note: to compare Map keys/values against a value it is recommended that you use either a sub-query or use Map.keySet (for keys, obviously!) or Map.values. - Anonymous Queries
It is now possible to perform "anonymous" queries, for example to join values together or to perform EXECUTE ON functions.
To perform an anonymous query just use "null" as the class for the query.
Thus:will return a List with a single inner List with the values: "val1" and "val2" at indices 0 and 1 respectively.SELECT 'val1', 'val2' FROM null
This is similar to the "dual table" used by Oracle. The number of times the statement is "evaluated" is dependent upon the number of objects passed into the Query.execute(List) method. If "null" is passed then a List with a single object is created internally and used so that the statement will be evaluated once.
Note: this is useful for "merging" lists/maps together. i.e.SELECT [*] (SELECT [*] value FROM :vals), [*] (SELECT [*] value FROM :vals2) FROM null
Changes for version 1.1 (17/Nov/2005)
New Features
- Add new package
Added new package: org.josql.incubator where some experimental classes have been placed.
FilteredArrayList - allows a JoSQL WHERE clause to be used to ensure that the array list only contains elements that match the WHERE clause, i.e. where the WHERE clause evaluates to "true". Also allows the list to be resorted according to a ORDER BY clause, if present, otherwise the natural ordering is used. FilteredArrayList is stable.
ObjectIndex - is experimental at creating an object index for any object type using accessors, shouldn't really be used but is useful as a reference. Not stable.
Note: classes in the "incubator" MAY be moved at any time to another package, use with care! - New class JoSQLJSPQueryTag
Added new class: org.josql.contrib.JoSQLJSPQueryTag added to allow a JoSQL statement to be used in a JSP. See javadoc for usage and details.
The JoSQL-1.1.jar file contains a
METAINF/taglib.tld
file which provides the information about the tag library. See file:
data/josql-taglib.tld
in the distribution for more details. You'll still need to include the 3rd-party-jars/gentlyWEB-utils-1.1.jar file in the WEB-INF/lib directory. - Added new function
Added new function get to allow a value to be retrieved from a Map. - Added new class JoSQLAntFileSelector
Added new org.josql.contrib.JoSQLAntFileSelector to allow a JoSQL WHERE clause to be used to select files in filesets etc. See the JavaDoc for the class for full details. - Added new classes to support JFreeChart
Added new classes to supportJFreeChart, namely:
See the javadocs for usage.
Changes
- Enhanced isTrue function
Enhanced isTrue(java.lang.Object,org.josql.Query) such that if the function returns an instance of "java.lang.Boolean" then theboolean
value will be returned. This allows for expressions such as:to be evaluated correctly rather than just returningSELECT * FROM java.io.File WHERE file
true
for a non-null result.
Bug Fixes
- Fix to InExpression
Trivial bug fix to org.josql.expressions.InExpression to returnfalse
when the IN value isnull
but the LHS is notnull
and returntrue
when the IN value isnull
AND the LHS isnull
.
© Gary Bentley 2004-2007. All Rights Reserved.