• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

freeeve / tinykvs / 21186884278

20 Jan 2026 08:54PM UTC coverage: 71.178% (-0.1%) from 71.295%
21186884278

push

github

freeeve
refactor(writer): extract helpers from flushmemtable

43 of 55 new or added lines in 1 file covered. (78.18%)

273 existing lines in 4 files now uncovered.

5717 of 8032 relevant lines covered (71.18%)

407987.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.93
/cmd/tinykvs/shell_sql.go
1
package main
2

3
import (
4
        "encoding/hex"
5
        "strconv"
6
        "strings"
7

8
        "github.com/blastrain/vitess-sqlparser/sqlparser"
9
)
10

11
// preprocessFunctions expands SQL function calls to hex literals.
12
// Supported functions:
13
//   - uint64_be(n) → 8-byte big-endian encoding of n
14
//   - uint64_le(n) → 8-byte little-endian encoding of n
15
//   - uint32_be(n) → 4-byte big-endian encoding of n
16
//   - uint32_le(n) → 4-byte little-endian encoding of n
17
//   - byte(n) → single byte (0-255)
18
//   - fnv64(s) → FNV-1a 64-bit hash of string s
19
//
20
// Concatenation with || operator:
21
//   - x'14' || uint64_be(28708) → x'140000000000007024'
22
//
23
// Examples:
24
//   - k STARTS WITH x'10' || uint64_be(7341141)
25
//   - k STARTS WITH byte(0x14) || uint64_be(28708) || fnv64('library-123')
26
func preprocessFunctions(sql string) string {
423✔
27
        // Expand each function type to x'...' literals
423✔
28
        sql = expandFunction(sql, "uint64_be", encodeUint64BE)
423✔
29
        sql = expandFunction(sql, "uint64_le", encodeUint64LE)
423✔
30
        sql = expandFunction(sql, "uint32_be", encodeUint32BE)
423✔
31
        sql = expandFunction(sql, "uint32_le", encodeUint32LE)
423✔
32
        sql = expandFunction(sql, "byte", encodeByte)
423✔
33
        sql = expandFunction(sql, "fnv64", encodeFNV64)
423✔
34

423✔
35
        // Concatenate adjacent x'...' || x'...' literals
423✔
36
        return concatenateHexLiterals(sql)
423✔
37
}
423✔
38

39
// encodeUint64BE encodes a uint64 as 8 bytes big-endian.
40
func encodeUint64BE(arg string) ([]byte, bool) {
5✔
41
        val, err := parseUint(arg)
5✔
42
        if err != nil {
5✔
43
                return nil, false
×
44
        }
×
45
        b := make([]byte, 8)
5✔
46
        for i := 7; i >= 0; i-- {
45✔
47
                b[7-i] = byte(val >> (i * 8))
40✔
48
        }
40✔
49
        return b, true
5✔
50
}
51

52
// encodeUint64LE encodes a uint64 as 8 bytes little-endian.
53
func encodeUint64LE(arg string) ([]byte, bool) {
1✔
54
        val, err := parseUint(arg)
1✔
55
        if err != nil {
1✔
56
                return nil, false
×
UNCOV
57
        }
×
58
        b := make([]byte, 8)
1✔
59
        for i := 0; i < 8; i++ {
9✔
60
                b[i] = byte(val >> (i * 8))
8✔
61
        }
8✔
62
        return b, true
1✔
63
}
64

65
// encodeUint32BE encodes a uint32 as 4 bytes big-endian.
66
func encodeUint32BE(arg string) ([]byte, bool) {
2✔
67
        val, err := parseUint(arg)
2✔
68
        if err != nil {
2✔
UNCOV
69
                return nil, false
×
UNCOV
70
        }
×
71
        b := make([]byte, 4)
2✔
72
        for i := 3; i >= 0; i-- {
10✔
73
                b[3-i] = byte(val >> (i * 8))
8✔
74
        }
8✔
75
        return b, true
2✔
76
}
77

78
// encodeUint32LE encodes a uint32 as 4 bytes little-endian.
79
func encodeUint32LE(arg string) ([]byte, bool) {
1✔
80
        val, err := parseUint(arg)
1✔
81
        if err != nil {
1✔
UNCOV
82
                return nil, false
×
UNCOV
83
        }
×
84
        b := make([]byte, 4)
1✔
85
        for i := 0; i < 4; i++ {
5✔
86
                b[i] = byte(val >> (i * 8))
4✔
87
        }
4✔
88
        return b, true
1✔
89
}
90

91
// encodeByte encodes a single byte value.
92
func encodeByte(arg string) ([]byte, bool) {
3✔
93
        val, err := parseUint(arg)
3✔
94
        if err != nil || val > 255 {
3✔
UNCOV
95
                return nil, false
×
UNCOV
96
        }
×
97
        return []byte{byte(val)}, true
3✔
98
}
99

