-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add key prefix matching to KEYS command (#237)
Related to #234 and !236. This is the implementation that was requested in the original issue. I updated KEYS command to be redis-valid and implemented prefix search. There is also a rather interesting test, I could you use some feedback here. I noticed that it might not be possible to reduce the complexity of the KEYS command. Because even if you use Scan, you will have to store the counter of all found keys before you do WriteBulk of the actual keys. @prologic here is what you probably had in mind: ``` s.db.Scan([]byte(prefix), func(key []byte) error { conn.WriteBulk(key) return nil }) ``` But there is no way to call `conn.WriteArray(n)` with the number of keys until you iterate through all of them, hence the second loop over found keys. Co-authored-by: Ivan Elfimov <[email protected]> Co-authored-by: James Mills <[email protected]> Reviewed-on: https://git.mills.io/prologic/bitcask/pulls/237 Reviewed-by: James Mills <[email protected]> Co-authored-by: biozz <biozz@[email protected]> Co-committed-by: biozz <biozz@[email protected]>
- Loading branch information
1 parent
2279245
commit 21a824e
Showing
3 changed files
with
137 additions
and
3 deletions.
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 |
---|---|---|
|
@@ -17,3 +17,4 @@ Yash Chandra <[email protected]> | |
Yury Fedorov orlangure | ||
o2gy84 <[email protected]> | ||
garsue <[email protected]> | ||
biozz <[email protected]> |
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,102 @@ | ||
package main | ||
|
||
import ( | ||
"net" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/tidwall/redcon" | ||
) | ||
|
||
func TestHandleKeys(t *testing.T) { | ||
s, err := newServer(":61234", "./test.db") | ||
if err != nil { | ||
t.Fatalf("Unable to create server: %v", err) | ||
} | ||
s.db.Put([]byte("foo"), []byte("bar")) | ||
testCases := []TestCase{ | ||
{ | ||
Command: redcon.Command{ | ||
Raw: []byte("KEYS *"), | ||
Args: [][]byte{[]byte("KEYS"), []byte("*")}, | ||
}, | ||
Expected: "1,foo", | ||
}, | ||
{ | ||
Command: redcon.Command{ | ||
Raw: []byte("KEYS fo*"), | ||
Args: [][]byte{[]byte("KEYS"), []byte("fo*")}, | ||
}, | ||
Expected: "1,foo", | ||
}, | ||
{ | ||
Command: redcon.Command{ | ||
Raw: []byte("KEYS ba*"), | ||
Args: [][]byte{[]byte("KEYS"), []byte("ba*")}, | ||
}, | ||
Expected: "0", | ||
}, | ||
{ | ||
Command: redcon.Command{ | ||
Raw: []byte("KEYS *oo"), | ||
Args: [][]byte{[]byte("KEYS"), []byte("*oo")}, | ||
}, | ||
Expected: "0", | ||
}, | ||
} | ||
for _, testCase := range testCases { | ||
conn := DummyConn{} | ||
s.handleKeys(testCase.Command, &conn) | ||
if testCase.Expected != conn.Result { | ||
t.Fatalf("s.handleKeys failed: expected '%s', got '%s'", testCase.Expected, conn.Result) | ||
} | ||
} | ||
} | ||
|
||
type TestCase struct { | ||
Command redcon.Command | ||
Expected string | ||
} | ||
|
||
type DummyConn struct { | ||
Result string | ||
} | ||
|
||
func (dc *DummyConn) RemoteAddr() string { | ||
return "" | ||
} | ||
func (dc *DummyConn) Close() error { | ||
return nil | ||
} | ||
func (dc *DummyConn) WriteError(msg string) {} | ||
func (dc *DummyConn) WriteString(str string) {} | ||
func (dc *DummyConn) WriteBulk(bulk []byte) { | ||
dc.Result += "," + string(bulk) | ||
} | ||
func (dc *DummyConn) WriteBulkString(bulk string) {} | ||
func (dc *DummyConn) WriteInt(num int) {} | ||
func (dc *DummyConn) WriteInt64(num int64) {} | ||
func (dc *DummyConn) WriteUint64(num uint64) {} | ||
func (dc *DummyConn) WriteArray(count int) { | ||
dc.Result = strconv.Itoa(count) | ||
} | ||
func (dc *DummyConn) WriteNull() {} | ||
func (dc *DummyConn) WriteRaw(data []byte) {} | ||
func (dc *DummyConn) WriteAny(any interface{}) {} | ||
func (dc *DummyConn) Context() interface{} { | ||
return nil | ||
} | ||
func (dc *DummyConn) SetContext(v interface{}) {} | ||
func (dc *DummyConn) SetReadBuffer(bytes int) {} | ||
func (dc *DummyConn) Detach() redcon.DetachedConn { | ||
return nil | ||
} | ||
func (dc *DummyConn) ReadPipeline() []redcon.Command { | ||
return nil | ||
} | ||
func (dc *DummyConn) PeekPipeline() []redcon.Command { | ||
return nil | ||
} | ||
func (dc *DummyConn) NetConn() net.Conn { | ||
return nil | ||
} |