Created
March 19, 2020 20:34
-
-
Save michael-grunder/0a6a49b39660c9d55e13c551ca78b2ee to your computer and use it in GitHub Desktop.
Quick and dirty redisearch calls in hiredis
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "hiredis.h" | |
#include "sds.h" | |
void panicAbort(const char *fmt, ...) { | |
va_list args; | |
va_start(args, fmt); | |
vfprintf(stderr, fmt, args); | |
va_end(args); | |
exit(-1); | |
} | |
const char *replyTypeString(int type) { | |
switch (type) { | |
case REDIS_REPLY_STRING: | |
return "string"; | |
case REDIS_REPLY_ARRAY: | |
return "array"; | |
case REDIS_REPLY_INTEGER: | |
return "integer"; | |
case REDIS_REPLY_NIL: | |
return "nil"; | |
case REDIS_REPLY_STATUS: | |
return "status"; | |
case REDIS_REPLY_ERROR: | |
return "error"; | |
default: | |
return "unknown"; | |
} | |
} | |
void freeReplyType(redisReply *r, int type) { | |
if (r == NULL) { | |
panicAbort("Redis returned NULL reply!"); | |
} else if (r->type != type) { | |
if (r->type == REDIS_REPLY_ERROR) { | |
fprintf(stderr, "Redis Error: %s\n", r->str); | |
} | |
panicAbort("Expected type '%s' (%d) but got type '%s' (%d)\n", | |
replyTypeString(type), type, replyTypeString(r->type), | |
r->type); | |
} | |
freeReplyObject(r); | |
} | |
void freeReplyOrAbort(redisReply *r) { | |
if (r == NULL) { | |
panicAbort("Error: hiredis returned NULL reply!\n"); | |
} | |
freeReplyObject(r); | |
} | |
static sds cliFormatReplyTTY(redisReply *r, char *prefix) { | |
sds out = sdsempty(); | |
switch (r->type) { | |
case REDIS_REPLY_ERROR: | |
out = sdscatprintf(out,"(error) %s\n", r->str); | |
break; | |
case REDIS_REPLY_STATUS: | |
out = sdscat(out,r->str); | |
out = sdscat(out,"\n"); | |
break; | |
case REDIS_REPLY_INTEGER: | |
out = sdscatprintf(out,"(integer) %lld\n",r->integer); | |
break; | |
case REDIS_REPLY_STRING: | |
/* If you are producing output for the standard output we want | |
* a more interesting output with quoted characters and so forth, | |
* unless it's a verbatim string type. */ | |
if (r->type == REDIS_REPLY_STRING) { | |
out = sdscatrepr(out,r->str,r->len); | |
out = sdscat(out,"\n"); | |
} else { | |
out = sdscatlen(out,r->str,r->len); | |
out = sdscat(out,"\n"); | |
} | |
break; | |
case REDIS_REPLY_ARRAY: | |
if (r->elements == 0) { | |
if (r->type == REDIS_REPLY_ARRAY) | |
out = sdscat(out,"(empty array)\n"); | |
else | |
out = sdscat(out,"(empty aggregate type)\n"); | |
} else { | |
unsigned int i, idxlen = 0; | |
char _prefixlen[16]; | |
char _prefixfmt[16]; | |
sds _prefix; | |
sds tmp; | |
/* Calculate chars needed to represent the largest index */ | |
i = r->elements; | |
do { | |
idxlen++; | |
i /= 10; | |
} while(i); | |
/* Prefix for nested multi bulks should grow with idxlen+2 spaces */ | |
memset(_prefixlen,' ',idxlen+2); | |
_prefixlen[idxlen+2] = '\0'; | |
_prefix = sdscat(sdsnew(prefix),_prefixlen); | |
/* Setup prefix format for every entry */ | |
char numsep = ')'; | |
snprintf(_prefixfmt,sizeof(_prefixfmt),"%%s%%%ud%c ",idxlen,numsep); | |
for (i = 0; i < r->elements; i++) { | |
unsigned int human_idx = i; | |
human_idx++; /* Make it 1-based. */ | |
/* Don't use the prefix for the first element, as the parent | |
* caller already prepended the index number. */ | |
out = sdscatprintf(out,_prefixfmt,i == 0 ? "" : prefix,human_idx); | |
/* Format the multi bulk entry */ | |
tmp = cliFormatReplyTTY(r->element[i],_prefix); | |
out = sdscatlen(out,tmp,sdslen(tmp)); | |
sdsfree(tmp); | |
} | |
sdsfree(_prefix); | |
} | |
break; | |
default: | |
fprintf(stderr,"Unknown reply type: %d\n", r->type); | |
exit(1); | |
} | |
return out; | |
} | |
int main(void) { | |
redisContext *c = redisConnect("localhost", 6379); | |
redisReply *r; | |
r = redisCommand(c, "FT.CREATE my_index SCHEMA title TEXT body TEXT"); | |
freeReplyOrAbort(r); | |
r = redisCommand(c, "FT.ADD my_index doc1 1.0 FIELDS title foo body bar"); | |
freeReplyOrAbort(r); | |
r = redisCommand(c, "FT.ADD my_index doc2 1.0 FIELDS title foo_2 body bar_2"); | |
freeReplyOrAbort(r); | |
r = redisCommand(c, "FT.SEARCH my_index foo"); | |
if (r == NULL || r->type != REDIS_REPLY_ARRAY) { | |
panicAbort("Error: Malformed FT.SEARCH reply"); | |
} | |
sds disp = cliFormatReplyTTY(r, ""); | |
printf("%s", disp); | |
freeReplyObject(r); | |
redisFree(c); | |
sdsfree(disp); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment