From 40e1893b7ddc7fb31625125109561922f6d7e339 Mon Sep 17 00:00:00 2001 From: Gabriel Erzse Date: Fri, 8 Mar 2024 09:33:00 +0200 Subject: [PATCH 1/2] Support NOVALUES parameter for HSCAN Issue #2919 The NOVALUES parameter instructs HSCAN to only return the hash keys, without values. --- commands_test.go | 22 ++++++++++++++++++++-- hash_commands.go | 15 +++++++++++++++ iterator_test.go | 16 ++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/commands_test.go b/commands_test.go index d30a9d8bb..18213e7b0 100644 --- a/commands_test.go +++ b/commands_test.go @@ -1100,8 +1100,26 @@ var _ = Describe("Commands", func() { keys, cursor, err := client.HScan(ctx, "myhash", 0, "", 0).Result() Expect(err).NotTo(HaveOccurred()) - Expect(keys).NotTo(BeEmpty()) - Expect(cursor).NotTo(BeZero()) + // If we don't get at least two items back, it's really strange. + Expect(cursor).To(BeNumerically(">=", 2)) + Expect(len(keys)).To(BeNumerically(">=", 2)) + Expect(keys[0]).To(HavePrefix("key")) + Expect(keys[1]).To(Equal("hello")) + }) + + It("should HScan without values", func() { + for i := 0; i < 1000; i++ { + sadd := client.HSet(ctx, "myhash", fmt.Sprintf("key%d", i), "hello") + Expect(sadd.Err()).NotTo(HaveOccurred()) + } + + keys, cursor, err := client.HScanNoValues(ctx, "myhash", 0, "", 0).Result() + Expect(err).NotTo(HaveOccurred()) + // If we don't get at least two items back, it's really strange. + Expect(cursor).To(BeNumerically(">=", 2)) + Expect(len(keys)).To(BeNumerically(">=", 2)) + Expect(keys[0]).To(HavePrefix("key")) + Expect(keys[1]).To(HavePrefix("key")) }) It("should ZScan", func() { diff --git a/hash_commands.go b/hash_commands.go index 2c62a75ad..ac3ca6c30 100644 --- a/hash_commands.go +++ b/hash_commands.go @@ -16,6 +16,7 @@ type HashCmdable interface { HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd + HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd HVals(ctx context.Context, key string) *StringSliceCmd HRandField(ctx context.Context, key string, count int) *StringSliceCmd HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd @@ -172,3 +173,17 @@ func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match str _ = c(ctx, cmd) return cmd } + +func (c cmdable) HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd { + args := []interface{}{"hscan", key, cursor} + if match != "" { + args = append(args, "match", match) + } + if count > 0 { + args = append(args, "count", count) + } + args = append(args, "novalues") + cmd := NewScanCmd(ctx, c, args...) + _ = c(ctx, cmd) + return cmd +} diff --git a/iterator_test.go b/iterator_test.go index ccd941478..dfa8fbbed 100644 --- a/iterator_test.go +++ b/iterator_test.go @@ -96,6 +96,22 @@ var _ = Describe("ScanIterator", func() { Expect(vals).To(HaveLen(71 * 2)) Expect(vals).To(ContainElement("K01")) Expect(vals).To(ContainElement("K71")) + Expect(vals).To(ContainElement("x")) + }) + + It("should hscan without values across multiple pages", func() { + Expect(hashSeed(71)).NotTo(HaveOccurred()) + + var vals []string + iter := client.HScanNoValues(ctx, hashKey, 0, "", 10).Iterator() + for iter.Next(ctx) { + vals = append(vals, iter.Val()) + } + Expect(iter.Err()).NotTo(HaveOccurred()) + Expect(vals).To(HaveLen(71)) + Expect(vals).To(ContainElement("K01")) + Expect(vals).To(ContainElement("K71")) + Expect(vals).NotTo(ContainElement("x")) }) It("should scan to page borders", func() { From ed5e3038b11a70ce83018bf349f1432f0f107fcf Mon Sep 17 00:00:00 2001 From: ofekshenawa <104765379+ofekshenawa@users.noreply.github.com> Date: Thu, 20 Jun 2024 01:08:56 +0300 Subject: [PATCH 2/2] Update hash_commands.go --- hash_commands.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hash_commands.go b/hash_commands.go index 099fb2fa0..ef69064e0 100644 --- a/hash_commands.go +++ b/hash_commands.go @@ -187,6 +187,9 @@ func (c cmdable) HScanNoValues(ctx context.Context, key string, cursor uint64, m } args = append(args, "novalues") cmd := NewScanCmd(ctx, c, args...) + _ = c(ctx, cmd) + return cmd +} type HExpireArgs struct { NX bool