Repository: go-redis/redis
Pull request #1263 (2020-02-19 13:15:28)

Rename HMSet to HSet and restore old HMSet
Fixes https://github.com/go-redis/redis/issues/1262
Closes https://github.com/go-redis/redis/pull/1246
Closes https://github.com/go-redis/redis/pull/1245


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cfa44d..88701cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## v7.2
+
+- Existing `HMSet` is renamed to `HSet` and old deprecated `HMSet` is restored for Redis 3 users.
+
 ## v7
 
 - *Important*. Tx.Pipeline now returns a non-transactional pipeline. Use Tx.TxPipeline for a transactional pipeline.
@@ -11,6 +15,7 @@
 - Add PubSub.ChannelWithSubscriptions that sends `*Subscription` in addition to `*Message` to allow detecting reconnections.
 - `time.Time` is now marshalled in RFC3339 format. `rdb.Get("foo").Time()` helper is added to parse the time.
 - `SetLimiter` is removed and added `Options.Limiter` instead.
+- `HMSet` is deprecated as of Redis v4.
 
 ## v6.15
 
diff --git a/commands.go b/commands.go
index 40d98da..d4447c4 100644
--- a/commands.go
+++ b/commands.go
@@ -130,8 +130,8 @@ type Cmdable interface {
 	HKeys(key string) *StringSliceCmd
 	HLen(key string) *IntCmd
 	HMGet(key string, fields ...string) *SliceCmd
-	HMSet(key string, values ...interface{}) *IntCmd
-	HSet(key, field string, value interface{}) *BoolCmd
+	HSet(key string, values ...interface{}) *IntCmd
+	HMSet(key string, values ...interface{}) *BoolCmd
 	HSetNX(key, field string, value interface{}) *BoolCmd
 	HVals(key string) *StringSliceCmd
 	BLPop(timeout time.Duration, keys ...string) *StringSliceCmd
@@ -983,13 +983,13 @@ func (c cmdable) HMGet(key string, fields ...string) *SliceCmd {
 	return cmd
 }
 
-// HMSet is like HSet, but accepts multiple values:
+// HSet accepts values in following formats:
 //   - HMSet("myhash", "key1", "value1", "key2", "value2")
 //   - HMSet("myhash", []string{"key1", "value1", "key2", "value2"})
 //   - HMSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
 //
-// Note that it uses HSET Redis command underneath because HMSET is deprecated.
-func (c cmdable) HMSet(key string, values ...interface{}) *IntCmd {
+// Note that it requires Redis v4 for multiple field/value pairs support.
+func (c cmdable) HSet(key string, values ...interface{}) *IntCmd {
 	args := make([]interface{}, 2, 2+len(values))
 	args[0] = "hset"
 	args[1] = key
@@ -999,8 +999,13 @@ func (c cmdable) HMSet(key string, values ...interface{}) *IntCmd {
 	return cmd
 }
 
-func (c cmdable) HSet(key, field string, value interface{}) *BoolCmd {
-	cmd := NewBoolCmd("hset", key, field, value)
+// HMSet is a deprecated version of HSet left for compatibility with Redis 3.
+func (c cmdable) HMSet(key string, values ...interface{}) *BoolCmd {
+	args := make([]interface{}, 2, 2+len(values))
+	args[0] = "hmset"
+	args[1] = key
+	args = appendArgs(args, values)
+	cmd := NewBoolCmd(args...)
 	_ = c(cmd)
 	return cmd
 }


Test patch:
diff --git a/commands_test.go b/commands_test.go
index e4fbf6a..1919cd7 100644
--- a/commands_test.go
+++ b/commands_test.go
@@ -1325,7 +1325,7 @@ var _ = Describe("Commands", func() {
 		It("should HIncrByFloat", func() {
 			hSet := client.HSet("hash", "field", "10.50")
 			Expect(hSet.Err()).NotTo(HaveOccurred())
-			Expect(hSet.Val()).To(Equal(true))
+			Expect(hSet.Val()).To(Equal(int64(1)))
 
 			hIncrByFloat := client.HIncrByFloat("hash", "field", 0.1)
 			Expect(hIncrByFloat.Err()).NotTo(HaveOccurred())
@@ -1333,7 +1333,7 @@ var _ = Describe("Commands", func() {
 
 			hSet = client.HSet("hash", "field", "5.0e3")
 			Expect(hSet.Err()).NotTo(HaveOccurred())
-			Expect(hSet.Val()).To(Equal(false))
+			Expect(hSet.Val()).To(Equal(int64(0)))
 
 			hIncrByFloat = client.HIncrByFloat("hash", "field", 2.0e2)
 			Expect(hIncrByFloat.Err()).NotTo(HaveOccurred())
@@ -1367,7 +1367,7 @@ var _ = Describe("Commands", func() {
 		})
 
 		It("should HMGet", func() {
-			err := client.HMSet("hash", "key1", "hello1", "key2", "hello2").Err()
+			err := client.HSet("hash", "key1", "hello1", "key2", "hello2").Err()
 			Expect(err).NotTo(HaveOccurred())
 
 			vals, err := client.HMGet("hash", "key1", "key2", "_").Result()
@@ -1375,8 +1375,8 @@ var _ = Describe("Commands", func() {
 			Expect(vals).To(Equal([]interface{}{"hello1", "hello2", nil}))
 		})
 
-		It("should HMSet", func() {
-			ok, err := client.HMSet("hash", map[string]interface{}{
+		It("should HSet", func() {
+			ok, err := client.HSet("hash", map[string]interface{}{
 				"key1": "hello1",
 				"key2": "hello2",
 			}).Result()
@@ -1399,7 +1399,7 @@ var _ = Describe("Commands", func() {
 		It("should HSet", func() {
 			hSet := client.HSet("hash", "key", "hello")
 			Expect(hSet.Err()).NotTo(HaveOccurred())
-			Expect(hSet.Val()).To(Equal(true))
+			Expect(hSet.Val()).To(Equal(int64(1)))
 
 			hGet := client.HGet("hash", "key")
 			Expect(hGet.Err()).NotTo(HaveOccurred())