Expressions (modelled using the Expression object) are the basic "unit" within JoSQL. As such expressions can be interchanged and used just about everywhere (this means that even binary expressions such as x = y can be used in the SELECT part of the statement).

There are various types of JoSQL expression (most of which map to their standard SQL equivalent):
  • Binary expression - this type of expression represents the result of comparing a LHS with a RHS. For example 1 = 1. Just about all expressions that can be used in a WHERE clause are binary expressions.
  • Aliased expression - this type of expression represents an expression that has an alias associated with it.
  • Value expressions - this type of expression represents a value, such as a constant, a bind variable, the result of executing a function or even a sub-query.
All expressions sub-class Expression, because of this all expressions have the following properties (enforced via abstract methods. Note: it was felt that because of the fixed nature of JoSQL having an Expression interface that is implemented by an AbstractExpression abstract class was overkill and not needed, hindsight has shown this to be a suitable choice):
Expressions can be evaluated to a boolean value
That is each expression must indicate whether it is true or false (determined by calling: isTrue(java.lang.Object, org.josql.Query)). This may seem strange (especially for constant expressions) but it does allow for more flexibility and since consistent rules are used in the implementation this property can be exploited.

For instance, consider the following statement:
SELECT ifThenElse (:value,
FROM   MyObject
The value of the value bind variable passed in will determine whether firstValue or secondValue is evaluated and returned. Since the relevant expression object takes care of class issues the actually object provided for the bind variable does not matter, if the object is a number then any value greater than 0 will cause a true value to returned and firstValue will be called and the value returned; if the object is null then false will be returned and secondValue is called and the value returned and so on. This property of expressions can also be used in the WHERE clause, for example:
FROM   MyObject
WHERE  firstValue
Again, depending upon the value that the firstValue method returns will determine whether the WHERE clause evaluates to true and the relevant object returned in the results.
Expressions must return a value
Each expression in JoSQL must return a value, even if the value is null. In this way it means that comparisons between expressions can occur and the result of evaluating an expression is suitable for returning in query execution results.

The value is gained by calling: getValue(java.lang.Object, org.josql.Query).

For example:
SELECT // Will use a value expression.
       'hello world',
       // Will use a sub-select expression.
       (SELECT *
        FROM   innerList),
       // Will use a boolean expression which is formed
       // from an accessor expression on the LHS 
       // and a bind variable expression on the RHS.
       myAccessor = :myvalue,
       // Will use a function expression and a bind variable
       // expression as the argument.
       transform (:myvalue)
FROM   MyObject
Fixed Results
If JoSQL detects that a particular expression will always return the same result then the expression will only be evaluated once. The result of evaluating the expression will be remembered and that result returned for all subsequent evaluations of the expression. In this case the expression is said to have a fixed result.

This behavior can lead to unexpected results when using functions so care must be taken. That is that if a function's arguments all have fixed results then execution of the function will have a fixed result (regardless of whether the function returns different values).

JoSQL determines that an expression should have a fixed result if all arguments for the expression have a fixed result.
Expressions that always have a fixed result
The following expressions will automatically have fixed results, that is that method hasFixedResult(org.josql.Query) returns true (they are considered to be constants):
Expressions that never have a fixed result
The following expressions will always return false from hasFixedResult(org.josql.Query):
Expressions that may have a fixed result
The following expressions return a value dependent upon whether their arguments ALL return true from hasFixedResult(org.josql.Query):