diff --git a/src/Makefile b/src/Makefile index 054857ca..8056f910 100644 --- a/src/Makefile +++ b/src/Makefile @@ -117,7 +117,7 @@ endif REDIS_SERVER_NAME=redis-server REDIS_SENTINEL_NAME=redis-sentinel -REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o zset.o geojson.o +REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o zset.o REDIS_GEOHASH_OBJ=../deps/geohash-int/geohash.o ../deps/geohash-int/geohash_helper.o REDIS_CLI_NAME=redis-cli REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o diff --git a/src/geo.c b/src/geo.c index 296cf7e0..802acb91 100644 --- a/src/geo.c +++ b/src/geo.c @@ -29,7 +29,6 @@ #include "geo.h" #include "geohash_helper.h" -#include "geojson.h" #include "zset.h" /* ==================================================================== @@ -110,49 +109,15 @@ static double extractDistanceOrReply(redisClient *c, robj **argv, return distance * to_meters; } -/* Output Reply Helper */ -static void latLongToGeojsonAndReply(redisClient *c, struct geojsonPoint *gp, - char *units) { - sds geojson = geojsonLatLongToPointFeature( - gp->latitude, gp->longitude, gp->set, gp->member, gp->dist, units); - - addReplyBulkCBuffer(c, geojson, sdslen(geojson)); - sdsfree(geojson); -} - -/* Output Reply Helper */ -static void decodeGeohashToGeojsonBoundsAndReply(redisClient *c, - uint64_t hashbits, - struct geojsonPoint *gp) { - GeoHashArea area = {{0,0},{0,0},{0,0}}; - GeoHashBits hash = { .bits = hashbits, .step = GEO_STEP_MAX }; - - geohashDecodeWGS84(hash, &area); - - sds geojson = geojsonBoxToPolygonFeature( - area.latitude.min, area.longitude.min, area.latitude.max, - area.longitude.max, gp->set, gp->member); - addReplyBulkCBuffer(c, geojson, sdslen(geojson)); - sdsfree(geojson); -} - /* The defailt addReplyDouble has too much accuracy. We use this * for returning location distances. "5.21 meters away" is nicer * than "5.2144992818115 meters away." */ -static inline void addReplyDoubleNicer(redisClient *c, double d) { +static inline void addReplyDoubleMeters(redisClient *c, double d) { char dbuf[128] = { 0 }; int dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", d); addReplyBulkCBuffer(c, dbuf, dlen); } -/* Output Reply Helper */ -static void replyGeojsonCollection(redisClient *c, struct geojsonPoint *gp, - long result_length, char *units) { - sds geojson = geojsonFeatureCollection(gp, result_length, units); - addReplyBulkCBuffer(c, geojson, sdslen(geojson)); - sdsfree(geojson); -} - /* geohash range+zset access helper */ /* Obtain all members between the min/max of this geohash bounding box. */ /* Returns list of results. List must be listRelease()'d later. */ @@ -291,7 +256,7 @@ static int publishLocationUpdate(const sds zset, const sds member, /* Sort comparators for qsort() */ static int sort_gp_asc(const void *a, const void *b) { - const struct geojsonPoint *gpa = a, *gpb = b; + const struct geoPoint *gpa = a, *gpb = b; /* We can't do adist - bdist because they are doubles and * the comparator returns an int. */ if (gpa->dist > gpb->dist) @@ -431,12 +396,8 @@ static void geoRadiusGeneric(redisClient *c, int type) { return; } - sds units = c->argv[base_args - 2 + 1]->ptr; - /* Discover and populate all optional parameters. */ - int withdist = 0, withhash = 0, withcoords = 0, - withgeojson = 0, withgeojsonbounds = 0, - withgeojsoncollection = 0, noproperties = 0; + int withdist = 0, withhash = 0, withcoords = 0, noproperties = 0; int sort = SORT_NONE; if (c->argc > base_args) { int remaining = c->argc - base_args; @@ -448,14 +409,6 @@ static void geoRadiusGeneric(redisClient *c, int type) { withhash = 1; else if (!strncasecmp(arg, "withcoord", 9)) withcoords = 1; - else if (!strncasecmp(arg, "withgeojsonbound", 16)) - withgeojsonbounds = 1; - else if (!strncasecmp(arg, "withgeojsoncollection", 21)) - withgeojsoncollection = 1; - else if (!strncasecmp(arg, "withgeo", 7) || - !strcasecmp(arg, "geojson") || !strcasecmp(arg, "json") || - !strcasecmp(arg, "withjson")) - withgeojson = 1; else if (!strncasecmp(arg, "noprop", 6) || !strncasecmp(arg, "withoutprop", 11)) noproperties = 1; @@ -471,8 +424,6 @@ static void geoRadiusGeneric(redisClient *c, int type) { } } - int withgeo = withgeojsonbounds || withgeojsoncollection || withgeojson; - /* Get all neighbor geohash boxes for our radius search */ GeoHashRadius georadius = geohashGetAreasByRadiusWGS84(latlong[0], latlong[1], radius_meters); @@ -508,23 +459,17 @@ static void geoRadiusGeneric(redisClient *c, int type) { if (withhash) option_length++; - if (withgeojson) - option_length++; - - if (withgeojsonbounds) - option_length++; - /* The multibulk len we send is exactly result_length. The result is either * all strings of just zset members *or* a nested multi-bulk reply * containing the zset member string _and_ all the additional options the * user enabled for this request. */ - addReplyMultiBulkLen(c, result_length + withgeojsoncollection); + addReplyMultiBulkLen(c, result_length); /* Iterate over results, populate struct used for sorting and result sending */ listIter li; listRewind(found_matches, &li); - struct geojsonPoint gp[result_length]; + struct geoPoint gp[result_length]; /* populate gp array from our results */ for (int i = 0; i < result_length; i++) { struct zipresult *zr = listNodeValue(listNext(&li)); @@ -534,7 +479,7 @@ static void geoRadiusGeneric(redisClient *c, int type) { gp[i].dist = zr->distance / conversion; gp[i].userdata = zr; - /* The layout of geojsonPoint allows us to pass the start offset + /* The layout of geoPoint allows us to pass the start offset * of the struct directly to decodeGeohash. */ decodeGeohash(zr->score, (double *)(gp + i)); } @@ -558,18 +503,14 @@ static void geoRadiusGeneric(redisClient *c, int type) { switch (zr->type) { case ZR_LONG: addReplyBulkLongLong(c, zr->val.v); - if (withgeo && !noproperties) - gp[i].member = sdscatprintf(sdsempty(), "%llu", zr->val.v); break; case ZR_STRING: addReplyBulkCBuffer(c, zr->val.s, sdslen(zr->val.s)); - if (withgeo && !noproperties) - gp[i].member = sdsdup(zr->val.s); break; } if (withdist) - addReplyDoubleNicer(c, gp[i].dist); + addReplyDoubleMeters(c, gp[i].dist); if (withhash) addReplyLongLong(c, zr->score); @@ -579,21 +520,7 @@ static void geoRadiusGeneric(redisClient *c, int type) { addReplyDouble(c, gp[i].latitude); addReplyDouble(c, gp[i].longitude); } - - if (withgeojson) - latLongToGeojsonAndReply(c, gp + i, units); - - if (withgeojsonbounds) - decodeGeohashToGeojsonBoundsAndReply(c, zr->score, gp + i); } - - if (withgeojsoncollection) - replyGeojsonCollection(c, gp, result_length, units); - - if (withgeo && !noproperties) - for (int i = 0; i < result_length; i++) - sdsfree(gp[i].member); - listRelease(found_matches); } @@ -610,18 +537,11 @@ void geoRadiusByMemberCommand(redisClient *c) { } void geoDecodeCommand(redisClient *c) { - /* args 0-1: ["geodecode", geohash]; - * optional: [geojson] */ - GeoHashBits geohash; if (getLongLongFromObjectOrReply(c, c->argv[1], (long long *)&geohash.bits, NULL) != REDIS_OK) return; - int withgeojson = 0; - if (c->argc == 3) - withgeojson = 1; - GeoHashArea area; geohash.step = GEO_STEP_MAX; geohashDecodeWGS84(geohash, &area); @@ -630,7 +550,7 @@ void geoDecodeCommand(redisClient *c) { double x = (area.longitude.min + area.longitude.max) / 2; /* Returning three nested replies */ - addReplyMultiBulkLen(c, 3 + withgeojson * 2); + addReplyMultiBulkLen(c, 3); /* First, the minimum corner */ addReplyMultiBulkLen(c, 2); @@ -646,50 +566,23 @@ void geoDecodeCommand(redisClient *c) { addReplyMultiBulkLen(c, 2); addReplyDouble(c, y); addReplyDouble(c, x); - - if (withgeojson) { - struct geojsonPoint gp = { .latitude = y, - .longitude = x, - .member = NULL }; - - /* Return geojson Feature Point */ - latLongToGeojsonAndReply(c, &gp, NULL); - - /* Return geojson Feature Polygon */ - decodeGeohashToGeojsonBoundsAndReply(c, geohash.bits, &gp); - } } void geoEncodeCommand(redisClient *c) { /* args 0-2: ["geoencode", lat, long]; - * optionals: [radius, units] - * - AND / OR - - * optional: [geojson] */ - - int withgeojson = 0; - for (int i = 3; i < c->argc; i++) { - char *arg = c->argv[i]->ptr; - if (!strncasecmp(arg, "withgeo", 7) || !strcasecmp(arg, "geojson") || - !strcasecmp(arg, "json") || !strcasecmp(arg, "withjson")) { - withgeojson = 1; - break; - } - } + * optionals: [radius, units] */ double radius_meters = 0; if (c->argc >= 5) { - if ((radius_meters = extractDistanceOrReply(c, c->argv + 3, NULL)) < - 0) { + if ((radius_meters = extractDistanceOrReply(c, c->argv + 3, NULL)) < 0) return; - } - } else if (c->argc == 4 && !withgeojson) { + } else if (c->argc == 4) { addReplyError(c, "must provide units when asking for radius encode"); return; } double latlong[2]; - if (!extractLatLongOrReply(c, c->argv + 1, latlong)) - return; + if (!extractLatLongOrReply(c, c->argv + 1, latlong)) return; /* Encode lat/long into our geohash */ GeoHashBits geohash; @@ -709,8 +602,8 @@ void geoEncodeCommand(redisClient *c) { double y = (area.latitude.min + area.latitude.max) / 2; double x = (area.longitude.min + area.longitude.max) / 2; - /* Return four nested multibulk replies with optional geojson returns */ - addReplyMultiBulkLen(c, 4 + withgeojson * 2); + /* Return four nested multibulk replies. */ + addReplyMultiBulkLen(c, 4); /* Return the binary geohash we calculated as 52-bit integer */ addReplyLongLong(c, bits); @@ -729,22 +622,4 @@ void geoEncodeCommand(redisClient *c) { addReplyMultiBulkLen(c, 2); addReplyDouble(c, y); addReplyDouble(c, x); - - if (withgeojson) { - struct geojsonPoint gp = { .latitude = y, - .longitude = x, - .member = NULL }; - - /* Return geojson Feature Point */ - latLongToGeojsonAndReply(c, &gp, NULL); - - /* Return geojson Feature Polygon (bounding box for this step size) */ - /* We don't use the helper function here because we can't re-calculate - * the area if we have a non-GEO_STEP_MAX step size. */ - sds geojson = geojsonBoxToPolygonFeature( - area.latitude.min, area.longitude.min, area.latitude.max, - area.longitude.max, gp.set, gp.member); - addReplyBulkCBuffer(c, geojson, sdslen(geojson)); - sdsfree(geojson); - } } diff --git a/src/geo.h b/src/geo.h index f8207166..9aa85cf9 100644 --- a/src/geo.h +++ b/src/geo.h @@ -9,4 +9,13 @@ void geoRadiusByMemberCommand(redisClient *c); void geoRadiusCommand(redisClient *c); void geoAddCommand(redisClient *c); +struct geoPoint { + double latitude; + double longitude; + double dist; + char *set; + char *member; + void *userdata; +}; + #endif diff --git a/src/geojson.c b/src/geojson.c deleted file mode 100644 index bb0befc9..00000000 --- a/src/geojson.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2014, Matt Stancliff . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "geojson.h" - -#define L server.lua - -/* ==================================================================== - * The Encoder - * ==================================================================== */ -static sds jsonEncode() { - /* When entering this function, stack is: [1:[geojson table to encode]] */ - lua_getglobal(L, "cjson"); - lua_getfield(L, -1, "encode"); - - /* Stack is now: [1:[geojson table], 2:'cjson', 3:'encode'] */ - - /* Move current top ('encode') to bottom of stack */ - lua_insert(L, 1); - - /* Move current top ('cjson') to bottom of stack so we can 'cjson.encode' */ - lua_insert(L, 1); - - /* Stack is now: [1:'cjson', 2:'encode', 3:[table of geojson to encode]] */ - - /* Call cjson.encode on the element above it on the stack; - * obtain one return value */ - if (lua_pcall(L, 1, 1, 0) != 0) - redisLog(REDIS_WARNING, "Could not encode geojson: %s", - lua_tostring(L, -1)); - - sds geojson = sdsnew(lua_tostring(L, -1)); - - /* We're done. Remove entire stack. Drop mic. Walk away. */ - lua_pop(L, lua_gettop(L)); - - /* Return sds the caller must sdsfree() on their own */ - return geojson; -} - -/* ==================================================================== - * The Lua Helpers - * ==================================================================== */ -static inline void luaCreateFieldFromPrevious(const char *field) { - lua_setfield(L, -2, field); -} - -static inline void luaCreateFieldStr(const char *field, const char *value) { - lua_pushstring(L, value); - luaCreateFieldFromPrevious(field); -} - -/* Creates [Lat, Long] array attached to "coordinates" key */ -static void luaCreateCoordinates(const double x, const double y) { - /* Create array table with two elements */ - lua_createtable(L, 2, 0); - - lua_pushnumber(L, x); - lua_rawseti(L, -2, 1); - lua_pushnumber(L, y); - lua_rawseti(L, -2, 2); -} - -static void luaCreatePropertyNull(void) { - /* Create empty table and give it a name. This is a json {} value. */ - lua_createtable(L, 0, 0); - luaCreateFieldFromPrevious("properties"); -} - -static void _luaCreateProperties(const char *k1, const char *v1, const char *k2, - const char *v2, const int noclose) { - /* we may add additional properties outside of here, so newtable instead of - * fixed-size createtable */ - lua_newtable(L); - - luaCreateFieldStr(k1, v1); - luaCreateFieldStr(k2, v2); - - if (!noclose) - luaCreateFieldFromPrevious("properties"); -} - -static void luaCreateProperties(const char *k1, const char *v1, const char *k2, - const char *v2) { - _luaCreateProperties(k1, v1, k2, v2, 0); -} - -/* ==================================================================== - * The Lua Aggregation Helpers - * ==================================================================== */ -static void attachProperties(const char *set, const char *member) { - if (member) - luaCreateProperties("set", set, "member", member); - else - luaCreatePropertyNull(); -} - -static void attachPropertiesWithDist(const char *set, const char *member, - double dist, const char *units) { - if (member) { - _luaCreateProperties("set", set, "member", member, 1); - if (units) { - /* Add units then distance. After encoding it comes - * out as distance followed by units in the json. */ - lua_pushstring(L, units); - luaCreateFieldFromPrevious("units"); - lua_pushnumber(L, dist); - luaCreateFieldFromPrevious("distance"); - } - - /* We requested to leave the properties table open, but now we - * are done and can close it. */ - luaCreateFieldFromPrevious("properties"); - } else { - luaCreatePropertyNull(); - } -} - -static void createGeometryPoint(const double x, const double y) { - lua_createtable(L, 0, 2); - - /* coordinates = [x, y] */ - luaCreateCoordinates(x, y); - luaCreateFieldFromPrevious("coordinates"); - - /* type = Point */ - luaCreateFieldStr("type", "Point"); - - /* geometry = (coordinates = [x, y]) */ - luaCreateFieldFromPrevious("geometry"); -} - -static void createGeometryBox(const double x1, const double y1, const double x2, - const double y2) { - lua_createtable(L, 0, 2); - - /* Result = [[[x1,y1],[x2,y1],[x2,y2],[x1,y2], [x1,y1]] */ - /* The end coord is the start coord to make a closed polygon */ - lua_createtable(L, 1, 0); - lua_createtable(L, 5, 0); - - /* Bottom left */ - luaCreateCoordinates(x1, y1); - lua_rawseti(L, -2, 1); - - /* Top Left */ - luaCreateCoordinates(x2, y1); - lua_rawseti(L, -2, 2); - - /* Top Right */ - luaCreateCoordinates(x2, y2); - lua_rawseti(L, -2, 3); - - /* Bottom Right */ - luaCreateCoordinates(x1, y2); - lua_rawseti(L, -2, 4); - - /* Bottom Left (Again) */ - luaCreateCoordinates(x1, y1); - lua_rawseti(L, -2, 5); - - /* Set the outer array of our inner array of the inner coords */ - lua_rawseti(L, -2, 1); - - /* Bundle those together in coordinates: [a, b, c, d] */ - luaCreateFieldFromPrevious("coordinates"); - - /* Add type field */ - luaCreateFieldStr("type", "Polygon"); - - luaCreateFieldFromPrevious("geometry"); -} - -static void createFeature() { - /* Features have three fields: type, geometry, and properties */ - lua_createtable(L, 0, 3); - - luaCreateFieldStr("type", "Feature"); - - /* You must call attachProperties on your own */ -} - -static void createCollection(size_t size) { - /* FeatureCollections have two fields: type and features */ - lua_createtable(L, 0, 2); - - luaCreateFieldStr("type", "FeatureCollection"); -} - -static void pointsToCollection(const struct geojsonPoint *pts, const size_t len, - const char *units) { - createCollection(len); - - lua_createtable(L, len, 0); - for (int i = 0; i < len; i++) { - createFeature(); - createGeometryPoint(pts[i].longitude, pts[i].latitude); /* x, y */ - attachPropertiesWithDist(pts[i].set, pts[i].member, pts[i].dist, units); - lua_rawseti(L, -2, i + 1); /* Attach this Feature to "features" array */ - } - luaCreateFieldFromPrevious("features"); -} - -static void latLongToPointFeature(const double latitude, - const double longitude) { - createFeature(); - createGeometryPoint(longitude, latitude); /* geojson is: x,y */ -} - -static void squareToPolygonFeature(const double x1, const double y1, - const double x2, const double y2) { - createFeature(); - createGeometryBox(x1, y1, x2, y2); -} - -/* ==================================================================== - * The Interface Functions - * ==================================================================== */ -sds geojsonFeatureCollection(const struct geojsonPoint *pts, const size_t len, - const char *units) { - pointsToCollection(pts, len, units); - return jsonEncode(); -} - -sds geojsonLatLongToPointFeature(const double latitude, const double longitude, - const char *set, const char *member, - const double dist, const char *units) { - latLongToPointFeature(latitude, longitude); - attachPropertiesWithDist(set, member, dist, units); - return jsonEncode(); -} - -sds geojsonBoxToPolygonFeature(const double y1, const double x1, - const double y2, const double x2, - const char *set, const char *member) { - squareToPolygonFeature(x1, y1, x2, y2); - attachProperties(set, member); - return jsonEncode(); -} diff --git a/src/geojson.h b/src/geojson.h deleted file mode 100644 index 55993bea..00000000 --- a/src/geojson.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2014, Matt Stancliff . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __GEOJSON_H__ -#define __GEOJSON_H__ - -#include "redis.h" -#include "geohash_helper.h" - -struct geojsonPoint { - double latitude; - double longitude; - double dist; - char *set; - char *member; - void *userdata; -}; - -sds geojsonLatLongToPointFeature(const double latitude, const double longitude, - const char *set, const char *member, - const double dist, const char *units); -sds geojsonBoxToPolygonFeature(const double x1, const double y1, - const double x2, const double y2, - const char *set, const char *member); -sds geojsonFeatureCollection(const struct geojsonPoint *pts, const size_t len, - const char *units); - -#endif diff --git a/src/redis.c b/src/redis.c index 359ccb35..e0561183 100644 --- a/src/redis.c +++ b/src/redis.c @@ -286,7 +286,7 @@ struct redisCommand redisCommandTable[] = { {"georadius",geoRadiusCommand,-6,"r",0,NULL,1,1,1,0,0}, {"georadiusbymember",geoRadiusByMemberCommand,-5,"r",0,NULL,1,1,1,0,0}, {"geoencode",geoEncodeCommand,-3,"r",0,NULL,0,0,0,0,0}, - {"geodecode",geoDecodeCommand,-2,"r",0,NULL,0,0,0,0,0}, + {"geodecode",geoDecodeCommand,2,"r",0,NULL,0,0,0,0,0}, {"pfselftest",pfselftestCommand,1,"r",0,NULL,0,0,0,0,0}, {"pfadd",pfaddCommand,-2,"wmF",0,NULL,1,1,1,0,0}, {"pfcount",pfcountCommand,-2,"r",0,NULL,1,1,1,0,0},