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

HDT3213 / godis / 13112161214

03 Feb 2025 11:10AM UTC coverage: 73.919% (+0.9%) from 73.041%
13112161214

push

github

HDT3213
fix test suits

6550 of 8861 relevant lines covered (73.92%)

0.82 hits per line

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

82.07
/database/hash.go
1
package database
2

3
import (
4
        Dict "github.com/hdt3213/godis/datastruct/dict"
5
        "github.com/hdt3213/godis/interface/database"
6
        "github.com/hdt3213/godis/interface/redis"
7
        "github.com/hdt3213/godis/lib/utils"
8
        "github.com/hdt3213/godis/redis/protocol"
9
        "strconv"
10
        "strings"
11
)
12

13
func (db *DB) getAsDict(key string) (Dict.Dict, protocol.ErrorReply) {
1✔
14
        entity, exists := db.GetEntity(key)
1✔
15
        if !exists {
2✔
16
                return nil, nil
1✔
17
        }
1✔
18
        dict, ok := entity.Data.(Dict.Dict)
1✔
19
        if !ok {
1✔
20
                return nil, &protocol.WrongTypeErrReply{}
×
21
        }
×
22
        return dict, nil
1✔
23
}
24

25
func (db *DB) getOrInitDict(key string) (dict Dict.Dict, inited bool, errReply protocol.ErrorReply) {
1✔
26
        dict, errReply = db.getAsDict(key)
1✔
27
        if errReply != nil {
1✔
28
                return nil, false, errReply
×
29
        }
×
30
        inited = false
1✔
31
        if dict == nil {
2✔
32
                dict = Dict.MakeSimple()
1✔
33
                db.PutEntity(key, &database.DataEntity{
1✔
34
                        Data: dict,
1✔
35
                })
1✔
36
                inited = true
1✔
37
        }
1✔
38
        return dict, inited, nil
1✔
39
}
40

41
// execHSet sets field in hash table
42
func execHSet(db *DB, args [][]byte) redis.Reply {
1✔
43
        // parse args
1✔
44
        key := string(args[0])
1✔
45
        field := string(args[1])
1✔
46
        value := args[2]
1✔
47

1✔
48
        // get or init entity
1✔
49
        dict, _, errReply := db.getOrInitDict(key)
1✔
50
        if errReply != nil {
1✔
51
                return errReply
×
52
        }
×
53

54
        result := dict.Put(field, value)
1✔
55
        db.addAof(utils.ToCmdLine3("hset", args...))
1✔
56
        return protocol.MakeIntReply(int64(result))
1✔
57
}
58

59
func undoHSet(db *DB, args [][]byte) []CmdLine {
1✔
60
        key := string(args[0])
1✔
61
        field := string(args[1])
1✔
62
        return rollbackHashFields(db, key, field)
1✔
63
}
1✔
64

65
// execHSetNX sets field in hash table only if field not exists
66
func execHSetNX(db *DB, args [][]byte) redis.Reply {
1✔
67
        // parse args
1✔
68
        key := string(args[0])
1✔
69
        field := string(args[1])
1✔
70
        value := args[2]
1✔
71

1✔
72
        dict, _, errReply := db.getOrInitDict(key)
1✔
73
        if errReply != nil {
1✔
74
                return errReply
×
75
        }
×
76

77
        result := dict.PutIfAbsent(field, value)
1✔
78
        if result > 0 {
2✔
79
                db.addAof(utils.ToCmdLine3("hsetnx", args...))
1✔
80

1✔
81
        }
1✔
82
        return protocol.MakeIntReply(int64(result))
1✔
83
}
84

85
// execHGet gets field value of hash table
86
func execHGet(db *DB, args [][]byte) redis.Reply {
1✔
87
        // parse args
1✔
88
        key := string(args[0])
1✔
89
        field := string(args[1])
1✔
90

1✔
91
        // get entity
1✔
92
        dict, errReply := db.getAsDict(key)
1✔
93
        if errReply != nil {
1✔
94
                return errReply
×
95
        }
×
96
        if dict == nil {
1✔
97
                return &protocol.NullBulkReply{}
×
98
        }
×
99

100
        raw, exists := dict.Get(field)
1✔
101
        if !exists {
2✔
102
                return &protocol.NullBulkReply{}
1✔
103
        }
1✔
104
        value, _ := raw.([]byte)
1✔
105
        return protocol.MakeBulkReply(value)
1✔
106
}
107

