Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 106 additions & 7 deletions internal/server/crud.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ func (s *Server) cmdGET(msg *Message) (resp.Value, error) {

// >> Response

oval := buildObjectResponse(msg, o, start, kind, precision, withfields, msg.OutputType == JSON)

return oval, nil
}

func buildObjectResponse(msg *Message, o *object.Object, start time.Time, kind string, precision int64, withfields, json bool) resp.Value {
vals := make([]resp.Value, 0, 2)
var buf bytes.Buffer
if msg.OutputType == JSON {
Expand Down Expand Up @@ -240,7 +246,7 @@ func (s *Server) cmdGET(msg *Message) (resp.Value, error) {
}
var i int
o.Fields().Scan(func(f field.Field) bool {
if msg.OutputType == JSON {
if json {
if i > 0 {
buf.WriteString(`,`)
}
Expand All @@ -253,24 +259,24 @@ func (s *Server) cmdGET(msg *Message) (resp.Value, error) {
i++
return true
})
if msg.OutputType == JSON {
if json {
buf.WriteString(`}`)
} else {
vals = append(vals, resp.ArrayValue(fvals))
}
}
}
if msg.OutputType == JSON {
if json {
buf.WriteString(`,"elapsed":"` + time.Since(start).String() + "\"}")
return resp.StringValue(buf.String()), nil
return resp.StringValue(buf.String())
}
var oval resp.Value
if withfields {
oval = resp.ArrayValue(vals)
} else {
oval = vals[0]
}
return oval, nil
return oval
}

// DEL key id [ERRON404]
Expand Down Expand Up @@ -622,6 +628,10 @@ func (s *Server) cmdSET(msg *Message) (resp.Value, commandDetails, error) {
var ex int64
var xx bool
var nx bool
var ret bool
var withfields bool
kind := "object"
var precision int64
var oobj geojson.Object

args := msg.Args
Expand Down Expand Up @@ -665,6 +675,43 @@ func (s *Server) cmdSET(msg *Message) (resp.Value, commandDetails, error) {
return retwerr(errInvalidArgument(args[i]))
}
xx = true
case "return":
if ret {
return retwerr(errInvalidArgument(args[i]))
}
ret = true

for j := i; j < i+3; j++ {
if j >= len(args) {
break
}
switch strings.ToLower(args[j]) {
case "withfields":
withfields = true
i += 1
case "object":
kind = "object"
i += 1
case "point":
kind = "point"
i += 1
case "bounds":
kind = "bounds"
i += 1
case "hash":
kind = "hash"
j++
if j == len(args) {
return retwerr(errInvalidNumberOfArguments)
}
var err error
precision, err = strconv.ParseInt(args[j], 10, 64)
if err != nil || precision < 1 || precision > 12 {
return retwerr(errInvalidArgument(args[j]))
}
i += 2
}
}
case "string":
if i+1 >= len(args) {
return retwerr(errInvalidNumberOfArguments)
Expand Down Expand Up @@ -802,12 +849,16 @@ func (s *Server) cmdSET(msg *Message) (resp.Value, commandDetails, error) {
d.updated = true // perhaps we should do a diff on the previous object?
d.timestamp = time.Now()

if ret {
res := buildObjectResponse(msg, obj, start, kind, precision, withfields, msg.OutputType == JSON)
return res, d, nil
}

var res resp.Value
switch msg.OutputType {
default:
case JSON:
res = resp.StringValue(`{"ok":true,"elapsed":"` +
time.Since(start).String() + "\"}")
res = resp.StringValue(`{"ok":true,"elapsed":"` + time.Since(start).String() + "\"}")
case RESP:
res = resp.SimpleStringValue("OK")
}
Expand All @@ -833,6 +884,11 @@ func (s *Server) cmdFSET(msg *Message) (resp.Value, commandDetails, error) {
var id string
var key string
var xx bool
var ret bool
var withfields bool
kind := "object"
var precision int64

var fields []field.Field // raw fields

args := msg.Args
Expand All @@ -845,6 +901,44 @@ func (s *Server) cmdFSET(msg *Message) (resp.Value, commandDetails, error) {
switch strings.ToLower(arg) {
case "xx":
xx = true
case "return":
if ret {
return retwerr(errInvalidArgument(args[i]))
}
ret = true

for j := i; j < i+3; j++ {
if j >= len(args) {
break
}
switch strings.ToLower(args[j]) {
case "withfields":
withfields = true
i += 1
case "object":
kind = "object"
i += 1
case "point":
kind = "point"
i += 1
case "bounds":
kind = "bounds"
i += 1
case "hash":
kind = "hash"
j++
if j == len(args) {
return retwerr(errInvalidNumberOfArguments)
}
var err error
precision, err = strconv.ParseInt(args[j], 10, 64)
if err != nil || precision < 1 || precision > 12 {
return retwerr(errInvalidArgument(args[j]))
}
i += 2
}
}

default:
fkey := arg
i++
Expand Down Expand Up @@ -896,6 +990,11 @@ func (s *Server) cmdFSET(msg *Message) (resp.Value, commandDetails, error) {

var res resp.Value

if ret {
res := buildObjectResponse(msg, d.obj, start, kind, precision, withfields, msg.OutputType == JSON)
return res, d, nil
}

switch msg.OutputType {
case JSON:
res = resp.StringValue(`{"ok":true,"elapsed":"` +
Expand Down
38 changes: 38 additions & 0 deletions tests/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ func keys_FSET_test(mc *mockServer) error {
Do("FSET", "mykey", "myid", "f2", 0).Str("1"),
Do("GET", "mykey", "myid", "WITHFIELDS", "HASH", 7).Str("[9my5xp7]"),
Do("FSET", "mykey", "myid2", "xx", "f1", 1.1, "f2", 2.2).Str("0"),

Do("FSET", "mykey", "myid", "f1", 1, "RETURN", "HASH", 7, "WITHFIELDS").Str("[9my5xp7 [f1 1]]"),
Do("FSET", "mykey", "myid", "f2", 2, "RETURN", "HASH", 7, "WITHFIELDS").Str("[9my5xp7 [f1 1 f2 2]]"),
Do("FSET", "mykey", "myid", "f1", 0, "RETURN", "HASH", 7, "WITHFIELDS").Str("[9my5xp7 [f2 2]]"),
Do("FSET", "mykey", "myid", "f2", 0, "RETURN", "HASH", 7, "WITHFIELDS").Str("[9my5xp7]"),

Do("GET", "mykey", "myid2").Str("<nil>"),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),
Expand Down Expand Up @@ -333,6 +339,15 @@ func keys_SET_test(mc *mockServer) error {
Do("GET", "mykey", "myid").Str("<nil>"),
Do("SET", "mykey", "myid", "point", "33", "-112", "99").OK(),

Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN").Str(`{"type":"Point","coordinates":[-115,33]}`),
Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN", "POINT").Str("[33 -115]"),
Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN", "OBJECT").Str(`{"type":"Point","coordinates":[-115,33]}`),
Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN", "BOUNDS").Str("[[33 -115] [33 -115]]"),
Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN", "OBJECT").Str(`{"type":"Point","coordinates":[-115,33]}`),
Do("SET", "mykey", "myid", "POINT", 33, -115, "RETURN", "HASH", 7).Str("9my5xp7"),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

// Section: object
Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`).OK(),
Do("GET", "mykey", "myid", "POINT").Str("[33 -115]"),
Expand All @@ -342,6 +357,14 @@ func keys_SET_test(mc *mockServer) error {
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`, "RETURN").Str(`{"type":"Point","coordinates":[-115,33]}`),
Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`, "RETURN", "POINT").Str("[33 -115]"),
Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`, "RETURN", "BOUNDS").Str("[[33 -115] [33 -115]]"),
Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`, "RETURN", "OBJECT").Str(`{"type":"Point","coordinates":[-115,33]}`),
Do("SET", "mykey", "myid", "OBJECT", `{"type":"Point","coordinates":[-115,33]}`, "RETURN", "HASH", 7).Str("9my5xp7"),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

// Section: bounds
Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115).OK(),
Do("GET", "mykey", "myid", "POINT").Str("[33 -115]"),
Expand All @@ -351,16 +374,31 @@ func keys_SET_test(mc *mockServer) error {
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115, "RETURN").Str(`{"type":"Polygon","coordinates":[[[-115,33],[-115,33],[-115,33],[-115,33],[-115,33]]]}`),
Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115, "RETURN", "POINT").Str("[33 -115]"),
Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115, "RETURN", "BOUNDS").Str("[[33 -115] [33 -115]]"),
Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115, "RETURN", "OBJECT").Str(`{"type":"Polygon","coordinates":[[[-115,33],[-115,33],[-115,33],[-115,33],[-115,33]]]}`),
Do("SET", "mykey", "myid", "BOUNDS", 33, -115, 33, -115, "RETURN", "HASH", 7).Str("9my5xp7"),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

// Section: hash
Do("SET", "mykey", "myid", "HASH", "9my5xp7").OK(),
Do("GET", "mykey", "myid", "HASH", 7).Str("9my5xp7"),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),
Do("SET", "mykey", "myid", "HASH", "9my5xp7").JSON().OK(),

Do("SET", "mykey", "myid", "HASH", "9my5xp7", "RETURN").JSON().OK(),
Do("SET", "mykey", "myid", "HASH", "9my5xp7", "RETURN", "HASH", 7).JSON().Str(`{"ok":true,"hash":"9my5xp7"}`),
Do("DEL", "mykey", "myid").Str("1"),
Do("GET", "mykey", "myid").Str("<nil>"),

// Section: field
Do("SET", "mykey", "myid", "FIELD", "f1", 33, "FIELD", "a2", 44.5, "HASH", "9my5xp7").OK(),
Do("GET", "mykey", "myid", "WITHFIELDS", "HASH", 7).Str("[9my5xp7 [a2 44.5 f1 33]]"),
Do("DEL", "mykey", "myid").Str("1"),
Do("SET", "mykey", "myid", "FIELD", "f1", 33, "FIELD", "a2", 44.5, "HASH", "9my5xp7", "RETURN", "WITHFIELDS", "HASH", 7).Str("[9my5xp7 [a2 44.5 f1 33]]"),
Do("FSET", "mykey", "myid", "f1", 0).Str("1"),
Do("FSET", "mykey", "myid", "f1", 0).Str("0"),
Do("GET", "mykey", "myid", "WITHFIELDS", "HASH", 7).Str("[9my5xp7 [a2 44.5]]"),
Expand Down