core: add Backwards option for storage iterators

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
Anna Shaleva 2023-03-24 19:32:06 +03:00
parent 4f827de5cd
commit d5bea0ad4c
4 changed files with 19 additions and 3 deletions

View file

@ -44,6 +44,7 @@ func TestFindFlags(t *testing.T) {
require.EqualValues(t, storage.DeserializeValues, istorage.FindDeserialize) require.EqualValues(t, storage.DeserializeValues, istorage.FindDeserialize)
require.EqualValues(t, storage.PickField0, istorage.FindPick0) require.EqualValues(t, storage.PickField0, istorage.FindPick0)
require.EqualValues(t, storage.PickField1, istorage.FindPick1) require.EqualValues(t, storage.PickField1, istorage.FindPick1)
require.EqualValues(t, storage.Backwards, istorage.FindBackwards)
} }
type syscallTestCase struct { type syscallTestCase struct {

View file

@ -19,9 +19,10 @@ const (
FindDeserialize = 1 << 3 FindDeserialize = 1 << 3
FindPick0 = 1 << 4 FindPick0 = 1 << 4
FindPick1 = 1 << 5 FindPick1 = 1 << 5
FindBackwards = 1 << 7
FindAll = FindDefault | FindKeysOnly | FindRemovePrefix | FindValuesOnly | FindAll = FindDefault | FindKeysOnly | FindRemovePrefix | FindValuesOnly |
FindDeserialize | FindPick0 | FindPick1 FindDeserialize | FindPick0 | FindPick1 | FindBackwards
) )
// Iterator is an iterator state representation. // Iterator is an iterator state representation.
@ -111,8 +112,9 @@ func Find(ic *interop.Context) error {
if opts&FindDeserialize == 0 && (opts&FindPick0 != 0 || opts&FindPick1 != 0) { if opts&FindDeserialize == 0 && (opts&FindPick0 != 0 || opts&FindPick1 != 0) {
return fmt.Errorf("%w: PickN is specified without Deserialize", errFindInvalidOptions) return fmt.Errorf("%w: PickN is specified without Deserialize", errFindInvalidOptions)
} }
bkwrds := opts&FindBackwards != 0
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix}) seekres := ic.DAO.SeekAsync(ctx, stc.ID, storage.SeekRange{Prefix: prefix, Backwards: bkwrds})
item := NewIterator(seekres, prefix, opts) item := NewIterator(seekres, prefix, opts)
ic.VM.Estack().PushItem(stackitem.NewInterop(item)) ic.VM.Estack().PushItem(stackitem.NewInterop(item))
ic.RegisterCancelFunc(func() { ic.RegisterCancelFunc(func() {

View file

@ -197,7 +197,18 @@ func TestFind(t *testing.T) {
}), }),
}) })
}) })
t.Run("normal invocation, backwards", func(t *testing.T) {
testFind(t, []byte{0x01}, istorage.FindBackwards, []stackitem.Item{
stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(skeys[0]),
stackitem.NewByteArray(items[0]),
}),
stackitem.NewStruct([]stackitem.Item{
stackitem.NewByteArray(skeys[2]),
stackitem.NewByteArray(items[2]),
}),
})
})
t.Run("keys only", func(t *testing.T) { t.Run("keys only", func(t *testing.T) {
testFind(t, []byte{0x01}, istorage.FindKeysOnly, []stackitem.Item{ testFind(t, []byte{0x01}, istorage.FindKeysOnly, []stackitem.Item{
stackitem.NewByteArray(skeys[2]), stackitem.NewByteArray(skeys[2]),

View file

@ -36,6 +36,8 @@ const (
PickField0 FindFlags = 1 << 4 PickField0 FindFlags = 1 << 4
// PickField1 is used to get second field in a serialized struct or array. // PickField1 is used to get second field in a serialized struct or array.
PickField1 FindFlags = 1 << 5 PickField1 FindFlags = 1 << 5
// Backwards is used to iterate over elements in reversed (descending) order.
Backwards FindFlags = 1 << 7
) )
// ConvertContextToReadOnly returns new context from the given one, but with // ConvertContextToReadOnly returns new context from the given one, but with