108
// execHExists checks if a hash field exists
109
func execHExists(db *DB, args [][]byte) redis.Reply {
1✔
110
        // parse args
1✔
111
        key := string(args[0])
1✔
112
        field := string(args[1])
1✔
113

1✔
114
        // get entity
1✔
115
        dict, errReply := db.getAsDict(key)
1✔
116
        if errReply != nil {
1✔
117
                return errReply
×
118
        }
×
119
        if dict == nil {
1✔
120
                return protocol.MakeIntReply(0)
×
121
        }
×
122

123
        _, exists := dict.Get(field)
1✔
124
        if exists {
2✔
125
                return protocol.MakeIntReply(1)
1✔
126
        }
1✔
127
        return protocol.MakeIntReply(0)
×
128
}
129

130
// execHDel deletes a hash field
131
func execHDel(db *DB, args [][]byte) redis.Reply {
1✔
132
        // parse args
1✔
133
        key := string(args[0])
1✔
134
        fields := make([]string, len(args)-1)
1✔
135
        fieldArgs := args[1:]
1✔
136
        for i, v := range fieldArgs {
2✔
137
                fields[i] = string(v)
1✔
138
        }
1✔
139

140
        // get entity
141
        dict, errReply := db.getAsDict(key)
1✔
142
        if errReply != nil {
1✔
143
                return errReply
×
144
        }
×
145
        if dict == nil {
1✔
146
                return protocol.MakeIntReply(0)
×
147
        }
×
148

149
        deleted := 0
1✔
150
        for _, field := range fields {
2✔
151
                _, result := dict.Remove(field)
1✔
152
                deleted += result
1✔
153
        }
1✔
154
        if dict.Len() == 0 {
2✔
155
                db.Remove(key)
1✔
156
        }
1✔
157
        if deleted > 0 {
2✔
158
                db.addAof(utils.ToCmdLine3("hdel", args...))
1✔
159
        }
1✔
160

161
        return protocol.MakeIntReply(int64(deleted))
1✔
162
}
163

164
func undoHDel(db *DB, args [][]byte) []CmdLine {
1✔
165
        key := string(args[0])
1✔
166
        fields := make([]string, len(args)-1)
1✔
167
        fieldArgs := args[1:]
1✔
168
        for i, v := range fieldArgs {
2✔
169
                fields[i] = string(v)
1✔
170
        }
1✔
171
        return rollbackHashFields(db, key, fields...)
1✔
172
}
173

174
// execHLen gets number of fields in hash table
175
func execHLen(db *DB, args [][]byte) redis.Reply {
1✔
176
        // parse args
1✔
177
        key := string(args[0])
1✔
178

1✔
179
        dict, errReply := db.getAsDict(key)
1✔
180
        if errReply != nil {
1✔
181
                return errReply
×
182
        }
×
183
        if dict == nil {
2✔
184
                return protocol.MakeIntReply(0)
1✔
185
        }
1✔
186
        return protocol.MakeIntReply(int64(dict.Len()))
1✔
187
}
188

189
// execHStrlen Returns the string length of the value associated with field in the hash stored at key.
190
// If the key or the field do not exist, 0 is returned.
191
func execHStrlen(db *DB, args [][]byte) redis.Reply {
1✔
192
        key := string(args[0])
1✔
193
        field := string(args[1])
1✔
194

1✔
195
        dict, errReply := db.getAsDict(key)
1✔
196
        if errReply != nil {
1✔
197
                return errReply
×
198
        }
×
199
        if dict == nil {
1✔
200
                return protocol.MakeIntReply(0)
×
201
        }
×
202

203
        raw, exists := dict.Get(field)
1✔
204
        if exists {
2✔
205
                value, _ := raw.([]byte)
1✔
206
                return protocol.MakeIntReply(int64(len(value)))
1✔
207
        }
1✔
208
        return protocol.MakeIntReply(0)
×
209
}
210