100
// encodeFNV64 encodes the FNV-1a hash of a string as 8 bytes big-endian.
101
func encodeFNV64(arg string) ([]byte, bool) {
3✔
102
        s := strings.Trim(arg, "'\"")
3✔
103
        h := fnv64a(s)
3✔
104
        b := make([]byte, 8)
3✔
105
        for i := 7; i >= 0; i-- {
27✔
106
                b[7-i] = byte(h >> (i * 8))
24✔
107
        }
24✔
108
        return b, true
3✔
109
}
110

111
// parseUint parses a uint64 from decimal or hex (0x...) string
112
func parseUint(s string) (uint64, error) {
12✔
113
        s = strings.TrimSpace(s)
12✔
114
        if strings.HasPrefix(strings.ToLower(s), "0x") {
15✔
115
                return strconv.ParseUint(s[2:], 16, 64)
3✔
116
        }
3✔
117
        return strconv.ParseUint(s, 10, 64)
9✔
118
}
119

120
// fnv64a computes FNV-1a 64-bit hash
121
func fnv64a(s string) uint64 {
3✔
122
        const offset64 = 14695981039346656037
3✔
123
        const prime64 = 1099511628211
3✔
124
        h := uint64(offset64)
3✔
125
        for i := 0; i < len(s); i++ {
15✔
126
                h ^= uint64(s[i])
12✔
127
                h *= prime64
12✔
128
        }
12✔
129
        return h
3✔
130
}
131

132
// expandFunction finds and expands a single-argument function call to hex literal
133
func expandFunction(sql, funcName string, encode func(string) ([]byte, bool)) string {
2,538✔
134
        for {
5,091✔
135
                lower := strings.ToLower(sql)
2,553✔
136
                idx := strings.Index(lower, strings.ToLower(funcName)+"(")
2,553✔
137
                if idx == -1 {
5,091✔
138
                        return sql
2,538✔
139
                }
2,538✔
140

141
                start := idx + len(funcName) + 1
15✔
142
                depth := 1
15✔
143
                end := start
15✔
144
                for end < len(sql) && depth > 0 {
99✔
145
                        if sql[end] == '(' {
84✔
UNCOV
146
                                depth++
×
147
                        } else if sql[end] == ')' {
99✔
148
                                depth--
15✔
149
                        }
15✔
150
                        end++
84✔
151
                }
152
                if depth != 0 {
15✔
UNCOV
153
                        return sql
×
UNCOV
154
                }
×
155

156
                arg := strings.TrimSpace(sql[start : end-1])
15✔
157
                bytes, ok := encode(arg)
15✔
158
                if !ok {
15✔
UNCOV
159
                        return sql
×
UNCOV
160
                }
×
161

162
                hexStr := hex.EncodeToString(bytes)
15✔
163
                sql = sql[:idx] + "x'" + hexStr + "'" + sql[end:]
15✔
164
        }
165
}
166

167
// concatenateHexLiterals joins adjacent hex literals: x'ab' || x'cd' → x'abcd'
168
func concatenateHexLiterals(sql string) string {
423✔
169
        for {
853✔
170
                // Find pattern: x'...' followed by optional whitespace, ||, optional whitespace, x'...'
430✔
171
                idx := strings.Index(sql, "' ||")
430✔
172
                if idx == -1 {
853✔
173
                        return sql
423✔
174
                }
423✔
175

176
                // Check if there's x' before the closing quote
177
                startQuote := strings.LastIndex(sql[:idx], "x'")
7✔
178
                if startQuote == -1 {
7✔
UNCOV
179
                        // Try next occurrence
×
UNCOV
180
                        sql = sql[:idx] + "'\x00||" + sql[idx+4:] // Mark as processed
×
UNCOV
181
                        continue
×
182
                }
183

184
                // Get the first hex value
185
                hex1 := sql[startQuote+2 : idx]
7✔
186

7✔
187
                // Find x' after ||
7✔
188
                afterPipe := sql[idx+4:]
7✔
189
                afterPipe = strings.TrimSpace(afterPipe)
7✔
190
                if !strings.HasPrefix(strings.ToLower(afterPipe), "x'") {
8✔
191
                        sql = sql[:idx] + "'\x00||" + sql[idx+4:]
1✔
192
                        continue
1✔
193
                }
194

195
                // Find end of second hex literal
196
                endQuote := strings.Index(afterPipe[2:], "'")
6✔
197
                if endQuote == -1 {
6✔
UNCOV
198
                        return sql
×
UNCOV
199
                }
×
200
                hex2 := afterPipe[2 : 2+endQuote]
6✔
201

6✔
202
                // Calculate where the second literal ends in original string
6✔
203
                afterPipeStart := idx + 4 + (len(sql[idx+4:]) - len(afterPipe))
6✔
204
                secondLiteralEnd := afterPipeStart + 2 + endQuote + 1
6✔
205

6✔
206
                // Replace both literals with concatenated version
6✔
207
                sql = sql[:startQuote] + "x'" + hex1 + hex2 + "'" + sql[secondLiteralEnd:]
6✔
208
        }
209
}
210

