public class CompoundQuery extends DynamicQuery implements QueryConstants, RecordChangeListener
addComponent method variants. This query type can
combine both PreselectQuerys and RandomAccessQuerys as its
components. However, preselected tables must always be to the left of
(i.e., outward from) non-preselected tables in the query. That is, a
PreselectQuery object can never be added, once a
RandomAccessQuery object has been added to a compound query.
Inner and left outer joins are supported. However, inner joins must
always occur to the left (i.e., outward from) outer joins. If, at the
time a component query specified as an inner join is added, there are
previously added outer-join components which in their where
clause use one or more buffers as the inner-join component's
where clause, these outer-join components will automatically
be converted to an inner join, to satisfy the condition that all inner
joins are on the left of the outer-join components.
This query retrieves result records in two modes: iterating and random
access. Iterating mode is active when using the iterate() method
to advance the query to the next, composite row of records in the result
set. Random access mode is active when using any of the other retrieval
methods (first, last, next,
previous, current). The difference between the
modes is that iterating mode always terminates with a
QueryOffEndException when no further record retrieval is
possible; random access mode does not. Random access mode thus allows
client code to advance off the end of the result set and continue
processing.
CompoundQuery abstracts the use of multiple query
implementations to achieve a dynamic, multi-table query. It delegates the
record retrieval work to the underlying queries, but manages the overall
navigation of the results. Delegate queries must implement the Joinable interface. Each "row" in the "result set" is a logical
construct, the virtual composite of multiple record buffers. Advancing to
a new row (be it forwards, backwards, first, last) means advancing the
most specific query possible to the next matching record in its
predetermined progression. Once the most specific query can no longer
advance, the next most specific query is advanced, the most specific query
is reset to its starting state, and we try to find a joining match for the
most specific query again, given that its outer query has a new value with
which to join. This continues until the most specific possible query has
advanced, or we have moved to our least specific query component, and no
further match is possible. At this point, the query is "off-end". For
iterating mode, this is the end of query execution and an end condition is
raised. In random access mode, further navigation is possible.
Substitution Parameters
Query substitution parameters require different modes of resolution,
depending upon the type of parameter and the nature of the query. A query
may be set at construction to resolve all of its parameters once, up front
or iteratively, each time an iterative loop construct is entered. The
former corresponds with Progress' OPEN QUERY style queries; the latter
corresponds with all other iterative record retrieval constructs in
Progress (e.g., FOR EACH, DO PRESELECT, REPEAT PRESELECT, REPEAT FOR).
The number of times a parameter is resolved and the timing of such resolution becomes important if an iterative record retrieval construct modifies the values of such parameters during record retrieval. This may occur, for example, if the body of an outer FOR loop modifies the value of a variable used in the where clause of an inner FOR loop. While less of an issue for preselect type queries, these can still be affected if the where clause of a nested query component invokes a client-side function, which may in turn modify state on which the query or related logic depends.
The following conversion rules apply:
------------------------------------------------------------------------
Progress Construct CompoundQuery Modes
resolveOnce preselect
------------------------------------------------------------------------
OPEN QUERY FOR true (forced to false) false
OPEN QUERY PRESELECT true (ignored?) true
FOR {EACH | FIRST | LAST} false false
DO PRESELECT false true
REPEAT PRESELECT false true
------------------------------------------------------------------------
| Modifier and Type | Class and Description |
|---|---|
private class |
CompoundQuery.Optimizer
Inner class which attempts to optimize the enclosing, compound query's individual query
components into server-side joins.
|
private class |
CompoundQuery.SnapshotParameterFilter
Filter that handles parameters passed to the component's subquery which handles the target
buffer.
|
P2JQuery.Parameter, P2JQuery.ParamResolver, P2JQuery.QueryEventListener, P2JQuery.QueryOpenedListener| Modifier and Type | Field and Description |
|---|---|
private int |
activeIndex
Index of component query currently being iterated
|
private java.util.Map<RecordBuffer,java.lang.Integer> |
buffersMap
Map of all buffers participating in this query to their 0-based index positions
|
private Finalizable |
cleaner
Cleaner executed when this query's block is exit.
|
private java.util.ArrayList<CompoundComponent> |
components
Query components currently in use by the compound query
|
private int[] |
counters
Current index position in each component query loop
|
protected boolean |
currentRowDeleted
Determines if the current row was deleted by DELETE-RESULT-LIST-ENTRY.
|
private static boolean |
deferOptimization
Defer optimization until after first composite row has been retrieved (experimental)
|
private boolean |
forceFullResults
Flag indicating the entire result set will be retrieved (useful for FILL operations).
|
protected boolean |
foundFirst
Determines if we have fetched a result row.
|
private static CentralLogger |
log
Logger
|
private java.util.ArrayList<CompoundComponent> |
originalComponents
Query components originally added to the compound query
|
private boolean |
postponeAccumulation
Postpone accumulation on retrieve.
|
private boolean |
preselect
Force preselection of all results?
|
private boolean |
preselected
Have results been preselected?
|
private boolean |
regCleaner
Has query been registered for resource cleanup?
|
private boolean |
resolveOnce
Resolve arguments once, up front, or on every loop cycle?
|
private int |
tableCount
Total number of tables involved in this compound query
|
protected boolean |
unregisterOnCleanup
Determines if this will be unregistered from ChangeBroker on cleanup.
|
private boolean[] |
useSnapshot
Specifies if snapshot values (values at the time when the record was loaded) should be used
as FQL sub-query parameters for specific component instead of the actual values.
|
private boolean |
whereTranslated
Flag indicated if the WHERE clause has been translated.
|
cursorclosed, dynamicPredicate, errorHelper, excluded, included, indexedReposition, inverseSorting, lenientOffEnd, outer, parameterFilterCURRENT, FIRST, ITERATE, LAST, NEXT, NONE, PREVIOUS, RETRIEVE_MODES, UNIQUE| Constructor and Description |
|---|
CompoundQuery()
Default constructor.
|
| Modifier and Type | Method and Description |
|---|---|
void |
addComponent(Joinable query)
Add a joinable query to the compound query.
|
void |
addComponent(Joinable query,
int iteration)
Add a joinable query to the compound query, and specify the nature of
the iteration which will be performed (first, last, next, etc.) on that
component, when the compound query is iterated.
|
void |
addComponent(Joinable query,
int iteration,
boolean outer)
Add a joinable query to the compound query, and specify the nature of
the iteration which will be performed (first, last, next, etc.) on that
component, when the compound query is iterated.
|
(package private) void |
addCompoundComponent(CompoundComponent component)
Add a component query to this compound query and adjust the table count accordingly.
|
boolean |
addDynamicFilter(FieldReference fr,
BaseDataType val,
java.lang.String format)
Adds a new constraint term to the where predicate of this query, effectively filtering out
any rows whose referenced field does not match the requested value.
|
P2JQuery |
addExternalBuffers(DataModelObject... dmos)
Add one or more buffers to the list of those which this query references externally.
|
protected void |
afterReposition(boolean permitFetch,
boolean error)
This method is an extension to the AbstractQuery normal behavior.
|
protected boolean |
canOptimize()
Indicate whether this object can be optimized.
|
void |
cleanup()
Clean up resources associated with this query when its scope ends.
|
void |
clearDynamicFilters()
Clears any dynamically filters added at runtime.
|
void |
clearResults()
Clear the current results from the query, so the same query instance can be executed again, without
having to
re-open it. |
void |
close()
Explicitly close the prepared query.
|
void |
close(boolean inResource)
Explicitly close the prepared query.
|
private java.lang.Object[] |
collectRowData(int navigation)
Assemble an array of primary key IDs or DMOs for the current records in
the buffers underlying this query, from left-most to right-most (in the
sense of how the query joins the associated tables).
|
logical |
createResultListEntry()
Creates an entry in the result list for the current row.
|
boolean |
current()
Retrieve the current virtual, composite row of results for the compound
query.
|
boolean |
current(LockType lockType)
Retrieve the current virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
logical |
deleteResultListEntry(boolean allowBetweenRows)
Deletes the current row of a query's result list.
|
boolean |
first()
Retrieve the first virtual, composite row of results for the compound
query.
|
boolean |
first(boolean iterating)
Retrieve the first virtual, composite row of results for the compound
query.
|
boolean |
first(boolean iterating,
LockType lockType)
Retrieve the first virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
boolean |
first(LockType lockType)
Retrieve the first virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
protected java.lang.Object |
getBreakValue()
Return an object which represents a property value which defines the
end of a sort band.
|
double |
getCombinedExecutionTime()
Function that sums and returns the execution time of the components, denoting the total time of
execution of this query.
|
java.lang.String |
getCombinedFqls()
Function that combines the FQL of the components from this query.
|
private java.util.ArrayList<CompoundComponent> |
getComponents()
Retrieve the list of query components.
|
OffEnd |
getOffEnd()
Report the off-end status of this query, which is essentially the
off-end status of its outermost component query.
|
java.util.ArrayList<QueryOffEndListener> |
getOffEndListeners()
Get all the off-end listeners associated with this query.
|
(package private) java.util.ArrayList<CompoundComponent> |
getOriginalComponents()
Retrieve the list of original query components (unoptimized).
|
private RecordBuffer[] |
getRecordBuffersInternal()
Get an array of all record buffers managed by this query.
|
int |
getTableCount()
Get the number of tables joined by this query.
|
void |
hintFullResults()
Mark the query to retrieve the entire result set (useful for FILL operations).
|
character |
indexInformation(NumberType n)
Conversion of INDEX-INFORMATION attribute (KW_IDX_INFO).
|
CompoundQuery |
initialize(boolean resolveOnce,
boolean preselect)
Initialization logic.
|
CompoundQuery |
initialize2f()
Initialization logic.
|
private void |
initializeComponentQuery(Joinable query)
Initialize state of a component query.
|
protected void |
initReferenceRowSupport(boolean globalScope)
Init structures required to use reference row: create the map of all buffers, register
parameter filters for sub-queries and register this query as a record change listener.
|
protected boolean |
isPresorted()
Determines if the query is presorted, i.e.
|
boolean |
iterate()
Advance the compound query, triggering one or more of the underlying
queries to retrieve a new record.
|
boolean |
last()
Retrieve the last virtual, composite row of results for the compound
query.
|
boolean |
last(boolean iterating)
Retrieve the last virtual, composite row of results for the compound
query.
|
boolean |
last(boolean iterating,
LockType lockType)
Retrieve the last virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
boolean |
last(LockType lockType)
Retrieve the last virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
protected boolean |
loadByValues(java.lang.Object[] data,
LockType lockType,
boolean iterating)
Load a virtual, composite record by loading each record buffer managed
by this query with a DMO, given its primary key ID in the specified
ids array. |
protected void |
loadRowAtCursor()
Synchronize the query with the cursor by causing the query to load the
current row's results (if any) into its backing buffer(s).
|
private void |
maybeOptimize()
Method which attempts to optimize this object's query components into one or more
server-side joins.
|
boolean |
next()
Retrieve the next virtual, composite row of results for the compound
query.
|
boolean |
next(boolean iterating)
Retrieve the next virtual, composite row of results for the compound
query.
|
boolean |
next(boolean iterating,
LockType lockType)
Retrieve the next virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
boolean |
next(LockType lockType)
Retrieve the next virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
void |
notifyRepositionListeners(boolean closed,
boolean error,
int targetRepositionRow)
Notify all registered listeners that query is repositioned or closed.
|
void |
open()
Open the query once all query components have been added.
|
java.lang.Object[] |
peekFirst()
Fetch the array of primary key IDs associated with the first result in
this query's result list.
|
java.lang.Object[] |
peekLast()
Fetch the array of primary key IDs associated with the last result in
this query's result list.
|
java.lang.Object[] |
peekNext()
Fetch the array of primary key IDs associated with the next result in this query's result
list.
|
java.lang.Object[] |
peekPrevious()
Fetch the array of primary key IDs associated with the previous result
in this query's result list.
|
protected void |
postponeAccumulation()
Switch on postponed accumulation on next retrieve.
|
protected void |
preselectResults()
Preselect all results by creating a common cursor and
SimpleResults for each
component. |
protected void |
presort()
If the query is a presort query, then presort the results stored in the cursor.
|
boolean |
previous()
Retrieve the previous virtual, composite row of results for the compound
query.
|
boolean |
previous(boolean iterating)
Retrieve the previous virtual, composite row of results for the compound
query.
|
boolean |
previous(boolean iterating,
LockType lockType)
Retrieve the previous virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
boolean |
previous(LockType lockType)
Retrieve the previous virtual, composite row of results for the compound
query, overriding the lock type to apply to each underlying query.
|
private java.lang.Object[] |
processComponent(int navigation,
CompoundComponent component,
int count,
LockType lockType,
boolean peek)
Advance a single query component, according to the overall query
navigation direction, and that component's natural iteration type.
|
java.util.Iterator<RecordBuffer> |
recordBuffers()
Report the record buffers for whose changes this object is interested
in listening.
|
protected void |
registerCleaner()
Register a
Finalizable with the transaction manager for
resource cleanup when this query's scope ends. |
private boolean |
registerRecordChangeListeners()
Register the query within each component as a record change listener.
|
protected void |
releaseAllBuffers()
Release all backing buffers of for all components.
|
void |
releaseBuffers()
Releases buffers from all components.
|
protected void |
restoreAccumulation()
Switch on postponed accumulation on next retrieve.
|
protected java.lang.Object[] |
retrieve(int navigation,
LockType lockType,
boolean iterating)
Retrieve a virtual, composite row of results for the compound query.
|
protected java.lang.Object[] |
retrieve(int navigation,
LockType lockType,
boolean iterating,
boolean peek)
Retrieve a virtual, composite row of results for the compound query.
|
private java.lang.Object[] |
retrieveImpl(int navigation,
LockType lockType,
boolean iterating,
boolean peek)
Retrieve a virtual, composite row of results for the compound query.
|
void |
setBrowsed(boolean browsed)
Indicate to this query that whether it is associated with a browse widget or not.
|
private void |
setComponentsBrowsed()
Iterate the component queries of this object and set their browsed flags to match that of
this object.
|
void |
setDataRelation(DataRelation relation)
Set the recursive DATA-RELATION the query is to FILL for.
|
void |
setScrolling()
Create a cursor for this query and ensure that any component queries are scrollable, whether they
already have been added, or will be added in the future.
|
void |
setSkipDeletedRecord(logical on)
Setter for SKIP-DELETED-RECORD query attribute.
|
void |
setStandalone(boolean standalone)
Change the standalone nature of this query.
|
void |
stateChanged(RecordChangeEvent event)
Respond to a record change event.
|
private void |
translateWhere()
Translate the WHERE clause for all
components. |
_isOffEnd, backward, backward, currentRow, currentRowImpl, forward, forward, incrementMoves, isNativelyPreselect, isPreselect, isScrolling, reposition, reposition, repositionByID, repositionByID, repositionByID, reset, resetScrolling, size, verifyScrolling_getNext, _isSkipDeletedRecord, accumulate, addAccumulator, addAccumulator, addBuffer, addBuffer, addQueryEventListener, addRepositionListener, afterReposition, afterReposition, bufferHandle, bufferHandle, bufferHandle, bufferHandle, bufferHandle, buffersMatch, changeForwardOnly, changeForwardOnly, deleteResultListEntry, exclude, forwardOnly, getCache, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getDataRelation, getDefaultLock, getErrorHelper, getExternalBuffers, getExternalBuffersDefs, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getLast, getLast, getLast, getLast, getLast, getLast, getLast, getLast, getNext, getNext, getNext, getNext, getNext, getNext, getNext, getNumResults, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getReferencedBuffers, hasAccumulators, hasAny, hasAny, hasAny, hasAny, hasOne, hasOne, hasOne, hasOne, include, indexInformation, indexInformation, isBrowsed, isDynamicPredicate, isErrorIfNull, isFatalError, isFetchOnReposition, isFillingBrowseRows, isIndexedReposition, isIterating, isLastOfBreakGroup, isLenientOffEnd, isNewBreakGroup, isOffEnd, isOmitAlias, isOpen, isPresort, isRepositionNotificationActive, isSkipDeletedRecord, isStandalone, notifyQueryCloseListeners, notifyQueryOpenListeners, numBuffers, numResults, numResults, prepare, prepare, prepareFetch, prepareString, preprocessSubstitutionArguments, queryBackward, queryBackward, queryClose, queryForward, queryForward, queryOpen, queryReposition, queryReposition, queryRepositionByID, removeRepositionListener, setBuffers, setBuffers, setCache, setCache, setDynamicPredicate, setErrorIfNull, setFatalError, setFetchOnReposition, setFillingBrowseRows, setIndexedReposition, setIterating, setLenientOffEnd, setOmitAlias, setOuter, setParameterFilter, setPresort, silentCurrent, silentCurrent, silentFirst, silentFirst, silentLast, silentLast, silentNext, silentNext, silentPrevious, silentPrevious, silentUnique, silentUnique, translateSort, translateSort, translateWhereclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait_getNext, addAccumulator, addAccumulator, addQueryEventListener, addRepositionListener, changeForwardOnly, changeForwardOnly, deleteResultListEntry, exclude, forwardOnly, getBasicLogging, getCache, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getCurrent, getDataRelation, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getFirst, getJoin, getLast, getLast, getLast, getLast, getLast, getLast, getLast, getLast, getNext, getNext, getNext, getNext, getNext, getNext, getNext, getNext, getNumResults, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getPrevious, getRecordBuffers, hasAny, hasAny, hasAny, hasAny, hasOne, hasOne, hasOne, hasOne, include, indexInformation, indexInformation, isBrowsed, isDynamicPredicate, isFetchOnReposition, isFillingBrowseRows, isFindByRowid, isFirstOfGroup, isFirstOfGroup, isIndexedReposition, isIterating, isLastOfGroup, isLastOfGroup, isOffEnd, isPresort, isSkipDeletedRecord, isStandalone, notifyQueryCloseListeners, notifyQueryOpenListeners, prepare, prepare, prepareString, queryBackward, queryBackward, queryClose, queryForward, queryForward, queryOpen, queryReposition, queryReposition, queryRepositionByID, queryRepositionByID, removeRepositionListener, resetQuery, setBasicLogging, setBasicLogging, setCache, setCache, setDynamicPredicate, setErrorIfNull, setFetchOnReposition, setFillingBrowseRows, setIndexedReposition, setIterating, setLenientOffEnd, setParameterFilter, setPresort, unique, uniqueaddBuffer, addBuffer, addBuffer, addBuffer, bufferHandle, bufferHandle, bufferHandle, bufferHandle, bufferHandle, numBuffers, setBuffers, setBuffers, setBuffersprivate static final CentralLogger log
private static final boolean deferOptimization
protected boolean currentRowDeleted
protected boolean foundFirst
protected boolean unregisterOnCleanup
private boolean preselect
private final java.util.ArrayList<CompoundComponent> originalComponents
private boolean resolveOnce
private java.util.ArrayList<CompoundComponent> components
private boolean preselected
private int[] counters
private boolean[] useSnapshot
components.size() - 1 and excludes the first (outermost) component
because it cannot have FQL which includes fields of an outer component.private int activeIndex
private int tableCount
private boolean postponeAccumulation
private java.util.Map<RecordBuffer,java.lang.Integer> buffersMap
private boolean regCleaner
private boolean forceFullResults
private final Finalizable cleaner
private boolean whereTranslated
public CompoundQuery()
initialize() is
called.public void clearResults()
re-open it.clearResults in interface P2JQueryclearResults in class DynamicQuerypublic CompoundQuery initialize(boolean resolveOnce, boolean preselect)
This code is intentionally separated from the constructor. The purpose of this separation is to allow construction to occur in the prior scope while initialization can still occur within a method or lambda that is inside the next block's scope.
preselect - true to force preselection of all results; false otherwise.public CompoundQuery initialize2f()
This code is intentionally separated from the constructor. The purpose of this separation is to allow construction to occur in the prior scope while initialization can still occur within a method or lambda that is inside the next block's scope.
public void setScrolling()
setScrolling in interface P2JQuerysetScrolling in class DynamicQuerypublic int getTableCount()
getTableCount in interface P2JQuerypublic java.util.ArrayList<QueryOffEndListener> getOffEndListeners()
getOffEndListeners in interface P2JQuerypublic void hintFullResults()
hintFullResults in interface P2JQuerypublic void addComponent(Joinable query)
NEXT iteration type.query - Query which will perform the fundamental work for this
component when the compound query is iterated.java.lang.IllegalStateException - if this method is invoked during an iteration cycle.iterate()public void addComponent(Joinable query, int iteration)
query - Query which will perform the fundamental work for this
component when the compound query is iterated.iteration - A constant indicating the type of work
to be performed upon an iteration of the compound query. This
parameter determines whether the underlying query will be asked
to perform a first, last, next, previous, or unique record
retrieval.java.lang.IllegalStateException - if this method is invoked during an iteration cycle.iterate()public void addComponent(Joinable query, int iteration, boolean outer)
outer.query - Query which will perform the fundamental work for this
component when the compound query is iterated.iteration - A constant indicating the type of work
to be performed upon an iteration of the compound query. This
parameter determines whether the underlying query will be asked
to perform a first, last, next, previous, or unique record
retrieval.outer - true if this component should be joined to the
previously added component via a left outer join;
false if an inner join is required.
If, at the time a component query specified as an inner join is added, there are
previously added outer-join components which in their where clause
use one or more buffers as the inner-join component's where clause,
these outer-join components will automatically be converted to an inner join,
to satisfy the condition that all inner joins are on the left of the outer-join
components.
java.lang.IllegalStateException - if this method is invoked during an iteration cycle.iterate()public P2JQuery addExternalBuffers(DataModelObject... dmos)
This method overrides the default implementation to set external buffers on the most recently added component of this compound query. It therefore must be called immediately after the target component is added and before the query is opened, optimized, or executed.
addExternalBuffers in interface P2JQueryaddExternalBuffers in class AbstractQuerydmos - One or more external buffers to add to the most recently added query component.java.lang.IllegalStateException - if called before a component has been added or after query has been optimized.public void setSkipDeletedRecord(logical on)
setSkipDeletedRecord in interface P2JQuerysetSkipDeletedRecord in class AbstractQueryon - New value for the attribute.public void setBrowsed(boolean browsed)
setBrowsed in interface P2JQuerysetBrowsed in class AbstractQuerybrowsed - true to indicate the query has an associated browse widget, else false.public void open()
open in interface P2JQueryopen in class DynamicQuerypublic boolean iterate()
QueryOffEndException - if no more records can be retrieved by the underlying queries.ErrorConditionException - if an underlying query triggers an error.public boolean first()
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
first in interface P2JQuerytrue if query could retrive the first record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean first(boolean iterating)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.true if query could retrive the first record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean first(LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
first in interface P2JQuerylockType - Lock type which should override that of any underlying query.true if query could retrive the first record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean first(boolean iterating,
LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.lockType - Lock type which should override that of any underlying query.true if query could retrive the first record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean last()
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
last in interface P2JQuerytrue if query could retrive the last record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean last(boolean iterating)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.true if query could retrive the last record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean last(LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
last in interface P2JQuerylockType - Lock type which should override that of any underlying query.true if query could retrive the last record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean last(boolean iterating,
LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.lockType - Lock type which should override that of any underlying query.true if query could retrive the last record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean next()
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
next in interface P2JQuerytrue if query could retrive the next record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean next(boolean iterating)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.true if query could retrive the next record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean next(LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
next in interface P2JQuerylockType - Lock type which should override that of any underlying query.true if query could retrive the next record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean next(boolean iterating,
LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.lockType - Lock type which should override that of any underlying query.true if query could retrive the next record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean previous()
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
previous in interface P2JQuerytrue if query could retrive the previous record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean previous(boolean iterating)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.true if query could retrive the previous record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean previous(LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
previous in interface P2JQuerylockType - Lock type which should override that of any underlying query.true if query could retrive the previous record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean previous(boolean iterating,
LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.lockType - Lock type which should override that of any underlying query.true if query could retrive the previous record succefully;
false if unsuccessful and lenientOffEnd is set on true.QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an underlying query triggers an error.public boolean current()
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
current in interface P2JQuerytrue if query could retrive the current record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public boolean current(LockType lockType)
This is a combination of records retrieved by each component query. If the compound query involves outer joins, some of the underlying buffers may be empty when this method returns.
current in interface P2JQuerylockType - Lock type which should override that of any underlying query.true if query could retrive the current record succefully;
false if unsuccessful and lenientOffEnd is set on true.ErrorConditionException - if an underlying query triggers an error.public java.lang.Object[] peekFirst()
This implementation actually updates the underlying record buffer(s).
null if there is no such result.public java.lang.Object[] peekLast()
This implementation actually updates the underlying record buffer(s).
null if there is no such result.public java.lang.Object[] peekNext()
This implementation actually updates the underlying record buffer(s). The difference between
this function and next() function is that this function calls
Scrollable.peekNext() on sub-queries in order to get the next record from underlying
results, while next() returns the next record after the current row.
peekNext in interface Scrollablenull if there is no such result.public java.lang.Object[] peekPrevious()
This implementation actually updates the underlying record buffer(s). The difference between
this function and previous() function is that this function calls
Scrollable.peekPrevious() on sub-queries in order to get the next record from
underlying results, while previous() returns the next record after the current row.
peekPrevious in interface Scrollablenull if there is no such result.public void notifyRepositionListeners(boolean closed,
boolean error,
int targetRepositionRow)
notifyRepositionListeners in interface P2JQuerynotifyRepositionListeners in class AbstractQueryclosed - A true value will inform all listeners that the
query was explicitly closed.error - true if an error happened during reposition.targetRepositionRow - Row used as the target for reposition. If it was deleted, reposition with fetching
may end up on a different row.public java.util.Iterator<RecordBuffer> recordBuffers()
ChangeBroker to receive notifications of any change to DMOs whose
interface types match those returned by the RecordBuffer.getDMOInterface() methods of the returned buffers.recordBuffers in interface RecordChangeListenerpublic void stateChanged(RecordChangeEvent event) throws PersistenceException
stateChanged in interface RecordChangeListenerevent - Event which describes the DMO state change.PersistenceException - if any error occurs while processing the state change event.public void setStandalone(boolean standalone)
setStandalone in interface P2JQuerysetStandalone in class AbstractQuerystandalone - true to set query as standalone;
false to set query as contained.public void close()
close in interface P2JQueryclose in class AbstractQuerypublic void close(boolean inResource)
public void cleanup()
cleanup in interface P2JQuerycleanup in class AbstractQuerypublic OffEnd getOffEnd()
public character indexInformation(NumberType n)
indexInformation in interface IndexInformationindexInformation in interface P2JQueryindexInformation in class AbstractQueryn - An integer expression that evaluates to the level of join for which you want index
information.public logical deleteResultListEntry(boolean allowBetweenRows)
deleteResultListEntry in interface P2JQuerydeleteResultListEntry in class AbstractQueryallowBetweenRows - If true then the cursor can be positioned between rows (the next
row will be deleted). false for conventional DELETE-RESULT-LIST-ENTRY()
mode where the cursor should be positioned on a row (otherwise false is
returned).true on success.public logical createResultListEntry()
createResultListEntry in interface P2JQuerycreateResultListEntry in class AbstractQuerytrue on success.public void setDataRelation(DataRelation relation)
setDataRelation in interface P2JQuerysetDataRelation in class AbstractQueryrelation - the recursive DATA-RELATION the query is to FILL forpublic java.lang.String getCombinedFqls()
public double getCombinedExecutionTime()
CompoundQuery.protected void registerCleaner()
Finalizable with the transaction manager for
resource cleanup when this query's scope ends.protected void afterReposition(boolean permitFetch,
boolean error)
afterReposition in class AbstractQuerypermitFetch - true to permit immediate record fetch;
false to override fetchOnReposition
flag and explicitly disallow immediate record fetch.error - true if error happened during reposition.protected void initReferenceRowSupport(boolean globalScope)
globalScope - Flag indicating if the block at which this query is registered as record change listener is
the global scope.protected java.lang.Object getBreakValue()
order by clause.
If the break value for this query currently is non-null,
this indicates that the most recently retrieved record has crossed a
sort band boundary, and that a new band has begun. This value
will only be non-null at the point at which such a record
is found, and will be null for all other records.
Note: break values are only tracked for invocations of
next and previous. Other retrievals will
result in break value being null.
getBreakValue in class DynamicQuerynull always; when a compound query is the backing query for
a dynamic results object, it should never return a non-null value,
because it cannot shift into a preselect mode.protected java.lang.Object[] retrieve(int navigation,
LockType lockType,
boolean iterating)
Preselect Mode
CompoundQuery generally operates as a dynamic query,
though it can be used to generate a fixed list of preselected results.
When in this mode, the first time this method is executed, a results
list is generated. This is done by retrieving each virtual, composite
row which meets the overall query's criteria, and caching the primary
keys of these records in the underlying cursor. Each underlying query
is assigned the correct subset of these IDs, such that subsequent
retrieval requests can safely use the cursor to retrieve the correct
records. As a result, in preselect mode, this method is only ever
invoked once per query.
navigation - Type of advancement applied to the compound query; i.e., how
the virtual composite result set is navigated as a whole:
forward (next), backward (previous), jump to first or last, or
reload current records in all buffers.lockType - Overriding lock type to apply to each underlying buffer.iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.null if no more results were available (and we
were not iterating).QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an error occurred retrieving the record for an underlying
query.protected java.lang.Object[] retrieve(int navigation,
LockType lockType,
boolean iterating,
boolean peek)
Preselect Mode
CompoundQuery generally operates as a dynamic query,
though it can be used to generate a fixed list of preselected results.
When in this mode, the first time this method is executed, a results
list is generated. This is done by retrieving each virtual, composite
row which meets the overall query's criteria, and caching the primary
keys of these records in the underlying cursor. Each underlying query
is assigned the correct subset of these IDs, such that subsequent
retrieval requests can safely use the cursor to retrieve the correct
records. As a result, in preselect mode, this method is only ever
invoked once per query.
navigation - Type of advancement applied to the compound query; i.e., how
the virtual composite result set is navigated as a whole:
forward (next), backward (previous), jump to first or last, or
reload current records in all buffers.lockType - Overriding lock type to apply to each underlying buffer.iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.peek - true if sub-queries should be interrogated using
Scrollable.peekNext()/Scrollable.peekPrevious()
rather than P2JQuery.next()/P2JQuery.previous().
The difference is that in the first case sub-queries return the
next/previous record from underlying results, while in the second
case they return the next/previous record after the current row.null if no more results were available (and we
were not iterating).QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an error occurred retrieving the record for an underlying
query.protected boolean isPresorted()
true if the query is presorted.protected void presort()
protected void preselectResults()
SimpleResults for each
component.protected void loadRowAtCursor()
loadRowAtCursor in class AbstractQueryprotected boolean loadByValues(java.lang.Object[] data,
LockType lockType,
boolean iterating)
ids array. The IDs are arranged to coincide with the
tables underlying the query, from left-most to right-most (in the sense
of how they are joined by the query).data - Array of primary key IDs or DMOs, one per table involved in the
querylockType - Lock type which should override that of any underlying query.
Set to null to allow underlying query to use its
existing lock type.iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.true if ids was not
null; else false.collectRowData(int)protected boolean canOptimize()
true by default. Subclasses should override this behavior as needed.private boolean registerRecordChangeListeners()
true if the global scope is used for registration.private void maybeOptimize()
This method must only be invoked after the first query result is fetched via the un-optimized query, to ensure we correctly preserve the pre-query state of the involved record buffers, in the event the compound query runs off end immediately.
private RecordBuffer[] getRecordBuffersInternal()
private void setComponentsBrowsed()
private java.lang.Object[] collectRowData(int navigation)
This snapshot is only generated for scrolling queries.
navigation - Type of advancement applied to the compound query; i.e., how
the virtual composite result set is navigated as a whole:
forward (next), backward (previous), jump to first or last, or
reload current records in all buffers.loadByValues(java.lang.Object[], com.goldencode.p2j.persist.lock.LockType, boolean)private java.lang.Object[] retrieveImpl(int navigation,
LockType lockType,
boolean iterating,
boolean peek)
navigation - Type of advancement applied to the compound query; i.e., how
the virtual composite result set is navigated as a whole:
forward (next), backward (previous), jump to first or last, or
reload current records in all buffers.lockType - Overriding lock type to apply to each underlying buffer.iterating - true if this method is being invoked within the
context of an iterating loop, which can only be exited by
raising an end condition; false if end condition
should not be raised, even if no further advancement of the
composite result is possible.peek - true if sub-queries should be interrogated using
Scrollable.peekNext()/Scrollable.peekPrevious()
rather than P2JQuery.next()/P2JQuery.previous().
The difference is that in the first case sub-queries return the
next/previous record from underlying results, while in the second
case they return the next/previous record after the current row.null if no more results were available (and we
were not iterating).QueryOffEndException - if no more results were available in iterating mode.ErrorConditionException - if an error occurred retrieving the record for an underlying
query.protected void postponeAccumulation()
protected void restoreAccumulation()
protected void releaseAllBuffers()
void addCompoundComponent(CompoundComponent component)
component - Query component to be added.java.util.ArrayList<CompoundComponent> getOriginalComponents()
private java.util.ArrayList<CompoundComponent> getComponents()
private void initializeComponentQuery(Joinable query)
query - Component query to be initialized.private java.lang.Object[] processComponent(int navigation,
CompoundComponent component,
int count,
LockType lockType,
boolean peek)
navigation - Type of advancement applied to the compound query; i.e., how
the virtual composite result set is navigated as a whole:
forward (next), backward (previous), jump to first or last, or
reload current records in all buffers.component - Query component being asked to retrieve a record.count - Index of this query component's result within the current join.lockType - Lock type to apply to the retrieved record for this query
componentpeek - true if sub-queries should be interrogated using
Scrollable.peekNext()/Scrollable.peekPrevious()
rather than P2JQuery.next()/P2JQuery.previous().
The difference is that in the first case sub-queries return the
next/previous record from underlying results, while in the second
case they return the next/previous record after the current row.
Peeking works only for NEXT and PREV iteration types.peek is true: an array of
the primary key IDs for the query component, if a result was
successfully retrieved; null if no more results
were available.
If peek is false: always returns
null.
QueryOffEndException - if query component is being asked to retrieve a FIRST, LAST,
or UNIQUE record, and it has already done so in the current
iteration pass (prevents looping infinitely on these
constructs).QueryConstants.RETRIEVE_MODESprivate void translateWhere()
components.
This is done only once.
public void releaseBuffers()
releaseBuffers in interface P2JQueryreleaseBuffers in class AbstractQuerypublic boolean addDynamicFilter(FieldReference fr, BaseDataType val, java.lang.String format)
new-where := (fr = val) AND (old-query).
Note: The constraints are exclusive meaning that if constraints will be added for same field of same buffer, the query will return an empty result because the field cannot be at the same time equals to two different values.
Use clearDynamicFilters() to clean all dynamically added criteria and restore the
sorting order of the query to its original form.
addDynamicFilter in interface P2JQueryfr - A reference to field used as filtering criterion. Only the rows that matches the
specified value for this field will be selected. Must not be null.val - The filtering value for this constraint. Can be null or unknown, in
which case the SQL null value will be assumed. In this case the predicate
will look like:
new-where := (fr IS NULL) AND (old-query)
format - The format to be used when comparing values. The reason for this parameter is that
for some datatype (ex: decimal) the on-screen value can be different from
the database (because of rounding).true if the filtering constraint was successfully added. If the field
reference is not related to the buffer(s) of this query, false is returned.public void clearDynamicFilters()
clearDynamicFilters in interface P2JQuery