211
// execHMSet sets multi fields in hash table
212
func execHMSet(db *DB, args [][]byte) redis.Reply {
1✔
213
        // parse args
1✔
214
        if len(args)%2 != 1 {
1✔
215
                return protocol.MakeSyntaxErrReply()
×
216
        }
×
217
        key := string(args[0])
1✔
218
        size := (len(args) - 1) / 2
1✔
219
        fields := make([]string, size)
1✔
220
        values := make([][]byte, size)
1✔
221
        for i := 0; i < size; i++ {
2✔
222
                fields[i] = string(args[2*i+1])
1✔
223
                values[i] = args[2*i+2]
1✔
224
        }
1✔
225

226
        // get or init entity
227
        dict, _, errReply := db.getOrInitDict(key)
1✔
228
        if errReply != nil {
1✔
229
                return errReply
×
230
        }
×
231

232
        // put data
233
        for i, field := range fields {
2✔
234
                value := values[i]
1✔
235
                dict.Put(field, value)
1✔
236
        }
1✔
237
        db.addAof(utils.ToCmdLine3("hmset", args...))
1✔
238
        return &protocol.OkReply{}
1✔
239
}
240

241
func undoHMSet(db *DB, args [][]byte) []CmdLine {
1✔
242
        key := string(args[0])
1✔
243
        size := (len(args) - 1) / 2
1✔
244
        fields := make([]string, size)
1✔
245
        for i := 0; i < size; i++ {
2✔
246
                fields[i] = string(args[2*i+1])
1✔
247
        }
1✔
248
        return rollbackHashFields(db, key, fields...)
1✔
249
}
250

251
// execHMGet gets multi fields in hash table
252
func execHMGet(db *DB, args [][]byte) redis.Reply {
1✔
253
        key := string(args[0])
1✔
254
        size := len(args) - 1
1✔
255
        fields := make([]string, size)
1✔
256
        for i := 0; i < size; i++ {
2✔
257
                fields[i] = string(args[i+1])
1✔
258
        }
1✔
259

260
        // get entity
261
        result := make([][]byte, size)
1✔
262
        dict, errReply := db.getAsDict(key)
1✔
263
        if errReply != nil {
1✔
264
                return errReply
×
265
        }
×
266
        if dict == nil {
1✔
267
                return protocol.MakeMultiBulkReply(result)
×
268
        }
×
269

270
        for i, field := range fields {
2✔
271
                value, ok := dict.Get(field)
1✔
272
                if !ok {
1✔
273
                        result[i] = nil
×
274
                } else {
1✔
275
                        bytes, _ := value.([]byte)
1✔
276
                        result[i] = bytes
1✔
277
                }
1✔
278
        }
279
        return protocol.MakeMultiBulkReply(result)
1✔
280
}
281

282
// execHKeys gets all field names in hash table
283
func execHKeys(db *DB, args [][]byte) redis.Reply {
1✔
284
        key := string(args[0])
1✔
285

1✔
286
        dict, errReply := db.getAsDict(key)
1✔
287
        if errReply != nil {
1✔
288
                return errReply
×
289
        }
×
290
        if dict == nil {
1✔
291
                return &protocol.EmptyMultiBulkReply{}
×
292
        }
×
293

294
        fields := make([][]byte, dict.Len())
1✔
295
        i := 0
1✔
296
        dict.ForEach(func(key string, val interface{}) bool {
2✔
297
                fields[i] = []byte(key)
1✔
298
                i++
1✔
299
                return true
1✔
300
        })
1✔
301
        return protocol.MakeMultiBulkReply(fields[:i])
1✔
302
}
303

304
// execHVals gets all field value in hash table
305
func execHVals(db *DB, args [][]byte) redis.Reply {
1✔
306
        key := string(args[0])
1✔
307

1✔
308
        // get entity
1✔
309
        dict, errReply := db.getAsDict(key)
1✔
310
        if errReply != nil {
1✔
311
                return errReply
×
312
        }
×
313
        if dict == nil {
1✔
314
                return &protocol.EmptyMultiBulkReply{}
×
315
        }
×
316

317
        values := make([][]byte, dict.Len())
1✔
318
        i := 0
1✔
319
        dict.ForEach(func(key string, val interface{}) bool {
2✔
320
                values[i], _ = val.([]byte)
1✔
321
                i++
1✔
322
                return true
1✔
323
        })
1✔
324
        return protocol.MakeMultiBulkReply(values[:i])
1✔
325
}
326

