Skip to content

Commit 54151ef

Browse files
authored
Rewritten list query, test and fix (#83)
1 parent b23222e commit 54151ef

File tree

2 files changed

+62
-9
lines changed

2 files changed

+62
-9
lines changed

pkg/kine/drivers/generic/generic.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ var (
2424

2525
listSQL = fmt.Sprintf(`
2626
SELECT %s
27-
FROM kine AS kv
28-
LEFT JOIN kine kv2
29-
ON kv.name = kv2.name
30-
AND kv.id < kv2.id
31-
WHERE kv2.name IS NULL
32-
AND kv.name >= ? AND kv.name < ?
33-
AND (? OR kv.deleted = 0)
34-
%%s
27+
FROM kine kv
28+
JOIN (
29+
SELECT MAX(mkv.id) as id
30+
FROM kine mkv
31+
WHERE
32+
mkv.name >= ? AND mkv.name < ?
33+
%%s
34+
GROUP BY mkv.name) maxkv
35+
ON maxkv.id = kv.id
36+
WHERE
37+
(kv.deleted = 0 OR ?)
3538
ORDER BY kv.id ASC
3639
`, columns)
3740

@@ -200,7 +203,7 @@ func Open(ctx context.Context, driverName, dataSourceName string, paramCharacter
200203
WHERE kv.id = ?`, columns), paramCharacter, numbered),
201204

202205
GetCurrentSQL: q(fmt.Sprintf(listSQL, ""), paramCharacter, numbered),
203-
ListRevisionStartSQL: q(fmt.Sprintf(listSQL, "AND kv.id <= ?"), paramCharacter, numbered),
206+
ListRevisionStartSQL: q(fmt.Sprintf(listSQL, "AND mkv.id <= ?"), paramCharacter, numbered),
204207
GetRevisionAfterSQL: q(revisionAfterSQL, paramCharacter, numbered),
205208

206209
CountSQL: q(fmt.Sprintf(`

test/update_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"testing"
7+
"time"
78

89
. "github.com/onsi/gomega"
910
clientv3 "go.etcd.io/etcd/client/v3"
@@ -77,6 +78,24 @@ func TestUpdate(t *testing.T) {
7778
g.Expect(resp.Kvs[0].ModRevision).To(BeNumerically(">", resp.Kvs[0].CreateRevision))
7879
}
7980
})
81+
t.Run("UpdateSameKeyLinearity", func(t *testing.T) {
82+
g := NewWithT(t)
83+
84+
// Add a large number of entries, two times and
85+
// it should take approximately same amout of time
86+
numAddEntries := 1000
87+
88+
startFirst := time.Now()
89+
addSameEntries(ctx, g, client, numAddEntries, true)
90+
durationFirstBatch := time.Since(startFirst)
91+
92+
startSecond := time.Now()
93+
addSameEntries(ctx, g, client, numAddEntries, false)
94+
durationSecondBatch := time.Since(startSecond)
95+
96+
g.Expect(durationSecondBatch <= durationFirstBatch*2).To(BeTrue())
97+
98+
})
8099

81100
// Trying to update an old revision(in compare) should fail
82101
t.Run("UpdateOldRevisionFails", func(t *testing.T) {
@@ -125,6 +144,37 @@ func TestUpdate(t *testing.T) {
125144

126145
}
127146

147+
func addSameEntries(ctx context.Context, g Gomega, client *clientv3.Client, numEntries int, create_first bool) {
148+
for i := 0; i < numEntries; i++ {
149+
key := "testkey-same"
150+
value := fmt.Sprintf("value-%d", i)
151+
152+
if i != 0 || !create_first {
153+
updateEntry(ctx, g, client, key, value)
154+
} else {
155+
addEntry(ctx, g, client, key, value)
156+
}
157+
}
158+
}
159+
160+
func updateEntry(ctx context.Context, g Gomega, client *clientv3.Client, key string, value string) {
161+
162+
resp, err := client.Get(ctx, key, clientv3.WithRange(""))
163+
164+
g.Expect(err).To(BeNil())
165+
g.Expect(resp.Kvs).To(HaveLen(1))
166+
167+
resp2, err2 := client.Txn(ctx).
168+
If(clientv3.Compare(clientv3.ModRevision(key), "=", resp.Kvs[0].ModRevision)).
169+
Then(clientv3.OpPut(key, value)).
170+
Else(clientv3.OpGet(key, clientv3.WithRange(""))).
171+
Commit()
172+
173+
g.Expect(err2).To(BeNil())
174+
g.Expect(resp2.Succeeded).To(BeTrue())
175+
176+
}
177+
128178
// BenchmarkUpdate is a benchmark for the Update operation.
129179
func BenchmarkUpdate(b *testing.B) {
130180
ctx := context.Background()

0 commit comments

Comments
 (0)