Hi,
a quick recap of the discussion we had in the last telecon. This was
sparked by the discussion whether Query.compile() may need database
access, i.e. whether it should fail when called outside transaction
borders.
(TL;DR): See conclusion below.
Querying usually requires the following steps: query compilation
(building an abstract syntax tree, query optimization and query execution.
Query compilation is rather simple, all it needs is knowledge of the
database data model in order to verify compliance with the database schema.
Query optimization is usually more complicated, it can use static
heuristics that are known on each client (table sizes, min/max values of
indexes) but may also use information that is only available in the
database. Information that is only available in the database included,
for example, how many object does an index have in a given range. If one
index has 4 objects and the other has 500, then using the first index
may be the better choice.
JDO supports two separate steps: compilation and execution. The idea (as
I understand) is to reuse queries efficiently by executing the
compilation only once, while allowing to change parameters on compiled
queries.
It seems that some query optimization can be done during the compilation
step (such as removing redundant terms or choosing indexes based on
static information, for example if there is only one index). Others,
like choosing between different index, may depend on the actual
parameters given and on the actual value distribution in a given index,
as noted above.
It appears that query optimization could, and maybe should, be split
into two parts. The first part is based on static information and can be
performed during the compile() step. The second part may require
database access, but may depends on the actual query parameters, so it
will often be impossible to do this in the compilation step where the
parameters may not be known. The second part can in many cases only be
done during query execution.
Conclusion: At least for the optimizations that we considered, the
current API works perfectly fine. Static optimization can be done during
compile(), dynamic optimization can be done during execute(). This mean
that compile() should work fine outside transactions boundaries.
Cheers,
Tilmann