327
// execHGetAll gets all key-value entries in hash table
328
func execHGetAll(db *DB, args [][]byte) redis.Reply {
1✔
329
        key := string(args[0])
1✔
330

1✔
331
        // get entity
1✔
332
        dict, errReply := db.getAsDict(key)
1✔
333
        if errReply != nil {
1✔
334
                return errReply
×
335
        }
×
336
        if dict == nil {
1✔
337
                return &protocol.EmptyMultiBulkReply{}
×
338
        }
×
339

340
        size := dict.Len()
1✔
341
        result := make([][]byte, size*2)
1✔
342
        i := 0
1✔
343
        dict.ForEach(func(key string, val interface{}) bool {
2✔
344
                result[i] = []byte(key)
1✔
345
                i++
1✔
346
                result[i], _ = val.([]byte)
1✔
347
                i++
1✔
348
                return true
1✔
349
        })
1✔
350
        return protocol.MakeMultiBulkReply(result[:i])
1✔
351
}
352

353
// execHIncrBy increments the integer value of a hash field by the given number
354
func execHIncrBy(db *DB, args [][]byte) redis.Reply {
1✔
355
        key := string(args[0])
1✔
356
        field := string(args[1])
1✔
357
        rawDelta := string(args[2])
1✔
358
        delta, err := strconv.ParseInt(rawDelta, 10, 64)
1✔
359
        if err != nil {
1✔
360
                return protocol.MakeErrReply("ERR value is not an integer or out of range")
×
361
        }
×
362

363
        dict, _, errReply := db.getOrInitDict(key)
1✔
364
        if errReply != nil {
1✔
365
                return errReply
×
366
        }
×
367

368
        value, exists := dict.Get(field)
1✔
369
        if !exists {
2✔
370
                dict.Put(field, args[2])
1✔
371
                db.addAof(utils.ToCmdLine3("hincrby", args...))
1✔
372
                return protocol.MakeBulkReply(args[2])
1✔
373
        }
1✔
374
        val, err := strconv.ParseInt(string(value.([]byte)), 10, 64)
1✔
375
        if err != nil {
1✔
376
                return protocol.MakeErrReply("ERR hash value is not an integer")
×
377
        }
×
378
        val += delta
1✔
379
        bytes := []byte(strconv.FormatInt(val, 10))
1✔
380
        dict.Put(field, bytes)
1✔
381
        db.addAof(utils.ToCmdLine3("hincrby", args...))
1✔
382
        return protocol.MakeBulkReply(bytes)
1✔
383
}
384

385
func undoHIncr(db *DB, args [][]byte) []CmdLine {
1✔
386
        key := string(args[0])
1✔
387
        field := string(args[1])
1✔
388
        return rollbackHashFields(db, key, field)
1✔
389
}
1✔
390

391
// execHIncrByFloat increments the float value of a hash field by the given number
392
func execHIncrByFloat(db *DB, args [][]byte) redis.Reply {
1✔
393
        key := string(args[0])
1✔
394
        field := string(args[1])
1✔
395
        rawDelta := string(args[2])
1✔
396
        delta, err := strconv.ParseFloat(rawDelta, 64)
1✔
397
        if err != nil {
1✔
398
                return protocol.MakeErrReply("ERR value is not a valid float")
×
399
        }
×
400

401
        // get or init entity
402
        dict, _, errReply := db.getOrInitDict(key)
1✔
403
        if errReply != nil {
1✔
404
                return errReply
×
405
        }
×
406

407
        value, exists := dict.Get(field)
1✔
408
        if !exists {
2✔
409
                dict.Put(field, args[2])
1✔
410
                return protocol.MakeBulkReply(args[2])
1✔
411
        }
1✔
412
        val, err := strconv.ParseFloat(string(value.([]byte)), 64)
1✔
413
        if err != nil {
1✔
414
                return protocol.MakeErrReply("ERR hash value is not a float")
×
415
        }
×
416
        result := val + delta
1✔
417
        resultBytes := []byte(strconv.FormatFloat(result, 'f', -1, 64))
1✔
418
        dict.Put(field, resultBytes)
1✔
419
        db.addAof(utils.ToCmdLine3("hincrbyfloat", args...))
1✔
420
        return protocol.MakeBulkReply(resultBytes)
1✔
421
}
422

