mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
0a82fe8447
Adds RM_SetCommandInfo, allowing modules to provide the following command info: * summary * complexity * since * history * hints * arity * key specs * args This information affects the output of `COMMAND`, `COMMAND INFO` and `COMMAND DOCS`, Cluster, ACL and is used to filter commands with the wrong number of arguments before the call reaches the module code. The recently added API functions for key specs (never released) are removed. A minimalist example would look like so: ```c RedisModuleCommand *mycmd = RedisModule_GetCommand(ctx,"mymodule.mycommand"); RedisModuleCommandInfo mycmd_info = { .version = REDISMODULE_COMMAND_INFO_VERSION, .arity = -5, .summary = "some description", }; if (RedisModule_SetCommandInfo(mycmd, &mycmd_info) == REDISMODULE_ERR) return REDISMODULE_ERR; ```` Notes: * All the provided information (including strings) is copied, not keeping references to the API input data. * The version field is actually a static struct that contains the sizes of the the structs used in arrays, so we can extend these in the future and old version will still be able to take the part they can support.
99 lines
3.7 KiB
C
99 lines
3.7 KiB
C
#include "redismodule.h"
|
|
|
|
#define UNUSED(V) ((void) V)
|
|
|
|
int cmd_set(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|
UNUSED(argv);
|
|
UNUSED(argc);
|
|
RedisModule_ReplyWithSimpleString(ctx, "OK");
|
|
return REDISMODULE_OK;
|
|
}
|
|
|
|
int cmd_get(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|
UNUSED(argv);
|
|
UNUSED(argc);
|
|
RedisModule_ReplyWithSimpleString(ctx, "OK");
|
|
return REDISMODULE_OK;
|
|
}
|
|
|
|
int cmd_get_fullname(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|
UNUSED(argv);
|
|
UNUSED(argc);
|
|
|
|
const char *command_name = RedisModule_GetCurrentCommandName(ctx);
|
|
RedisModule_ReplyWithSimpleString(ctx, command_name);
|
|
return REDISMODULE_OK;
|
|
}
|
|
|
|
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|
REDISMODULE_NOT_USED(argv);
|
|
REDISMODULE_NOT_USED(argc);
|
|
|
|
if (RedisModule_Init(ctx, "subcommands", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
if (RedisModule_CreateCommand(ctx,"subcommands.bitarray",NULL,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
RedisModuleCommand *parent = RedisModule_GetCommand(ctx,"subcommands.bitarray");
|
|
|
|
if (RedisModule_CreateSubcommand(parent,"set",cmd_set,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
RedisModuleCommand *subcmd = RedisModule_GetCommand(ctx,"subcommands.bitarray|set");
|
|
RedisModuleCommandInfo cmd_set_info = {
|
|
.version = REDISMODULE_COMMAND_INFO_VERSION,
|
|
.key_specs = (RedisModuleCommandKeySpec[]){
|
|
{
|
|
.flags = REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE,
|
|
.begin_search_type = REDISMODULE_KSPEC_BS_INDEX,
|
|
.bs.index.pos = 1,
|
|
.find_keys_type = REDISMODULE_KSPEC_FK_RANGE,
|
|
.fk.range = {0,1,0}
|
|
},
|
|
{0}
|
|
}
|
|
};
|
|
if (RedisModule_SetCommandInfo(subcmd, &cmd_set_info) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
if (RedisModule_CreateSubcommand(parent,"get",cmd_get,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
subcmd = RedisModule_GetCommand(ctx,"subcommands.bitarray|get");
|
|
RedisModuleCommandInfo cmd_get_info = {
|
|
.version = REDISMODULE_COMMAND_INFO_VERSION,
|
|
.key_specs = (RedisModuleCommandKeySpec[]){
|
|
{
|
|
.flags = REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_ACCESS,
|
|
.begin_search_type = REDISMODULE_KSPEC_BS_INDEX,
|
|
.bs.index.pos = 1,
|
|
.find_keys_type = REDISMODULE_KSPEC_FK_RANGE,
|
|
.fk.range = {0,1,0}
|
|
},
|
|
{0}
|
|
}
|
|
};
|
|
if (RedisModule_SetCommandInfo(subcmd, &cmd_get_info) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
/* Get the name of the command currently running. */
|
|
if (RedisModule_CreateCommand(ctx,"subcommands.parent_get_fullname",cmd_get_fullname,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
/* Get the name of the subcommand currently running. */
|
|
if (RedisModule_CreateCommand(ctx,"subcommands.sub",NULL,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
RedisModuleCommand *fullname_parent = RedisModule_GetCommand(ctx,"subcommands.sub");
|
|
if (RedisModule_CreateSubcommand(fullname_parent,"get_fullname",cmd_get_fullname,"",0,0,0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
/* Sanity */
|
|
|
|
/* Trying to create the same subcommand fails */
|
|
RedisModule_Assert(RedisModule_CreateSubcommand(parent,"get",NULL,"",0,0,0) == REDISMODULE_ERR);
|
|
|
|
/* Trying to create a sub-subcommand fails */
|
|
RedisModule_Assert(RedisModule_CreateSubcommand(subcmd,"get",NULL,"",0,0,0) == REDISMODULE_ERR);
|
|
|
|
return REDISMODULE_OK;
|
|
}
|