211
// preprocessStartsWith converts "STARTS WITH" syntax to LIKE syntax before SQL parsing.
212
// Converts:
213
//   - k STARTS WITH x'14' → k LIKE '$$HEX$$14%'
214
//   - k STARTS WITH '14' → k LIKE '14%'
215
func preprocessStartsWith(sql string) string {
423✔
216
        // Case-insensitive match for "STARTS WITH"
423✔
217
        lower := strings.ToLower(sql)
423✔
218
        idx := strings.Index(lower, "starts with")
423✔
219
        if idx == -1 {
846✔
220
                return sql
423✔
221
        }
423✔
222

223
        // Find what comes after "starts with"
224
        afterIdx := idx + len("starts with")
×
225
        after := strings.TrimSpace(sql[afterIdx:])
×
226

×
227
        // Check if it's a hex literal x'...' or X'...'
×
228
        if len(after) >= 4 && (after[0] == 'x' || after[0] == 'X') && after[1] == '\'' {
×
229
                // Find closing quote
×
230
                endQuote := strings.Index(after[2:], "'")
×
231
                if endQuote != -1 {
×
232
                        hexVal := after[2 : 2+endQuote]
×
233
                        rest := after[2+endQuote+1:]
×
234
                        // Convert to: LIKE '$$HEX$$<hexval>%'
×
235
                        return sql[:idx] + "LIKE '$$HEX$$" + hexVal + "%'" + rest
×
UNCOV
236
                }
×
UNCOV
237
        } else if len(after) >= 2 && after[0] == '\'' {
×
238
                // String literal '...'
×
UNCOV
239
                endQuote := strings.Index(after[1:], "'")
×
UNCOV
240
                if endQuote != -1 {
×
UNCOV
241
                        strVal := after[1 : 1+endQuote]
×
UNCOV
242
                        rest := after[1+endQuote+1:]
×
UNCOV
243
                        // Convert to: LIKE '<strval>%'
×
UNCOV
244
                        return sql[:idx] + "LIKE '" + strVal + "%'" + rest
×
UNCOV
245
                }
×
246
        }
247

UNCOV
248
        return sql
×
249
}
250

251
func extractValue(expr sqlparser.Expr) string {
287✔
252
        switch v := expr.(type) {
287✔
253
        case *sqlparser.SQLVal:
287✔
254
                switch v.Type {
287✔
255
                case sqlparser.StrVal:
283✔
256
                        return string(v.Val)
283✔
257
                case sqlparser.HexVal:
4✔
258
                        // x'deadbeef'
4✔
259
                        decoded, _ := hexDecode(string(v.Val))
4✔
260
                        return string(decoded)
4✔
UNCOV
261
                case sqlparser.IntVal:
×
UNCOV
262
                        return string(v.Val)
×
263
                }
264
        }
UNCOV
265
        return ""
×
266
}
267

268
// extractValueForLike extracts a value, with special handling for hex LIKE patterns.
269
// Supports:
270
//   - '0x14%' syntax - string starting with 0x followed by hex bytes and %
271
//   - '$$HEX$$14%' syntax - preprocessed from STARTS WITH x'14'
272
func extractValueForLike(expr sqlparser.Expr, operator string) (string, bool) {
110✔
273
        switch v := expr.(type) {
110✔
274
        case *sqlparser.SQLVal:
110✔
275
                return extractSQLValForLike(v, operator)
110✔
276
        }
UNCOV
277
        return "", false
×
278
}
279

280
// extractSQLValForLike handles SQLVal extraction with hex LIKE pattern support.
281
func extractSQLValForLike(v *sqlparser.SQLVal, operator string) (string, bool) {
110✔
282
        switch v.Type {
110✔
283
        case sqlparser.StrVal:
97✔
284
                return extractStrValForLike(string(v.Val), operator)
97✔
285
        case sqlparser.HexVal:
11✔
286
                decoded, _ := hexDecode(string(v.Val))
11✔
287
                return string(decoded), false
11✔
288
        case sqlparser.IntVal:
2✔
289
                return string(v.Val), false
2✔
290
        }
291
        return "", false
×
292
}
293