423
// execHRandField return a random field(or field-value) from the hash value stored at key.
424
func execHRandField(db *DB, args [][]byte) redis.Reply {
1✔
425
        key := string(args[0])
1✔
426
        count := 1
1✔
427
        withvalues := 0
1✔
428

1✔
429
        if len(args) > 3 {
1✔
430
                return protocol.MakeErrReply("ERR wrong number of arguments for 'hrandfield' command")
×
431
        }
×
432

433
        if len(args) == 3 {
2✔
434
                if strings.ToLower(string(args[2])) == "withvalues" {
2✔
435
                        withvalues = 1
1✔
436
                } else {
1✔
437
                        return protocol.MakeSyntaxErrReply()
×
438
                }
×
439
        }
440

441
        if len(args) >= 2 {
2✔
442
                count64, err := strconv.ParseInt(string(args[1]), 10, 64)
1✔
443
                if err != nil {
1✔
444
                        return protocol.MakeErrReply("ERR value is not an integer or out of range")
×
445
                }
×
446
                count = int(count64)
1✔
447
        }
448

449
        dict, errReply := db.getAsDict(key)
1✔
450
        if errReply != nil {
1✔
451
                return errReply
×
452
        }
×
453
        if dict == nil {
1✔
454
                return &protocol.EmptyMultiBulkReply{}
×
455
        }
×
456

457
        if count > 0 {
2✔
458
                fields := dict.RandomDistinctKeys(count)
1✔
459
                Numfield := len(fields)
1✔
460
                if withvalues == 0 {
2✔
461
                        result := make([][]byte, Numfield)
1✔
462
                        for i, v := range fields {
2✔
463
                                result[i] = []byte(v)
1✔
464
                        }
1✔
465
                        return protocol.MakeMultiBulkReply(result)
1✔
466
                } else {
1✔
467
                        result := make([][]byte, 2*Numfield)
1✔
468
                        for i, v := range fields {
2✔
469
                                result[2*i] = []byte(v)
1✔
470
                                raw, _ := dict.Get(v)
1✔
471
                                result[2*i+1] = raw.([]byte)
1✔
472
                        }
1✔
473
                        return protocol.MakeMultiBulkReply(result)
1✔
474
                }
475
        } else if count < 0 {
2✔
476
                fields := dict.RandomKeys(-count)
1✔
477
                Numfield := len(fields)
1✔
478
                if withvalues == 0 {
2✔
479
                        result := make([][]byte, Numfield)
1✔
480
                        for i, v := range fields {
2✔
481
                                result[i] = []byte(v)
1✔
482
                        }
1✔
483
                        return protocol.MakeMultiBulkReply(result)
1✔
484
                } else {
1✔
485
                        result := make([][]byte, 2*Numfield)
1✔
486
                        for i, v := range fields {
2✔
487
                                result[2*i] = []byte(v)
1✔
488
                                raw, _ := dict.Get(v)
1✔
489
                                result[2*i+1] = raw.([]byte)
1✔
490
                        }
1✔
491
                        return protocol.MakeMultiBulkReply(result)
1✔
492
                }
493
        }
494

495
        // 'count' is 0 will reach.
496
        return &protocol.EmptyMultiBulkReply{}
1✔
497
}
498

