Skip to content

Commit

Permalink
Go: add SUnion command (valkey-io#2787)
Browse files Browse the repository at this point in the history
Go: add SUnion command

---------

Signed-off-by: Chloe Yip <[email protected]>
Co-authored-by: James Xin <[email protected]>
  • Loading branch information
cyip10 and jamesx-improving authored Dec 14, 2024
1 parent 8b049d4 commit 68c56e7
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#### Changes

* Go: Add SUNIONSTORE command ([#2805](https://github.com/valkey-io/valkey-glide/pull/2805)
* Go: Add SUNION ([#2787](https://github.com/valkey-io/valkey-glide/pull/2787)
* Java: bump `netty` version ([#2795](https://github.com/valkey-io/valkey-glide/pull/2795))
* Java: Bump protobuf (protoc) version ([#2796](https://github.com/valkey-io/valkey-glide/pull/2796), [#2800](https://github.com/valkey-io/valkey-glide/pull/2800))
* Go: Add `SInterStore` ([#2779](https://github.com/valkey-io/valkey-glide/issues/2779))
Expand Down
9 changes: 9 additions & 0 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,15 @@ func (client *baseClient) SMIsMember(key string, members []string) ([]Result[boo
return handleBooleanArrayResponse(result)
}

func (client *baseClient) SUnion(keys []string) (map[Result[string]]struct{}, error) {
result, err := client.executeCommand(C.SUnion, keys)
if err != nil {
return nil, err
}

return handleStringSetResponse(result)
}

func (client *baseClient) LRange(key string, start int64, end int64) ([]Result[string], error) {
result, err := client.executeCommand(C.LRange, []string{key, utils.IntToString(start), utils.IntToString(end)})
if err != nil {
Expand Down
34 changes: 34 additions & 0 deletions go/api/set_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,38 @@ type SetCommands interface {
//
// [valkey.io]: https://valkey.io/commands/sunionstore/
SUnionStore(destination string, keys []string) (Result[int64], error)

// SUnion gets the union of all the given sets.
//
// Note: When in cluster mode, all keys must map to the same hash slot.
//
// See [valkey.io] for details.
//
// Parameters:
// keys - The keys of the sets.
//
// Return value:
// A map[Result[string]]struct{} of members which are present in at least one of the given sets.
// If none of the sets exist, an empty map will be returned.
//
//
// Example:
// result1, err := client.SAdd("my_set1", []string {"member1", "member2"})
// // result.Value(): 2
// // result.IsNil(): false
//
// result2, err := client.SAdd("my_set2", []string {"member2", "member3"})
// // result.Value(): 2
// // result.IsNil(): false
//
// result3, err := client.SUnion([]string {"my_set1", "my_set2"})
// // result3.Value(): "{'member1', 'member2', 'member3'}"
// // err: nil
//
// result4, err := client.SUnion([]string {"my_set1", "non_existing_set"})
// // result4.Value(): "{'member1', 'member2'}"
// // err: nil
//
// [valkey.io]: https://valkey.io/commands/sunion/
SUnion(keys []string) (map[Result[string]]struct{}, error)
}
56 changes: 56 additions & 0 deletions go/integTest/shared_commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,62 @@ func (suite *GlideTestSuite) TestSMIsMember() {
})
}

func (suite *GlideTestSuite) TestSUnion() {
suite.runWithDefaultClients(func(client api.BaseClient) {
key1 := "{key}-1-" + uuid.NewString()
key2 := "{key}-2-" + uuid.NewString()
key3 := "{key}-3-" + uuid.NewString()
nonSetKey := uuid.NewString()
memberList1 := []string{"a", "b", "c"}
memberList2 := []string{"b", "c", "d", "e"}
expected1 := map[api.Result[string]]struct{}{
api.CreateStringResult("a"): {},
api.CreateStringResult("b"): {},
api.CreateStringResult("c"): {},
api.CreateStringResult("d"): {},
api.CreateStringResult("e"): {},
}
expected2 := map[api.Result[string]]struct{}{
api.CreateStringResult("a"): {},
api.CreateStringResult("b"): {},
api.CreateStringResult("c"): {},
}

res1, err := client.SAdd(key1, memberList1)
assert.Nil(suite.T(), err)
assert.Equal(suite.T(), int64(3), res1.Value())
assert.False(suite.T(), res1.IsNil())

res2, err := client.SAdd(key2, memberList2)
assert.Nil(suite.T(), err)
assert.Equal(suite.T(), int64(4), res2.Value())
assert.False(suite.T(), res2.IsNil())

res3, err := client.SUnion([]string{key1, key2})
assert.Nil(suite.T(), err)
assert.True(suite.T(), reflect.DeepEqual(res3, expected1))

res4, err := client.SUnion([]string{key3})
assert.Nil(suite.T(), err)
assert.Equal(suite.T(), map[api.Result[string]]struct{}{}, res4)

res5, err := client.SUnion([]string{key1, key3})
assert.Nil(suite.T(), err)
assert.True(suite.T(), reflect.DeepEqual(res5, expected2))

// Exceptions with empty keys
res6, err := client.SUnion([]string{})
assert.Nil(suite.T(), res6)
assert.IsType(suite.T(), &api.RequestError{}, err)

// Exception with a non-set key
suite.verifyOK(client.Set(nonSetKey, "value"))
res7, err := client.SUnion([]string{nonSetKey, key1})
assert.Nil(suite.T(), res7)
assert.IsType(suite.T(), &api.RequestError{}, err)
})
}

func (suite *GlideTestSuite) TestLRange() {
suite.runWithDefaultClients(func(client api.BaseClient) {
list := []string{"value4", "value3", "value2", "value1"}
Expand Down

0 comments on commit 68c56e7

Please sign in to comment.