Skip to content

Commit 1cb643a

Browse files
authored
Merge branch 'master' into feature/missing_vset_features
2 parents 80530fb + a6741de commit 1cb643a

2 files changed

Lines changed: 89 additions & 2 deletions

File tree

command.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7591,7 +7591,7 @@ type VectorScoreSliceCmd struct {
75917591

75927592
var _ Cmder = (*VectorScoreSliceCmd)(nil)
75937593

7594-
func NewVectorInfoSliceCmd(ctx context.Context, args ...any) *VectorScoreSliceCmd {
7594+
func NewVectorScoreSliceCmd(ctx context.Context, args ...any) *VectorScoreSliceCmd {
75957595
return &VectorScoreSliceCmd{
75967596
baseCmd: baseCmd{
75977597
ctx: ctx,
@@ -7600,6 +7600,11 @@ func NewVectorInfoSliceCmd(ctx context.Context, args ...any) *VectorScoreSliceCm
76007600
}
76017601
}
76027602

7603+
// NewVectorInfoSliceCmd is an alias for NewVectorScoreSliceCmd kept for backwards compatibility.
7604+
func NewVectorInfoSliceCmd(ctx context.Context, args ...any) *VectorScoreSliceCmd {
7605+
return NewVectorScoreSliceCmd(ctx, args...)
7606+
}
7607+
76037608
func (cmd *VectorScoreSliceCmd) SetVal(val []VectorScore) {
76047609
cmd.val = val
76057610
}
@@ -7617,11 +7622,29 @@ func (cmd *VectorScoreSliceCmd) String() string {
76177622
}
76187623

76197624
func (cmd *VectorScoreSliceCmd) readReply(rd *proto.Reader) error {
7620-
n, err := rd.ReadMapLen()
7625+
typ, err := rd.PeekReplyType()
76217626
if err != nil {
76227627
return err
76237628
}
76247629

7630+
var n int
7631+
if typ == proto.RespMap {
7632+
n, err = rd.ReadMapLen()
7633+
if err != nil {
7634+
return err
7635+
}
7636+
} else {
7637+
// RESP2 returns a flat array [name, score, name, score, ...]
7638+
n, err = rd.ReadArrayLen()
7639+
if err != nil {
7640+
return err
7641+
}
7642+
if n%2 != 0 {
7643+
return fmt.Errorf("redis: VectorScoreSliceCmd expects even number of elements, got %d", n)
7644+
}
7645+
n /= 2
7646+
}
7647+
76257648
cmd.val = make([]VectorScore, n)
76267649
for i := 0; i < n; i++ {
76277650
name, err := rd.ReadString()

vectorset_commands_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package redis
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"reflect"
78
"strings"
89
"testing"
@@ -715,5 +716,68 @@ func TestVIsMember(t *testing.T) {
715716
cmd := m.lastCmd.(*BoolCmd)
716717
if cmd.args[0] != "vismember" || cmd.args[1] != "k" || cmd.args[2] != "e" {
717718
t.Errorf("unexpected args: %v", cmd.args)
719+
}
720+
}
721+
722+
// TestVectorScoreSliceCmdReadReply tests that VectorScoreSliceCmd.readReply handles
723+
// both RESP2 (flat array) and RESP3 (map) protocol responses.
724+
func TestVectorScoreSliceCmdReadReply(t *testing.T) {
725+
tests := []struct {
726+
name string
727+
respData []byte
728+
want []VectorScore
729+
wantErr bool
730+
}{
731+
{
732+
// RESP3 map: %2\r\n +elem1\r\n ,0.9\r\n +elem2\r\n ,0.8\r\n
733+
name: "RESP3 map response",
734+
respData: []byte("%2\r\n+elem1\r\n,0.9\r\n+elem2\r\n,0.8\r\n"),
735+
want: []VectorScore{
736+
{Name: "elem1", Score: 0.9},
737+
{Name: "elem2", Score: 0.8},
738+
},
739+
},
740+
{
741+
// RESP2 flat array: *4\r\n $5\r\nelem1\r\n $3\r\n0.9\r\n $5\r\nelem2\r\n $3\r\n0.8\r\n
742+
name: "RESP2 flat array response",
743+
respData: []byte(fmt.Sprintf("*4\r\n$5\r\nelem1\r\n$%d\r\n%s\r\n$5\r\nelem2\r\n$%d\r\n%s\r\n",
744+
len("0.9"), "0.9", len("0.8"), "0.8")),
745+
want: []VectorScore{
746+
{Name: "elem1", Score: 0.9},
747+
{Name: "elem2", Score: 0.8},
748+
},
749+
},
750+
{
751+
// RESP3 empty map
752+
name: "RESP3 empty map",
753+
respData: []byte("%0\r\n"),
754+
want: []VectorScore{},
755+
},
756+
{
757+
// RESP2 empty array
758+
name: "RESP2 empty array",
759+
respData: []byte("*0\r\n"),
760+
want: []VectorScore{},
761+
},
762+
{
763+
// RESP2 odd-length array should return an error
764+
name: "RESP2 odd array returns error",
765+
respData: []byte("*3\r\n$5\r\nelem1\r\n$3\r\n0.9\r\n$5\r\nelem2\r\n"),
766+
wantErr: true,
767+
},
768+
}
769+
770+
for _, tt := range tests {
771+
t.Run(tt.name, func(t *testing.T) {
772+
rd := proto.NewReader(newMockConn(tt.respData))
773+
cmd := NewVectorScoreSliceCmd(context.Background(), "vsim", "key", "withscores")
774+
err := cmd.readReply(rd)
775+
if (err != nil) != tt.wantErr {
776+
t.Fatalf("readReply() error = %v, wantErr %v", err, tt.wantErr)
777+
}
778+
if !tt.wantErr && !reflect.DeepEqual(cmd.Val(), tt.want) {
779+
t.Errorf("Val() = %v, want %v", cmd.Val(), tt.want)
780+
}
781+
})
718782
}
719783
}

0 commit comments

Comments
 (0)