Skip to content

Commit ce66b76

Browse files
authored
Merge pull request #103 from alicebob/keys
allow newlines in keys
2 parents 0195e13 + 3d33259 commit ce66b76

File tree

9 files changed

+57
-30
lines changed

9 files changed

+57
-30
lines changed

cmd_generic.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func (m *Miniredis) cmdKeys(c *server.Peer, cmd string, args []string) {
334334
withTx(m, c, func(c *server.Peer, ctx *connCtx) {
335335
db := m.db(ctx.selectedDB)
336336

337-
keys := matchKeys(db.allKeys(), key)
337+
keys, _ := matchKeys(db.allKeys(), key)
338338
c.WriteLen(len(keys))
339339
for _, s := range keys {
340340
c.WriteBulk(s)
@@ -507,7 +507,7 @@ func (m *Miniredis) cmdScan(c *server.Peer, cmd string, args []string) {
507507

508508
keys := db.allKeys()
509509
if withMatch {
510-
keys = matchKeys(keys, match)
510+
keys, _ = matchKeys(keys, match)
511511
}
512512

513513
c.WriteLen(2)

cmd_hash.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ func (m *Miniredis) cmdHscan(c *server.Peer, cmd string, args []string) {
598598

599599
members := db.hashFields(key)
600600
if withMatch {
601-
members = matchKeys(members, match)
601+
members, _ = matchKeys(members, match)
602602
}
603603

604604
c.WriteLen(2)

cmd_set.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ func (m *Miniredis) cmdSscan(c *server.Peer, cmd string, args []string) {
661661

662662
members := db.setMembers(key)
663663
if withMatch {
664-
members = matchKeys(members, match)
664+
members, _ = matchKeys(members, match)
665665
}
666666

667667
c.WriteLen(2)

cmd_sorted_set.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,8 +1360,7 @@ func (m *Miniredis) cmdZscan(c *server.Peer, cmd string, args []string) {
13601360

13611361
withTx(m, c, func(c *server.Peer, ctx *connCtx) {
13621362
db := m.db(ctx.selectedDB)
1363-
// We return _all_ (matched) keys every time.
1364-
1363+
// Paging is not implementend, all results are returned for cursor 0.
13651364
if cursor != 0 {
13661365
// Invalid cursor.
13671366
c.WriteLen(2)
@@ -1376,7 +1375,7 @@ func (m *Miniredis) cmdZscan(c *server.Peer, cmd string, args []string) {
13761375

13771376
members := db.ssetMembers(key)
13781377
if withMatch {
1379-
members = matchKeys(members, match)
1378+
members, _ = matchKeys(members, match)
13801379
}
13811380

13821381
c.WriteLen(2)

integration/sorted_set_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,17 @@ func TestSortedSet(t *testing.T) {
8383
succ("DEL", "z2"),
8484
succ("EXISTS", "z2"),
8585
)
86+
87+
testCommands(t,
88+
succ("ZADD", "z", 0, "new\nline\n"),
89+
succ("ZADD", "z", 0, "line"),
90+
succ("ZADD", "z", 0, "another\nnew\nline\n"),
91+
succ("ZSCAN", "z", 0, "MATCH", "*"),
92+
succ("ZRANGEBYLEX", "z", "[a", "[z"),
93+
succ("ZRANGE", "z", 0, -1, "WITHSCORES"),
94+
)
8695
}
96+
8797
func TestSortedSetAdd(t *testing.T) {
8898
testCommands(t,
8999
succ("ZADD", "z",
@@ -484,8 +494,8 @@ func TestSortedSetRangeByLex(t *testing.T) {
484494
fail("ZRANGEBYLEX", "key", "!a", "[b"),
485495
fail("ZRANGEBYLEX", "key", "[a", "!b"),
486496
fail("ZRANGEBYLEX", "key", "[a", "b]"),
487-
fail("ZRANGEBYLEX", "key", "[a", ""),
488-
fail("ZRANGEBYLEX", "key", "", "[b"),
497+
failWith("not valid string range item", "ZRANGEBYLEX", "key", "[a", ""),
498+
failWith("not valid string range item", "ZRANGEBYLEX", "key", "", "[b"),
489499
fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT"),
490500
fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", 1),
491501
fail("ZRANGEBYLEX", "key", "[a", "[b", "LIMIT", "a", 1),

integration/test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func fail(cmd string, args ...interface{}) command {
6060
}
6161
}
6262

63-
// expect an error, with `sub` in both errors
63+
// expect an error, with both errors containing `sub`
6464
func failWith(sub string, cmd string, args ...interface{}) command {
6565
return command{
6666
cmd: cmd,

keys.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
// The general strategy is to sandwich all non-meta characters between \Q...\E.
1313
func patternRE(k string) *regexp.Regexp {
1414
re := bytes.Buffer{}
15-
re.WriteString(`^\Q`)
15+
re.WriteString(`(?s)^\Q`)
1616
for i := 0; i < len(k); i++ {
1717
p := k[i]
1818
switch p {
@@ -63,3 +63,21 @@ func patternRE(k string) *regexp.Regexp {
6363
re.WriteString(`\E$`)
6464
return regexp.MustCompile(re.String())
6565
}
66+
67+
// matchKeys filters only matching keys.
68+
// The returned boolean is whether the match pattern was valid
69+
func matchKeys(keys []string, match string) ([]string, bool) {
70+
re := patternRE(match)
71+
if re == nil {
72+
// Special case: the given pattern won't match anything or is invalid.
73+
return nil, false
74+
}
75+
var res []string
76+
for _, k := range keys {
77+
if !re.MatchString(k) {
78+
continue
79+
}
80+
res = append(res, k)
81+
}
82+
return res, true
83+
}

keys_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,22 @@ func TestKeysSel(t *testing.T) {
121121
test2(`[]ap`) // empty char class
122122
test2(`ap\`) // trailing \
123123
}
124+
125+
func TestMatchKeys(t *testing.T) {
126+
t.Run("simple", func(t *testing.T) {
127+
m, ok := matchKeys([]string{"a", "b", "c"}, "*")
128+
equals(t, true, ok)
129+
equals(t, []string{"a", "b", "c"}, m)
130+
})
131+
132+
t.Run("newlines", func(t *testing.T) {
133+
m, ok := matchKeys([]string{"a", "b\nb", "c"}, "*")
134+
equals(t, true, ok)
135+
equals(t, []string{"a", "b\nb", "c"}, m)
136+
})
137+
138+
t.Run("invalid", func(t *testing.T) {
139+
_, ok := matchKeys([]string{"a", "b", "c"}, "[")
140+
equals(t, false, ok)
141+
})
142+
}

redis.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,3 @@ func redisRange(l, start, end int, stringSymantics bool) (int, int) {
188188
}
189189
return start, end
190190
}
191-
192-
// matchKeys filters only matching keys.
193-
// Will return an empty list on invalid match expression.
194-
func matchKeys(keys []string, match string) []string {
195-
re := patternRE(match)
196-
if re == nil {
197-
// Special case, the given pattern won't match anything / is
198-
// invalid.
199-
return nil
200-
}
201-
res := []string{}
202-
for _, k := range keys {
203-
if !re.MatchString(k) {
204-
continue
205-
}
206-
res = append(res, k)
207-
}
208-
return res
209-
}

0 commit comments

Comments
 (0)