Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagination types and helper func #6353

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions types/query/pagination.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package query

import (
"github.com/cosmos/cosmos-sdk/store/types"
)

// Paginate does pagination of the results in the prefixStore based on the
// provided PageRequest. onResult should be used to do actual unmarshaling.
//
// Ex:
// prefixStore := prefix.NewStore(store, someRequestParam)
// var results []Result
// pageRes, err := query.Paginate(accountStore, req.Page, func(key []byte, value []byte) error {
// var result Result
// err := Unmarshal(value, &balance)
// results = append(results, result)
// ...
// })
func Paginate(
prefixStore types.KVStore,
req *PageRequest,
onResult func(key []byte, value []byte) error,
) (*PageResponse, error) {
offset := req.Offset
key := req.Key
limit := req.Limit

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
}

err := onResult(iterator.Key(), iterator.Value())
if err != nil {
return nil, err
}

count++
}

return &PageResponse{
NextKey: nextKey,
}, nil
} else {
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
} else if count <= end {
err := onResult(iterator.Key(), iterator.Value())
if err != nil {
return nil, err
}
} else if !req.CountTotal {
nextKey = iterator.Key()
break
}
}

res := &PageResponse{NextKey: nextKey}
if req.CountTotal {
res.Total = count
}

return res, nil
}
}
Loading