Skip to content

Commit 9e869e0

Browse files
authored
Merge branch 'master' into exists
2 parents c17482a + 62bb041 commit 9e869e0

File tree

9 files changed

+116
-7
lines changed

9 files changed

+116
-7
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ To set a field when an object already exists:
144144
> fset fleet truck1 speed 90
145145
```
146146

147+
To get a field when an object already exists:
148+
```
149+
> fget fleet truck1 speed
150+
```
151+
147152
## Searching
148153

149154
Tile38 has support to search for objects and points that are within or intersects other objects. All object types can be searched including Polygons, MultiPolygons, GeometryCollections, etc.

core/commands.json

+20
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,26 @@
232232
"since": "1.0.0",
233233
"group": "keys"
234234
},
235+
"FGET": {
236+
"summary": "Gets the value for the field of an id",
237+
"complexity": "O(1)",
238+
"arguments": [
239+
{
240+
"name": "key",
241+
"type": "string"
242+
},
243+
{
244+
"name": "id",
245+
"type": "string"
246+
},
247+
{
248+
"name": "field",
249+
"type": "string"
250+
}
251+
],
252+
"since": "1.33.0",
253+
"group": "keys"
254+
},
235255
"BOUNDS": {
236256
"summary": "Get the combined bounds of all the objects in a key",
237257
"complexity": "O(1)",

core/commands_gen.go

+20
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,26 @@ var commandsJSON = `{
398398
"since": "1.0.0",
399399
"group": "keys"
400400
},
401+
"FGET": {
402+
"summary": "Gets the value for the field of an id",
403+
"complexity": "O(1)",
404+
"arguments": [
405+
{
406+
"name": "key",
407+
"type": "string"
408+
},
409+
{
410+
"name": "id",
411+
"type": "string"
412+
},
413+
{
414+
"name": "field",
415+
"type": "string"
416+
}
417+
],
418+
"since": "1.33.0",
419+
"group": "keys"
420+
},
401421
"BOUNDS": {
402422
"summary": "Get the combined bounds of all the objects in a key",
403423
"complexity": "O(1)",

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,5 @@ require (
112112
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
113113
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
114114
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
115-
google.golang.org/protobuf v1.31.0 // indirect
115+
google.golang.org/protobuf v1.33.0 // indirect
116116
)

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -732,8 +732,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
732732
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
733733
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
734734
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
735-
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
736-
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
735+
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
736+
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
737737
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
738738
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
739739
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/server/crud.go

+40
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,46 @@ func (s *Server) cmdFSET(msg *Message) (resp.Value, commandDetails, error) {
907907
return res, d, nil
908908
}
909909

910+
// FGET key id field
911+
func (s *Server) cmdFGET(msg *Message) (resp.Value, error) {
912+
start := time.Now()
913+
914+
// >> Args
915+
916+
args := msg.Args
917+
918+
if len(args) < 4 {
919+
return retrerr(errInvalidNumberOfArguments)
920+
}
921+
key, id, field := args[1], args[2], args[3]
922+
923+
// >> Operation
924+
925+
col, _ := s.cols.Get(key)
926+
if col == nil {
927+
return retrerr(errKeyNotFound)
928+
}
929+
o := col.Get(id)
930+
if o == nil {
931+
return retrerr(errIDNotFound)
932+
}
933+
f := o.Fields().Get(field)
934+
935+
// >> Response
936+
937+
var buf bytes.Buffer
938+
switch msg.OutputType {
939+
case JSON:
940+
buf.WriteString(`{"ok":true`)
941+
buf.WriteString(`,"value":` + f.Value().JSON())
942+
buf.WriteString(`,"elapsed":"` + time.Since(start).String() + "\"}")
943+
return resp.StringValue(buf.String()), nil
944+
case RESP:
945+
return resp.StringValue(f.Value().Data()), nil
946+
}
947+
return NOMessage, nil
948+
}
949+
910950
// EXPIRE key id seconds
911951
func (s *Server) cmdEXPIRE(msg *Message) (resp.Value, commandDetails, error) {
912952
start := time.Now()

internal/server/scripts.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ func (s *Server) commandInScript(msg *Message) (
665665
res, err = s.cmdBOUNDS(msg)
666666
case "get":
667667
res, err = s.cmdGET(msg)
668+
case "fget":
669+
res, err = s.cmdFGET(msg)
668670
case "jget":
669671
res, err = s.cmdJget(msg)
670672
case "jset":
@@ -739,7 +741,7 @@ func (s *Server) luaTile38AtomicRW(msg *Message) (resp.Value, error) {
739741
return resp.NullValue(), errReadOnly
740742
}
741743
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
742-
"ttl", "bounds", "server", "info", "type", "jget", "exists", "fexists", "test":
744+
"ttl", "bounds", "server", "info", "type", "jget", "fget", "exists", "fexists", "test":
743745
// read operations
744746
if s.config.followHost() != "" && !s.fcuponce {
745747
return resp.NullValue(), errCatchingUp
@@ -792,7 +794,7 @@ func (s *Server) luaTile38AtomicRO(msg *Message) (resp.Value, error) {
792794
return resp.NullValue(), errReadOnly
793795

794796
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
795-
"ttl", "bounds", "server", "info", "type", "jget", "exists", "fexists", "test":
797+
"ttl", "bounds", "server", "info", "type", "jget", "fget", "exists", "fexists", "test":
796798
// read operations
797799
if s.config.followHost() != "" && !s.fcuponce {
798800
return resp.NullValue(), errCatchingUp
@@ -843,7 +845,7 @@ func (s *Server) luaTile38NonAtomic(msg *Message) (resp.Value, error) {
843845
return resp.NullValue(), errReadOnly
844846
}
845847
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks", "search",
846-
"ttl", "bounds", "server", "info", "type", "jget", "exists", "fexists", "test":
848+
"ttl", "bounds", "server", "info", "type", "jget", "fget", "exists", "fexists", "test":
847849
// read operations
848850
s.mu.RLock()
849851
defer s.mu.RUnlock()

internal/server/server.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ func (s *Server) handleInputCommand(client *Client, msg *Message) error {
10241024
}
10251025
case "get", "keys", "scan", "nearby", "within", "intersects", "hooks",
10261026
"chans", "search", "ttl", "bounds", "server", "info", "type", "jget",
1027-
"evalro", "evalrosha", "healthz", "role", "exists", "fexists":
1027+
"evalro", "evalrosha", "healthz", "role", "fget", "exists", "fexists":
10281028
// read operations
10291029

10301030
s.mu.RLock()
@@ -1227,6 +1227,8 @@ func (s *Server) command(msg *Message, client *Client) (
12271227
res, err = s.cmdBOUNDS(msg)
12281228
case "get":
12291229
res, err = s.cmdGET(msg)
1230+
case "fget":
1231+
res, err = s.cmdFGET(msg)
12301232
case "jget":
12311233
res, err = s.cmdJget(msg)
12321234
case "jset":

tests/keys_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func subTestKeys(g *testGroup) {
1919
g.regSubTest("RENAMENX", keys_RENAMENX_test)
2020
g.regSubTest("EXPIRE", keys_EXPIRE_test)
2121
g.regSubTest("FSET", keys_FSET_test)
22+
g.regSubTest("FGET", keys_FGET_test)
2223
g.regSubTest("GET", keys_GET_test)
2324
g.regSubTest("KEYS", keys_KEYS_test)
2425
g.regSubTest("PERSIST", keys_PERSIST_test)
@@ -203,6 +204,25 @@ func keys_FSET_test(mc *mockServer) error {
203204
Do("FSET", "mykey", "myid", "f2", 0).JSON().OK(),
204205
)
205206
}
207+
func keys_FGET_test(mc *mockServer) error {
208+
return mc.DoBatch(
209+
Do("SET", "mykey", "myid", "HASH", "9my5xp7").OK(),
210+
Do("GET", "mykey", "myid", "WITHFIELDS", "HASH", 7).Str("[9my5xp7]"),
211+
Do("FSET", "mykey", "myid", "f1", 105.6).Str("1"),
212+
Do("FGET", "mykey", "myid", "f1").Str("105.6"),
213+
Do("FSET", "mykey", "myid", "f1", 1.1, "f2", 2.2).Str("2"),
214+
Do("FGET", "mykey", "myid", "f2").Str("2.2"),
215+
Do("FGET", "mykey", "myid", "f1").Str("1.1"),
216+
Do("FGET", "mykey", "myid", "f1").JSON().Str(`{"ok":true,"value":1.1}`),
217+
Do("FSET", "mykey", "myid", "f3", "a").Str("1"),
218+
Do("FGET", "mykey", "myid", "f3").Str("a"),
219+
Do("FGET", "mykey", "myid", "f4").Str("0"),
220+
Do("FGET", "mykey", "myid", "f4").JSON().Str(`{"ok":true,"value":0}`),
221+
Do("FGET", "mykey", "myid").Err("wrong number of arguments for 'fget' command"),
222+
Do("FGET", "mykey2", "myid", "a", "b").Err("key not found"),
223+
Do("FGET", "mykey", "myid2", "a", "b").Err("id not found"),
224+
)
225+
}
206226
func keys_GET_test(mc *mockServer) error {
207227
return mc.DoBatch(
208228
Do("SET", "mykey", "myid", "STRING", "value").OK(),

0 commit comments

Comments
 (0)