diff --git a/types/query/collections_pagination.go b/types/query/collections_pagination.go index 1c9babcc6a..4edea99794 100644 --- a/types/query/collections_pagination.go +++ b/types/query/collections_pagination.go @@ -128,13 +128,10 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V], T any]( return nil, nil, err } defer iterator.Close() - // we advance the iter equal to the provided offset - if !advanceIter(iterator, offset) { - return nil, nil, collections.ErrInvalidIterator - } var ( count uint64 + skipped uint64 nextKey []byte results []T ) @@ -149,6 +146,11 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V], T any]( } // if no predicate function is specified then we just include the result if predicateFunc == nil { + if skipped < offset { + skipped++ + continue + } + transformed, err := transformFunc(kv.Key, kv.Value) if err != nil { return nil, nil, err @@ -163,6 +165,12 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V], T any]( return nil, nil, err } if include { + // Item matches filter - check if we need to skip it for offset + if skipped < offset { + skipped++ + continue + } + transformed, err := transformFunc(kv.Key, kv.Value) if err != nil { return nil, nil, err @@ -224,20 +232,6 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V], T any]( return results, resp, nil } -func advanceIter[I interface { - Next() - Valid() bool -}](iter I, offset uint64, -) bool { - for i := uint64(0); i < offset; i++ { - if !iter.Valid() { - return false - } - iter.Next() - } - return true -} - // collFilteredPaginateByKey paginates a collection when a starting key // is provided in the PageRequest. Predicate is applied only if not nil. func collFilteredPaginateByKey[K, V any, C Collection[K, V], T any]( diff --git a/types/query/collections_pagination_test.go b/types/query/collections_pagination_test.go index 87cfc549a9..3455776132 100644 --- a/types/query/collections_pagination_test.go +++ b/types/query/collections_pagination_test.go @@ -154,6 +154,25 @@ func TestCollectionPagination(t *testing.T) { {Key: 295, Value: 295}, }, }, + "filtered with offset": { + req: &PageRequest{ + Offset: 3, + Limit: 3, + CountTotal: true, + }, + expResp: &PageResponse{ + NextKey: encodeKey(12), + Total: 150, + }, + filter: func(key, value uint64) (bool, error) { + return key%2 == 0, nil + }, + expResults: []collections.KeyValue[uint64, uint64]{ + {Key: 6, Value: 6}, + {Key: 8, Value: 8}, + {Key: 10, Value: 10}, + }, + }, "filtered no key with error": { req: &PageRequest{ Limit: 3,