-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
346 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
--- | ||
title: HSCAN | ||
description: Documentation for the DiceDB command HSCAN | ||
--- | ||
|
||
The `HSCAN` command is used to incrementally iterate over the fields of a hash stored at a given key. It returns both the next cursor and the matching fields. | ||
|
||
## Syntax | ||
|
||
``` | ||
HSCAN key cursor [MATCH pattern] [COUNT count] | ||
``` | ||
|
||
## Parameters | ||
|
||
- `key`: The key of the hash to scan. | ||
- `cursor`: The cursor indicating the starting position of the scan. | ||
- `MATCH pattern` (optional): Specifies a pattern to match against the fields. Only the fields that match the pattern will be returned. | ||
- `COUNT count` (optional): Specifies the maximum number of fields to return. | ||
|
||
## Return Value | ||
|
||
The `HSCAN` command returns an array containing the next cursor and the matching fields. The format of the returned array is `[nextCursor, [field1, value1, field2, value2, ...]]`. | ||
|
||
## Behaviour | ||
When the `HSCAN` command is executed: | ||
|
||
1. DiceDB checks if the specified key exists. | ||
2. If the key exists and is associated with a hash, DiceDB scans the fields of the hash and returns the next cursor and the matching fields. | ||
3. If the key does not exist, DiceDB returns an empty array. | ||
4. If the key exists but is not associated with a hash, an error is returned. | ||
5. If the key exists and all keys have been scanned, cursor is reset to 0. | ||
|
||
## Error handling | ||
The `HSCAN` command can raise the following errors: | ||
|
||
- `WRONGTYPE Operation against a key holding the wrong kind of value`: This error occurs if the specified key exists but is not associated with a hash. For example, if the key is associated with a string, list, set, or any other data type, this error will be raised. | ||
- `Invalid integer value for COUNT`: This error occurs if the value provided for the `COUNT` option is not a valid integer or is out of range. | ||
|
||
|
||
|
||
## Examples | ||
|
||
```DiceDB | ||
> HSET myhash field1 "value1" field2 "value2" | ||
1) (integer) 2 | ||
> HSCAN myhash 0 | ||
1) "2" | ||
2) 1) "field1" | ||
2) "value1" | ||
3) "field2" | ||
4) "value2" | ||
> HSCAN myhash 0 MATCH field* COUNT 1 | ||
1) "1" | ||
2) 1) "field1" | ||
2) "value1" | ||
> HSCAN myhash 1 MATCH field* COUNT 1 | ||
1) "0" | ||
2) 1) "field2" | ||
2) "value2" | ||
``` | ||
|
||
|
||
## Additional Notes | ||
|
||
- The `HSCAN` command has a time complexity of O(N), where N is the number of keys in the hash. This is in contrast to Redis, which implements `HSCAN` in O(1) time complexity by maintaining a cursor. | ||
- The `HSCAN` command is particularly useful for iterating over the fields of a hash in a cursor-based manner, allowing for efficient processing of large hashes. | ||
- The `MATCH` pattern allows for flexible filtering of fields based on their names, making it easy to target specific fields or groups of fields. | ||
- The `COUNT` option enables limiting the number of fields returned, which can be beneficial for performance and memory usage considerations. | ||
- The cursor returned by `HSCAN` can be used to resume the scan from the last position, making it suitable for use cases where the scan needs to be interrupted and resumed later. |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package async | ||
|
||
import ( | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
) | ||
|
||
var THREE int64 = 3 | ||
var FOUR int64 = 4 | ||
|
||
func TestHSCAN(t *testing.T) { | ||
conn := getLocalConnection() | ||
defer conn.Close() | ||
|
||
testCases := []TestCase{ | ||
{ | ||
commands: []string{"HSCAN empty_hash 0"}, | ||
expected: []interface{}{[]interface{}{"0", []interface{}{}}}, | ||
}, | ||
{ | ||
commands: []string{ | ||
"HSET test_hash field1 value1 field2 value2 field3 value3", | ||
"HSCAN test_hash 0", | ||
}, | ||
expected: []interface{}{ | ||
THREE, | ||
[]interface{}{ | ||
"0", | ||
[]interface{}{"field1", "value1", "field2", "value2", "field3", "value3"}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
commands: []string{ | ||
"HSET pattern_hash foo1 bar1 foo2 bar2 baz1 qux1 baz2 qux2", | ||
"HSCAN pattern_hash 0 MATCH foo*", | ||
}, | ||
expected: []interface{}{ | ||
FOUR, | ||
[]interface{}{ | ||
"0", | ||
[]interface{}{"foo1", "bar1", "foo2", "bar2"}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
commands: []string{ | ||
"HSET large_hash field1 value1 field2 value2", | ||
"HSCAN large_hash 0 COUNT 2", | ||
}, | ||
expected: []interface{}{ | ||
TWO, | ||
[]interface{}{"0", []interface{}{"field1", "value1", "field2", "value2"}}, | ||
}, | ||
}, | ||
{ | ||
commands: []string{ | ||
"SET wrong_type_key string_value", | ||
"HSCAN wrong_type_key 0", | ||
}, | ||
expected: []interface{}{ | ||
"OK", | ||
"WRONGTYPE Operation against a key holding the wrong kind of value", | ||
}, | ||
}, | ||
{ | ||
commands: []string{"HSCAN"}, | ||
expected: []interface{}{"ERR wrong number of arguments for 'hscan' command"}, | ||
}, | ||
{ | ||
commands: []string{ | ||
"HSET test_hash1 field1 value1 field2 value2 field3 value3 field4 value4", | ||
"HSCAN test_hash1 0 COUNT 2", | ||
"HSCAN test_hash1 2 COUNT 2", | ||
}, | ||
expected: []interface{}{ | ||
FOUR, | ||
[]interface{}{"2", []interface{}{"field1", "value1", "field2", "value2"}}, | ||
[]interface{}{"0", []interface{}{"field3", "value3", "field4", "value4"}}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
for i, cmd := range tc.commands { | ||
result := FireCommand(conn, cmd) | ||
assert.DeepEqual(t, tc.expected[i], result) | ||
} | ||
} | ||
} |
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
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
Oops, something went wrong.