aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2022-05-17 08:33:49 +1000
committerSteve Bennett <steveb@workware.net.au>2022-05-17 08:34:16 +1000
commit34d0e14824c2491002fe5763c11b66c196a0f109 (patch)
tree4ce1cb5a2d166414be9c195b139dca2a67ae8246
parent7f75234e8e68394271ecb8b56a0a117a1d6066a7 (diff)
downloadjimtcl-34d0e14824c2491002fe5763c11b66c196a0f109.zip
jimtcl-34d0e14824c2491002fe5763c11b66c196a0f109.tar.gz
jimtcl-34d0e14824c2491002fe5763c11b66c196a0f109.tar.bz2
jim-redis: Add support for -type
For retrieving type information of return values. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--README.redis38
-rw-r--r--examples/redis.tcl11
-rw-r--r--jim-redis.c65
3 files changed, 95 insertions, 19 deletions
diff --git a/README.redis b/README.redis
index adae3b5..59fc860 100644
--- a/README.redis
+++ b/README.redis
@@ -11,7 +11,7 @@ Usage
~~~~~
The redis extension exports an Object Based interface. In order
-to open a connection, a stream sock must be open to the redis server.
+to open a connection, a stream socket must be open to the redis server.
e.g.
set r [redis [socket stream localhost:6379]]
@@ -21,7 +21,7 @@ Or to connect via the unix domain socket:
set r [redis [socket unix /tmp/redis.sock]]
The [redis] command returns a handle, that is a command name that
-can be used to perform operations on the redis instance. A real example:
+can be used to perform operations on the redis instance. For example:
. package require redis
1.0
@@ -51,15 +51,45 @@ format will be stored and returned exactly.
Return values
~~~~~~~~~~~~~
-The response from redis contains a type, and these types are handled as follows:
+Responses from redis contain type information. These types are handled as follows:
* integer - returns the integer result
* string - returns the string result
* array - returns a list of elements (where each element is a redis type)
-* null - returns the empty string
+* nil - returns the empty string
* status - returns the status as a string
* error - returns an error with the message as the value
+Accessing type information
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Normally the type of the return value doesn't matter as Jim treats everything as a string,
+however it can be useful to differentiate between the empty string and nil, or between a status
+return and an error return. In order to support this, the '-type' option is allowed as the
+first word of the subcommand. In this case, whenever a value is returned, a list of {value type}
+is returned instead. This is true recursively, so an array will return both the type for the array
+and each element will include a type. The types are identified as follows:
+
+* integer - "int"
+* string - "str"
+* array - "array"
+* nil - "nil"
+* status - "status"
+* error - "error"
+
+The following example illustrates the use of types:
+
+ . $r -type KEYS a*
+ {{abc str}} array
+ . $r -type SET def 3
+ OK status
+ . $r INCR def
+ 4 int
+ . $r -type GET missing
+ {} nil
+ . $r -type KEYS
+ {ERR wrong number of arguments for 'keys' command} error
+
The read subcommand
~~~~~~~~~~~~~~~~~~~
diff --git a/examples/redis.tcl b/examples/redis.tcl
index 3044ab8..aa3d246 100644
--- a/examples/redis.tcl
+++ b/examples/redis.tcl
@@ -27,6 +27,17 @@ $r HMSET env {*}$env
set result [$r HGET env testing]
puts "HGET: testing=$result"
+# Now the same with -type
+set result [$r -type HGET env testing]
+puts "HGET (-type): testing=$result"
+
+# Now a missing value with -type
+set result [$r -type HGET env doesnotexist]
+puts "HGET (-type): doesnotexist=$result"
+
+set result [$r -type HGETALL env]
+puts "HGETALL (-type): $result"
+
set size [$r HLEN env]
puts "Size of env is $size"
diff --git a/jim-redis.c b/jim-redis.c
index 72f55eb..2534347 100644
--- a/jim-redis.c
+++ b/jim-redis.c
@@ -13,30 +13,63 @@
/**
* Recursively decode a redis reply as Tcl data structure.
*/
-static Jim_Obj *jim_redis_get_result(Jim_Interp *interp, redisReply *reply)
+static Jim_Obj *jim_redis_get_result(Jim_Interp *interp, redisReply *reply, int addtype)
{
int i;
+ Jim_Obj *obj;
+
switch (reply->type) {
case REDIS_REPLY_INTEGER:
- return Jim_NewIntObj(interp, reply->integer);
+ obj = Jim_NewIntObj(interp, reply->integer);
+ break;
case REDIS_REPLY_STATUS:
case REDIS_REPLY_ERROR:
case REDIS_REPLY_STRING:
- return Jim_NewStringObj(interp, reply->str, reply->len);
+ obj = Jim_NewStringObj(interp, reply->str, reply->len);
break;
case REDIS_REPLY_ARRAY:
- {
- Jim_Obj *obj = Jim_NewListObj(interp, NULL, 0);
- for (i = 0; i < reply->elements; i++) {
- Jim_ListAppendElement(interp, obj, jim_redis_get_result(interp, reply->element[i]));
- }
- return obj;
+ obj = Jim_NewListObj(interp, NULL, 0);
+ for (i = 0; i < reply->elements; i++) {
+ Jim_ListAppendElement(interp, obj, jim_redis_get_result(interp, reply->element[i], addtype));
}
+ break;
case REDIS_REPLY_NIL:
- return Jim_NewStringObj(interp, NULL, 0);
+ obj = Jim_NewStringObj(interp, NULL, 0);
+ break;
default:
- return Jim_NewStringObj(interp, "badtype", -1);
+ obj = Jim_NewStringObj(interp, "badtype", -1);
+ break;
}
+ if (addtype) {
+ const char *type;
+
+ switch (reply->type) {
+ case REDIS_REPLY_INTEGER:
+ type = "int";
+ break;
+ case REDIS_REPLY_STATUS:
+ type = "status";
+ break;
+ case REDIS_REPLY_ERROR:
+ type = "error";
+ break;
+ case REDIS_REPLY_STRING:
+ type = "str";
+ break;
+ case REDIS_REPLY_ARRAY:
+ type = "array";
+ break;
+ case REDIS_REPLY_NIL:
+ type = "nil";
+ break;
+ default:
+ type = "invalid";
+ break;
+ }
+ obj = Jim_NewListObj(interp, &obj, 1);
+ Jim_ListAppendElement(interp, obj, Jim_NewStringObj(interp, type, -1));
+ }
+ return obj;
}
/**
@@ -56,12 +89,14 @@ static int jim_redis_subcmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
const char **args;
size_t *arglens;
int ret = JIM_OK;
+ int addtype = 0;
redisReply *reply;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
- return JIM_ERR;
+ if (argc >= 3 && Jim_CompareStringImmediate(interp, argv[1], "-type")) {
+ addtype = 1;
+ argc--;
+ argv++;
}
if (Jim_CompareStringImmediate(interp, argv[1], "readable")) {
@@ -94,7 +129,7 @@ static int jim_redis_subcmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
/* sometimes commands return NULL */
if (reply) {
- Jim_SetResult(interp, jim_redis_get_result(interp, reply));
+ Jim_SetResult(interp, jim_redis_get_result(interp, reply, addtype));
if (reply->type == REDIS_REPLY_ERROR) {
ret = JIM_ERR;
}