Add support of RESP3 attribute type
Currently, Redis DEBUG PROTOCOL 'attrib' command will return an attribute type, but hiredis doesn't support it yet. So it got the protocol type error: ``` 127.0.0.1:6379> DEBUG PROTOCOL attrib Error: Protocol error, got "|" as reply type byte ``` After apply this PR, it should reply: ``` 127.0.0.1:6379> DEBUG PROTOCOL attrib 1# "key-popularity" 1# 1) "key:123" 2) (integer) 90 ```
This commit is contained in:
parent
ff7a064490
commit
3eb0348ddd
@ -102,6 +102,7 @@ void freeReplyObject(void *reply) {
|
|||||||
break; /* Nothing to free */
|
break; /* Nothing to free */
|
||||||
case REDIS_REPLY_ARRAY:
|
case REDIS_REPLY_ARRAY:
|
||||||
case REDIS_REPLY_MAP:
|
case REDIS_REPLY_MAP:
|
||||||
|
case REDIS_REPLY_ATTR:
|
||||||
case REDIS_REPLY_SET:
|
case REDIS_REPLY_SET:
|
||||||
case REDIS_REPLY_PUSH:
|
case REDIS_REPLY_PUSH:
|
||||||
if (r->element != NULL) {
|
if (r->element != NULL) {
|
||||||
@ -160,6 +161,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -192,6 +194,7 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -212,6 +215,8 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -249,6 +254,7 @@ static void *createDoubleObject(const redisReadTask *task, double value, char *s
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -267,6 +273,7 @@ static void *createNilObject(const redisReadTask *task) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -287,6 +294,7 @@ static void *createBoolObject(const redisReadTask *task, int bval) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
|
parent->type == REDIS_REPLY_ATTR ||
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
|
|||||||
7
read.c
7
read.c
@ -250,6 +250,7 @@ static void moveToNextTask(redisReader *r) {
|
|||||||
prv = r->task[r->ridx-1];
|
prv = r->task[r->ridx-1];
|
||||||
assert(prv->type == REDIS_REPLY_ARRAY ||
|
assert(prv->type == REDIS_REPLY_ARRAY ||
|
||||||
prv->type == REDIS_REPLY_MAP ||
|
prv->type == REDIS_REPLY_MAP ||
|
||||||
|
prv->type == REDIS_REPLY_ATTR ||
|
||||||
prv->type == REDIS_REPLY_SET ||
|
prv->type == REDIS_REPLY_SET ||
|
||||||
prv->type == REDIS_REPLY_PUSH);
|
prv->type == REDIS_REPLY_PUSH);
|
||||||
if (cur->idx == prv->elements-1) {
|
if (cur->idx == prv->elements-1) {
|
||||||
@ -534,7 +535,7 @@ static int processAggregateItem(redisReader *r) {
|
|||||||
|
|
||||||
moveToNextTask(r);
|
moveToNextTask(r);
|
||||||
} else {
|
} else {
|
||||||
if (cur->type == REDIS_REPLY_MAP) elements *= 2;
|
if (cur->type == REDIS_REPLY_MAP || cur->type == REDIS_REPLY_ATTR) elements *= 2;
|
||||||
|
|
||||||
if (r->fn && r->fn->createArray)
|
if (r->fn && r->fn->createArray)
|
||||||
obj = r->fn->createArray(cur,elements);
|
obj = r->fn->createArray(cur,elements);
|
||||||
@ -602,6 +603,9 @@ static int processItem(redisReader *r) {
|
|||||||
case '%':
|
case '%':
|
||||||
cur->type = REDIS_REPLY_MAP;
|
cur->type = REDIS_REPLY_MAP;
|
||||||
break;
|
break;
|
||||||
|
case '|':
|
||||||
|
cur->type = REDIS_REPLY_ATTR;
|
||||||
|
break;
|
||||||
case '~':
|
case '~':
|
||||||
cur->type = REDIS_REPLY_SET;
|
cur->type = REDIS_REPLY_SET;
|
||||||
break;
|
break;
|
||||||
@ -642,6 +646,7 @@ static int processItem(redisReader *r) {
|
|||||||
return processBulkItem(r);
|
return processBulkItem(r);
|
||||||
case REDIS_REPLY_ARRAY:
|
case REDIS_REPLY_ARRAY:
|
||||||
case REDIS_REPLY_MAP:
|
case REDIS_REPLY_MAP:
|
||||||
|
case REDIS_REPLY_ATTR:
|
||||||
case REDIS_REPLY_SET:
|
case REDIS_REPLY_SET:
|
||||||
case REDIS_REPLY_PUSH:
|
case REDIS_REPLY_PUSH:
|
||||||
return processAggregateItem(r);
|
return processAggregateItem(r);
|
||||||
|
|||||||
20
test.c
20
test.c
@ -795,6 +795,26 @@ static void test_reply_reader(void) {
|
|||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
redisReaderFree(reader);
|
redisReaderFree(reader);
|
||||||
|
|
||||||
|
test("Can parse RESP3 attribute: ");
|
||||||
|
reader = redisReaderCreate();
|
||||||
|
redisReaderFeed(reader, "|2\r\n+foo\r\n:123\r\n+bar\r\n#t\r\n",26);
|
||||||
|
ret = redisReaderGetReply(reader,&reply);
|
||||||
|
test_cond(ret == REDIS_OK &&
|
||||||
|
((redisReply*)reply)->type == REDIS_REPLY_ATTR &&
|
||||||
|
((redisReply*)reply)->elements == 4 &&
|
||||||
|
((redisReply*)reply)->element[0]->type == REDIS_REPLY_STATUS &&
|
||||||
|
((redisReply*)reply)->element[0]->len == 3 &&
|
||||||
|
!strcmp(((redisReply*)reply)->element[0]->str,"foo") &&
|
||||||
|
((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER &&
|
||||||
|
((redisReply*)reply)->element[1]->integer == 123 &&
|
||||||
|
((redisReply*)reply)->element[2]->type == REDIS_REPLY_STATUS &&
|
||||||
|
((redisReply*)reply)->element[2]->len == 3 &&
|
||||||
|
!strcmp(((redisReply*)reply)->element[2]->str,"bar") &&
|
||||||
|
((redisReply*)reply)->element[3]->type == REDIS_REPLY_BOOL &&
|
||||||
|
((redisReply*)reply)->element[3]->integer);
|
||||||
|
freeReplyObject(reply);
|
||||||
|
redisReaderFree(reader);
|
||||||
|
|
||||||
test("Can parse RESP3 set: ");
|
test("Can parse RESP3 set: ");
|
||||||
reader = redisReaderCreate();
|
reader = redisReaderCreate();
|
||||||
redisReaderFeed(reader, "~5\r\n+orange\r\n$5\r\napple\r\n#f\r\n:100\r\n:999\r\n",40);
|
redisReaderFeed(reader, "~5\r\n+orange\r\n$5\r\napple\r\n#f\r\n:100\r\n:999\r\n",40);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user