Class UnionCursor<T>

  • Type Parameters:
    T - the type of elements returned by the cursor
    All Implemented Interfaces:
    RecordCursor<T>, AutoCloseable, Iterator<T>

    @API(MAINTAINED)
    public class UnionCursor<T>
    extends Object
    A cursor that implements a union of all the records from a set of cursors, all of whom are ordered compatibly. In this instance, "compatibly ordered" means that all cursors should return results sorted by the "comparison key". For instance, a UnionCursor of type FDBQueriedRecord might get the primary key of each record as the comparison key function. This is legal as long as all its children also return records ordered by primary key. This cursor removes any duplicates (relying solely on the comparison key to indicate that two elements are equal), and it returns results ordered by the comparison key.

    If any child of this cursor stops because it hits a limit, then this cursor will also stop. This differs from the behavior of the UnorderedUnionCursor. This cursor requires all of its children have returned a value before it can determine which value to return next (as otherwise, it does not know what the minimum value is according to the comparison key). If it were to continue returning results, there may be anomalies in the order of returned results across continuation boundaries.

    • Method Detail

      • create

        @Nonnull
        public static <M extends Message,​S extends FDBRecord<M>> UnionCursor<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 a union cursor from two compatibly-ordered cursors. This cursor is identical to the cursor that would be produced by calling the overload of create() that takes a list of cursors.
        Type Parameters:
        M - the type of the Protobuf record elements of the cursor
        S - the type of record wrapping a record of type M
        Parameters:
        store - record store from which records will be fetched
        comparisonKey - the key expression used to compare records from different cursors
        reverse - whether records are returned in descending or ascending order by the comparison key
        left - a function to produce the first RecordCursor from a continuation
        right - a function to produce the second RecordCursor from a continuation
        continuation - any continuation from a previous scan
        Returns:
        a cursor containing any records in any child cursors
        See Also:
        create(FDBRecordStoreBase, KeyExpression, boolean, List, byte[])
      • create

        @Nonnull
        public static <T> UnionCursor<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[] byteContinuation,
                                                @Nullable
                                                FDBStoreTimer timer)
        Create a union cursor from two compatibly-ordered cursors. This cursor is identical to the cursor that would be produced by calling the overload of create() 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 cursors
        reverse - whether records are returned in descending or ascending order by the comparison key
        left - a function to produce the first RecordCursor from a continuation
        right - a function to produce the second RecordCursor from a continuation
        byteContinuation - any continuation from a previous scan
        timer - the timer used to instrument events
        Returns:
        a cursor containing all elements in both child cursors
      • create

        @Nonnull
        public static <M extends Message,​S extends FDBRecord<M>> UnionCursor<S> create​(@Nonnull
                                                                                             FDBRecordStoreBase<M> store,
                                                                                             @Nonnull
                                                                                             KeyExpression comparisonKey,
                                                                                             boolean reverse,
                                                                                             @Nonnull
                                                                                             List<Function<byte[],​RecordCursor<S>>> cursorFunctions,
                                                                                             @Nullable
                                                                                             byte[] continuation)
        Create a union 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 cursor
        S - the type of record wrapping a record of type M
        Parameters:
        store - record store from which records will be fetched
        comparisonKey - the key expression used to compare records from different cursors
        reverse - whether records are returned in descending or ascending order by the comparison key
        cursorFunctions - a list of functions to produce RecordCursors from a continuation
        continuation - any continuation from a previous scan
        Returns:
        a cursor containing any records in any child cursors
        See Also:
        create(Function, boolean, List, byte[], FDBStoreTimer)
      • create

        @Nonnull
        public static <T> UnionCursor<T> create​(@Nonnull
                                                Function<? super T,​? extends List<Object>> comparisonKeyFunction,
                                                boolean reverse,
                                                @Nonnull
                                                List<Function<byte[],​RecordCursor<T>>> cursorFunctions,
                                                @Nullable
                                                byte[] byteContinuation,
                                                @Nullable
                                                FDBStoreTimer timer)
        Create a union 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 any records that appear in any of the provided cursors, preserving order. All cursors must return records in the same order, and that order should be determined by the comparison key function, i.e., if reverse is false, then the records should be returned in ascending order by that key, and if reverse is true, they should be returned in descending order. Additionally, if the comparison key function evaluates to the same value when applied to two records (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 union. 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 RecordCursors. These functions should create a new RecordCursor instance with a given continuation appropriate for that cursor type. The value of that continuation will be determined by this function from the continuation parameter for the union 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 cursors
        reverse - whether records are returned in descending or ascending order by the comparison key
        cursorFunctions - a list of functions to produce RecordCursors from a continuation
        byteContinuation - any continuation from a previous scan
        timer - the timer used to instrument events
        Returns:
        a cursor containing any records in any child cursors
      • mergeNoNextReasons

        @Nonnull
        protected RecordCursor.NoNextReason mergeNoNextReasons()
        Merges all of the cursors and whether they have stopped and returns the "strongest" reason for the result to stop. It will return an out-of-band reason if any of the children stopped for an out-of-band reason, and it will only return SOURCE_EXHAUSTED if all of the cursors are exhausted.
        Returns:
        the strongest reason for stopping
      • 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 a RecordCursorResult, which represents exactly one of the following:
        1. The next object of type T produced by the cursor. In addition to the next record, this result includes a RecordCursorContinuation 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 always false on the returned continuation.
        2. 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's NoNextReason is anything other than RecordCursor.NoNextReason.SOURCE_EXHAUSTED, the returned continuation must not be an end continuation. Conversely, if the result's NoNextReason is SOURCE_EXHAUSTED, then the returned continuation must be an an "end continuation".
        In either case, the returned RecordCursorContinuation can be serialized to an opaque byte array using RecordCursorContinuation.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 interface RecordCursor<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
      • 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 interface RecordCursor<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 accept null to mean no continuation, that is, start from the beginning, one must check for null from getContinuation to keep from starting over. Result is not always defined if called before onHasNext or before next after onHasNext has returned true. That is, a continuation is only guaranteed when called "between" records from a while (hasNext) next loop or after its end.
      • accept

        public boolean accept​(@Nonnull
                              RecordCursorVisitor visitor)
        Description copied from interface: RecordCursor
        Accept a visit from hierarchical visitor, which implements RecordCursorVisitor. By contract, implementations of this method must return the value of visitor.visitLeave(this), which determines whether or not subsequent siblings of this cursor should be visited.
        Specified by:
        accept in interface RecordCursor<T>
        Parameters:
        visitor - a hierarchical visitor
        Returns:
        true if the subsequent siblings of the cursor should be visited, and false otherwise