1 package redis
2
3 import (
4 "context"
5 "time"
6
7 "github.com/redis/go-redis/v9/internal/hashtag"
8 )
9
10 type HashCmdable interface {
11 HDel(ctx context.Context, key string, fields ...string) *IntCmd
12 HExists(ctx context.Context, key, field string) *BoolCmd
13 HGet(ctx context.Context, key, field string) *StringCmd
14 HGetAll(ctx context.Context, key string) *MapStringStringCmd
15 HGetDel(ctx context.Context, key string, fields ...string) *StringSliceCmd
16 HGetEX(ctx context.Context, key string, fields ...string) *StringSliceCmd
17 HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd
18 HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
19 HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
20 HKeys(ctx context.Context, key string) *StringSliceCmd
21 HLen(ctx context.Context, key string) *IntCmd
22 HMGet(ctx context.Context, key string, fields ...string) *SliceCmd
23 HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
24 HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
25 HSetEX(ctx context.Context, key string, fieldsAndValues ...string) *IntCmd
26 HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd
27 HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
28 HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
29 HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
30 HVals(ctx context.Context, key string) *StringSliceCmd
31 HRandField(ctx context.Context, key string, count int) *StringSliceCmd
32 HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd
33 HStrLen(ctx context.Context, key, field string) *IntCmd
34 HExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd
35 HExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
36 HPExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd
37 HPExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
38 HExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd
39 HExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
40 HPExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd
41 HPExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd
42 HPersist(ctx context.Context, key string, fields ...string) *IntSliceCmd
43 HExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd
44 HPExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd
45 HTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd
46 HPTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd
47 }
48
49 func (c cmdable) HDel(ctx context.Context, key string, fields ...string) *IntCmd {
50 args := make([]interface{}, 2+len(fields))
51 args[0] = "hdel"
52 args[1] = key
53 for i, field := range fields {
54 args[2+i] = field
55 }
56 cmd := NewIntCmd(ctx, args...)
57 _ = c(ctx, cmd)
58 return cmd
59 }
60
61 func (c cmdable) HExists(ctx context.Context, key, field string) *BoolCmd {
62 cmd := NewBoolCmd(ctx, "hexists", key, field)
63 _ = c(ctx, cmd)
64 return cmd
65 }
66
67 func (c cmdable) HGet(ctx context.Context, key, field string) *StringCmd {
68 cmd := NewStringCmd(ctx, "hget", key, field)
69 _ = c(ctx, cmd)
70 return cmd
71 }
72
73 func (c cmdable) HGetAll(ctx context.Context, key string) *MapStringStringCmd {
74 cmd := NewMapStringStringCmd(ctx, "hgetall", key)
75 _ = c(ctx, cmd)
76 return cmd
77 }
78
79 func (c cmdable) HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd {
80 cmd := NewIntCmd(ctx, "hincrby", key, field, incr)
81 _ = c(ctx, cmd)
82 return cmd
83 }
84
85 func (c cmdable) HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd {
86 cmd := NewFloatCmd(ctx, "hincrbyfloat", key, field, incr)
87 _ = c(ctx, cmd)
88 return cmd
89 }
90
91 func (c cmdable) HKeys(ctx context.Context, key string) *StringSliceCmd {
92 cmd := NewStringSliceCmd(ctx, "hkeys", key)
93 _ = c(ctx, cmd)
94 return cmd
95 }
96
97 func (c cmdable) HLen(ctx context.Context, key string) *IntCmd {
98 cmd := NewIntCmd(ctx, "hlen", key)
99 _ = c(ctx, cmd)
100 return cmd
101 }
102
103
104
105 func (c cmdable) HMGet(ctx context.Context, key string, fields ...string) *SliceCmd {
106 args := make([]interface{}, 2+len(fields))
107 args[0] = "hmget"
108 args[1] = key
109 for i, field := range fields {
110 args[2+i] = field
111 }
112 cmd := NewSliceCmd(ctx, args...)
113 _ = c(ctx, cmd)
114 return cmd
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 func (c cmdable) HSet(ctx context.Context, key string, values ...interface{}) *IntCmd {
142 args := make([]interface{}, 2, 2+len(values))
143 args[0] = "hset"
144 args[1] = key
145 args = appendArgs(args, values)
146 cmd := NewIntCmd(ctx, args...)
147 _ = c(ctx, cmd)
148 return cmd
149 }
150
151
152 func (c cmdable) HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd {
153 args := make([]interface{}, 2, 2+len(values))
154 args[0] = "hmset"
155 args[1] = key
156 args = appendArgs(args, values)
157 cmd := NewBoolCmd(ctx, args...)
158 _ = c(ctx, cmd)
159 return cmd
160 }
161
162 func (c cmdable) HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd {
163 cmd := NewBoolCmd(ctx, "hsetnx", key, field, value)
164 _ = c(ctx, cmd)
165 return cmd
166 }
167
168 func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
169 cmd := NewStringSliceCmd(ctx, "hvals", key)
170 _ = c(ctx, cmd)
171 return cmd
172 }
173
174
175 func (c cmdable) HRandField(ctx context.Context, key string, count int) *StringSliceCmd {
176 cmd := NewStringSliceCmd(ctx, "hrandfield", key, count)
177 _ = c(ctx, cmd)
178 return cmd
179 }
180
181
182 func (c cmdable) HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd {
183 cmd := NewKeyValueSliceCmd(ctx, "hrandfield", key, count, "withvalues")
184 _ = c(ctx, cmd)
185 return cmd
186 }
187
188 func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
189 args := []interface{}{"hscan", key, cursor}
190 if match != "" {
191 args = append(args, "match", match)
192 }
193 if count > 0 {
194 args = append(args, "count", count)
195 }
196 cmd := NewScanCmd(ctx, c, args...)
197 if hashtag.Present(match) {
198 cmd.SetFirstKeyPos(4)
199 }
200 _ = c(ctx, cmd)
201 return cmd
202 }
203
204 func (c cmdable) HStrLen(ctx context.Context, key, field string) *IntCmd {
205 cmd := NewIntCmd(ctx, "hstrlen", key, field)
206 _ = c(ctx, cmd)
207 return cmd
208 }
209 func (c cmdable) HScanNoValues(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
210 args := []interface{}{"hscan", key, cursor}
211 if match != "" {
212 args = append(args, "match", match)
213 }
214 if count > 0 {
215 args = append(args, "count", count)
216 }
217 args = append(args, "novalues")
218 cmd := NewScanCmd(ctx, c, args...)
219 if hashtag.Present(match) {
220 cmd.SetFirstKeyPos(4)
221 }
222 _ = c(ctx, cmd)
223 return cmd
224 }
225
226 type HExpireArgs struct {
227 NX bool
228 XX bool
229 GT bool
230 LT bool
231 }
232
233
234
235
236
237
238
239 func (c cmdable) HExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd {
240 args := []interface{}{"HEXPIRE", key, formatSec(ctx, expiration), "FIELDS", len(fields)}
241
242 for _, field := range fields {
243 args = append(args, field)
244 }
245 cmd := NewIntSliceCmd(ctx, args...)
246 _ = c(ctx, cmd)
247 return cmd
248 }
249
250
251
252
253
254
255
256
257 func (c cmdable) HExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
258 args := []interface{}{"HEXPIRE", key, formatSec(ctx, expiration)}
259
260
261
262 if expirationArgs.NX {
263 args = append(args, "NX")
264 } else if expirationArgs.XX {
265 args = append(args, "XX")
266 } else if expirationArgs.GT {
267 args = append(args, "GT")
268 } else if expirationArgs.LT {
269 args = append(args, "LT")
270 }
271
272 args = append(args, "FIELDS", len(fields))
273
274 for _, field := range fields {
275 args = append(args, field)
276 }
277 cmd := NewIntSliceCmd(ctx, args...)
278 _ = c(ctx, cmd)
279 return cmd
280 }
281
282
283
284
285
286
287
288
289 func (c cmdable) HPExpire(ctx context.Context, key string, expiration time.Duration, fields ...string) *IntSliceCmd {
290 args := []interface{}{"HPEXPIRE", key, formatMs(ctx, expiration), "FIELDS", len(fields)}
291
292 for _, field := range fields {
293 args = append(args, field)
294 }
295 cmd := NewIntSliceCmd(ctx, args...)
296 _ = c(ctx, cmd)
297 return cmd
298 }
299
300
301
302
303
304
305
306
307 func (c cmdable) HPExpireWithArgs(ctx context.Context, key string, expiration time.Duration, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
308 args := []interface{}{"HPEXPIRE", key, formatMs(ctx, expiration)}
309
310
311
312 if expirationArgs.NX {
313 args = append(args, "NX")
314 } else if expirationArgs.XX {
315 args = append(args, "XX")
316 } else if expirationArgs.GT {
317 args = append(args, "GT")
318 } else if expirationArgs.LT {
319 args = append(args, "LT")
320 }
321
322 args = append(args, "FIELDS", len(fields))
323
324 for _, field := range fields {
325 args = append(args, field)
326 }
327 cmd := NewIntSliceCmd(ctx, args...)
328 _ = c(ctx, cmd)
329 return cmd
330 }
331
332
333
334
335
336
337
338
339 func (c cmdable) HExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd {
340
341 args := []interface{}{"HEXPIREAT", key, tm.Unix(), "FIELDS", len(fields)}
342
343 for _, field := range fields {
344 args = append(args, field)
345 }
346 cmd := NewIntSliceCmd(ctx, args...)
347 _ = c(ctx, cmd)
348 return cmd
349 }
350
351 func (c cmdable) HExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
352 args := []interface{}{"HEXPIREAT", key, tm.Unix()}
353
354
355
356 if expirationArgs.NX {
357 args = append(args, "NX")
358 } else if expirationArgs.XX {
359 args = append(args, "XX")
360 } else if expirationArgs.GT {
361 args = append(args, "GT")
362 } else if expirationArgs.LT {
363 args = append(args, "LT")
364 }
365
366 args = append(args, "FIELDS", len(fields))
367
368 for _, field := range fields {
369 args = append(args, field)
370 }
371 cmd := NewIntSliceCmd(ctx, args...)
372 _ = c(ctx, cmd)
373 return cmd
374 }
375
376
377
378
379
380
381
382 func (c cmdable) HPExpireAt(ctx context.Context, key string, tm time.Time, fields ...string) *IntSliceCmd {
383 args := []interface{}{"HPEXPIREAT", key, tm.UnixNano() / int64(time.Millisecond), "FIELDS", len(fields)}
384
385 for _, field := range fields {
386 args = append(args, field)
387 }
388 cmd := NewIntSliceCmd(ctx, args...)
389 _ = c(ctx, cmd)
390 return cmd
391 }
392
393 func (c cmdable) HPExpireAtWithArgs(ctx context.Context, key string, tm time.Time, expirationArgs HExpireArgs, fields ...string) *IntSliceCmd {
394 args := []interface{}{"HPEXPIREAT", key, tm.UnixNano() / int64(time.Millisecond)}
395
396
397
398 if expirationArgs.NX {
399 args = append(args, "NX")
400 } else if expirationArgs.XX {
401 args = append(args, "XX")
402 } else if expirationArgs.GT {
403 args = append(args, "GT")
404 } else if expirationArgs.LT {
405 args = append(args, "LT")
406 }
407
408 args = append(args, "FIELDS", len(fields))
409
410 for _, field := range fields {
411 args = append(args, field)
412 }
413 cmd := NewIntSliceCmd(ctx, args...)
414 _ = c(ctx, cmd)
415 return cmd
416 }
417
418
419
420
421
422
423
424
425 func (c cmdable) HPersist(ctx context.Context, key string, fields ...string) *IntSliceCmd {
426 args := []interface{}{"HPERSIST", key, "FIELDS", len(fields)}
427
428 for _, field := range fields {
429 args = append(args, field)
430 }
431 cmd := NewIntSliceCmd(ctx, args...)
432 _ = c(ctx, cmd)
433 return cmd
434 }
435
436
437
438
439
440
441
442
443
444 func (c cmdable) HExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd {
445 args := []interface{}{"HEXPIRETIME", key, "FIELDS", len(fields)}
446
447 for _, field := range fields {
448 args = append(args, field)
449 }
450 cmd := NewIntSliceCmd(ctx, args...)
451 _ = c(ctx, cmd)
452 return cmd
453 }
454
455
456
457
458
459
460
461
462
463 func (c cmdable) HPExpireTime(ctx context.Context, key string, fields ...string) *IntSliceCmd {
464 args := []interface{}{"HPEXPIRETIME", key, "FIELDS", len(fields)}
465
466 for _, field := range fields {
467 args = append(args, field)
468 }
469 cmd := NewIntSliceCmd(ctx, args...)
470 _ = c(ctx, cmd)
471 return cmd
472 }
473
474
475
476
477
478
479
480
481 func (c cmdable) HTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd {
482 args := []interface{}{"HTTL", key, "FIELDS", len(fields)}
483
484 for _, field := range fields {
485 args = append(args, field)
486 }
487 cmd := NewIntSliceCmd(ctx, args...)
488 _ = c(ctx, cmd)
489 return cmd
490 }
491
492
493
494
495
496
497
498
499
500 func (c cmdable) HPTTL(ctx context.Context, key string, fields ...string) *IntSliceCmd {
501 args := []interface{}{"HPTTL", key, "FIELDS", len(fields)}
502
503 for _, field := range fields {
504 args = append(args, field)
505 }
506 cmd := NewIntSliceCmd(ctx, args...)
507 _ = c(ctx, cmd)
508 return cmd
509 }
510
511 func (c cmdable) HGetDel(ctx context.Context, key string, fields ...string) *StringSliceCmd {
512 args := []interface{}{"HGETDEL", key, "FIELDS", len(fields)}
513 for _, field := range fields {
514 args = append(args, field)
515 }
516 cmd := NewStringSliceCmd(ctx, args...)
517 _ = c(ctx, cmd)
518 return cmd
519 }
520
521 func (c cmdable) HGetEX(ctx context.Context, key string, fields ...string) *StringSliceCmd {
522 args := []interface{}{"HGETEX", key, "FIELDS", len(fields)}
523 for _, field := range fields {
524 args = append(args, field)
525 }
526 cmd := NewStringSliceCmd(ctx, args...)
527 _ = c(ctx, cmd)
528 return cmd
529 }
530
531
532 type HGetEXExpirationType string
533
534 const (
535 HGetEXExpirationEX HGetEXExpirationType = "EX"
536 HGetEXExpirationPX HGetEXExpirationType = "PX"
537 HGetEXExpirationEXAT HGetEXExpirationType = "EXAT"
538 HGetEXExpirationPXAT HGetEXExpirationType = "PXAT"
539 HGetEXExpirationPERSIST HGetEXExpirationType = "PERSIST"
540 )
541
542 type HGetEXOptions struct {
543 ExpirationType HGetEXExpirationType
544 ExpirationVal int64
545 }
546
547 func (c cmdable) HGetEXWithArgs(ctx context.Context, key string, options *HGetEXOptions, fields ...string) *StringSliceCmd {
548 args := []interface{}{"HGETEX", key}
549 if options.ExpirationType != "" {
550 args = append(args, string(options.ExpirationType))
551 if options.ExpirationType != HGetEXExpirationPERSIST {
552 args = append(args, options.ExpirationVal)
553 }
554 }
555
556 args = append(args, "FIELDS", len(fields))
557 for _, field := range fields {
558 args = append(args, field)
559 }
560
561 cmd := NewStringSliceCmd(ctx, args...)
562 _ = c(ctx, cmd)
563 return cmd
564 }
565
566 type HSetEXCondition string
567
568 const (
569 HSetEXFNX HSetEXCondition = "FNX"
570 HSetEXFXX HSetEXCondition = "FXX"
571 )
572
573 type HSetEXExpirationType string
574
575 const (
576 HSetEXExpirationEX HSetEXExpirationType = "EX"
577 HSetEXExpirationPX HSetEXExpirationType = "PX"
578 HSetEXExpirationEXAT HSetEXExpirationType = "EXAT"
579 HSetEXExpirationPXAT HSetEXExpirationType = "PXAT"
580 HSetEXExpirationKEEPTTL HSetEXExpirationType = "KEEPTTL"
581 )
582
583 type HSetEXOptions struct {
584 Condition HSetEXCondition
585 ExpirationType HSetEXExpirationType
586 ExpirationVal int64
587 }
588
589 func (c cmdable) HSetEX(ctx context.Context, key string, fieldsAndValues ...string) *IntCmd {
590 args := []interface{}{"HSETEX", key, "FIELDS", len(fieldsAndValues) / 2}
591 for _, field := range fieldsAndValues {
592 args = append(args, field)
593 }
594
595 cmd := NewIntCmd(ctx, args...)
596 _ = c(ctx, cmd)
597 return cmd
598 }
599
600 func (c cmdable) HSetEXWithArgs(ctx context.Context, key string, options *HSetEXOptions, fieldsAndValues ...string) *IntCmd {
601 args := []interface{}{"HSETEX", key}
602 if options.Condition != "" {
603 args = append(args, string(options.Condition))
604 }
605 if options.ExpirationType != "" {
606 args = append(args, string(options.ExpirationType))
607 if options.ExpirationType != HSetEXExpirationKEEPTTL {
608 args = append(args, options.ExpirationVal)
609 }
610 }
611 args = append(args, "FIELDS", len(fieldsAndValues)/2)
612 for _, field := range fieldsAndValues {
613 args = append(args, field)
614 }
615
616 cmd := NewIntCmd(ctx, args...)
617 _ = c(ctx, cmd)
618 return cmd
619 }
620
View as plain text