final class HQLHelper extends java.lang.Object implements QueryConstants
Type
objects to match a
substitution parameter array.
This class is the work horse behind RandomAccessQuery
, generating
one or more HQL select statements for each type of navigation/retrieval
request issued by that query. An instance of HQLBundle
is created
lazily for each such command type received from the query. These instances
are cached to speed subsequent lookups within the current context.
Given a RecordBuffer
, an optional where clause, an optional sort
clause, an optional DynamicJoin
, and an indicator whether this
query is a projection query which fetches only the primary key of a
record, this class will:
preprocess
the where clause to account for
any implicit ANSI joins necessary to resolve certain complex uses of
subscripts;
order by
clause for the query;
HQLBundle
instance for each type of
navigation/retrieval request processed by the query;
HQLBundle
instance with the full HQL
statement(s), accessor method(s), and query substitution parameter
indices needed to service a particular navigation/retrieval request.
Modifier and Type | Field and Description |
---|---|
private java.util.List<SortCriterion> |
altCriteria
Components of a parsed order by clause, using dirty database dialect
|
private java.lang.String |
altOrderBy
Order by clause for dirty database use
|
private HQLPreprocessor |
altPreprocessor
HQL where clause preprocessor, using dirty database dialect
|
private HQLBundle[] |
bundleCache
Cache of HQL bundles, indexed by retrieval request type constant
|
private static HQLHelperCache |
cache
Cache of all active helper objects in the current context
|
private java.lang.String |
dmoAlias
Alias used to represent DMO instance in HQL statements
|
private java.lang.String |
dmoEntity
DMO entity name used by query
|
private HQLPreprocessor |
hqlPreprocessor
HQL where clause preprocessor
|
private boolean |
idOnly
Whether query should return primary key ID only, or entire DMO
|
private HQLExpression |
joinHQL
HQL expression for dynamic join via a foreign key relation
|
private static java.util.logging.Logger |
LOG
Logger
|
private boolean |
multiplexed
Are multiplex semantics required?
|
private boolean |
multiplexSort
Does sort clause need to be augmented with multiplex ID?
|
private java.lang.String |
orderBy
Order by clause for query, adjusted for navigation direction
|
private java.util.List<SortCriterion> |
sortCriteria
Components of a parsed order by clause
|
private SortIndex |
sortIndex
Sort index used by query
|
private java.lang.String |
where
Base where clause for associated query
|
CURRENT, FIRST, LAST, NEXT, NONE, PREVIOUS, RETRIEVE_MODES, UNIQUE
Modifier | Constructor and Description |
---|---|
private |
HQLHelper(RecordBuffer buffer,
RecordBuffer[] referencedBuffers,
java.lang.String schema,
java.lang.String dmoAlias,
boolean idOnly,
HQLExpression joinHQL,
java.lang.String where,
java.lang.String sort,
java.lang.Object[] args)
Constructor which sets fundamental data upon which final HQL statements will be based.
|
Modifier and Type | Method and Description |
---|---|
private void |
assembleFromClause(java.lang.StringBuilder buf)
Assemble the
from clause for an HQL query. |
private void |
assembleOrderByClause(java.lang.StringBuilder buf,
java.lang.String orderPhrase)
Assemble the
order by clause for an HQL query. |
private void |
assembleSelectClause(java.lang.StringBuilder buf)
Assemble the
select clause for an HQL query. |
private java.lang.String |
buildSortClause(boolean invert,
java.util.List<SortCriterion> sortCrit)
Compose an HQL compliant order by clause from the sort components
parsed from the base order by clause submitted at construction,
optionally inverting the sort direction of each component.
|
(package private) HQLBundle |
createBundle(int type)
Create a bundle containing a single HQL statement and no getter methods, designed to
retrieve the last, the first or a single, unique record which matches the base
where clause criteria.
|
private void |
fillBundleLists(HQLBundle bundle,
boolean invert,
java.util.List<SortCriterion> sortCrit,
boolean primary)
Fill an HQL bundle's internal HQL statement and getter method lists
with the appropriate statements and methods, respectively.
|
(package private) HQLBundle |
first()
Create a bundle containing a single HQL statement and no getter methods,
designed to retrieve the first record which matches the base where
clause criteria.
|
(package private) HQLPreprocessor |
getHQLPreprocessor()
Return the primary HQL preprocessor used for the underlying query's
where clause.
|
(package private) SortIndex |
getSortIndex()
Return the sort index used by the helper's query.
|
private void |
injectMultiplexSort(boolean invert,
java.lang.StringBuilder buf)
Inject a sort expression into the given buffer using the well-known
multiplex ID field name with the appropriate DMO alias, and a sort
direction.
|
(package private) boolean |
isFindTemplate(java.lang.Object[] queryParams,
java.lang.Class<?> dmoClass)
Test whether the predicate of this query looks up for the template record (a direct access
using rowid/recid of the table using a negative index).
|
(package private) HQLBundle |
last()
Create a bundle containing a single HQL statement and no getter methods,
designed to retrieve the last record which matches the base where
clause criteria.
|
(package private) HQLBundle |
next()
Create a bundle containing the HQL statement(s) and getter method(s)
necessary to retrieve the next record which matches the base where
clause criteria.
|
(package private) static HQLHelper |
obtain(RecordBuffer buffer,
RecordBuffer[] referencedBuffers,
java.lang.Object[] args,
boolean idOnly,
java.lang.String where,
java.lang.String sort,
AbstractJoin join)
Obtain an instance of an
HQLHelper for the given buffer and query criteria. |
private void |
postProcessBundle(HQLBundle bundle,
boolean primary)
Post-process the augmented where clauses stored during the first pass
of HQL bundle creation.
|
private HQLExpression |
preprocessWhere(boolean needWhere,
HQLPreprocessor preproc)
Preprocess the where clause to account for temp table multiplexing and
foreign relation joins.
|
(package private) HQLBundle |
previous()
Create a bundle containing the HQL statement(s) and getter method(s)
necessary to retrieve the previous record which matches the base where
clause criteria.
|
(package private) HQLBundle |
unique()
Create a bundle containing a single HQL statement and no getter methods,
designed to retrieve a single, unique record which matches the base
where clause criteria.
|
private static final java.util.logging.Logger LOG
private static final HQLHelperCache cache
private final java.lang.String where
private final HQLPreprocessor hqlPreprocessor
private final HQLPreprocessor altPreprocessor
private final java.lang.String dmoEntity
private final java.lang.String dmoAlias
private final boolean idOnly
private final boolean multiplexed
private final boolean multiplexSort
private final HQLExpression joinHQL
private final java.util.List<SortCriterion> sortCriteria
private final java.util.List<SortCriterion> altCriteria
private final HQLBundle[] bundleCache
private final SortIndex sortIndex
private java.lang.String orderBy
private java.lang.String altOrderBy
private HQLHelper(RecordBuffer buffer, RecordBuffer[] referencedBuffers, java.lang.String schema, java.lang.String dmoAlias, boolean idOnly, HQLExpression joinHQL, java.lang.String where, java.lang.String sort, java.lang.Object[] args) throws PersistenceException
sort
into its property and directional components,
which are later used to augment the base where clause for single-record retrievals.buffer
- Record buffer against which the current query operates.referencedBuffers
- All buffers referenced by the where clause.schema
- Name of schema associated with query's buffer.dmoAlias
- Alias used to represent DMO instance in HQL statements.idOnly
- If true
, the HQL statements generated by this object will begin with a
select clause which specifies only the record's primary key identifier; if
false
, no select clause will be prepended.joinHQL
- HQL expression snippet for a join via a foreign key relation. May be null
.where
- Base where clause for associated query.sort
- Base order by clause for associated query.args
- Query substitution parameters.PersistenceException
- if there is any error parsing the given sort
clause.static HQLHelper obtain(RecordBuffer buffer, RecordBuffer[] referencedBuffers, java.lang.Object[] args, boolean idOnly, java.lang.String where, java.lang.String sort, AbstractJoin join)
HQLHelper
for the given buffer and query criteria. The
instance is obtained from the cache if present, otherwise, it is created and cached.buffer
- Record buffer against which the current query operates.referencedBuffers
- All buffers referenced by the where clause.args
- Query substitution parameters.idOnly
- If true
, the HQL statements generated by this object will begin with a
select clause which specifies only the record's primary key identifier; if
false
, no select clause will be prepended.where
- Base where clause supplied to the current query.sort
- Base order by clause supplied to the current query.join
- Helper object for a join via a foreign key relation. May be null
.SortIndex getSortIndex()
HQLPreprocessor getHQLPreprocessor()
HQLBundle first()
No augmented HQL statements are produced for the bundle.
The resulting bundle is cached within the current context; subsequent requests return the cached bundle.
HQLBundle last()
No augmented HQL statements are produced for the bundle.
The resulting bundle is cached within the current context; subsequent requests return the cached bundle.
HQLBundle next()
One or more augmented HQL statements are produced for the bundle.
There will be one getter method per statement. The statements are
ordered from most to least specific. Refer to the class description of
HQLBundle
for further implementation details.
The resulting bundle is cached within the current context; subsequent requests return the cached bundle.
HQLBundle previous()
One or more augmented HQL statements are produced for the bundle.
There will be one getter method per statement. The statements are
ordered from most to least specific. Refer to the class description of
HQLBundle
for further implementation details.
The resulting bundle is cached within the current context; subsequent requests return the cached bundle.
HQLBundle unique()
No augmented HQL statements are produced for the bundle. Since only a single record is sought, sorting is irrelevant.
The resulting bundle is cached within the current context; subsequent requests return the cached bundle.
HQLBundle createBundle(int type)
first()
, last()
or unique()
for each
specific case.type
- Target bundle type. Can be QueryConstants.FIRST
, QueryConstants.LAST
or QueryConstants.UNIQUE
.boolean isFindTemplate(java.lang.Object[] queryParams, java.lang.Class<?> dmoClass)
The current implementation only identifies simple form where the predicate is composed from a single equality test between the rowid/recid of the record and a negative value (as P2J convention). This is enough for supporting the standard idiom for loading template records in P4GL.
More complex queries can be defined using AND/OR clauses in the WHERE predicate but they are not supported by P2J. They do not make sense since, if if the template record exists for a table, it is well defined only by it rowid/recid and immutable.
queryParams
- The current parameter list for the query.dmoClass
- The dmo class. We verify whether this is indeed the correct template id for
respective table.true
if the query should load the template record for the buffer.private HQLExpression preprocessWhere(boolean needWhere, HQLPreprocessor preproc)
HQLPreprocessor
, but
before it is augmented to account for the sort criteria in fillBundleLists(com.goldencode.p2j.persist.HQLBundle, boolean, java.util.List<com.goldencode.p2j.persist.SortCriterion>, boolean)
.
If multiplexing is called for, this will prepend a test for the proper multiplex ID before the where clause, if any.
If a foreign relation join is called for, the proper HQL will be
generated to compare a local entity with a foreign one (the foreign
entity is represented by a query substitution character:
?
).
needWhere
- true
if "where" prefix should be added.preproc
- HQL preprocessor to use for the base where clause.null
if no where
clause was generated.private void postProcessBundle(HQLBundle bundle, boolean primary)
bundle
- HQL bundle to be post-processed.primary
- true
to process HQL statement for primary database
dialect; false
to process for dirty database
dialect.private java.lang.String buildSortClause(boolean invert, java.util.List<SortCriterion> sortCrit)
invert
- true
to invert sort direction (i.e., asc-->desc,
desc-->asc); else false
.sortCrit
- List of SortCriterion
objects appropriate to the
database dialect.private void injectMultiplexSort(boolean invert, java.lang.StringBuilder buf)
invert
- If true
the sort direction is descending; if
false
, it is ascending.buf
- String builder into which the expression is injected.private void fillBundleLists(HQLBundle bundle, boolean invert, java.util.List<SortCriterion> sortCrit, boolean primary)
This method represents the first pass in a two step process to create
a set of full, HQL statements (postProcessBundle(com.goldencode.p2j.persist.HQLBundle, boolean)
represents
the second pass). In this pass, only augmented where clauses (and
their associated getter methods) are stored in the bundle. The base
where clause is augmented with a binary match phrase for each sort
component, each of which is AND'd together. The last test in the
augmented where clause is always a range match, whereas the previous
tests are always equality matches. The range match operator is
determined by the sort direction of the sort component, and the value
of the invert
parameter.
For example, given the following query criteria, with
invert
set to false
...
DMO: Customer alias: customer where: customer.number = ? and customer.creditLimit = ? order by: customer.creditLimit asc, customer.name asc
...this method would produce the following list of augmented where clauses...
1) where (customer.number = ? and customer.creditLimit = ?) and (customer.creditLimit = ? and customer.name = ? and customer.id > ?) 2) where (customer.number = ? and customer.creditLimit = ?) and (customer.creditLimit = ? and customer.name > ?) 3) where (customer.number = ? and customer.creditLimit = ?) and (customer.creditLimit > ?)
...and the following list of DMO "getter" methods...
1) Customer.getCreditLimit() 2) Customer.getName() 3) Customer.getId()
Note that the above example assumes neither creditLimit
nor name
(nor the combination of the two) represent a
unique constraint. If this assumption was not valid, the method would
produce the following augmented where clauses instead...
1) where (customer.number = ? and customer.creditLimit = ?) and (customer.creditLimit = ? and customer.name > ?) 2) where (customer.number = ? and customer.creditLimit = ?) and (customer.creditLimit > ?)
...and the following list of DMO "getter" methods...
1) Customer.getCreditLimit() 2) Customer.getName()
If a temp table is involved in the where clause, and/or if a foreign relation join between tables is required, additional preprocessing of the where clause must occur.
bundle
- HQL bundle to be populated.invert
- true
to invert sort direction (i.e., asc-->desc,
desc-->asc) of each sort component when generating the range
match portion of the augmented where clause; else
false
. Inverting the sort direction in this
context means using the opposite range operator in the match
test (>
becomes <
and vice
versa).sortCrit
- List of SortCriterion
objects appropriate to the
database dialect.primary
- true
to add generated HQL statement to the HQL
bundle for use with the primary database; false
to add it for use with the dirty database.preprocessWhere(boolean, com.goldencode.p2j.persist.HQLPreprocessor)
private void assembleSelectClause(java.lang.StringBuilder buf)
select
clause for an HQL query. Uses the
form:
select {dmo}.id
buf
- String buffer into which clause is assembled.private void assembleFromClause(java.lang.StringBuilder buf)
from
clause for an HQL query. Uses the form:
from {DmoImpl} as {dmo} [ join {dmo}.{property} as {dmo}_{property} [...] ]
buf
- String buffer into which clause is assembled.private void assembleOrderByClause(java.lang.StringBuilder buf, java.lang.String orderPhrase)
order by
clause for an HQL query. Uses the
form:
order by {dmo1} {asc/desc} [, {dmo2} {asc/desc} [...]]
buf
- String buffer into which clause is assembled.orderPhrase
- Order by phrase to appended to the buffer if not
null
.