mirror of https://github.com/tidwall/tile38.git
Merge branch 'fset_multi_xx' of https://github.com/rshura/tile38 into rshura-fset_multi_xx
This commit is contained in:
commit
fb6c29203b
|
@ -233,6 +233,24 @@ func (c *Collection) SetField(id, field string, value float64) (obj geojson.Obje
|
||||||
return item.object, c.getFieldValues(id), updated, true
|
return item.object, c.getFieldValues(id), updated, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFields is similar to SetField, just setting multiple fields at once
|
||||||
|
func (c *Collection) SetFields(id string, in_fields []string, in_values []float64) (
|
||||||
|
obj geojson.Object, fields []float64, updated_count int, ok bool,
|
||||||
|
) {
|
||||||
|
i := c.items.Get(&itemT{id: id})
|
||||||
|
if i == nil {
|
||||||
|
ok = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item := i.(*itemT)
|
||||||
|
for idx, field := range in_fields {
|
||||||
|
if c.setField(item, field, in_values[idx]) {
|
||||||
|
updated_count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item.object, c.getFieldValues(id), updated_count, true
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Collection) setField(item *itemT, field string, value float64) (updated bool) {
|
func (c *Collection) setField(item *itemT, field string, value float64) (updated bool) {
|
||||||
idx, ok := c.fieldMap[field]
|
idx, ok := c.fieldMap[field]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -780,8 +780,9 @@ notok:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) parseFSetArgs(vs []resp.Value) (d commandDetailsT, err error) {
|
func (c *Controller) parseFSetArgs(vs []resp.Value) (
|
||||||
var svalue string
|
d commandDetailsT, fields []string, values []float64, xx bool, err error,
|
||||||
|
) {
|
||||||
var ok bool
|
var ok bool
|
||||||
if vs, d.key, ok = tokenval(vs); !ok || d.key == "" {
|
if vs, d.key, ok = tokenval(vs); !ok || d.key == "" {
|
||||||
err = errInvalidNumberOfArguments
|
err = errInvalidNumberOfArguments
|
||||||
|
@ -791,62 +792,73 @@ func (c *Controller) parseFSetArgs(vs []resp.Value) (d commandDetailsT, err erro
|
||||||
err = errInvalidNumberOfArguments
|
err = errInvalidNumberOfArguments
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if vs, d.field, ok = tokenval(vs); !ok || d.field == "" {
|
for len(vs) > 0 {
|
||||||
|
var name string
|
||||||
|
if vs, name, ok = tokenval(vs); !ok || name == "" {
|
||||||
err = errInvalidNumberOfArguments
|
err = errInvalidNumberOfArguments
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if isReservedFieldName(d.field) {
|
if lc(name, "xx") {
|
||||||
err = errInvalidNumberOfArguments
|
xx = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if isReservedFieldName(name) {
|
||||||
|
err = errInvalidArgument(name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var svalue string
|
||||||
|
var value float64
|
||||||
if vs, svalue, ok = tokenval(vs); !ok || svalue == "" {
|
if vs, svalue, ok = tokenval(vs); !ok || svalue == "" {
|
||||||
err = errInvalidNumberOfArguments
|
err = errInvalidNumberOfArguments
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(vs) != 0 {
|
value, err = strconv.ParseFloat(svalue, 64)
|
||||||
err = errInvalidNumberOfArguments
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.value, err = strconv.ParseFloat(svalue, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errInvalidArgument(svalue)
|
err = errInvalidArgument(svalue)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fields = append(fields, name)
|
||||||
|
values = append(values, value)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) cmdFset(msg *server.Message) (res resp.Value, d commandDetailsT, err error) {
|
func (c *Controller) cmdFset(msg *server.Message) (res resp.Value, d commandDetailsT, err error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
vs := msg.Values[1:]
|
vs := msg.Values[1:]
|
||||||
d, err = c.parseFSetArgs(vs)
|
var fields []string
|
||||||
|
var values []float64
|
||||||
|
var xx bool
|
||||||
|
var updated_count int
|
||||||
|
d, fields, values, xx, err = c.parseFSetArgs(vs)
|
||||||
|
|
||||||
col := c.getCol(d.key)
|
col := c.getCol(d.key)
|
||||||
if col == nil {
|
if col == nil {
|
||||||
err = errKeyNotFound
|
err = errKeyNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var ok bool
|
var ok bool
|
||||||
d.obj, d.fields, d.updated, ok = col.SetField(d.id, d.field, d.value)
|
d.obj, d.fields, updated_count, ok = col.SetFields(d.id, fields, values)
|
||||||
if !ok {
|
if !(ok || xx) {
|
||||||
err = errIDNotFound
|
err = errIDNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if ok {
|
||||||
d.command = "fset"
|
d.command = "fset"
|
||||||
d.timestamp = time.Now()
|
d.timestamp = time.Now()
|
||||||
|
d.updated = updated_count > 0
|
||||||
fmap := col.FieldMap()
|
fmap := col.FieldMap()
|
||||||
d.fmap = make(map[string]int)
|
d.fmap = make(map[string]int)
|
||||||
for key, idx := range fmap {
|
for key, idx := range fmap {
|
||||||
d.fmap[key] = idx
|
d.fmap[key] = idx
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch msg.OutputType {
|
switch msg.OutputType {
|
||||||
case server.JSON:
|
case server.JSON:
|
||||||
res = resp.StringValue(`{"ok":true,"elapsed":"` + time.Now().Sub(start).String() + "\"}")
|
res = resp.StringValue(`{"ok":true,"elapsed":"` + time.Now().Sub(start).String() + "\"}")
|
||||||
case server.RESP:
|
case server.RESP:
|
||||||
if d.updated {
|
res = resp.IntegerValue(updated_count)
|
||||||
res = resp.IntegerValue(1)
|
|
||||||
} else {
|
|
||||||
res = resp.IntegerValue(0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@
|
||||||
"group": "keys"
|
"group": "keys"
|
||||||
},
|
},
|
||||||
"FSET": {
|
"FSET": {
|
||||||
"summary": "Set the value for a single field of an id",
|
"summary": "Set the value for one or more fields of an id",
|
||||||
"complexity": "O(1)",
|
"complexity": "O(1)",
|
||||||
"arguments":[
|
"arguments":[
|
||||||
{
|
{
|
||||||
|
@ -177,12 +177,15 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "field",
|
"command": "XX",
|
||||||
"type": "string"
|
"name": [],
|
||||||
|
"type": [],
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "value",
|
"name": ["field","value"],
|
||||||
"type": "double"
|
"type": ["string","double"],
|
||||||
|
"multiple": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"since": "1.0.0",
|
"since": "1.0.0",
|
||||||
|
|
|
@ -80,9 +80,16 @@ func keys_FSET_test(mc *mockServer) error {
|
||||||
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7]"},
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7]"},
|
||||||
{"FSET", "mykey", "myid", "f1", 105.6}, {1},
|
{"FSET", "mykey", "myid", "f1", 105.6}, {1},
|
||||||
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7 [f1 105.6]]"},
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7 [f1 105.6]]"},
|
||||||
|
{"FSET", "mykey", "myid", "f1", 1.1, "f2", 2.2}, {2},
|
||||||
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7 [f1 1.1 f2 2.2]]"},
|
||||||
|
{"FSET", "mykey", "myid", "f1", 1.1, "f2", 22.22}, {1},
|
||||||
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7 [f1 1.1 f2 22.22]]"},
|
||||||
{"FSET", "mykey", "myid", "f1", 0}, {1},
|
{"FSET", "mykey", "myid", "f1", 0}, {1},
|
||||||
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7 [f2 22.22]]"},
|
||||||
|
{"FSET", "mykey", "myid", "f2", 0}, {1},
|
||||||
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7]"},
|
{"GET", "mykey", "myid", "WITHFIELDS", "HASH", 7}, {"[9my5xp7]"},
|
||||||
{"FSET", "mykey", "myid", "f1", 0}, {0},
|
{"FSET", "mykey", "myid2", "xx", "f1", 1.1, "f2", 2.2}, {0},
|
||||||
|
{"GET", "mykey", "myid2"}, {nil},
|
||||||
{"DEL", "mykey", "myid"}, {"1"},
|
{"DEL", "mykey", "myid"}, {"1"},
|
||||||
{"GET", "mykey", "myid"}, {nil},
|
{"GET", "mykey", "myid"}, {nil},
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue