package query import ( "fmt" "github.com/cosmos/cosmos-sdk/store/types" ) // defaultLimit is the default `limit` for queries // if the `limit` is not supplied, paginate will use `defaultLimit` const defaultLimit = 100 // Paginate does pagination of all the results in the PrefixStore based on the // provided PageRequest. onResult should be used to do actual unmarshaling. func Paginate( prefixStore types.KVStore, pageRequest *PageRequest, onResult func(key []byte, value []byte) error, ) (*PageResponse, error) { // if the PageRequest is nil, use default PageRequest if pageRequest == nil { pageRequest = &PageRequest{} } offset := pageRequest.Offset key := pageRequest.Key limit := pageRequest.Limit countTotal := pageRequest.CountTotal if offset > 0 && key != nil { return nil, fmt.Errorf("invalid request, either offset or key is expected, got both") } if limit == 0 { limit = defaultLimit // count total results when the limit is zero/not supplied countTotal = true } if len(key) != 0 { iterator := prefixStore.Iterator(key, nil) defer iterator.Close() var count uint64 var nextKey []byte for ; iterator.Valid(); iterator.Next() { if count == limit { nextKey = iterator.Key() break } if iterator.Error() != nil { return nil, iterator.Error() } err := onResult(iterator.Key(), iterator.Value()) if err != nil { return nil, err } count++ } return &PageResponse{ NextKey: nextKey, }, nil } iterator := prefixStore.Iterator(nil, nil) defer iterator.Close() end := offset + limit var count uint64 var nextKey []byte for ; iterator.Valid(); iterator.Next() { count++ if count <= offset { continue } if count <= end { err := onResult(iterator.Key(), iterator.Value()) if err != nil { return nil, err } } else if count == end+1 { nextKey = iterator.Key() if !countTotal { break } } if iterator.Error() != nil { return nil, iterator.Error() } } res := &PageResponse{NextKey: nextKey} if countTotal { res.Total = count } return res, nil }