summaryrefslogtreecommitdiff
path: root/src/db.c
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2022-02-08 10:01:35 +0200
committerGitHub <noreply@github.com>2022-02-08 10:01:35 +0200
commit66be30f7fc2f7f6378eedc8d7b219db18addbc06 (patch)
tree4a000502264ba3a03238c40080b3745dcf616009 /src/db.c
parentbb875603fb7ff3f9d19aad906bd45d7db98d9a39 (diff)
downloadredis-66be30f7fc2f7f6378eedc8d7b219db18addbc06.tar.gz
Handle key-spec flags with modules (#10237)
- add COMMAND GETKEYSANDFLAGS sub-command - add RM_KeyAtPosWithFlags and GetCommandKeysWithFlags - RM_KeyAtPos and RM_CreateCommand set flags requiring full access for keys - RM_CreateCommand set VARIABLE_FLAGS - expose `variable_flags` flag in COMMAND INFO key-specs - getKeysFromCommandWithSpecs prefers key-specs over getkeys-api - add tests for all of these
Diffstat (limited to 'src/db.c')
-rw-r--r--src/db.c50
1 files changed, 33 insertions, 17 deletions
diff --git a/src/db.c b/src/db.c
index 218eaf567..11665fa1d 100644
--- a/src/db.c
+++ b/src/db.c
@@ -1821,31 +1821,47 @@ invalid_spec:
* associated with how Redis will access the key.
*
* 'cmd' must be point to the corresponding entry into the redisCommand
- * table, according to the command name in argv[0].
- *
- * This function uses the command's key specs, which contain the key-spec flags,
- * (e.g. RO / RW) and only resorts to the command-specific helper function if
- * any of the keys-specs are marked as INCOMPLETE. */
+ * table, according to the command name in argv[0]. */
int getKeysFromCommandWithSpecs(struct redisCommand *cmd, robj **argv, int argc, int search_flags, getKeysResult *result) {
- if (cmd->flags & CMD_MODULE_GETKEYS) {
+ /* The command has at least one key-spec not marked as CHANNEL */
+ int has_keyspec = (getAllKeySpecsFlags(cmd, 1) & CMD_KEY_CHANNEL);
+ /* The command has at least one key-spec marked as VARIABLE_FLAGS */
+ int has_varflags = (getAllKeySpecsFlags(cmd, 0) & CMD_KEY_VARIABLE_FLAGS);
+
+ /* Flags indicating that we have a getkeys callback */
+ int has_module_getkeys = cmd->flags & CMD_MODULE_GETKEYS;
+ int has_native_getkeys = !(cmd->flags & CMD_MODULE) && cmd->getkeys_proc;
+
+ /* The key-spec that's auto generated by RM_CreateCommand sets VARIABLE_FLAGS since no flags are given.
+ * If the module provides getkeys callback, we'll prefer it, but if it didn't, we'll use key-spec anyway. */
+ if ((cmd->flags & CMD_MODULE) && has_varflags && !has_module_getkeys)
+ has_varflags = 0;
+
+ /* We prefer key-specs if there are any, and their flags are reliable. */
+ if (has_keyspec && !has_varflags) {
+ int ret = getKeysUsingKeySpecs(cmd,argv,argc,search_flags,result);
+ if (ret >= 0)
+ return ret;
+ /* If the specs returned with an error (probably an INVALID or INCOMPLETE spec),
+ * fallback to the callback method. */
+ }
+
+ /* Resort to getkeys callback methods. */
+ if (has_module_getkeys)
return moduleGetCommandKeysViaAPI(cmd,argv,argc,result);
- } else {
- if (!(getAllKeySpecsFlags(cmd, 0) & CMD_KEY_VARIABLE_FLAGS)) {
- int ret = getKeysUsingKeySpecs(cmd,argv,argc,search_flags,result);
- if (ret >= 0)
- return ret;
- }
- if (!(cmd->flags & CMD_MODULE) && cmd->getkeys_proc)
- return cmd->getkeys_proc(cmd,argv,argc,result);
- return 0;
- }
+
+ /* We use native getkeys as a last resort, since not all these native getkeys provide
+ * flags properly (only the ones that correspond to INVALID, INCOMPLETE or VARIABLE_FLAGS do.*/
+ if (has_native_getkeys)
+ return cmd->getkeys_proc(cmd,argv,argc,result);
+ return 0;
}
/* This function returns a sanity check if the command may have keys. */
int doesCommandHaveKeys(struct redisCommand *cmd) {
return (!(cmd->flags & CMD_MODULE) && cmd->getkeys_proc) || /* has getkeys_proc (non modules) */
(cmd->flags & CMD_MODULE_GETKEYS) || /* module with GETKEYS */
- (getAllKeySpecsFlags(cmd, 1) & CMD_KEY_CHANNEL); /* has at least one key-spec not marked as CHANNEL */
+ (getAllKeySpecsFlags(cmd, 1) & CMD_KEY_CHANNEL); /* has at least one key-spec not marked as CHANNEL */
}
/* The base case is to use the keys position as given in the command table