RESP3: fix cases of NULL reported instead of empty aggregate.
This commit is contained in:
parent
b12ccc840e
commit
06d490342f
10
src/server.c
10
src/server.c
@ -2161,6 +2161,16 @@ void createSharedObjects(void) {
|
|||||||
shared.nullarray[2] = createObject(OBJ_STRING,sdsnew("*-1\r\n"));
|
shared.nullarray[2] = createObject(OBJ_STRING,sdsnew("*-1\r\n"));
|
||||||
shared.nullarray[3] = createObject(OBJ_STRING,sdsnew("_\r\n"));
|
shared.nullarray[3] = createObject(OBJ_STRING,sdsnew("_\r\n"));
|
||||||
|
|
||||||
|
shared.emptymap[0] = NULL;
|
||||||
|
shared.emptymap[1] = NULL;
|
||||||
|
shared.emptymap[2] = createObject(OBJ_STRING,sdsnew("*0\r\n"));
|
||||||
|
shared.emptymap[3] = createObject(OBJ_STRING,sdsnew("%0\r\n"));
|
||||||
|
|
||||||
|
shared.emptyset[0] = NULL;
|
||||||
|
shared.emptyset[1] = NULL;
|
||||||
|
shared.emptyset[2] = createObject(OBJ_STRING,sdsnew("*0\r\n"));
|
||||||
|
shared.emptyset[3] = createObject(OBJ_STRING,sdsnew("~0\r\n"));
|
||||||
|
|
||||||
for (j = 0; j < PROTO_SHARED_SELECT_CMDS; j++) {
|
for (j = 0; j < PROTO_SHARED_SELECT_CMDS; j++) {
|
||||||
char dictid_str[64];
|
char dictid_str[64];
|
||||||
int dictid_len;
|
int dictid_len;
|
||||||
|
@ -897,7 +897,7 @@ struct moduleLoadQueueEntry {
|
|||||||
|
|
||||||
struct sharedObjectsStruct {
|
struct sharedObjectsStruct {
|
||||||
robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *pong, *space,
|
robj *crlf, *ok, *err, *emptybulk, *czero, *cone, *pong, *space,
|
||||||
*colon, *queued, *null[4], *nullarray[4],
|
*colon, *queued, *null[4], *nullarray[4], *emptymap[4], *emptyset[4],
|
||||||
*emptyarray, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,
|
*emptyarray, *wrongtypeerr, *nokeyerr, *syntaxerr, *sameobjecterr,
|
||||||
*outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr,
|
*outofrangeerr, *noscripterr, *loadingerr, *slowscripterr, *bgsaveerr,
|
||||||
*masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,
|
*masterdownerr, *roslaveerr, *execaborterr, *noautherr, *noreplicaserr,
|
||||||
|
@ -772,8 +772,8 @@ void genericHgetallCommand(client *c, int flags) {
|
|||||||
hashTypeIterator *hi;
|
hashTypeIterator *hi;
|
||||||
int length, count = 0;
|
int length, count = 0;
|
||||||
|
|
||||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL
|
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptymap[c->resp]))
|
||||||
|| checkType(c,o,OBJ_HASH)) return;
|
== NULL || checkType(c,o,OBJ_HASH)) return;
|
||||||
|
|
||||||
/* We return a map if the user requested keys and values, like in the
|
/* We return a map if the user requested keys and values, like in the
|
||||||
* HGETALL case. Otherwise to use a flat array makes more sense. */
|
* HGETALL case. Otherwise to use a flat array makes more sense. */
|
||||||
|
@ -402,7 +402,7 @@ void lrangeCommand(client *c) {
|
|||||||
if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||
|
if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != C_OK) ||
|
||||||
(getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;
|
(getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != C_OK)) return;
|
||||||
|
|
||||||
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL
|
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray)) == NULL
|
||||||
|| checkType(c,o,OBJ_LIST)) return;
|
|| checkType(c,o,OBJ_LIST)) return;
|
||||||
llen = listTypeLength(o);
|
llen = listTypeLength(o);
|
||||||
|
|
||||||
@ -414,7 +414,7 @@ void lrangeCommand(client *c) {
|
|||||||
/* Invariant: start >= 0, so this test will be true when end < 0.
|
/* Invariant: start >= 0, so this test will be true when end < 0.
|
||||||
* The range is empty when start > end or start >= length. */
|
* The range is empty when start > end or start >= length. */
|
||||||
if (start > end || start >= llen) {
|
if (start > end || start >= llen) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (end >= llen) end = llen-1;
|
if (end >= llen) end = llen-1;
|
||||||
|
10
src/t_set.c
10
src/t_set.c
@ -418,10 +418,10 @@ void spopWithCountCommand(client *c) {
|
|||||||
if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.null[c->resp]))
|
if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.null[c->resp]))
|
||||||
== NULL || checkType(c,set,OBJ_SET)) return;
|
== NULL || checkType(c,set,OBJ_SET)) return;
|
||||||
|
|
||||||
/* If count is zero, serve an empty multibulk ASAP to avoid special
|
/* If count is zero, serve an empty set ASAP to avoid special
|
||||||
* cases later. */
|
* cases later. */
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyset[c->resp]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,13 +632,13 @@ void srandmemberWithCountCommand(client *c) {
|
|||||||
uniq = 0;
|
uniq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp]))
|
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyset[c->resp]))
|
||||||
== NULL || checkType(c,set,OBJ_SET)) return;
|
== NULL || checkType(c,set,OBJ_SET)) return;
|
||||||
size = setTypeSize(set);
|
size = setTypeSize(set);
|
||||||
|
|
||||||
/* If count is zero, serve it ASAP to avoid special cases later. */
|
/* If count is zero, serve it ASAP to avoid special cases later. */
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyset[c->resp]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +813,7 @@ void sinterGenericCommand(client *c, robj **setkeys,
|
|||||||
}
|
}
|
||||||
addReply(c,shared.czero);
|
addReply(c,shared.czero);
|
||||||
} else {
|
} else {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyset[c->resp]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
18
src/t_zset.c
18
src/t_zset.c
@ -2426,7 +2426,7 @@ void zrangeGenericCommand(client *c, int reverse) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL
|
if ((zobj = lookupKeyReadOrReply(c,key,shared.emptyarray)) == NULL
|
||||||
|| checkType(c,zobj,OBJ_ZSET)) return;
|
|| checkType(c,zobj,OBJ_ZSET)) return;
|
||||||
|
|
||||||
/* Sanitize indexes. */
|
/* Sanitize indexes. */
|
||||||
@ -2438,7 +2438,7 @@ void zrangeGenericCommand(client *c, int reverse) {
|
|||||||
/* Invariant: start >= 0, so this test will be true when end < 0.
|
/* Invariant: start >= 0, so this test will be true when end < 0.
|
||||||
* The range is empty when start > end or start >= length. */
|
* The range is empty when start > end or start >= length. */
|
||||||
if (start > end || start >= llen) {
|
if (start > end || start >= llen) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (end >= llen) end = llen-1;
|
if (end >= llen) end = llen-1;
|
||||||
@ -2574,7 +2574,7 @@ void genericZrangebyscoreCommand(client *c, int reverse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ok, lookup the key and get the range */
|
/* Ok, lookup the key and get the range */
|
||||||
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL ||
|
if ((zobj = lookupKeyReadOrReply(c,key,shared.emptyarray)) == NULL ||
|
||||||
checkType(c,zobj,OBJ_ZSET)) return;
|
checkType(c,zobj,OBJ_ZSET)) return;
|
||||||
|
|
||||||
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
if (zobj->encoding == OBJ_ENCODING_ZIPLIST) {
|
||||||
@ -2594,7 +2594,7 @@ void genericZrangebyscoreCommand(client *c, int reverse) {
|
|||||||
|
|
||||||
/* No "first" element in the specified interval. */
|
/* No "first" element in the specified interval. */
|
||||||
if (eptr == NULL) {
|
if (eptr == NULL) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2661,7 +2661,7 @@ void genericZrangebyscoreCommand(client *c, int reverse) {
|
|||||||
|
|
||||||
/* No "first" element in the specified interval. */
|
/* No "first" element in the specified interval. */
|
||||||
if (ln == NULL) {
|
if (ln == NULL) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2919,7 +2919,7 @@ void genericZrangebylexCommand(client *c, int reverse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ok, lookup the key and get the range */
|
/* Ok, lookup the key and get the range */
|
||||||
if ((zobj = lookupKeyReadOrReply(c,key,shared.null[c->resp])) == NULL ||
|
if ((zobj = lookupKeyReadOrReply(c,key,shared.emptyarray)) == NULL ||
|
||||||
checkType(c,zobj,OBJ_ZSET))
|
checkType(c,zobj,OBJ_ZSET))
|
||||||
{
|
{
|
||||||
zslFreeLexRange(&range);
|
zslFreeLexRange(&range);
|
||||||
@ -2942,7 +2942,7 @@ void genericZrangebylexCommand(client *c, int reverse) {
|
|||||||
|
|
||||||
/* No "first" element in the specified interval. */
|
/* No "first" element in the specified interval. */
|
||||||
if (eptr == NULL) {
|
if (eptr == NULL) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
zslFreeLexRange(&range);
|
zslFreeLexRange(&range);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3006,7 +3006,7 @@ void genericZrangebylexCommand(client *c, int reverse) {
|
|||||||
|
|
||||||
/* No "first" element in the specified interval. */
|
/* No "first" element in the specified interval. */
|
||||||
if (ln == NULL) {
|
if (ln == NULL) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
zslFreeLexRange(&range);
|
zslFreeLexRange(&range);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3160,7 +3160,7 @@ void genericZpopCommand(client *c, robj **keyv, int keyc, int where, int emitkey
|
|||||||
|
|
||||||
/* No candidate for zpopping, return empty. */
|
/* No candidate for zpopping, return empty. */
|
||||||
if (!zobj) {
|
if (!zobj) {
|
||||||
addReplyNull(c);
|
addReply(c,shared.emptyarray);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user