Issue commands
Construct commands and send them to the Redis server.
Unlike the other client libraries,
hiredis
doesn't provide an extensive API to construct the many different
Redis commands. However, it does provide a lightweight and
flexible API to help you construct commands and parse their replies from
your own code.
The sections below describe the available functions in detail.
Construct synchronous commands
Use the redisCommand()
function to send commands to the server:
void *redisCommand(redisContext *c, const char *format, ...);
This function receives a redisContext
pointer and a pointer
to a string containing the command (see
Connect
to learn how to obtain the context pointer). The command text is the
same as the equivalent redis-cli
command. For example, to issue the command:
SET foo bar
you would use the following command with an existing redisContext* c
:
redisReply *reply = redisCommand(c, "SET foo bar");
See the Command reference for examples
of CLI commands that you can use with hiredis
. Most code examples
in other sections of the docs also have a CLI tab showing
command sequences that are equivalent to the code.
The command string is interpreted in a similar way to the format
string for printf()
, so you can easily interpolate string values from
your code into the command with the %s
format specifier:
char *myKeyNumber = "1";
char *myValue = "Hello";
// This issues the command 'SET key:1 Hello'.
redisReply *reply = redisCommand(c, "SET key:%s %s", myKeyNumber, myValue);
You may need to include binary data in the command (for example, to store
vector embeddings
in fields of a hash) object.
To do this, use the %b
format specifier and pass a pointer to the
data buffer, followed by a size_t
value indicating its length in bytes.
As the example below shows, you can freely mix %s
and %b
specifiers
in the same format string. Also, you can use the sequence %%
to
denote a literal percent sign, but the other printf()
specifiers,
such as %d
, are not supported.
char *entryNumber = "1";
char *embedding = "<binary data>";
char *url = "https://redis.io/";
size_t embLength = 13;
redisReply *reply = redisCommand(c,
"HSET entry:%s embedding %b url %s",
entryNumber,
embedding, embLength,
url
);
The redisCommand()
function has a variant called redisCommandArgv()
:
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
This doesn't take a format string but instead builds the command from an array
of strings passed in the argv
parameter.
Use the argc
value to
specify the length of this array and the argvlen
array to specify
the lengths of each of the strings in the array. If you pass NULL
for argvlen
then the function will attempt to use strlen()
to
get the length of each string. However, this will not work if any of
the strings contains binary data, so you should pass argvlen
explicitly in this case. The example below shows how to use
redisCommandArgv()
with a simple command:
const char *argv[3] = { "SET", "greeting", "hello"};
int argc = 3;
const size_t argvlen[] = {3, 8, 5};
redisReply *reply = redisCommandArgv(c, argc, argv, argvlen);
Construct asynchronous commands
Use the redisAsyncCommand()
and redisAsyncCommandArgv()
functions to send commands to the server asynchronously:
#include <hiredis/async.h>
.
.
.
int redisAsyncCommand(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
const char *format, ...);
int redisAsyncCommandArgv(
redisAsyncContext *ac, redisCallbackFn *fn, void *privdata,
int argc, const char **argv, const size_t *argvlen);
These work the same way as redisCommand()
and redisCommandArgv()
(see Construct synchronous commands
above) but they have two extra parameters. The first is a pointer to
a optional callback function and the second is a pointer to your own
custom data, which will be passed to the callback when it
executes. Pass NULL
for both of these pointers if you don't need
to use them.
The callback has the following signature:
void(redisAsyncContext *c, void *reply, void *privdata);
The first parameter is the asynchronous connection context and
the second is a pointer to the reply object. Use a cast to
(redisReply *)
to access the reply in the usual way (see
Handle command replies
for a full description of redisReply
). The last parameter
is the custom data pointer that you supplied during the
redisAsyncCommand()
call. This is passed to your function
without any modification.
The example below shows how you can use redisAsyncCommand()
with
or without a reply callback:
// The callback expects the key for the data in the `privdata`
// custom data parameter.
void getCallback(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
char *key = privdata;
if (reply == NULL) {
if (c->errstr) {
printf("errstr: %s\n", c->errstr);
}
return;
}
printf("Key: %s, value: %s\n", key, reply->str);
/* Disconnect after receiving the reply to GET */
redisAsyncDisconnect(c);
}
.
.
.
// Key and string value to pass to `SET`.
char *key = "testkey";
char *value = "testvalue";
// We aren't interested in the simple status reply for
// `SET`, so use NULL for the callback and custom data
// pointers.
redisAsyncCommand(c, NULL, NULL, "SET %s %s", key, value);
// The reply from `GET` is essential, so set a callback
// to retrieve it. Also, pass the key to the callback
// as the custom data.
redisAsyncCommand(c, getCallback, key, "GET %s", key);
Note that you should normally disconnect asynchronously from a
callback when you have finished using the connection.
Use redisAsyncDisconnect()
to disconnect gracefully, letting
pending commands execute and activate their callbacks.
Use redisAsyncFree()
to disconnect immediately. If you do this then
any pending callbacks from commands that have already executed will be
called with a NULL
reply pointer.
Command replies
The information in the redisReply
object has several formats,
and the format for a particular reply depends on the command that generated it.
See
Handle replies
to learn about the different reply formats and how to use them.