Home
Version Changes/Release NotesVersion Changes/Release Notes
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 the External site, opens in new window FindBugs 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 an External site, opens in new window Iterator or a External site, opens in new window 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
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:
    public int findMin (List ints)
    And then have usage such as:
    SELECT *
    FROM   MyObject
    WHERE  findMin ([first, second, third])
    JoSQL will then pass a list of expression values to the findMin function.

    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
Bug Fixes
Changes for version 1.7 (19/May/2007)
Focus
Version 1.7 focuses on bug fixes.
 
Bug Fixes
Changes for version 1.6 (12/May/2007)
Focus
Version 1.6 focuses on bug fixes.
 
New Features
Changes
  • Code
    Modified org.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
    Modified org.josql.Query.clearResults() to also clear the group by results.
  • Code
    Modified InExpression to handle the LHS being null but RHS is not 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
Changes
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: External site, opens in new window 1449339
Changes for version 1.3 (06/Mar/2006)
Focus
Focuses on bug fixes and the addition of new methods/functions.
 
New Features
Changes
Bug Fixes
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:
    SELECT *
    FROM   MyObject
    WHERE  (SELECT *
            FROM   myList
            WHERE  name LIKE '%thing')
    In this case getMyList would be a method in object MyObject 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 the myList 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 the myList 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:
    SELECT *
    FROM   MyObject
    WHERE  (SELECT *
            FROM   myList
            WHERE  (SELECT *
                    FROM   myMap.values
                    WHERE  name = 'thing'))
    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.

    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:
    SELECT (SELECT value
            FROM   myList
            WHERE  name = 'thing')
    FROM   MyObject
    In this case a new list would be returned for the value from the objects held in the myList Collection (which have a name = 'thing') for each object.

    It is also possible to append an accessor on the sub-query (note the accessor must be from the java.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:
    SELECT (SELECT *
            FROM   ?).size
    FROM   MyObject
    Sub-queries are supported in the following contexts:
    * WHERE clause - IN expressions RHS, such as:
    SELECT * 
         FROM   MyObject
         WHERE name IN ((SELECT [*] nameAttribute
                        FROM    listVals))
    - LIKE expressions LHS, such as:
    SELECT *
         FROM   MyObject
         WHERE  (SELECT [*] nameAttribute
                 FROM   listVals) LIKE '%me%'
    - Equals expressions LHS or RHS, such as:
    SELECT *
    FROM   MyObject
    WHERE  (SELECT [*] nameAttribute
            FROM   listVals) = 'me'
    AND    'you' != (SELECT [*] nameAttribute
                     FROM   listVals)
    - >, <, >=, <= expressions LHS or RHS, such as:
    SELECT *
    FROM   MyObject
    WHERE  (SELECT [*] valueAttribute
            FROM   listVals) >= 10
    AND    255 < (SELECT [*] valueAttribute
                  FROM   listVals)
    - BETWEEN expressions LHS or RHS (either value), such as:
    SELECT *
    FROM   MyObject
    WHERE  10 BETWEEN (SELECT [*] valueAttribute
                       FROM   listVals)
              AND (SELECT [*] otherValueAttribute
                   FROM   listVals)
    or Note: in this case, all values in LHS sub-query must match the BETWEEN clause):
    SELECT *
    FROM   MyObject
    WHERE  (SELECT [*] valueAttribute
            FROM   listVals) BETWEEN 10 AND 20
    * SELECT clause, EXECUTE ON clause, LIMIT clause, GROUP BY clause, ORDER BY clause

  • 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:
    SELECT [*] value,
           [*] name
    FROM   MyObject
    In this case the results will consist of a mix of the "value" and "name" values gained from the 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:
    SELECT [*] (SELECT [*] value
                FROM   ?
                WHERE  value > 10),
           [*] (SELECT [*] someValue
                FROM   ?
                WHERE  value BETWEEN 10 AND 50)
    FROM   java.lang.Object
    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.

    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:
    SELECT *
    FROM   MyObject
    WHERE  30 >= myListOfValues
    would not work as may have been expected.

    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:
    SELECT *
    FROM   MyObject
    WHERE  :myValues >= myListOfValues
    in this case every value in the collection provided by the myValues bind variable must be >= to ALL values in the collection provided by the myListOfValues 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:
    SELECT 'val1',
           'val2'
    FROM   null
    will return a List with a single inner List with the values: "val1" and "val2" at indices 0 and 1 respectively.

    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 support External site, opens in new window JFreeChart, 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 the boolean value will be returned. This allows for expressions such as:
    SELECT *
    FROM   java.io.File
    WHERE  file
    to be evaluated correctly rather than just returning true for a non-null result.
Bug Fixes
  • Fix to InExpression
    Trivial bug fix to org.josql.expressions.InExpression to return false when the IN value is null but the LHS is not null and return true when the IN value is null AND the LHS is null.