294
// extractStrValForLike handles string value extraction with hex LIKE pattern support.
295
func extractStrValForLike(s string, operator string) (string, bool) {
97✔
296
        if operator != "like" {
174✔
297
                return s, false
77✔
298
        }
77✔
299
        // Support '$$HEX$$14%' from preprocessed STARTS WITH x'14'
300
        if decoded, ok := tryDecodeHexMarkerPattern(s); ok {
20✔
UNCOV
301
                return decoded, true
×
UNCOV
302
        }
×
303
        // Support '0x14%' or '0X14%' syntax for hex prefix matching
304
        if decoded, ok := tryDecodeHexPrefixPattern(s); ok {
20✔
305
                return decoded, true
×
306
        }
×
307
        return s, false
20✔
308
}
309

310
// tryDecodeHexMarkerPattern decodes '$$HEX$$<hex>%' pattern from STARTS WITH preprocessing.
311
func tryDecodeHexMarkerPattern(s string) (string, bool) {
20✔
312
        if !strings.HasPrefix(s, "$$HEX$$") {
40✔
313
                return "", false
20✔
314
        }
20✔
UNCOV
315
        hexPart := s[7:] // skip $$HEX$$
×
UNCOV
316
        if !strings.HasSuffix(hexPart, "%") {
×
UNCOV
317
                return "", false
×
UNCOV
318
        }
×
UNCOV
319
        hexPart = hexPart[:len(hexPart)-1]
×
UNCOV
320
        decoded, err := hex.DecodeString(hexPart)
×
UNCOV
321
        if err != nil {
×
322
                return "", false
×
323
        }
×
324
        return string(decoded), true
×
325
}
326

327
// tryDecodeHexPrefixPattern decodes '0x<hex>%' pattern for hex prefix matching.
328
func tryDecodeHexPrefixPattern(s string) (string, bool) {
20✔
329
        if !strings.HasPrefix(s, "0x") && !strings.HasPrefix(s, "0X") {
40✔
330
                return "", false
20✔
331
        }
20✔
UNCOV
332
        hexPart := s[2:]
×
UNCOV
333
        if !strings.HasSuffix(hexPart, "%") {
×
UNCOV
334
                return "", false
×
UNCOV
335
        }
×
UNCOV
336
        hexPart = hexPart[:len(hexPart)-1]
×
UNCOV
337
        decoded, err := hex.DecodeString(hexPart)
×
UNCOV
338
        if err != nil {
×
UNCOV
339
                return "", false
×
UNCOV
340
        }
×
UNCOV
341
        return string(decoded), true
×
342
}
343

344
func hexDecode(s string) ([]byte, error) {
31✔
345
        // Remove any spaces
31✔
346
        s = strings.ReplaceAll(s, " ", "")
31✔
347
        result := make([]byte, len(s)/2)
31✔
348
        for i := 0; i < len(s)/2; i++ {
218✔
349
                b, err := strconv.ParseUint(s[i*2:i*2+2], 16, 8)
187✔
350
                if err != nil {
188✔
351
                        return nil, err
1✔
352
                }
1✔
353
                result[i] = byte(b)
186✔
354
        }
355
        return result, nil
30✔
356
}
357

358
// extractValueAndType returns the value string and whether it was a hex value
359
func extractValueAndType(expr sqlparser.Expr) (value string, hexBytes []byte, isHex bool) {
268✔
360
        switch v := expr.(type) {
268✔
361
        case *sqlparser.SQLVal:
268✔
362
                switch v.Type {
268✔
363
                case sqlparser.StrVal:
253✔
364
                        return string(v.Val), nil, false
253✔
365
                case sqlparser.HexVal:
12✔
366
                        decoded, _ := hexDecode(string(v.Val))
12✔
367
                        return string(decoded), decoded, true
12✔
368
                case sqlparser.IntVal:
3✔
369
                        return string(v.Val), nil, false
3✔
370
                }
371
        }
UNCOV
372
        return "", nil, false
×
373
}
374

375
// isMsgpackMap checks if data starts with a msgpack map marker
376
func isMsgpackMap(data []byte) bool {
19✔
377
        if len(data) == 0 {
21✔
378
                return false
2✔
379
        }
2✔
380
        b := data[0]
17✔
381
        // fixmap (0x80-0x8f), map16 (0xde), map32 (0xdf)
17✔
382
        return (b >= 0x80 && b <= 0x8f) || b == 0xde || b == 0xdf
17✔
383
}
384

385
// extractNestedField extracts a nested field value from a record using a dotted path.
386
// For example, path "address.city" extracts record["address"]["city"].
387
func extractNestedField(record map[string]any, path string) (any, bool) {
123✔
388
        parts := strings.Split(path, ".")
123✔
389
        var current any = record
123✔
390
        for _, part := range parts {
274✔
391
                m, ok := current.(map[string]any)
151✔
392
                if !ok {
152✔
393
                        return nil, false
1✔
394
                }
1✔
395
                current, ok = m[part]
150✔
396
                if !ok {
174✔
397
                        return nil, false
24✔
398
                }
24✔
399
        }
400
        return current, true
98✔
401
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc