Merge branch 'iwpnd-feat/add-sector-area'

This commit is contained in:
tidwall 2021-09-29 07:20:27 -07:00
commit ad6e5aeab8
16 changed files with 899 additions and 244 deletions

View File

@ -1,5 +1,5 @@
{
"SET":{
"SET": {
"summary": "Sets the value of an id",
"complexity": "O(1)",
"arguments": [
@ -35,14 +35,14 @@
{
"name": "XX"
}
]
]
},
{
"name": "value",
{
"name": "value",
"enumargs": [
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -51,7 +51,7 @@
},
{
"name": "POINT",
"arguments":[
"arguments": [
{
"name": "lat",
"type": "double"
@ -69,7 +69,7 @@
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -90,7 +90,7 @@
},
{
"name": "HASH",
"arguments":[
"arguments": [
{
"name": "geohash",
"type": "geohash"
@ -99,7 +99,7 @@
},
{
"name": "STRING",
"arguments":[
"arguments": [
{
"name": "value",
"type": "string"
@ -115,7 +115,7 @@
"EXPIRE": {
"summary": "Set a timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -135,7 +135,7 @@
"TTL": {
"summary": "Get a timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -151,7 +151,7 @@
"PERSIST": {
"summary": "Remove the existing timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -167,7 +167,7 @@
"FSET": {
"summary": "Set the value for one or more fields of an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -183,12 +183,12 @@
"optional": true
},
{
"name": ["field","value"],
"type": ["string","double"]
"name": ["field", "value"],
"type": ["string", "double"]
},
{
"name": ["field","value"],
"type": ["string","double"],
"name": ["field", "value"],
"type": ["string", "double"],
"multiple": true,
"optional": true
}
@ -199,7 +199,7 @@
"BOUNDS": {
"summary": "Get the combined bounds of all the objects in a key",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -211,7 +211,7 @@
"GET": {
"summary": "Get the object of an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -257,7 +257,7 @@
"DEL": {
"summary": "Delete an id from a key",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -273,7 +273,7 @@
"DROP": {
"summary": "Remove a key from the database",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -317,7 +317,7 @@
"KEYS": {
"summary": "Finds all keys matching the given pattern",
"complexity": "O(N) where N is the number of keys in the database",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -329,7 +329,7 @@
"STATS": {
"summary": "Show stats for one or more keys",
"complexity": "O(N) where N is the number of keys being requested",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string",
@ -342,7 +342,7 @@
"SEARCH": {
"summary": "Search for string values in a key",
"complexity": "O(N) where N is the number of values in the key",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -375,35 +375,35 @@
{
"name": "DESC"
}
]
},
]
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -433,7 +433,7 @@
"SCAN": {
"summary": "Incrementally iterate though a key",
"complexity": "O(N) where N is the number of ids in the key",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -466,35 +466,35 @@
{
"name": "DESC"
}
]
},
]
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -542,7 +542,7 @@
"NEARBY": {
"summary": "Searches for ids that are nearby a point",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -579,31 +579,31 @@
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -684,7 +684,7 @@
},
{
"name": "ROAM",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -708,7 +708,7 @@
"WITHIN": {
"summary": "Searches for ids that completely within the area",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -739,31 +739,31 @@
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -840,7 +840,7 @@
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -861,7 +861,7 @@
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -887,7 +887,7 @@
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -904,7 +904,7 @@
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -919,6 +919,31 @@
"type": "geohash"
}
]
},
{
"name": "SECTOR",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "radius",
"type": "double"
},
{
"name": "startBearing",
"type": "double"
},
{
"name": "endBearing",
"type": "double"
}
]
}
]
}
@ -929,7 +954,7 @@
"INTERSECTS": {
"summary": "Searches for ids that intersect an area",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -960,31 +985,31 @@
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -1067,7 +1092,7 @@
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -1088,7 +1113,7 @@
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -1114,7 +1139,7 @@
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -1131,7 +1156,7 @@
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -1146,6 +1171,31 @@
"type": "geohash"
}
]
},
{
"name": "SECTOR",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "radius",
"type": "double"
},
{
"name": "startBearing",
"type": "double"
},
{
"name": "endBearing",
"type": "double"
}
]
}
]
}
@ -1155,7 +1205,7 @@
},
"CONFIG GET": {
"summary": "Get the value of a configuration parameter",
"arguments":[
"arguments": [
{
"name": "parameter",
"type": "string"
@ -1165,7 +1215,7 @@
},
"CONFIG SET": {
"summary": "Set a configuration parameter to the given value",
"arguments":[
"arguments": [
{
"name": "parameter",
"type": "string"
@ -1180,18 +1230,18 @@
},
"CONFIG REWRITE": {
"summary": "Rewrite the configuration file with the in memory configuration",
"arguments":[],
"arguments": [],
"group": "server"
},
"SERVER": {
"summary":"Show server stats and details",
"summary": "Show server stats and details",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
"group": "server"
},
"GC": {
"summary":"Forces a garbage collection",
"summary": "Forces a garbage collection",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
@ -1202,14 +1252,14 @@
"complexity": "O(1)",
"arguments": [
{
"enum": ["yes","no"]
"enum": ["yes", "no"]
}
],
"since": "1.0.0",
"group": "server"
},
"FLUSHDB": {
"summary":"Removes all keys",
"summary": "Removes all keys",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
@ -1335,7 +1385,7 @@
"name": ["name", "value"],
"type": ["string", "string"],
"optional": true,
"multiple": true
"multiple": true
},
{
"command": "EX",
@ -1373,7 +1423,6 @@
"type": "string",
"variadic": true
}
],
"group": "webhook"
},
@ -1389,7 +1438,7 @@
},
"HOOKS": {
"summary": "Finds all hooks matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1399,7 +1448,7 @@
},
"PDELHOOK": {
"summary": "Removes all hooks matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1420,7 +1469,7 @@
"name": ["name", "value"],
"type": ["string", "string"],
"optional": true,
"multiple": true
"multiple": true
},
{
"command": "EX",
@ -1458,7 +1507,6 @@
"type": "string",
"variadic": true
}
],
"group": "pubsub"
},
@ -1474,7 +1522,7 @@
},
"CHANS": {
"summary": "Finds all channels matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1484,7 +1532,7 @@
},
"PDELCHAN": {
"summary": "Removes all channels matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1494,7 +1542,7 @@
},
"SUBSCRIBE": {
"summary": "Subscribe to a geofence channel",
"arguments":[
"arguments": [
{
"name": "channel",
"type": "string",
@ -1505,7 +1553,7 @@
},
"PSUBSCRIBE": {
"summary": "Subscribes the client to the given patterns",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern",
@ -1516,12 +1564,12 @@
},
"PDEL": {
"summary": "Removes all objects matching a pattern",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
},
{
{
"name": "pattern",
"type": "pattern"
}
@ -1531,7 +1579,7 @@
"JGET": {
"summary": "Get a value from a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1556,7 +1604,7 @@
"JSET": {
"summary": "Set a value in a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1591,7 +1639,7 @@
"JDEL": {
"summary": "Delete a value from a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1607,7 +1655,7 @@
],
"group": "keys"
},
"EVAL":{
"EVAL": {
"summary": "Evaluates a Lua script",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1635,7 +1683,7 @@
"since": "1.10.0",
"group": "scripting"
},
"EVALSHA":{
"EVALSHA": {
"summary": "Evaluates a Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1663,7 +1711,7 @@
"since": "1.10.0",
"group": "scripting"
},
"EVALRO":{
"EVALRO": {
"summary": "Evaluates a read-only Lua script",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1691,7 +1739,7 @@
"since": "1.10.0",
"group": "scripting"
},
"EVALROSHA":{
"EVALROSHA": {
"summary": "Evaluates a read-only Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1719,7 +1767,7 @@
"since": "1.10.0",
"group": "scripting"
},
"EVALNA":{
"EVALNA": {
"summary": "Evaluates a Lua script in a non-atomic fashion",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1747,7 +1795,7 @@
"since": "1.10.0",
"group": "scripting"
},
"EVALNASHA":{
"EVALNASHA": {
"summary": "Evaluates, in a non-atomic fashion, a Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1775,7 +1823,7 @@
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT EXISTS":{
"SCRIPT EXISTS": {
"summary": "Returns information about the existence of the scripts in server cache",
"complexity": "O(N) where N is the number of provided sha1 arguments",
"arguments": [
@ -1788,7 +1836,7 @@
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT LOAD":{
"SCRIPT LOAD": {
"summary": "Loads the compiled version of a script into the server cache, without executing",
"complexity": "O(N) where N is the number of bytes in the script",
"arguments": [
@ -1800,13 +1848,13 @@
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT FLUSH":{
"SCRIPT FLUSH": {
"summary": "Flushes the server cache of Lua scripts",
"complexity": "O(1)",
"since": "1.10.0",
"group": "scripting"
},
"TEST":{
"TEST": {
"summary": "Performs spatial test",
"complexity": "One test per command, complexity depends on the test",
"arguments": [
@ -1841,7 +1889,7 @@
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -1862,7 +1910,7 @@
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -1888,7 +1936,7 @@
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -1905,7 +1953,7 @@
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -1971,7 +2019,7 @@
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -1992,7 +2040,7 @@
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -2018,7 +2066,7 @@
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -2035,7 +2083,7 @@
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"

View File

@ -165,7 +165,7 @@ var Commands = func() map[string]Command {
}()
var commandsJSON = `{
"SET":{
"SET": {
"summary": "Sets the value of an id",
"complexity": "O(1)",
"arguments": [
@ -201,14 +201,14 @@ var commandsJSON = `{
{
"name": "XX"
}
]
]
},
{
"name": "value",
{
"name": "value",
"enumargs": [
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -217,7 +217,7 @@ var commandsJSON = `{
},
{
"name": "POINT",
"arguments":[
"arguments": [
{
"name": "lat",
"type": "double"
@ -235,7 +235,7 @@ var commandsJSON = `{
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -256,7 +256,7 @@ var commandsJSON = `{
},
{
"name": "HASH",
"arguments":[
"arguments": [
{
"name": "geohash",
"type": "geohash"
@ -265,7 +265,7 @@ var commandsJSON = `{
},
{
"name": "STRING",
"arguments":[
"arguments": [
{
"name": "value",
"type": "string"
@ -281,7 +281,7 @@ var commandsJSON = `{
"EXPIRE": {
"summary": "Set a timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -301,7 +301,7 @@ var commandsJSON = `{
"TTL": {
"summary": "Get a timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -317,7 +317,7 @@ var commandsJSON = `{
"PERSIST": {
"summary": "Remove the existing timeout on an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -333,7 +333,7 @@ var commandsJSON = `{
"FSET": {
"summary": "Set the value for one or more fields of an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -349,12 +349,12 @@ var commandsJSON = `{
"optional": true
},
{
"name": ["field","value"],
"type": ["string","double"]
"name": ["field", "value"],
"type": ["string", "double"]
},
{
"name": ["field","value"],
"type": ["string","double"],
"name": ["field", "value"],
"type": ["string", "double"],
"multiple": true,
"optional": true
}
@ -365,7 +365,7 @@ var commandsJSON = `{
"BOUNDS": {
"summary": "Get the combined bounds of all the objects in a key",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -377,7 +377,7 @@ var commandsJSON = `{
"GET": {
"summary": "Get the object of an id",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -423,7 +423,7 @@ var commandsJSON = `{
"DEL": {
"summary": "Delete an id from a key",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -439,7 +439,7 @@ var commandsJSON = `{
"DROP": {
"summary": "Remove a key from the database",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -483,7 +483,7 @@ var commandsJSON = `{
"KEYS": {
"summary": "Finds all keys matching the given pattern",
"complexity": "O(N) where N is the number of keys in the database",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -495,7 +495,7 @@ var commandsJSON = `{
"STATS": {
"summary": "Show stats for one or more keys",
"complexity": "O(N) where N is the number of keys being requested",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string",
@ -508,7 +508,7 @@ var commandsJSON = `{
"SEARCH": {
"summary": "Search for string values in a key",
"complexity": "O(N) where N is the number of values in the key",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -541,35 +541,35 @@ var commandsJSON = `{
{
"name": "DESC"
}
]
},
]
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -599,7 +599,7 @@ var commandsJSON = `{
"SCAN": {
"summary": "Incrementally iterate though a key",
"complexity": "O(N) where N is the number of ids in the key",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -632,35 +632,35 @@ var commandsJSON = `{
{
"name": "DESC"
}
]
},
]
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -708,7 +708,7 @@ var commandsJSON = `{
"NEARBY": {
"summary": "Searches for ids that are nearby a point",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -745,31 +745,31 @@ var commandsJSON = `{
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -850,7 +850,7 @@ var commandsJSON = `{
},
{
"name": "ROAM",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -874,7 +874,7 @@ var commandsJSON = `{
"WITHIN": {
"summary": "Searches for ids that completely within the area",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -905,31 +905,31 @@ var commandsJSON = `{
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -1006,7 +1006,7 @@ var commandsJSON = `{
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -1027,7 +1027,7 @@ var commandsJSON = `{
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -1053,7 +1053,7 @@ var commandsJSON = `{
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -1070,7 +1070,7 @@ var commandsJSON = `{
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -1085,6 +1085,31 @@ var commandsJSON = `{
"type": "geohash"
}
]
},
{
"name": "SECTOR",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "radius",
"type": "double"
},
{
"name": "startBearing",
"type": "double"
},
{
"name": "endBearing",
"type": "double"
}
]
}
]
}
@ -1095,7 +1120,7 @@ var commandsJSON = `{
"INTERSECTS": {
"summary": "Searches for ids that intersect an area",
"complexity": "O(log(N)) where N is the number of ids in the area",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1126,31 +1151,31 @@ var commandsJSON = `{
},
{
"command": "WHERE",
"name": ["field","min","max"],
"type": ["string","double","double"],
"name": ["field", "min", "max"],
"type": ["string", "double", "double"],
"optional": true,
"multiple": true
},
{
"command": "WHEREIN",
"name": ["field","count","value"],
"type": ["string","integer","double"],
"name": ["field", "count", "value"],
"type": ["string", "integer", "double"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVAL",
"name": ["script","numargs","arg"],
"type": ["string","integer","string"],
"name": ["script", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
},
{
"command": "WHEREEVALSHA",
"name": ["sha1","numargs","arg"],
"type": ["string","integer","string"],
"name": ["sha1", "numargs", "arg"],
"type": ["string", "integer", "string"],
"optional": true,
"multiple": true,
"variadic": true
@ -1233,7 +1258,7 @@ var commandsJSON = `{
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -1254,7 +1279,7 @@ var commandsJSON = `{
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -1280,7 +1305,7 @@ var commandsJSON = `{
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -1297,7 +1322,7 @@ var commandsJSON = `{
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -1312,6 +1337,31 @@ var commandsJSON = `{
"type": "geohash"
}
]
},
{
"name": "SECTOR",
"arguments": [
{
"name": "lat",
"type": "double"
},
{
"name": "lon",
"type": "double"
},
{
"name": "radius",
"type": "double"
},
{
"name": "startBearing",
"type": "double"
},
{
"name": "endBearing",
"type": "double"
}
]
}
]
}
@ -1321,7 +1371,7 @@ var commandsJSON = `{
},
"CONFIG GET": {
"summary": "Get the value of a configuration parameter",
"arguments":[
"arguments": [
{
"name": "parameter",
"type": "string"
@ -1331,7 +1381,7 @@ var commandsJSON = `{
},
"CONFIG SET": {
"summary": "Set a configuration parameter to the given value",
"arguments":[
"arguments": [
{
"name": "parameter",
"type": "string"
@ -1346,18 +1396,18 @@ var commandsJSON = `{
},
"CONFIG REWRITE": {
"summary": "Rewrite the configuration file with the in memory configuration",
"arguments":[],
"arguments": [],
"group": "server"
},
"SERVER": {
"summary":"Show server stats and details",
"summary": "Show server stats and details",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
"group": "server"
},
"GC": {
"summary":"Forces a garbage collection",
"summary": "Forces a garbage collection",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
@ -1368,14 +1418,14 @@ var commandsJSON = `{
"complexity": "O(1)",
"arguments": [
{
"enum": ["yes","no"]
"enum": ["yes", "no"]
}
],
"since": "1.0.0",
"group": "server"
},
"FLUSHDB": {
"summary":"Removes all keys",
"summary": "Removes all keys",
"complexity": "O(1)",
"arguments": [],
"since": "1.0.0",
@ -1501,7 +1551,7 @@ var commandsJSON = `{
"name": ["name", "value"],
"type": ["string", "string"],
"optional": true,
"multiple": true
"multiple": true
},
{
"command": "EX",
@ -1539,7 +1589,6 @@ var commandsJSON = `{
"type": "string",
"variadic": true
}
],
"group": "webhook"
},
@ -1555,7 +1604,7 @@ var commandsJSON = `{
},
"HOOKS": {
"summary": "Finds all hooks matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1565,7 +1614,7 @@ var commandsJSON = `{
},
"PDELHOOK": {
"summary": "Removes all hooks matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1586,7 +1635,7 @@ var commandsJSON = `{
"name": ["name", "value"],
"type": ["string", "string"],
"optional": true,
"multiple": true
"multiple": true
},
{
"command": "EX",
@ -1624,7 +1673,6 @@ var commandsJSON = `{
"type": "string",
"variadic": true
}
],
"group": "pubsub"
},
@ -1640,7 +1688,7 @@ var commandsJSON = `{
},
"CHANS": {
"summary": "Finds all channels matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1650,7 +1698,7 @@ var commandsJSON = `{
},
"PDELCHAN": {
"summary": "Removes all channels matching a pattern",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern"
@ -1660,7 +1708,7 @@ var commandsJSON = `{
},
"SUBSCRIBE": {
"summary": "Subscribe to a geofence channel",
"arguments":[
"arguments": [
{
"name": "channel",
"type": "string",
@ -1671,7 +1719,7 @@ var commandsJSON = `{
},
"PSUBSCRIBE": {
"summary": "Subscribes the client to the given patterns",
"arguments":[
"arguments": [
{
"name": "pattern",
"type": "pattern",
@ -1682,12 +1730,12 @@ var commandsJSON = `{
},
"PDEL": {
"summary": "Removes all objects matching a pattern",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
},
{
{
"name": "pattern",
"type": "pattern"
}
@ -1697,7 +1745,7 @@ var commandsJSON = `{
"JGET": {
"summary": "Get a value from a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1722,7 +1770,7 @@ var commandsJSON = `{
"JSET": {
"summary": "Set a value in a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1757,7 +1805,7 @@ var commandsJSON = `{
"JDEL": {
"summary": "Delete a value from a JSON document",
"complexity": "O(1)",
"arguments":[
"arguments": [
{
"name": "key",
"type": "string"
@ -1773,7 +1821,7 @@ var commandsJSON = `{
],
"group": "keys"
},
"EVAL":{
"EVAL": {
"summary": "Evaluates a Lua script",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1801,7 +1849,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"EVALSHA":{
"EVALSHA": {
"summary": "Evaluates a Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1829,7 +1877,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"EVALRO":{
"EVALRO": {
"summary": "Evaluates a read-only Lua script",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1857,7 +1905,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"EVALROSHA":{
"EVALROSHA": {
"summary": "Evaluates a read-only Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1885,7 +1933,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"EVALNA":{
"EVALNA": {
"summary": "Evaluates a Lua script in a non-atomic fashion",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1913,7 +1961,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"EVALNASHA":{
"EVALNASHA": {
"summary": "Evaluates, in a non-atomic fashion, a Lua script cached on the server by its SHA1 digest",
"complexity": "Depends on the evaluated script",
"arguments": [
@ -1941,7 +1989,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT EXISTS":{
"SCRIPT EXISTS": {
"summary": "Returns information about the existence of the scripts in server cache",
"complexity": "O(N) where N is the number of provided sha1 arguments",
"arguments": [
@ -1954,7 +2002,7 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT LOAD":{
"SCRIPT LOAD": {
"summary": "Loads the compiled version of a script into the server cache, without executing",
"complexity": "O(N) where N is the number of bytes in the script",
"arguments": [
@ -1966,13 +2014,13 @@ var commandsJSON = `{
"since": "1.10.0",
"group": "scripting"
},
"SCRIPT FLUSH":{
"SCRIPT FLUSH": {
"summary": "Flushes the server cache of Lua scripts",
"complexity": "O(1)",
"since": "1.10.0",
"group": "scripting"
},
"TEST":{
"TEST": {
"summary": "Performs spatial test",
"complexity": "One test per command, complexity depends on the test",
"arguments": [
@ -2007,7 +2055,7 @@ var commandsJSON = `{
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -2028,7 +2076,7 @@ var commandsJSON = `{
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -2054,7 +2102,7 @@ var commandsJSON = `{
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -2071,7 +2119,7 @@ var commandsJSON = `{
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"
@ -2137,7 +2185,7 @@ var commandsJSON = `{
},
{
"name": "BOUNDS",
"arguments":[
"arguments": [
{
"name": "minlat",
"type": "double"
@ -2158,7 +2206,7 @@ var commandsJSON = `{
},
{
"name": "OBJECT",
"arguments":[
"arguments": [
{
"name": "geojson",
"type": "geojson"
@ -2184,7 +2232,7 @@ var commandsJSON = `{
},
{
"name": "TILE",
"arguments":[
"arguments": [
{
"name": "x",
"type": "double"
@ -2201,7 +2249,7 @@ var commandsJSON = `{
},
{
"name": "QUADKEY",
"arguments":[
"arguments": [
{
"name": "quadkey",
"type": "string"

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/eclipse/paho.mqtt.golang v1.3.1
github.com/golang/protobuf v1.4.3
github.com/gomodule/redigo v1.8.3
github.com/iwpnd/sectr v0.1.2
github.com/mmcloughlin/geohash v0.10.0
github.com/nats-io/nats-server/v2 v2.2.0 // indirect
github.com/nats-io/nats.go v1.10.1-0.20210228004050-ed743748acac

2
go.sum
View File

@ -214,6 +214,8 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/iwpnd/sectr v0.1.2 h1:FauaPRn5C2tC42HTF7gM3FJZXvGXWc6jabBbIxzTMag=
github.com/iwpnd/sectr v0.1.2/go.mod h1:Dm6YXDJCRx1NTfMX/1RMIkGfVp2ORjCY/cQGfbknz4c=
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=

View File

@ -3,10 +3,12 @@ package server
import (
"bytes"
"errors"
"fmt"
"strconv"
"strings"
"time"
"github.com/iwpnd/sectr"
"github.com/mmcloughlin/geohash"
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
@ -280,6 +282,66 @@ func (server *Server) cmdSearchArgs(
if err != nil {
return
}
case "sector":
if s.clip {
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var slat, slon, smeters, sb1, sb2 string
if vs, slat, ok = tokenval(vs); !ok || slat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, slon, ok = tokenval(vs); !ok || slon == "" {
err = errInvalidNumberOfArguments
return
}
if vs, smeters, ok = tokenval(vs); !ok || smeters == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sb1, ok = tokenval(vs); !ok || sb1 == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sb2, ok = tokenval(vs); !ok || sb2 == "" {
err = errInvalidNumberOfArguments
return
}
var lat, lon, meters, b1, b2 float64
if lat, err = strconv.ParseFloat(slat, 64); err != nil {
err = errInvalidArgument(slat)
return
}
if lon, err = strconv.ParseFloat(slon, 64); err != nil {
err = errInvalidArgument(slon)
return
}
if meters, err = strconv.ParseFloat(smeters, 64); err != nil {
err = errInvalidArgument(smeters)
return
}
if b1, err = strconv.ParseFloat(sb1, 64); err != nil {
err = errInvalidArgument(sb1)
return
}
if b2, err = strconv.ParseFloat(sb2, 64); err != nil {
err = errInvalidArgument(sb2)
return
}
if b1 == b2 {
err = fmt.Errorf("equal bearings (%s == %s), use CIRCLE instead", sb1, sb2)
return
}
origin := sectr.Point{Lng: lon, Lat: lat}
sector := sectr.NewSector(origin, meters, b1, b2)
s.obj, err = geojson.Parse(string(sector.JSON()), &server.geomParseOpts)
if err != nil {
return
}
case "bounds", "hash", "tile", "quadkey":
vs, s.obj, err = parseRectArea(ltyp, vs)
if err != nil {
@ -379,7 +441,7 @@ func (server *Server) cmdSearchArgs(
var nearbyTypes = []string{"point"}
var withinOrIntersectsTypes = []string{
"geo", "bounds", "hash", "tile", "quadkey", "get", "object", "circle"}
"geo", "bounds", "hash", "tile", "quadkey", "get", "object", "circle", "sector"}
func (server *Server) cmdNearby(msg *Message) (res resp.Value, err error) {
start := time.Now()

View File

@ -9,6 +9,7 @@ import (
"strings"
"time"
"github.com/iwpnd/sectr"
"github.com/mmcloughlin/geohash"
"github.com/tidwall/geojson"
"github.com/tidwall/geojson/geometry"
@ -47,6 +48,67 @@ func (s *Server) parseArea(ovs []string, doClip bool) (vs []string, o geojson.Ob
return
}
o = geojson.NewPoint(geometry.Point{X: lon, Y: lat})
case "sector":
if doClip {
err = errInvalidArgument("cannot clip with " + ltyp)
return
}
var slat, slon, smeters, sb1, sb2 string
if vs, slat, ok = tokenval(vs); !ok || slat == "" {
err = errInvalidNumberOfArguments
return
}
if vs, slon, ok = tokenval(vs); !ok || slon == "" {
err = errInvalidNumberOfArguments
return
}
if vs, smeters, ok = tokenval(vs); !ok || smeters == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sb1, ok = tokenval(vs); !ok || sb1 == "" {
err = errInvalidNumberOfArguments
return
}
if vs, sb2, ok = tokenval(vs); !ok || sb2 == "" {
err = errInvalidNumberOfArguments
return
}
var lat, lon, meters, b1, b2 float64
if lat, err = strconv.ParseFloat(slat, 64); err != nil {
err = errInvalidArgument(slat)
return
}
if lon, err = strconv.ParseFloat(slon, 64); err != nil {
err = errInvalidArgument(slon)
return
}
if meters, err = strconv.ParseFloat(smeters, 64); err != nil {
err = errInvalidArgument(smeters)
return
}
if b1, err = strconv.ParseFloat(sb1, 64); err != nil {
err = errInvalidArgument(sb1)
return
}
if b2, err = strconv.ParseFloat(sb2, 64); err != nil {
err = errInvalidArgument(sb2)
return
}
if b1 == b2 {
err = fmt.Errorf("equal bearings (%s == %s), use CIRCLE instead", sb1, sb2)
return
}
origin := sectr.Point{Lng: lon, Lat: lat}
sector := sectr.NewSector(origin, meters, b1, b2)
o, err = geojson.Parse(string(sector.JSON()), &s.geomParseOpts)
if err != nil {
return
}
case "circle":
if doClip {
err = fmt.Errorf("invalid clip type '%s'", typ)

View File

@ -763,7 +763,7 @@ loop:
ae = &areaExpression{op: OR, children: []*areaExpression{ae}}
}
vsout = nvs
case "point", "circle", "object", "bounds", "hash", "quadkey", "tile", "get":
case "point", "circle", "object", "bounds", "hash", "quadkey", "tile", "get", "sector":
parsedVs, parsedObj, areaErr := s.parseArea(vsout, doClip)
if areaErr != nil {
err = areaErr

View File

@ -19,7 +19,9 @@ func subTestSearch(t *testing.T, mc *mockServer) {
runStep(t, mc, "KNN_CURSOR", keys_KNN_cursor_test)
runStep(t, mc, "NEARBY_SPARSE", keys_NEARBY_SPARSE_test)
runStep(t, mc, "WITHIN_CIRCLE", keys_WITHIN_CIRCLE_test)
runStep(t, mc, "WITHIN_SECTOR", keys_WITHIN_SECTOR_test)
runStep(t, mc, "INTERSECTS_CIRCLE", keys_INTERSECTS_CIRCLE_test)
runStep(t, mc, "INTERSECTS_SECTOR", keys_INTERSECTS_SECTOR_test)
runStep(t, mc, "WITHIN", keys_WITHIN_test)
runStep(t, mc, "WITHIN_CURSOR", keys_WITHIN_CURSOR_test)
runStep(t, mc, "WITHIN_CLIPBY", keys_WITHIN_CLIPBY_test)
@ -144,6 +146,8 @@ func keys_WITHIN_test(mc *mockServer) error {
]
]
}`}, {"[0 [point1 point2 line3 poly4 multipoly5 poly8]]"},
{"WITHIN", "mykey", "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {"[0 [point1 point2 line3 poly4 multipoly5 poly8]]"},
{"WITHIN", "mykey", "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "0"}, {"ERR equal bearings (0 == 0), use CIRCLE instead"},
{"SET", "key2", "poly9", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.44037926197052,37.73313523548048],[-122.44017541408539,37.73313523548048],[-122.44017541408539,37.73336857568778],[-122.44037926197052,37.73336857568778],[-122.44037926197052,37.73313523548048]]]}`}, {"OK"},
{"SET", "key2", "poly10", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.44040071964262,37.73359343010089],[-122.4402666091919,37.73359343010089],[-122.4402666091919,37.73373767596864],[-122.44040071964262,37.73373767596864],[-122.44040071964262,37.73359343010089]]]}`}, {"OK"},
@ -203,6 +207,8 @@ func keys_WITHIN_CURSOR_test(mc *mockServer) error {
"[6 [poly8]]"},
{"WITHIN", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
"[7 [point9]]"},
{"WITHIN", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {
"[7 [point9]]"},
})
}
@ -273,6 +279,8 @@ func keys_INTERSECTS_test(mc *mockServer) error {
]
]
}`}, {"[0 [point1 point2 line3 poly4 multipoly5 poly8]]"},
{"INTERSECTS", "mykey", "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {"[0 [point1 point2 line3 poly4 multipoly5 poly8]]"},
{"INTERSECTS", "mykey", "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "0"}, {"ERR equal bearings (0 == 0), use CIRCLE instead"},
{"SET", "key2", "poly9", "OBJECT", `{"type": "Polygon","coordinates": [[[-122.44037926197052,37.73313523548048],[-122.44017541408539,37.73313523548048],[-122.44017541408539,37.73336857568778],[-122.44037926197052,37.73336857568778],[-122.44037926197052,37.73313523548048]]]}`}, {"OK"},
{"SET", "key2", "poly10", "OBJECT", `{"type": "Polygon","coordinates": [[[-122.44040071964262,37.73359343010089],[-122.4402666091919,37.73359343010089],[-122.4402666091919,37.73373767596864],[-122.44040071964262,37.73373767596864],[-122.44040071964262,37.73359343010089]]]}`}, {"OK"},
@ -379,6 +387,8 @@ func keys_INTERSECTS_CURSOR_test(mc *mockServer) error {
"[6 [poly8]]"},
{"INTERSECTS", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
"[7 [point9]]"},
{"INTERSECTS", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {
"[7 [point9]]"},
})
}
@ -398,6 +408,22 @@ func keys_WITHIN_CIRCLE_test(mc *mockServer) error {
})
}
func keys_WITHIN_SECTOR_test(mc *mockServer) error {
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "1", "POINT", 37.7324, -122.4424}, {"OK"},
{"SET", "mykey", "2", "POINT", 37.73241, -122.44241}, {"OK"},
{"SET", "mykey", "3", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "4", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
{"SET", "mykey", "5", "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]]}`}, {"OK"},
{"SET", "mykey", "6", "POINT", -5, 5}, {"OK"},
{"SET", "mykey", "7", "POINT", 33, 21}, {"OK"},
{"WITHIN", "mykey", "IDS", "SECTOR", 37.731930, -122.443270, 1000, 0, 90}, {
"[0 [1 2 3 4 5]]"},
{"WITHIN", "mykey", "IDS", "SECTOR", 37.731930, -122.443270, 100, 0, 90}, {
"[0 [1 2]]"},
})
}
func keys_NEARBY_SPARSE_test(mc *mockServer) error {
// https://github.com/tidwall/tile38/issues/618
return mc.DoBatch([][]interface{}{
@ -497,6 +523,22 @@ func keys_INTERSECTS_CIRCLE_test(mc *mockServer) error {
})
}
func keys_INTERSECTS_SECTOR_test(mc *mockServer) error {
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "1", "POINT", 37.7324, -122.4424}, {"OK"},
{"SET", "mykey", "2", "POINT", 37.73241, -122.44241}, {"OK"},
{"SET", "mykey", "3", "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
{"SET", "mykey", "4", "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
{"SET", "mykey", "5", "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]]}`}, {"OK"},
{"SET", "mykey", "6", "POINT", -5, 5}, {"OK"},
{"SET", "mykey", "7", "POINT", 33, 21}, {"OK"},
{"INTERSECTS", "mykey", "IDS", "SECTOR", 37.731930, -122.443270, 1000, 0, 90}, {
"[0 [1 2 3 4 5]]"},
{"INTERSECTS", "mykey", "IDS", "SECTOR", 37.731930, -122.443270, 100, 0, 90}, {
"[0 [1 2]]"},
})
}
func keys_SCAN_CURSOR_test(mc *mockServer) error {
return mc.DoBatch([][]interface{}{
{"SET", "mykey", "id1", "FIELD", "foo", 1, "STRING", "bar1"}, {"OK"},

View File

@ -40,10 +40,12 @@ func testcmd_WITHIN_test(mc *mockServer) error {
{"SET", "mykey", "poly8", "OBJECT", poly8}, {"OK"},
{"TEST", "GET", "mykey", "point1", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "point1", "WITHIN", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {"1"},
{"TEST", "GET", "mykey", "line3", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly4", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "multipoly5", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly8", "WITHIN", "OBJECT", poly}, {"1"},
{"TEST", "GET", "mykey", "poly8", "WITHIN", "SECTOR", "37.72999", "-122.44760", "1000", "0", "90"}, {"1"},
{"TEST", "GET", "mykey", "point6", "WITHIN", "OBJECT", poly}, {"0"},
{"TEST", "GET", "mykey", "point7", "WITHIN", "OBJECT", poly}, {"0"},

19
vendor/github.com/iwpnd/sectr/.gitignore generated vendored Normal file
View File

@ -0,0 +1,19 @@
.ipynb_checkpoints/
/tmp/
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
.DS_Store
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

119
vendor/github.com/iwpnd/sectr/.gitlint generated vendored Normal file
View File

@ -0,0 +1,119 @@
# Edit this file as you like.
#
# All these sections are optional. Each section with the exception of [general] represents
# one rule and each key in it is an option for that specific rule.
#
# Rules and sections can be referenced by their full name or by id. For example
# section "[body-max-line-length]" could also be written as "[B1]". Full section names are
# used in here for clarity.
#
[general]
# Ignore certain rules, this example uses both full name and id
# ignore=title-trailing-punctuation, T3
# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this
# verbosity = 2
# By default gitlint will ignore merge, revert, fixup and squash commits.
# ignore-merge-commits=true
# ignore-revert-commits=true
# ignore-fixup-commits=true
# ignore-squash-commits=true
# Ignore any data send to gitlint via stdin
# ignore-stdin=true
# Fetch additional meta-data from the local repository when manually passing a
# commit message to gitlint via stdin or --commit-msg. Disabled by default.
# staged=true
# Enable debug mode (prints more output). Disabled by default.
# debug=true
# Enable community contributed rules
# See http://jorisroovers.github.io/gitlint/contrib_rules for details
contrib=contrib-title-conventional-commits
# Set the extra-path where gitlint will search for user defined rules
# See http://jorisroovers.github.io/gitlint/user_defined_rules for details
# extra-path=examples/
# This is an example of how to configure the "title-max-length" rule and
# set the line-length it enforces to 80
# [title-max-length]
# line-length=50
# Conversely, you can also enforce minimal length of a title with the
# "title-min-length" rule:
# [title-min-length]
# min-length=5
# [title-must-not-contain-word]
# Comma-separated list of words that should not occur in the title. Matching is case
# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING"
# will not cause a violation, but "WIP: my title" will.
# words=wip
# [title-match-regex]
# python-style regex that the commit-msg title must match
# Note that the regex can contradict with other rules if not used correctly
# (e.g. title-must-not-contain-word).
# regex=^US[0-9]*
# [body-max-line-length]
# line-length=72
# [body-min-length]
# min-length=5
#[body-is-missing]
# Whether to ignore this rule on merge commits (which typically only have a title)
# default = True
#ignore-merge-commits=false
# [body-changed-file-mention]
# List of files that need to be explicitly mentioned in the body when they are changed
# This is useful for when developers often erroneously edit certain files or git submodules.
# By specifying this rule, developers can only change the file when they explicitly reference
# it in the commit message.
# files=gitlint/rules.py,README.md
# [body-match-regex]
# python-style regex that the commit-msg body must match.
# E.g. body must end in My-Commit-Tag: foo
# regex=My-Commit-Tag: foo$
# [author-valid-email]
# python-style regex that the commit author email address must match.
# For example, use the following regex if you only want to allow email addresses from foo.com
# regex=[^@]+@foo.com
# [ignore-by-title]
# Ignore certain rules for commits of which the title matches a regex
# E.g. Match commit titles that start with "Release"
# regex=^Release(.*)
# Ignore certain rules, you can reference them by their id or by their full name
# Use 'all' to ignore all rules
ignore=B6,CC1
# [ignore-by-body]
# Ignore certain rules for commits of which the body has a line that matches a regex
# E.g. Match bodies that have a line that that contain "release"
# regex=(.*)release(.*)
#
# Ignore certain rules, you can reference them by their id or by their full name
# Use 'all' to ignore all rules
# ignore=T1,body-min-length
# [ignore-body-lines]
# Ignore certain lines in a commit body that match a regex.
# E.g. Ignore all lines that start with 'Co-Authored-By'
# regex=^Co-Authored-By
# This is a contrib rule - a community contributed rule. These are disabled by default.
# You need to explicitly enable them one-by-one by adding them to the "contrib" option
# under [general] section above.
# [contrib-title-conventional-commits]
# Specify allowed commit types. For details see: https://www.conventionalcommits.org/
#types = feat,fix,refactor,docs,ci,chore

13
vendor/github.com/iwpnd/sectr/.pre-commit-config.yaml generated vendored Normal file
View File

@ -0,0 +1,13 @@
repos:
- repo: git://github.com/dnephin/pre-commit-golang
rev: v0.4.0
hooks:
- id: go-fmt
- id: go-vet
- id: go-lint
- id: go-imports
- id: go-mod-tidy
- repo: https://github.com/jorisroovers/gitlint
rev: v0.15.1
hooks:
- id: gitlint

3
vendor/github.com/iwpnd/sectr/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/iwpnd/sectr
go 1.16

71
vendor/github.com/iwpnd/sectr/readme.md generated vendored Normal file
View File

@ -0,0 +1,71 @@
# sectr 🍕
Build a circular sector (pizza piece 😅 ) spanning the angle between two given bearings, a radius and a center point.
## installation
```
go get -u github.com/iwpnd/sectr
```
## usage
<img src=".github/img/sectr_bg.png" alt="Logo" width="500" height="227">
```go
package main
import (
"fmt"
"github.com/iwpnd/sectr"
)
func main() {
p := sectr.Point{Lat: 52.25, Lng: 13.37}
sector := sectr.NewSector(p, 100, 0, 90)
fmt.Printf("%s", sector.JSON())
}
>> {
"type": "Polygon",
"coordinates": [
[
[13.37,52.25],
[13.37,52.25089932],
[13.37012803,52.2508959],
[13.3702803,52.2508828],
[13.37040491,52.25086448],
[13.37055029,52.25083383],
[13.37068965,52.25079405],
[13.37080006,52.25075423],
[13.37092446,52.2506989],
[13.37103872,52.25063591],
[13.3711253,52.25057807],
[13.37121783,52.25050289],
[13.37128479,52.25043599],
[13.37135219,52.25035138],
[13.37140478,52.25026293],
[13.37143686,52.25018697],
[13.37146091,52.250094],
[13.37146896,52.24999999],
[13.37,52.25]
]
]
}
```
## License
MIT
## Acknowledgement
[Chris Veness](https://github.com/chrisveness) for refreshing my university left-overs with this blog [moveable-type](https://www.movable-type.co.uk/scripts/latlong.html)
## Maintainer
Benjamin Ramser - [@iwpnd](https://github.com/iwpnd)
Project Link: [https://github.com/iwpnd/sectr](https://github.com/iwpnd/sectr)

160
vendor/github.com/iwpnd/sectr/sectr.go generated vendored Normal file
View File

@ -0,0 +1,160 @@
package sectr
import (
"encoding/json"
"math"
)
const earthRadius = 6371008.8 // earth radius
// Point ...
type Point struct {
Lng, Lat float64
}
// Sector ...
type Sector struct {
coordinates [][][]float64
origin Point
radius float64
bearing1 float64
bearing2 float64
}
// SectorGeometry ...
type SectorGeometry struct {
Type string `json:"type"`
Coordinates [][][]float64 `json:"coordinates"`
}
func radToDegree(rad float64) float64 {
return rad * 180 / math.Pi
}
func degreeToRad(degree float64) float64 {
return degree * math.Pi / 180
}
func distanceToRadians(distance float64) float64 {
const r = earthRadius
return distance / r
}
// terminal calculates the terminal position travelling a distance
// from a given origin
// see https://www.movable-type.co.uk/scripts/latlong.html
func terminal(start Point, distance, bearing float64) Point {
φ1 := degreeToRad(start.Lat)
λ1 := degreeToRad(start.Lng)
bearingRad := degreeToRad(bearing)
distanceRad := distanceToRadians(distance)
φ2 := math.Asin(
math.Sin(φ1)*
math.Cos(distanceRad) +
math.Cos(φ1)*
math.Sin(distanceRad)*
math.Cos(bearingRad))
λ2 := λ1 + math.Atan2(
math.Sin(bearingRad)*
math.Sin(distanceRad)*
math.Cos(φ1),
math.Cos(distanceRad)-
math.Sin(φ1)*
math.Sin(φ2))
// cap decimals at .00000001 degree ~= 1.11mm
lng := math.Round(radToDegree(λ2)*100000000) / 100000000
lat := math.Round(radToDegree(φ2)*100000000) / 100000000
return Point{Lng: lng, Lat: lat}
}
func bearingToAngle(bearing float64) float64 {
angle := math.Mod(bearing, 360)
if angle < 0 {
angle = angle + 360
}
return angle
}
// NewSector creates a sector from a given origin point, a radius and two bearings
func NewSector(origin Point, radius, bearing1, bearing2 float64) *Sector {
// to cap the maximum positions in a sector/circle to 64
// the higher the smoother, yet the bigger the coordinate array
const steps = 64
s := &Sector{
origin: origin,
bearing1: bearing1,
bearing2: bearing2,
radius: radius,
}
angle1 := bearingToAngle(bearing1)
angle2 := bearingToAngle(bearing2)
// if angle1 == angle2 return circle
if angle1 == angle2 {
for i := 1; i < steps; i++ {
α := float64(i * -360 / steps)
t := terminal(origin, radius, α)
s.addPoint(t)
}
s.coordinates[0] = append(s.coordinates[0], s.coordinates[0][0])
return s
}
var endDegree float64
startDegree := angle1
if angle1 < angle2 {
endDegree = angle2
} else {
endDegree = angle2 + 360
}
α := startDegree
s.addPoint(origin)
for i := 1; ; i++ {
if α < endDegree {
t := terminal(origin, radius, α)
s.addPoint(t)
α = startDegree + float64((i*360)/steps)
}
if α >= endDegree {
t := terminal(origin, radius, endDegree)
s.addPoint(t)
s.addPoint(origin)
return s
}
}
}
func (s *Sector) addPoint(p Point) {
if len(s.coordinates) == 0 {
s.coordinates = append(s.coordinates, [][]float64{{p.Lng, p.Lat}})
return
}
s.coordinates[0] = append(s.coordinates[0], []float64{p.Lng, p.Lat})
}
// JSON exports the Sector as json
func (s Sector) JSON() []byte {
f := SectorGeometry{Type: "Polygon", Coordinates: s.coordinates}
j, _ := json.Marshal(f)
return j
}

3
vendor/modules.txt vendored
View File

@ -103,6 +103,9 @@ github.com/googleapis/gax-go/v2
github.com/gorilla/websocket
# github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/go-uuid
# github.com/iwpnd/sectr v0.1.2
## explicit
github.com/iwpnd/sectr
# github.com/jcmturner/gofork v1.0.0
github.com/jcmturner/gofork/encoding/asn1
github.com/jcmturner/gofork/x/crypto/pbkdf2