From b5b2f49e81b32a155c422a5f98223fc9a00cd61d Mon Sep 17 00:00:00 2001 From: oren-lava <111131399+oren-lava@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:54:45 +0200 Subject: [PATCH] feat(collections): add collections reverse triple helpers (#22641) --- collections/CHANGELOG.md | 1 + collections/triple.go | 33 +++++++++++++++++++++++++++++++++ collections/triple_test.go | 22 +++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/collections/CHANGELOG.md b/collections/CHANGELOG.md index d0da0dcfa5..844df7e785 100644 --- a/collections/CHANGELOG.md +++ b/collections/CHANGELOG.md @@ -33,6 +33,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features +* [#22641](https://github.com/cosmos/cosmos-sdk/pull/22641) Add reverse iterator support for `Triple`. * [#17656](https://github.com/cosmos/cosmos-sdk/pull/17656) Introduces `Vec`, a collection type that allows to represent a growable array on top of a KVStore. * [#18933](https://github.com/cosmos/cosmos-sdk/pull/18933) Add LookupMap implementation. It is basic wrapping of the standard Map methods but is not iterable. * [#19343](https://github.com/cosmos/cosmos-sdk/pull/19343) Simplify IndexedMap creation by allowing to infer indexes through reflection. diff --git a/collections/triple.go b/collections/triple.go index d7dcb36056..7474e01ccd 100644 --- a/collections/triple.go +++ b/collections/triple.go @@ -352,3 +352,36 @@ func NewSuperPrefixedTripleRange[K1, K2, K3 any](k1 K1, k2 K2) Ranger[Triple[K1, end: RangeKeyPrefixEnd(key), } } + +// NewPrefixUntilTripleRangeReversed defines a collection query which ranges until the provided Pair prefix +// in reverse order. +// Unstable: this API might change in the future. +func NewPrefixUntilTripleRangeReversed[K1, K2, K3 any](k1 K1) Ranger[Triple[K1, K2, K3]] { + key := TriplePrefix[K1, K2, K3](k1) + return &Range[Triple[K1, K2, K3]]{ + end: RangeKeyPrefixEnd(key), + order: OrderDescending, + } +} + +// NewPrefixedTripleRangeReversed provides a Range for all keys prefixed with the given +// first part of the Triple key in reverse order. +func NewPrefixedTripleRangeReversed[K1, K2, K3 any](k1 K1) Ranger[Triple[K1, K2, K3]] { + key := TriplePrefix[K1, K2, K3](k1) + return &Range[Triple[K1, K2, K3]]{ + start: RangeKeyExact(key), + end: RangeKeyPrefixEnd(key), + order: OrderDescending, + } +} + +// NewSuperPrefixedTripleRangeReversed provides a Range for all keys prefixed with the given +// first and second parts of the Triple key in reverse order. +func NewSuperPrefixedTripleRangeReversed[K1, K2, K3 any](k1 K1, k2 K2) Ranger[Triple[K1, K2, K3]] { + key := TripleSuperPrefix[K1, K2, K3](k1, k2) + return &Range[Triple[K1, K2, K3]]{ + start: RangeKeyExact(key), + end: RangeKeyPrefixEnd(key), + order: OrderDescending, + } +} diff --git a/collections/triple_test.go b/collections/triple_test.go index 5ea53b3fe6..c605a7aeab 100644 --- a/collections/triple_test.go +++ b/collections/triple_test.go @@ -7,7 +7,7 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/collections/colltest" - "cosmossdk.io/core/testing" + coretesting "cosmossdk.io/core/testing" ) func TestTriple(t *testing.T) { @@ -45,10 +45,30 @@ func TestTripleRange(t *testing.T) { require.NoError(t, err) require.Equal(t, keys[:3], gotKeys) + // we prefix over (1) with "reverse" enabled, we expect 3 results in reverse order + iter, err = keySet.Iterate(ctx, collections.NewPrefixedTripleRangeReversed[uint64, string, []byte](uint64(1))) + require.NoError(t, err) + gotKeys, err = iter.Keys() + require.NoError(t, err) + require.Len(t, gotKeys, 3) + for i := range gotKeys { + require.Equal(t, gotKeys[i], keys[len(gotKeys)-i-1]) + } + // we super prefix over Join(1, "A") we expect 2 results iter, err = keySet.Iterate(ctx, collections.NewSuperPrefixedTripleRange[uint64, string, []byte](1, "A")) require.NoError(t, err) gotKeys, err = iter.Keys() require.NoError(t, err) require.Equal(t, keys[:2], gotKeys) + + // we prefix over Join(1, "A") with "reverse" enabled, we expect 2 results in reverse order + iter, err = keySet.Iterate(ctx, collections.NewSuperPrefixedTripleRangeReversed[uint64, string, []byte](1, "A")) + require.NoError(t, err) + gotKeys, err = iter.Keys() + require.NoError(t, err) + require.Len(t, gotKeys, 2) + for i := range gotKeys { + require.Equal(t, gotKeys[i], keys[len(gotKeys)-i-1]) + } }