Class IntersectionCursor<T>
- java.lang.Object
-
- com.apple.foundationdb.record.provider.foundationdb.cursors.IntersectionCursor<T>
-
- Type Parameters:
T
- the type of elements returned by the cursor
- All Implemented Interfaces:
RecordCursor<T>
,AutoCloseable
,Iterator<T>
@API(MAINTAINED) public class IntersectionCursor<T> extends Object
A cursor that implements an intersection of matching elements from a set of cursors all of whom are ordered compatibly. For every matching set, this will return the element from the first child cursor. If each cursor returns something slightly different and the use case requires accessing the different results from each child, then one should use theIntersectionMultiCursor
which returns a list of the child cursor values rather than just the first one.- See Also:
IntersectionMultiCursor
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from interface com.apple.foundationdb.record.RecordCursor
RecordCursor.NoNextReason
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description boolean
accept(RecordCursorVisitor visitor)
Accept a visit from hierarchical visitor, which implementsRecordCursorVisitor
.void
close()
protected CompletableFuture<List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>>>
computeNextResultStates()
Compute the next result states for the cursor based on the status of the existing states.static <M extends Message,S extends FDBRecord<M>>
IntersectionCursor<S>create(FDBRecordStoreBase<M> store, KeyExpression comparisonKey, boolean reverse, Function<byte[],RecordCursor<S>> left, Function<byte[],RecordCursor<S>> right, byte[] continuation)
Create an intersection cursor from two compatibly-ordered cursors.static <M extends Message,S extends FDBRecord<M>>
IntersectionCursor<S>create(FDBRecordStoreBase<M> store, KeyExpression comparisonKey, boolean reverse, List<Function<byte[],RecordCursor<S>>> cursorFunctions, byte[] continuation)
Create an intersection cursor from two or more compatibly-ordered cursors.static <T> IntersectionCursor<T>
create(Function<? super T,? extends List<Object>> comparisonKeyFunction, boolean reverse, Function<byte[],RecordCursor<T>> left, Function<byte[],RecordCursor<T>> right, byte[] continuation, FDBStoreTimer timer)
Create an intersection cursor from two compatibly-ordered cursors.static <T> IntersectionCursor<T>
create(Function<? super T,? extends List<Object>> comparisonKeyFunction, boolean reverse, List<Function<byte[],RecordCursor<T>>> cursorFunctions, byte[] continuation, FDBStoreTimer timer)
Create an intersection cursor from two or more compatibly-ordered cursors.protected static <T> List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>>
createCursorStates(Function<byte[],RecordCursor<T>> left, Function<byte[],RecordCursor<T>> right, byte[] byteContinuation, Function<? super T,? extends List<Object>> comparisonKeyFunction)
protected static <T> List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>>
createCursorStates(List<Function<byte[],RecordCursor<T>>> cursorFunctions, byte[] byteContinuation, Function<? super T,? extends List<Object>> comparisonKeyFunction)
protected Function<? super T,? extends List<Object>>
getComparisonKeyFunction()
byte[]
getContinuation()
Deprecated.com.apple.foundationdb.record.provider.foundationdb.cursors.IntersectionCursorContinuation
getContinuationObject()
Executor
getExecutor()
RecordCursor.NoNextReason
getNoNextReason()
Deprecated.FDBStoreTimer
getTimer()
Get theFDBStoreTimer
used to instrument events of this cursor.protected RecordCursor.NoNextReason
mergeNoNextReasons()
Merges all of the cursors and whether they have stopped and returns the "weakest" reason for the result to stop.U
next()
Deprecated.CompletableFuture<Boolean>
onHasNext()
Deprecated.CompletableFuture<RecordCursorResult<U>>
onNext()
Asynchronously return the next result from this cursor.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface java.util.Iterator
forEachRemaining, remove
-
Methods inherited from interface com.apple.foundationdb.record.RecordCursor
asIterator, asList, filter, filterAsync, filterAsyncInstrumented, filterAsyncInstrumented, filterInstrumented, filterInstrumented, first, flatMapPipelined, forEach, forEachAsync, forEachResult, forEachResultAsync, getCount, getNext, hasNext, limitRowsTo, limitTo, map, mapEffect, mapEffect, mapPipelined, orElse, reduce, skip, skipThenLimit
-
-
-
-
Method Detail
-
create
@Nonnull public static <M extends Message,S extends FDBRecord<M>> IntersectionCursor<S> create(@Nonnull FDBRecordStoreBase<M> store, @Nonnull KeyExpression comparisonKey, boolean reverse, @Nonnull Function<byte[],RecordCursor<S>> left, @Nonnull Function<byte[],RecordCursor<S>> right, @Nullable byte[] continuation)
Create an intersection cursor from two compatibly-ordered cursors. As its comparison key function, it will evaluate the provided comparison key on each record from each cursor. This otherwise behaves exactly the same way as the overload of this function that takes a function to extract a comparison key.- Type Parameters:
M
- the type of the Protobuf record elements of the cursorS
- the type of record wrapping a record of typeM
- Parameters:
store
- record store from which records will be fetchedcomparisonKey
- the key expression used to compare records from different cursorsreverse
- whether records are returned in descending or ascending order by the comparison keyleft
- a function to produce the firstRecordCursor
from a continuationright
- a function to produce the secondRecordCursor
from a continuationcontinuation
- any continuation from a previous scan- Returns:
- a cursor containing all records in both child cursors
- See Also:
create(Function, boolean, Function, Function, byte[], FDBStoreTimer)
-
create
@Nonnull public static <T> IntersectionCursor<T> create(@Nonnull Function<? super T,? extends List<Object>> comparisonKeyFunction, boolean reverse, @Nonnull Function<byte[],RecordCursor<T>> left, @Nonnull Function<byte[],RecordCursor<T>> right, @Nullable byte[] continuation, @Nullable FDBStoreTimer timer)
Create an intersection cursor from two compatibly-ordered cursors. This cursor is identical to the cursor that would be produced by calling the overload ofcreate()
that takes a list of cursors.- Type Parameters:
T
- the type of elements returned by the cursor- Parameters:
comparisonKeyFunction
- the function expression used to compare elements from different cursorsreverse
- whether records are returned in descending or ascending order by the comparison keyleft
- a function to produce the firstRecordCursor
from a continuationright
- a function to produce the secondRecordCursor
from a continuationcontinuation
- any continuation from a previous scantimer
- the timer used to instrument events- Returns:
- a cursor containing all elements in both child cursors
- See Also:
create(Function, boolean, List, byte[], FDBStoreTimer)
-
create
@Nonnull public static <M extends Message,S extends FDBRecord<M>> IntersectionCursor<S> create(@Nonnull FDBRecordStoreBase<M> store, @Nonnull KeyExpression comparisonKey, boolean reverse, @Nonnull List<Function<byte[],RecordCursor<S>>> cursorFunctions, @Nullable byte[] continuation)
Create an intersection cursor from two or more compatibly-ordered cursors. As its comparison key function, it will evaluate the provided comparison key on each record from each cursor. This otherwise behaves exactly the same way as the overload of this function that takes a function to extract a comparison key.- Type Parameters:
M
- the type of the Protobuf record elements of the cursorS
- the type of record wrapping a record of typeM
- Parameters:
store
- record store from which records will be fetchedcomparisonKey
- the key expression used to compare records from different cursorsreverse
- whether records are returned in descending or ascending order by the comparison keycursorFunctions
- a list of functions to produceRecordCursor
s from a continuationcontinuation
- any continuation from a previous scan- Returns:
- a cursor containing all records in all child cursors
- See Also:
create(Function, boolean, List, byte[], FDBStoreTimer)
-
create
@Nonnull public static <T> IntersectionCursor<T> create(@Nonnull Function<? super T,? extends List<Object>> comparisonKeyFunction, boolean reverse, @Nonnull List<Function<byte[],RecordCursor<T>>> cursorFunctions, @Nullable byte[] continuation, @Nullable FDBStoreTimer timer)
Create an intersection cursor from two or more compatibly-ordered cursors. Note that this will throw an error if the list of cursors does not have at least two elements. The returned cursor will return all elements that appear in all of the provided cursors, preserving order. All cursors must return elements in the same order, and that order should be determined by the comparison key function, i.e., ifreverse
isfalse
, then the elements should be returned in ascending order by that key, and ifreverse
istrue
, they should be returned in descending order. Additionally, if the comparison key function evaluates to the same value when applied to two elements (possibly from different cursors), then those two elements should be equal. In other words, the value of the comparison key should be the only necessary data that need to be extracted from each element returned by the child cursors to perform the intersection. Additionally, the provided comparison key function should not have any side-effects and should produce the same output every time it is applied to the same input.The cursors are provided as a list of functions rather than a list of
RecordCursor
s. These functions should create a newRecordCursor
instance with a given continuation appropriate for that cursor type. The value of that continuation will be determined by this function from thecontinuation
parameter for the intersection cursor as a whole.- Type Parameters:
T
- the type of elements returned by this cursor- Parameters:
comparisonKeyFunction
- the function evaluated to compare elements from different cursorsreverse
- whether records are returned in descending or ascending order by the comparison keycursorFunctions
- a list of functions to produceRecordCursor
s from a continuationcontinuation
- any continuation from a previous scantimer
- the timer used to instrument events- Returns:
- a cursor containing all records in all child cursors
-
computeNextResultStates
@Nonnull protected CompletableFuture<List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>>> computeNextResultStates()
Compute the next result states for the cursor based on the status of the existing states. This should return a (not necessarily proper) sublist of this cursor's cursor states. By default, this assumes the cursors return results in a compatible order based on their comparison key and loops until they all have matching values. Extenders of this class may choose an alternative approach depending on the semantics of that cursor.To indicate that the intersection cursor should stop, this function should either return an empty list of states or a list containing at least one state that does not have a next item.
- Returns:
- the list of states included in the next result
-
getComparisonKeyFunction
@Nonnull protected Function<? super T,? extends List<Object>> getComparisonKeyFunction()
-
mergeNoNextReasons
@Nonnull protected RecordCursor.NoNextReason mergeNoNextReasons()
Merges all of the cursors and whether they have stopped and returns the "weakest" reason for the result to stop. It will returnRecordCursor.NoNextReason.SOURCE_EXHAUSTED
if any of the cursors are exhausted. If any of the cursors have stopped due to an in-band limit, it will return an in-band limit as well. Finally, if all of the stopped cursors have done so due to hitting an out-of-band limit, it will return an out-of-band limit as well. Note that, in practice, because an intersection cursor will returnfalse
fromonHasNext
if any of its child cursors have stopped, it is likely that there are only a small number (maybe one or two) cursors that have actually stopped when this method is called (e.g., the first cursor to exhaust its source or the first cursor to hit a limit imposed by the element scan limiter).- Returns:
- the weakest reason for stopping
-
getContinuationObject
@Nonnull public com.apple.foundationdb.record.provider.foundationdb.cursors.IntersectionCursorContinuation getContinuationObject()
-
createCursorStates
@Nonnull protected static <T> List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>> createCursorStates(@Nonnull Function<byte[],RecordCursor<T>> left, @Nonnull Function<byte[],RecordCursor<T>> right, @Nullable byte[] byteContinuation, @Nonnull Function<? super T,? extends List<Object>> comparisonKeyFunction)
-
createCursorStates
@Nonnull protected static <T> List<com.apple.foundationdb.record.provider.foundationdb.cursors.KeyedMergeCursorState<T>> createCursorStates(@Nonnull List<Function<byte[],RecordCursor<T>>> cursorFunctions, @Nullable byte[] byteContinuation, @Nonnull Function<? super T,? extends List<Object>> comparisonKeyFunction)
-
onNext
@Nonnull public CompletableFuture<RecordCursorResult<U>> onNext()
Description copied from interface:RecordCursor
Asynchronously return the next result from this cursor. When complete, the future will contain aRecordCursorResult
, which represents exactly one of the following:-
The next object of type
T
produced by the cursor. In addition to the next record, this result includes aRecordCursorContinuation
that can be used to continue the cursor after the last record returned. The returned continuation is guaranteed not to be an "end continuation" representing the end of the cursor: specifically,RecordCursorContinuation.isEnd()
is alwaysfalse
on the returned continuation. -
The fact that the cursor is stopped and cannot produce another record and a
RecordCursor.NoNextReason
that explains why no record could be produced. The result include a continuation that can be used to continue the cursor after the last record returned. If the result'sNoNextReason
is anything other thanRecordCursor.NoNextReason.SOURCE_EXHAUSTED
, the returned continuation must not be an end continuation. Conversely, if the result'sNoNextReason
isSOURCE_EXHAUSTED
, then the returned continuation must be an an "end continuation".
RecordCursorContinuation
can be serialized to an opaque byte array usingRecordCursorContinuation.toBytes()
. This can be passed back into a new cursor of the same type, with all other parameters remaining the same.- Specified by:
onNext
in interfaceRecordCursor<T>
- Returns:
- a future for the next result from this cursor representing either the next record or an indication of why the cursor stopped
- See Also:
RecordCursorResult
,RecordCursorContinuation
-
The next object of type
-
onHasNext
@Nonnull @Deprecated public CompletableFuture<Boolean> onHasNext()
Deprecated.Description copied from interface:RecordCursor
Asynchronously check whether there are more records available from the cursor.- Specified by:
onHasNext
in interfaceRecordCursor<T>
- Returns:
- a future that when complete will hold
true
ifRecordCursor.next()
would return a record. - See Also:
AsyncIterator.onHasNext()
-
next
@Nullable @Deprecated public U next()
Deprecated.Description copied from interface:RecordCursor
Return the next value.
-
getContinuation
@Nullable @Deprecated public byte[] getContinuation()
Deprecated.Description copied from interface:RecordCursor
Get a byte string that can be used to continue a query after the last record returned.- Specified by:
getContinuation
in interfaceRecordCursor<T>
- Returns:
- opaque byte array denoting where the cursor should pick up. This can be passed back into a new
cursor of the same type, with all other parameters remaining the same.
Returns
null
if the underlying source is completely exhausted, independent of any limit passed to the cursor creator. Since such creators generally acceptnull
to mean no continuation, that is, start from the beginning, one must check fornull
fromgetContinuation
to keep from starting over. Result is not always defined if called beforeonHasNext
or beforenext
afteronHasNext
has returnedtrue
. That is, a continuation is only guaranteed when called "between" records from awhile (hasNext) next
loop or after its end.
-
getNoNextReason
@Nonnull @Deprecated public RecordCursor.NoNextReason getNoNextReason()
Deprecated.Description copied from interface:RecordCursor
Get the reason that the cursor has reached the end and returnedfalse
forRecordCursor.hasNext()
. IfhasNext
was not called or returnedtrue
last time, the result is undefined and may be an exception.- Specified by:
getNoNextReason
in interfaceRecordCursor<T>
- Returns:
- the reason that the cursor stopped
-
close
public void close()
- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceRecordCursor<T>
-
getExecutor
@Nonnull public Executor getExecutor()
- Specified by:
getExecutor
in interfaceRecordCursor<T>
-
getTimer
@Nullable public FDBStoreTimer getTimer()
Get theFDBStoreTimer
used to instrument events of this cursor.- Returns:
- the timer used to instrument this cursor
-
accept
public boolean accept(@Nonnull RecordCursorVisitor visitor)
Description copied from interface:RecordCursor
Accept a visit from hierarchical visitor, which implementsRecordCursorVisitor
. By contract, implementations of this method must return the value ofvisitor.visitLeave(this)
, which determines whether or not subsequent siblings of this cursor should be visited.- Specified by:
accept
in interfaceRecordCursor<T>
- Parameters:
visitor
- a hierarchical visitor- Returns:
true
if the subsequent siblings of thecursor
should be visited, andfalse
otherwise
-
-