499
func execHScan(db *DB, args [][]byte) redis.Reply {
1✔
500
        var count int = 10
1✔
501
        var pattern string = "*"
1✔
502
        if len(args) > 2 {
2✔
503
                for i := 2; i < len(args); i++ {
2✔
504
                        arg := strings.ToLower(string(args[i]))
1✔
505
                        if arg == "count" {
2✔
506
                                count0, err := strconv.Atoi(string(args[i+1]))
1✔
507
                                if err != nil {
1✔
508
                                        return &protocol.SyntaxErrReply{}
×
509
                                }
×
510
                                count = count0
1✔
511
                                i++
1✔
512
                        } else if arg == "match" {
2✔
513
                                pattern = string(args[i+1])
1✔
514
                                i++
1✔
515
                        } else {
1✔
516
                                return &protocol.SyntaxErrReply{}
×
517
                        }
×
518
                }
519
        }
520
        if len(args) < 2 {
1✔
521
                return &protocol.SyntaxErrReply{}
×
522
        }
×
523
        key := string(args[0])
1✔
524
        // get entity
1✔
525
        dict, errReply := db.getAsDict(key)
1✔
526
        if errReply != nil {
1✔
527
                return errReply
×
528
        }
×
529
        if dict == nil {
1✔
530
                return &protocol.NullBulkReply{}
×
531
        }
×
532
        cursor, err := strconv.Atoi(string(args[1]))
1✔
533
        if err != nil {
1✔
534
                return protocol.MakeErrReply("ERR invalid cursor")
×
535
        }
×
536

537
        keysReply, nextCursor := dict.DictScan(cursor, count, pattern)
1✔
538
        if nextCursor < 0 {
1✔
539
                return protocol.MakeErrReply("Invalid argument")
×
540
        }
×
541

542
        result := make([]redis.Reply, 2)
1✔
543
        result[0] = protocol.MakeBulkReply([]byte(strconv.FormatInt(int64(nextCursor), 10)))
1✔
544
        result[1] = protocol.MakeMultiBulkReply(keysReply)
1✔
545

1✔
546
        return protocol.MakeMultiRawReply(result)
1✔
547
}
548

549
func init() {
1✔
550
        registerCommand("HSet", execHSet, writeFirstKey, undoHSet, 4, flagWrite).
1✔
551
                attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
1✔
552
        registerCommand("HSetNX", execHSetNX, writeFirstKey, undoHSet, 4, flagWrite).
1✔
553
                attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
1✔
554
        registerCommand("HGet", execHGet, readFirstKey, nil, 3, flagReadOnly).
1✔
555
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
556
        registerCommand("HExists", execHExists, readFirstKey, nil, 3, flagReadOnly).
1✔
557
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
558
        registerCommand("HDel", execHDel, writeFirstKey, undoHDel, -3, flagWrite).
1✔
559
                attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
1✔
560
        registerCommand("HLen", execHLen, readFirstKey, nil, 2, flagReadOnly).
1✔
561
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
562
        registerCommand("HStrlen", execHStrlen, readFirstKey, nil, 3, flagReadOnly).
1✔
563
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
564
        registerCommand("HMSet", execHMSet, writeFirstKey, undoHMSet, -4, flagWrite).
1✔
565
                attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
1✔
566
        registerCommand("HMGet", execHMGet, readFirstKey, nil, -3, flagReadOnly).
1✔
567
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
568
        registerCommand("HGet", execHGet, readFirstKey, nil, -3, flagReadOnly).
1✔
569
                attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
1✔
570
        registerCommand("HKeys", execHKeys, readFirstKey, nil, 2, flagReadOnly).
1✔
571
                attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
1✔
572
        registerCommand("HVals", execHVals, readFirstKey, nil, 2, flagReadOnly).
1✔
573
                attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
1✔
574
        registerCommand("HGetAll", execHGetAll, readFirstKey, nil, 2, flagReadOnly).
1✔
575
                attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1)
1✔
576
        registerCommand("HIncrBy", execHIncrBy, writeFirstKey, undoHIncr, 4, flagWrite).
1✔
577
                attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
1✔
578
        registerCommand("HIncrByFloat", execHIncrByFloat, writeFirstKey, undoHIncr, 4, flagWrite).
1✔
579
                attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
1✔
580
        registerCommand("HRandField", execHRandField, readFirstKey, nil, -2, flagReadOnly).
1✔
581
                attachCommandExtra([]string{redisFlagRandom, redisFlagReadonly}, 1, 1, 1)
1✔
582
        registerCommand("HScan", execHScan, readFirstKey, nil, -2, flagReadOnly).
1✔
583
                attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
1✔
584
}
1✔
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