diff --git a/command.go b/command.go index e05f0ed3..6eba5640 100644 --- a/command.go +++ b/command.go @@ -4168,3 +4168,81 @@ func (cmd *LCSCmd) readPosition(rd *proto.Reader) (pos LCSPosition, err error) { return pos, nil } + +// ------------------------------------------------------------------------ + +type KeyFlags struct { + Key string + Flags []string +} + +type KeyFlagsCmd struct { + baseCmd + + val []KeyFlags +} + +var _ Cmder = (*KeyFlagsCmd)(nil) + +func NewKeyFlagsCmd(ctx context.Context, args ...interface{}) *KeyFlagsCmd { + return &KeyFlagsCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: args, + }, + } +} + +func (cmd *KeyFlagsCmd) SetVal(val []KeyFlags) { + cmd.val = val +} + +func (cmd *KeyFlagsCmd) Val() []KeyFlags { + return cmd.val +} + +func (cmd *KeyFlagsCmd) Result() ([]KeyFlags, error) { + return cmd.val, cmd.err +} + +func (cmd *KeyFlagsCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *KeyFlagsCmd) readReply(rd *proto.Reader) error { + n, err := rd.ReadArrayLen() + if err != nil { + return err + } + + if n == 0 { + cmd.val = make([]KeyFlags, 0) + return nil + } + + cmd.val = make([]KeyFlags, n) + + for i := 0; i < len(cmd.val); i++ { + + if err = rd.ReadFixedArrayLen(2); err != nil { + return err + } + + if cmd.val[i].Key, err = rd.ReadString(); err != nil { + return err + } + flagsLen, err := rd.ReadArrayLen() + if err != nil { + return err + } + cmd.val[i].Flags = make([]string, flagsLen) + + for j := 0; j < flagsLen; j++ { + if cmd.val[i].Flags[j], err = rd.ReadString(); err != nil { + return err + } + } + } + + return nil +} diff --git a/commands.go b/commands.go index 27f11fdb..200ec510 100644 --- a/commands.go +++ b/commands.go @@ -129,6 +129,8 @@ type Cmdable interface { Command(ctx context.Context) *CommandsInfoCmd CommandList(ctx context.Context, filter *FilterBy) *StringSliceCmd + CommandGetKeys(ctx context.Context, commands ...interface{}) *StringSliceCmd + CommandGetKeysAndFlags(ctx context.Context, commands ...interface{}) *KeyFlagsCmd ClientGetName(ctx context.Context) *StringCmd Echo(ctx context.Context, message interface{}) *StringCmd Ping(ctx context.Context) *StatusCmd @@ -568,6 +570,26 @@ func (c cmdable) CommandList(ctx context.Context, filter *FilterBy) *StringSlice return cmd } +func (c cmdable) CommandGetKeys(ctx context.Context, commands ...interface{}) *StringSliceCmd { + args := make([]interface{}, 2+len(commands)) + args[0] = "command" + args[1] = "getkeys" + copy(args[2:], commands) + cmd := NewStringSliceCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + +func (c cmdable) CommandGetKeysAndFlags(ctx context.Context, commands ...interface{}) *KeyFlagsCmd { + args := make([]interface{}, 2+len(commands)) + args[0] = "command" + args[1] = "getkeysandflags" + copy(args[2:], commands) + cmd := NewKeyFlagsCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + // ClientGetName returns the name of the connection. func (c cmdable) ClientGetName(ctx context.Context) *StringCmd { cmd := NewStringCmd(ctx, "client", "getname") diff --git a/commands_test.go b/commands_test.go index 05509f55..b6448609 100644 --- a/commands_test.go +++ b/commands_test.go @@ -132,6 +132,43 @@ var _ = Describe("Commands", func() { }, "30s").Should(Equal("Background saving started")) }) + It("Should CommandGetKeys", func() { + keys, err := client.CommandGetKeys(ctx, "MSET", "a", "b", "c", "d", "e", "f").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).To(Equal([]string{"a", "c", "e"})) + + keys, err = client.CommandGetKeys(ctx, "EVAL", "not consulted", "3", "key1", "key2", "key3", "arg1", "arg2", "arg3", "argN").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).To(Equal([]string{"key1", "key2", "key3"})) + + keys, err = client.CommandGetKeys(ctx, "SORT", "mylist", "ALPHA", "STORE", "outlist").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keys).To(Equal([]string{"mylist", "outlist"})) + + _, err = client.CommandGetKeys(ctx, "FAKECOMMAND", "arg1", "arg2").Result() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("ERR Invalid command specified")) + }) + + It("should CommandGetKeysAndFlags", func() { + keysAndFlags, err := client.CommandGetKeysAndFlags(ctx, "LMOVE", "mylist1", "mylist2", "left", "left").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(keysAndFlags).To(Equal([]redis.KeyFlags{ + { + Key: "mylist1", + Flags: []string{"RW", "access", "delete"}, + }, + { + Key: "mylist2", + Flags: []string{"RW", "insert"}, + }, + })) + + _, err = client.CommandGetKeysAndFlags(ctx, "FAKECOMMAND", "arg1", "arg2").Result() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("ERR Invalid command specified")) + }) + It("should ClientKill", func() { r := client.ClientKill(ctx, "1.1.1.1:1111") Expect(r.Err()).To(MatchError("ERR No such client"))