1#[derive(Debug, Clone, Copy)]
18pub struct Spec {
19 pub name: &'static str,
22 pub arity: i32,
25 pub flags: &'static [&'static str],
27 pub first_key: i32,
29 pub last_key: i32,
31 pub step: i32,
33 pub acl: &'static [&'static str],
35 pub since: &'static str,
37 pub complexity: &'static str,
39 pub summary: &'static str,
41 pub group: &'static str,
43}
44
45const READ_FAST: &[&str] = &["readonly", "fast"];
47const WRITE_FAST_OOM: &[&str] = &["write", "denyoom", "fast"];
49const WRITE_OOM: &[&str] = &["write", "denyoom"];
51const WRITE_OOM_ADMIN: &[&str] = &["write", "denyoom", "admin"];
53const AC_READ_FAST: &[&str] = &["@read", "@string", "@fast"];
55const AC_BIT_READ_FAST: &[&str] = &["@read", "@bitmap", "@fast"];
57const AC_BIT_READ: &[&str] = &["@read", "@bitmap", "@slow"];
59const AC_BIT_WRITE: &[&str] = &["@write", "@bitmap", "@slow"];
61
62const AC_HLL_WRITE_FAST: &[&str] = &["@write", "@hyperloglog", "@fast"];
64const AC_HLL_WRITE: &[&str] = &["@write", "@hyperloglog", "@slow"];
66const AC_HLL_READ: &[&str] = &["@read", "@hyperloglog", "@slow"];
68const AC_HLL_ADMIN: &[&str] = &["@hyperloglog", "@admin", "@slow", "@dangerous"];
70const AC_READ_SLOW: &[&str] = &["@read", "@string", "@slow"];
72const AC_WRITE_FAST: &[&str] = &["@write", "@string", "@fast"];
74const AC_WRITE_SLOW: &[&str] = &["@write", "@string", "@slow"];
76const WRITE_FAST: &[&str] = &["write", "fast"];
78const AC_SET_READ_FAST: &[&str] = &["@read", "@set", "@fast"];
80const AC_SET_READ_SLOW: &[&str] = &["@read", "@set", "@slow"];
82const AC_SET_WRITE_FAST: &[&str] = &["@write", "@set", "@fast"];
84const AC_SET_WRITE_SLOW: &[&str] = &["@write", "@set", "@slow"];
87const AC_HASH_READ_FAST: &[&str] = &["@read", "@hash", "@fast"];
89const AC_HASH_READ_SLOW: &[&str] = &["@read", "@hash", "@slow"];
91const AC_HASH_WRITE_FAST: &[&str] = &["@write", "@hash", "@fast"];
93const READ_SLOW: &[&str] = &["readonly"];
95const WRITE_SLOW: &[&str] = &["write"];
98const AC_LIST_READ_FAST: &[&str] = &["@read", "@list", "@fast"];
100const AC_LIST_READ_SLOW: &[&str] = &["@read", "@list", "@slow"];
102const AC_LIST_WRITE_FAST: &[&str] = &["@write", "@list", "@fast"];
105const AC_LIST_WRITE_SLOW: &[&str] = &["@write", "@list", "@slow"];
107const AC_LIST_WRITE_BLOCKING: &[&str] = &["@write", "@list", "@slow", "@blocking"];
110const AC_ZSET_READ_FAST: &[&str] = &["@read", "@sortedset", "@fast"];
112const AC_ZSET_READ_SLOW: &[&str] = &["@read", "@sortedset", "@slow"];
114const AC_ZSET_WRITE_FAST: &[&str] = &["@write", "@sortedset", "@fast"];
116const AC_ZSET_WRITE_SLOW: &[&str] = &["@write", "@sortedset", "@slow"];
119const AC_ZSET_BLOCKING_FAST: &[&str] = &["@write", "@sortedset", "@fast", "@blocking"];
122const AC_ZSET_BLOCKING_SLOW: &[&str] = &["@write", "@sortedset", "@slow", "@blocking"];
124const AC_GEO_READ: &[&str] = &["@read", "@geo", "@slow"];
129const AC_GEO_WRITE: &[&str] = &["@write", "@geo", "@slow"];
131const AC_GRAPH_READ_FAST: &[&str] = &["@read", "@graph", "@fast"];
133const AC_GRAPH_READ_SLOW: &[&str] = &["@read", "@graph", "@slow"];
135const AC_GRAPH_WRITE_FAST: &[&str] = &["@write", "@graph", "@fast"];
137const AC_ARRAY_READ_FAST: &[&str] = &["@read", "@array", "@fast"];
138const AC_ARRAY_READ_SLOW: &[&str] = &["@read", "@array", "@slow"];
141const AC_ARRAY_WRITE_FAST: &[&str] = &["@write", "@array", "@fast"];
143const AC_ARRAY_WRITE_SLOW: &[&str] = &["@write", "@array", "@slow"];
146const AC_STREAM_READ_FAST: &[&str] = &["@read", "@stream", "@fast"];
148const AC_STREAM_READ_SLOW: &[&str] = &["@read", "@stream", "@slow"];
150const AC_STREAM_WRITE_FAST: &[&str] = &["@write", "@stream", "@fast"];
153const AC_STREAM_WRITE_SLOW: &[&str] = &["@write", "@stream", "@slow"];
155const AC_STREAM_BLOCKING_READ: &[&str] = &["@read", "@stream", "@slow", "@blocking"];
157const AC_STREAM_BLOCKING_WRITE: &[&str] = &["@write", "@stream", "@slow", "@blocking"];
160const AC_STREAM_CONTAINER: &[&str] = &["@slow"];
163const READ_BLOCKING_MOVABLE: &[&str] = &["readonly", "blocking", "movablekeys"];
166const WRITE_BLOCKING_MOVABLE: &[&str] = &["write", "blocking", "movablekeys"];
168const READ_MOVABLE: &[&str] = &["readonly", "movablekeys"];
171const WRITE_MOVABLE: &[&str] = &["write", "denyoom", "movablekeys"];
173const MIGRATE_FLAGS: &[&str] = &["write", "movablekeys"];
179const AC_CONN: &[&str] = &["@fast", "@connection"];
181const AC_KEY_READ: &[&str] = &["@keyspace", "@read", "@fast"];
183const AC_KEY_READ_SLOW: &[&str] = &["@keyspace", "@read", "@slow"];
185const AC_KEY_READ_ALL: &[&str] = &["@keyspace", "@read", "@slow", "@dangerous"];
188const AC_KEY_WRITE_SLOW: &[&str] = &["@keyspace", "@write", "@slow"];
193const AC_KEY_WRITE_FAST: &[&str] = &["@keyspace", "@write", "@fast"];
196const AC_KEY_FLUSH: &[&str] = &["@keyspace", "@write", "@slow", "@dangerous"];
198const AC_SWAPDB: &[&str] = &["@keyspace", "@write", "@fast", "@dangerous"];
202const AC_RESTORE: &[&str] = &["@keyspace", "@write", "@slow", "@dangerous"];
207const AC_WAIT: &[&str] = &["@slow", "@blocking", "@connection"];
212const AC_SORT_WRITE: &[&str] = &[
216 "@write",
217 "@set",
218 "@sortedset",
219 "@list",
220 "@slow",
221 "@dangerous",
222];
223const AC_SORT_READ: &[&str] = &[
225 "@read",
226 "@set",
227 "@sortedset",
228 "@list",
229 "@slow",
230 "@dangerous",
231];
232
233pub static COMMANDS: &[Spec] = &[
235 Spec {
237 name: "set",
238 arity: -3,
239 flags: WRITE_OOM,
240 first_key: 1,
241 last_key: 1,
242 step: 1,
243 acl: AC_WRITE_SLOW,
244 since: "1.0.0",
245 complexity: "O(1)",
246 summary: "Set a key to a string value, whatever it held before.",
247 group: "string",
248 },
249 Spec {
250 name: "get",
251 arity: 2,
252 flags: READ_FAST,
253 first_key: 1,
254 last_key: 1,
255 step: 1,
256 acl: AC_READ_FAST,
257 since: "1.0.0",
258 complexity: "O(1)",
259 summary: "The string value of a key.",
260 group: "string",
261 },
262 Spec {
263 name: "getset",
264 arity: 3,
265 flags: WRITE_FAST_OOM,
266 first_key: 1,
267 last_key: 1,
268 step: 1,
269 acl: AC_WRITE_FAST,
270 since: "1.0.0",
271 complexity: "O(1)",
272 summary: "Set a key and hand back what it held.",
273 group: "string",
274 },
275 Spec {
276 name: "getdel",
277 arity: 2,
278 flags: &["write", "fast"],
279 first_key: 1,
280 last_key: 1,
281 step: 1,
282 acl: AC_WRITE_FAST,
283 since: "6.2.0",
284 complexity: "O(1)",
285 summary: "Read a key and delete it in the same step.",
286 group: "string",
287 },
288 Spec {
289 name: "getex",
290 arity: -2,
291 flags: &["write", "fast"],
292 first_key: 1,
293 last_key: 1,
294 step: 1,
295 acl: AC_WRITE_FAST,
296 since: "6.2.0",
297 complexity: "O(1)",
298 summary: "Read a key and change its deadline in the same step.",
299 group: "string",
300 },
301 Spec {
302 name: "setnx",
303 arity: 3,
304 flags: WRITE_FAST_OOM,
305 first_key: 1,
306 last_key: 1,
307 step: 1,
308 acl: AC_WRITE_FAST,
309 since: "1.0.0",
310 complexity: "O(1)",
311 summary: "Set a key only if it is not there.",
312 group: "string",
313 },
314 Spec {
315 name: "setex",
316 arity: 4,
317 flags: WRITE_OOM,
318 first_key: 1,
319 last_key: 1,
320 step: 1,
321 acl: AC_WRITE_SLOW,
322 since: "2.0.0",
323 complexity: "O(1)",
324 summary: "Set a key and give it a deadline in seconds.",
325 group: "string",
326 },
327 Spec {
328 name: "psetex",
329 arity: 4,
330 flags: WRITE_OOM,
331 first_key: 1,
332 last_key: 1,
333 step: 1,
334 acl: AC_WRITE_SLOW,
335 since: "2.6.0",
336 complexity: "O(1)",
337 summary: "Set a key and give it a deadline in milliseconds.",
338 group: "string",
339 },
340 Spec {
341 name: "mset",
342 arity: -3,
343 flags: WRITE_OOM,
344 first_key: 1,
345 last_key: -1,
346 step: 2,
347 acl: AC_WRITE_SLOW,
348 since: "1.0.1",
349 complexity: "O(N) with N the number of keys",
350 summary: "Set several keys, all of them or none.",
351 group: "string",
352 },
353 Spec {
354 name: "msetnx",
355 arity: -3,
356 flags: WRITE_OOM,
357 first_key: 1,
358 last_key: -1,
359 step: 2,
360 acl: AC_WRITE_SLOW,
361 since: "1.0.1",
362 complexity: "O(N) with N the number of keys",
363 summary: "Set several keys only if none of them are there.",
364 group: "string",
365 },
366 Spec {
367 name: "mget",
368 arity: -2,
369 flags: READ_FAST,
370 first_key: 1,
371 last_key: -1,
372 step: 1,
373 acl: AC_READ_FAST,
374 since: "1.0.0",
375 complexity: "O(N) with N the number of keys",
376 summary: "The values of several keys, in the order asked for.",
377 group: "string",
378 },
379 Spec {
380 name: "append",
381 arity: 3,
382 flags: WRITE_FAST_OOM,
383 first_key: 1,
384 last_key: 1,
385 step: 1,
386 acl: AC_WRITE_FAST,
387 since: "2.0.0",
388 complexity: "O(M) with M the length of the value being appended",
389 summary: "Add to the end of a string, creating it if it is not there.",
390 group: "string",
391 },
392 Spec {
393 name: "strlen",
394 arity: 2,
395 flags: READ_FAST,
396 first_key: 1,
397 last_key: 1,
398 step: 1,
399 acl: AC_READ_FAST,
400 since: "2.2.0",
401 complexity: "O(1)",
402 summary: "How long a string value is, without reading it.",
403 group: "string",
404 },
405 Spec {
406 name: "setrange",
407 arity: 4,
408 flags: WRITE_OOM,
409 first_key: 1,
410 last_key: 1,
411 step: 1,
412 acl: AC_WRITE_SLOW,
413 since: "2.2.0",
414 complexity: "O(M) with M the length of the replacement",
415 summary: "Overwrite part of a string at an offset, zero filling the gap.",
416 group: "string",
417 },
418 Spec {
419 name: "getrange",
420 arity: 4,
421 flags: &["readonly"],
422 first_key: 1,
423 last_key: 1,
424 step: 1,
425 acl: AC_READ_SLOW,
426 since: "2.4.0",
427 complexity: "O(N) with N the length of the answer",
428 summary: "Part of a string, by an inclusive range that may count backwards.",
429 group: "string",
430 },
431 Spec {
432 name: "substr",
433 arity: 4,
434 flags: &["readonly"],
435 first_key: 1,
436 last_key: 1,
437 step: 1,
438 acl: AC_READ_SLOW,
439 since: "1.0.0",
440 complexity: "O(N) with N the length of the answer",
441 summary: "GETRANGE under the name it had before 2.4.",
442 group: "string",
443 },
444 Spec {
445 name: "incr",
446 arity: 2,
447 flags: WRITE_FAST_OOM,
448 first_key: 1,
449 last_key: 1,
450 step: 1,
451 acl: AC_WRITE_FAST,
452 since: "1.0.0",
453 complexity: "O(1)",
454 summary: "Add one, starting from zero if the key is not there.",
455 group: "string",
456 },
457 Spec {
458 name: "decr",
459 arity: 2,
460 flags: WRITE_FAST_OOM,
461 first_key: 1,
462 last_key: 1,
463 step: 1,
464 acl: AC_WRITE_FAST,
465 since: "1.0.0",
466 complexity: "O(1)",
467 summary: "Take one away, starting from zero if the key is not there.",
468 group: "string",
469 },
470 Spec {
471 name: "incrby",
472 arity: 3,
473 flags: WRITE_FAST_OOM,
474 first_key: 1,
475 last_key: 1,
476 step: 1,
477 acl: AC_WRITE_FAST,
478 since: "1.0.0",
479 complexity: "O(1)",
480 summary: "Add a number, starting from zero if the key is not there.",
481 group: "string",
482 },
483 Spec {
484 name: "decrby",
485 arity: 3,
486 flags: WRITE_FAST_OOM,
487 first_key: 1,
488 last_key: 1,
489 step: 1,
490 acl: AC_WRITE_FAST,
491 since: "1.0.0",
492 complexity: "O(1)",
493 summary: "Take a number away, starting from zero if the key is not there.",
494 group: "string",
495 },
496 Spec {
497 name: "incrbyfloat",
498 arity: 3,
499 flags: WRITE_FAST_OOM,
500 first_key: 1,
501 last_key: 1,
502 step: 1,
503 acl: AC_WRITE_FAST,
504 since: "2.6.0",
505 complexity: "O(1)",
506 summary: "Add a float, starting from zero if the key is not there.",
507 group: "string",
508 },
509 Spec {
510 name: "lcs",
511 arity: -3,
512 flags: &["readonly"],
513 first_key: 1,
514 last_key: 2,
515 step: 1,
516 acl: AC_READ_SLOW,
517 since: "7.0.0",
518 complexity: "O(N*M) with N and M the lengths of the two values",
519 summary: "The longest subsequence two string values have in common.",
520 group: "string",
521 },
522 Spec {
523 name: "msetex",
524 arity: -4,
525 flags: &["write", "denyoom", "movablekeys"],
526 first_key: 0,
527 last_key: 0,
528 step: 0,
529 acl: AC_WRITE_SLOW,
530 since: "8.4.0",
531 complexity: "O(N) with N the number of keys",
532 summary: "Set several keys with one deadline and one condition over all of them.",
533 group: "string",
534 },
535 Spec {
536 name: "delex",
537 arity: -2,
538 flags: &["write", "fast"],
539 first_key: 1,
540 last_key: 1,
541 step: 1,
542 acl: AC_WRITE_FAST,
543 since: "8.4.0",
544 complexity: "O(1) by value, O(N) by digest",
545 summary: "Delete a key only if it still holds what the caller thinks.",
546 group: "string",
547 },
548 Spec {
549 name: "digest",
550 arity: 2,
551 flags: READ_FAST,
552 first_key: 1,
553 last_key: 1,
554 step: 1,
555 acl: AC_READ_FAST,
556 since: "8.4.0",
557 complexity: "O(N) with N the length of the value",
558 summary: "The XXH3 of a string value, as sixteen hex characters.",
559 group: "string",
560 },
561 Spec {
562 name: "increx",
563 arity: -2,
564 flags: WRITE_FAST_OOM,
565 first_key: 1,
566 last_key: 1,
567 step: 1,
568 acl: AC_WRITE_FAST,
569 since: "8.8.0",
570 complexity: "O(1)",
571 summary: "Count, with a bound, a saturation policy and a deadline.",
572 group: "string",
573 },
574 Spec {
576 name: "setbit",
577 arity: 4,
578 flags: WRITE_OOM,
579 first_key: 1,
580 last_key: 1,
581 step: 1,
582 acl: AC_BIT_WRITE,
583 since: "2.2.0",
584 complexity: "O(1)",
585 summary: "Set one bit of a string, growing it to reach the offset.",
586 group: "bitmap",
587 },
588 Spec {
589 name: "getbit",
590 arity: 3,
591 flags: READ_FAST,
592 first_key: 1,
593 last_key: 1,
594 step: 1,
595 acl: AC_BIT_READ_FAST,
596 since: "2.2.0",
597 complexity: "O(1)",
598 summary: "Read one bit of a string, or nought past its end.",
599 group: "bitmap",
600 },
601 Spec {
602 name: "bitcount",
603 arity: -2,
604 flags: &["readonly"],
605 first_key: 1,
606 last_key: 1,
607 step: 1,
608 acl: AC_BIT_READ,
609 since: "2.6.0",
610 complexity: "O(N)",
611 summary: "Count the set bits of a string, or of a range of it.",
612 group: "bitmap",
613 },
614 Spec {
615 name: "bitpos",
616 arity: -3,
617 flags: &["readonly"],
618 first_key: 1,
619 last_key: 1,
620 step: 1,
621 acl: AC_BIT_READ,
622 since: "2.8.7",
623 complexity: "O(N)",
624 summary: "Find the first bit set to one or nought in a string.",
625 group: "bitmap",
626 },
627 Spec {
628 name: "bitop",
629 arity: -4,
630 flags: WRITE_OOM,
631 first_key: 2,
632 last_key: -1,
633 step: 1,
634 acl: AC_BIT_WRITE,
635 since: "2.6.0",
636 complexity: "O(N) with N the length of the longest source",
637 summary: "Combine strings bit by bit and store the result.",
638 group: "bitmap",
639 },
640 Spec {
641 name: "bitfield",
642 arity: -2,
643 flags: WRITE_OOM,
644 first_key: 1,
645 last_key: 1,
646 step: 1,
647 acl: AC_BIT_WRITE,
648 since: "3.2.0",
649 complexity: "O(1) per subcommand",
650 summary: "Read and write packed integer fields inside a string.",
651 group: "bitmap",
652 },
653 Spec {
654 name: "bitfield_ro",
655 arity: -2,
656 flags: READ_FAST,
657 first_key: 1,
658 last_key: 1,
659 step: 1,
660 acl: AC_BIT_READ_FAST,
661 since: "6.0.0",
662 complexity: "O(1) per subcommand",
663 summary: "The read only half of BITFIELD, for a replica to answer.",
664 group: "bitmap",
665 },
666 Spec {
668 name: "pfadd",
669 arity: -2,
670 flags: WRITE_OOM,
671 first_key: 1,
672 last_key: 1,
673 step: 1,
674 acl: AC_HLL_WRITE_FAST,
675 since: "2.8.9",
676 complexity: "O(1) an element",
677 summary: "Add elements to a sketch, answering whether it changed.",
678 group: "hyperloglog",
679 },
680 Spec {
681 name: "pfcount",
682 arity: -2,
683 flags: &["readonly"],
684 first_key: 1,
685 last_key: -1,
686 step: 1,
687 acl: AC_HLL_READ,
688 since: "2.8.9",
689 complexity: "O(1) for one key, O(N) for N of them",
690 summary: "Estimate how many distinct elements the sketches hold.",
691 group: "hyperloglog",
692 },
693 Spec {
694 name: "pfmerge",
695 arity: -2,
696 flags: WRITE_OOM,
697 first_key: 1,
698 last_key: -1,
699 step: 1,
700 acl: AC_HLL_WRITE,
701 since: "2.8.9",
702 complexity: "O(N) in the number of sketches",
703 summary: "Merge sketches into the first one, which is a union.",
704 group: "hyperloglog",
705 },
706 Spec {
707 name: "pfdebug",
708 arity: 3,
709 flags: WRITE_OOM_ADMIN,
710 first_key: 2,
711 last_key: 2,
712 step: 1,
713 acl: AC_HLL_ADMIN,
714 since: "2.8.9",
715 complexity: "O(N)",
716 summary: "Look inside a sketch, and in one case convert it.",
717 group: "hyperloglog",
718 },
719 Spec {
720 name: "pfselftest",
721 arity: 1,
722 flags: &["admin"],
723 first_key: 0,
724 last_key: 0,
725 step: 0,
726 acl: AC_HLL_ADMIN,
727 since: "2.8.9",
728 complexity: "O(1)",
729 summary: "Check the sketch code, which our tests do at build time.",
730 group: "hyperloglog",
731 },
732 Spec {
734 name: "sadd",
735 arity: -3,
736 flags: WRITE_FAST_OOM,
737 first_key: 1,
738 last_key: 1,
739 step: 1,
740 acl: AC_SET_WRITE_FAST,
741 since: "1.0.0",
742 complexity: "O(N) with N the number of members being added",
743 summary: "Add members to a set, creating it if it is not there.",
744 group: "set",
745 },
746 Spec {
747 name: "srem",
748 arity: -3,
749 flags: WRITE_FAST,
750 first_key: 1,
751 last_key: 1,
752 step: 1,
753 acl: AC_SET_WRITE_FAST,
754 since: "1.0.0",
755 complexity: "O(N) with N the number of members being removed",
756 summary: "Take members out of a set, deleting the key if none are left.",
757 group: "set",
758 },
759 Spec {
760 name: "scard",
761 arity: 2,
762 flags: READ_FAST,
763 first_key: 1,
764 last_key: 1,
765 step: 1,
766 acl: AC_SET_READ_FAST,
767 since: "1.0.0",
768 complexity: "O(1)",
769 summary: "How many members a set has.",
770 group: "set",
771 },
772 Spec {
773 name: "sismember",
774 arity: 3,
775 flags: READ_FAST,
776 first_key: 1,
777 last_key: 1,
778 step: 1,
779 acl: AC_SET_READ_FAST,
780 since: "1.0.0",
781 complexity: "O(1)",
782 summary: "Whether a member is in a set.",
783 group: "set",
784 },
785 Spec {
786 name: "smismember",
787 arity: -3,
788 flags: READ_FAST,
789 first_key: 1,
790 last_key: 1,
791 step: 1,
792 acl: AC_SET_READ_FAST,
793 since: "6.2.0",
794 complexity: "O(N) with N the number of members being asked about",
795 summary: "Whether each of several members is in a set, in the order asked.",
796 group: "set",
797 },
798 Spec {
799 name: "smembers",
800 arity: 2,
801 flags: &["readonly"],
802 first_key: 1,
803 last_key: 1,
804 step: 1,
805 acl: AC_SET_READ_SLOW,
806 since: "1.0.0",
807 complexity: "O(N) with N the size of the set",
808 summary: "Every member of a set.",
809 group: "set",
810 },
811 Spec {
812 name: "spop",
813 arity: -2,
814 flags: WRITE_FAST,
815 first_key: 1,
816 last_key: 1,
817 step: 1,
818 acl: AC_SET_WRITE_FAST,
819 since: "1.0.0",
820 complexity: "O(1) without a count, O(N) with one",
821 summary: "Take members out of a set at random and hand them back.",
822 group: "set",
823 },
824 Spec {
825 name: "srandmember",
826 arity: -2,
827 flags: &["readonly"],
828 first_key: 1,
829 last_key: 1,
830 step: 1,
831 acl: AC_SET_READ_SLOW,
832 since: "1.0.0",
833 complexity: "O(1) without a count, O(N) with one",
834 summary: "Members of a set at random, leaving the set as it was.",
835 group: "set",
836 },
837 Spec {
838 name: "smove",
839 arity: 4,
840 flags: WRITE_FAST,
841 first_key: 1,
842 last_key: 2,
843 step: 1,
844 acl: AC_SET_WRITE_FAST,
845 since: "1.0.0",
846 complexity: "O(1)",
847 summary: "Move one member from one set to another.",
848 group: "set",
849 },
850 Spec {
851 name: "sscan",
852 arity: -3,
853 flags: &["readonly"],
854 first_key: 1,
855 last_key: 1,
856 step: 1,
857 acl: AC_SET_READ_SLOW,
858 since: "2.8.0",
859 complexity: "O(1) a call, O(N) for a whole iteration",
860 summary: "Walk part of a set and say where to carry on from.",
861 group: "set",
862 },
863 Spec {
864 name: "sinter",
865 arity: -2,
866 flags: &["readonly"],
867 first_key: 1,
868 last_key: -1,
869 step: 1,
870 acl: AC_SET_READ_SLOW,
871 since: "1.0.0",
872 complexity: "O(N*M) worst case, N the smallest set and M the number of sets",
873 summary: "The members every one of these sets has.",
874 group: "set",
875 },
876 Spec {
877 name: "sintercard",
878 arity: -3,
879 flags: READ_MOVABLE,
885 first_key: 0,
886 last_key: 0,
887 step: 0,
888 acl: AC_SET_READ_SLOW,
889 since: "7.0.0",
890 complexity: "O(N*M) worst case, N the smallest set and M the number of sets",
891 summary: "How many members every one of these sets has, up to a limit.",
892 group: "set",
893 },
894 Spec {
895 name: "sinterstore",
896 arity: -3,
897 flags: WRITE_OOM,
898 first_key: 1,
899 last_key: -1,
900 step: 1,
901 acl: AC_SET_WRITE_SLOW,
902 since: "1.0.0",
903 complexity: "O(N*M) worst case, N the smallest set and M the number of sets",
904 summary: "Store the members every one of these sets has.",
905 group: "set",
906 },
907 Spec {
908 name: "sunion",
909 arity: -2,
910 flags: &["readonly"],
911 first_key: 1,
912 last_key: -1,
913 step: 1,
914 acl: AC_SET_READ_SLOW,
915 since: "1.0.0",
916 complexity: "O(N) in the total number of members",
917 summary: "The members any of these sets has, each once.",
918 group: "set",
919 },
920 Spec {
921 name: "sunionstore",
922 arity: -3,
923 flags: WRITE_OOM,
924 first_key: 1,
925 last_key: -1,
926 step: 1,
927 acl: AC_SET_WRITE_SLOW,
928 since: "1.0.0",
929 complexity: "O(N) in the total number of members",
930 summary: "Store the members any of these sets has.",
931 group: "set",
932 },
933 Spec {
934 name: "sdiff",
935 arity: -2,
936 flags: &["readonly"],
937 first_key: 1,
938 last_key: -1,
939 step: 1,
940 acl: AC_SET_READ_SLOW,
941 since: "1.0.0",
942 complexity: "O(N) in the total number of members",
943 summary: "The members of the first set that no later set has.",
944 group: "set",
945 },
946 Spec {
947 name: "sdiffstore",
948 arity: -3,
949 flags: WRITE_OOM,
950 first_key: 1,
951 last_key: -1,
952 step: 1,
953 acl: AC_SET_WRITE_SLOW,
954 since: "1.0.0",
955 complexity: "O(N) in the total number of members",
956 summary: "Store the members of the first set that no later set has.",
957 group: "set",
958 },
959 Spec {
961 name: "hset",
962 arity: -4,
963 flags: WRITE_FAST_OOM,
964 first_key: 1,
965 last_key: 1,
966 step: 1,
967 acl: AC_HASH_WRITE_FAST,
968 since: "2.0.0",
969 complexity: "O(N) with N the number of pairs being written",
970 summary: "Write fields into a hash, creating it if it is not there.",
971 group: "hash",
972 },
973 Spec {
974 name: "hsetnx",
975 arity: 4,
976 flags: WRITE_FAST_OOM,
977 first_key: 1,
978 last_key: 1,
979 step: 1,
980 acl: AC_HASH_WRITE_FAST,
981 since: "2.0.0",
982 complexity: "O(1)",
983 summary: "Write a field only if the hash does not have it already.",
984 group: "hash",
985 },
986 Spec {
989 name: "hmset",
990 arity: -4,
991 flags: WRITE_FAST_OOM,
992 first_key: 1,
993 last_key: 1,
994 step: 1,
995 acl: AC_HASH_WRITE_FAST,
996 since: "2.0.0",
997 complexity: "O(N) with N the number of pairs being written",
998 summary: "Write fields into a hash and answer OK. Use HSET.",
999 group: "hash",
1000 },
1001 Spec {
1002 name: "hget",
1003 arity: 3,
1004 flags: READ_FAST,
1005 first_key: 1,
1006 last_key: 1,
1007 step: 1,
1008 acl: AC_HASH_READ_FAST,
1009 since: "2.0.0",
1010 complexity: "O(1)",
1011 summary: "The value of one field of a hash.",
1012 group: "hash",
1013 },
1014 Spec {
1015 name: "hmget",
1016 arity: -3,
1017 flags: READ_FAST,
1018 first_key: 1,
1019 last_key: 1,
1020 step: 1,
1021 acl: AC_HASH_READ_FAST,
1022 since: "2.0.0",
1023 complexity: "O(N) with N the number of fields asked for",
1024 summary: "The values of several fields, one reply entry each.",
1025 group: "hash",
1026 },
1027 Spec {
1028 name: "hdel",
1029 arity: -3,
1030 flags: WRITE_FAST,
1031 first_key: 1,
1032 last_key: 1,
1033 step: 1,
1034 acl: AC_HASH_WRITE_FAST,
1035 since: "2.0.0",
1036 complexity: "O(N) with N the number of fields being removed",
1037 summary: "Take fields out of a hash, deleting the key if none are left.",
1038 group: "hash",
1039 },
1040 Spec {
1041 name: "hlen",
1042 arity: 2,
1043 flags: READ_FAST,
1044 first_key: 1,
1045 last_key: 1,
1046 step: 1,
1047 acl: AC_HASH_READ_FAST,
1048 since: "2.0.0",
1049 complexity: "O(1)",
1050 summary: "How many fields a hash has.",
1051 group: "hash",
1052 },
1053 Spec {
1054 name: "hexists",
1055 arity: 3,
1056 flags: READ_FAST,
1057 first_key: 1,
1058 last_key: 1,
1059 step: 1,
1060 acl: AC_HASH_READ_FAST,
1061 since: "2.0.0",
1062 complexity: "O(1)",
1063 summary: "Whether a hash has a field.",
1064 group: "hash",
1065 },
1066 Spec {
1067 name: "hstrlen",
1068 arity: 3,
1069 flags: READ_FAST,
1070 first_key: 1,
1071 last_key: 1,
1072 step: 1,
1073 acl: AC_HASH_READ_FAST,
1074 since: "3.2.0",
1075 complexity: "O(1)",
1076 summary: "How many bytes a field's value is, without sending it.",
1077 group: "hash",
1078 },
1079 Spec {
1080 name: "hgetall",
1081 arity: 2,
1082 flags: &["readonly"],
1083 first_key: 1,
1084 last_key: 1,
1085 step: 1,
1086 acl: AC_HASH_READ_SLOW,
1087 since: "2.0.0",
1088 complexity: "O(N) in the size of the hash",
1089 summary: "Every field and value, as a map on RESP3.",
1090 group: "hash",
1091 },
1092 Spec {
1093 name: "hkeys",
1094 arity: 2,
1095 flags: &["readonly"],
1096 first_key: 1,
1097 last_key: 1,
1098 step: 1,
1099 acl: AC_HASH_READ_SLOW,
1100 since: "2.0.0",
1101 complexity: "O(N) in the size of the hash",
1102 summary: "Every field of a hash.",
1103 group: "hash",
1104 },
1105 Spec {
1106 name: "hvals",
1107 arity: 2,
1108 flags: &["readonly"],
1109 first_key: 1,
1110 last_key: 1,
1111 step: 1,
1112 acl: AC_HASH_READ_SLOW,
1113 since: "2.0.0",
1114 complexity: "O(N) in the size of the hash",
1115 summary: "Every value of a hash.",
1116 group: "hash",
1117 },
1118 Spec {
1119 name: "hincrby",
1120 arity: 4,
1121 flags: WRITE_FAST_OOM,
1122 first_key: 1,
1123 last_key: 1,
1124 step: 1,
1125 acl: AC_HASH_WRITE_FAST,
1126 since: "2.0.0",
1127 complexity: "O(1)",
1128 summary: "Add an integer to a field, treating a missing one as zero.",
1129 group: "hash",
1130 },
1131 Spec {
1132 name: "hincrbyfloat",
1133 arity: 4,
1134 flags: WRITE_FAST_OOM,
1135 first_key: 1,
1136 last_key: 1,
1137 step: 1,
1138 acl: AC_HASH_WRITE_FAST,
1139 since: "2.6.0",
1140 complexity: "O(1)",
1141 summary: "Add a float to a field, treating a missing one as zero.",
1142 group: "hash",
1143 },
1144 Spec {
1145 name: "hrandfield",
1146 arity: -2,
1147 flags: &["readonly"],
1148 first_key: 1,
1149 last_key: 1,
1150 step: 1,
1151 acl: AC_HASH_READ_SLOW,
1152 since: "6.2.0",
1153 complexity: "O(1) without a count, O(N) with one",
1154 summary: "Fields of a hash at random, leaving the hash as it was.",
1155 group: "hash",
1156 },
1157 Spec {
1158 name: "hscan",
1159 arity: -3,
1160 flags: &["readonly"],
1161 first_key: 1,
1162 last_key: 1,
1163 step: 1,
1164 acl: AC_HASH_READ_SLOW,
1165 since: "2.8.0",
1166 complexity: "O(1) a call, O(N) for a whole iteration",
1167 summary: "Walk part of a hash and say where to carry on from.",
1168 group: "hash",
1169 },
1170 Spec {
1171 name: "hexpire",
1172 arity: -6,
1173 flags: WRITE_FAST,
1174 first_key: 1,
1175 last_key: 1,
1176 step: 1,
1177 acl: AC_HASH_WRITE_FAST,
1178 since: "7.4.0",
1179 complexity: "O(N) with N the number of fields named",
1180 summary: "Put a deadline in seconds on hash fields.",
1181 group: "hash",
1182 },
1183 Spec {
1184 name: "hpexpire",
1185 arity: -6,
1186 flags: WRITE_FAST,
1187 first_key: 1,
1188 last_key: 1,
1189 step: 1,
1190 acl: AC_HASH_WRITE_FAST,
1191 since: "7.4.0",
1192 complexity: "O(N) with N the number of fields named",
1193 summary: "Put a deadline in milliseconds on hash fields.",
1194 group: "hash",
1195 },
1196 Spec {
1197 name: "hexpireat",
1198 arity: -6,
1199 flags: WRITE_FAST,
1200 first_key: 1,
1201 last_key: 1,
1202 step: 1,
1203 acl: AC_HASH_WRITE_FAST,
1204 since: "7.4.0",
1205 complexity: "O(N) with N the number of fields named",
1206 summary: "Put an absolute deadline in unix seconds on hash fields.",
1207 group: "hash",
1208 },
1209 Spec {
1210 name: "hpexpireat",
1211 arity: -6,
1212 flags: WRITE_FAST,
1213 first_key: 1,
1214 last_key: 1,
1215 step: 1,
1216 acl: AC_HASH_WRITE_FAST,
1217 since: "7.4.0",
1218 complexity: "O(N) with N the number of fields named",
1219 summary: "Put an absolute deadline in unix milliseconds on hash fields.",
1220 group: "hash",
1221 },
1222 Spec {
1223 name: "httl",
1224 arity: -5,
1225 flags: READ_FAST,
1226 first_key: 1,
1227 last_key: 1,
1228 step: 1,
1229 acl: AC_HASH_READ_FAST,
1230 since: "7.4.0",
1231 complexity: "O(N) with N the number of fields named",
1232 summary: "How long hash fields have left, in seconds.",
1233 group: "hash",
1234 },
1235 Spec {
1236 name: "hpttl",
1237 arity: -5,
1238 flags: READ_FAST,
1239 first_key: 1,
1240 last_key: 1,
1241 step: 1,
1242 acl: AC_HASH_READ_FAST,
1243 since: "7.4.0",
1244 complexity: "O(N) with N the number of fields named",
1245 summary: "How long hash fields have left, in milliseconds.",
1246 group: "hash",
1247 },
1248 Spec {
1249 name: "hexpiretime",
1250 arity: -5,
1251 flags: READ_FAST,
1252 first_key: 1,
1253 last_key: 1,
1254 step: 1,
1255 acl: AC_HASH_READ_FAST,
1256 since: "7.4.0",
1257 complexity: "O(N) with N the number of fields named",
1258 summary: "When hash fields fall due, in unix seconds.",
1259 group: "hash",
1260 },
1261 Spec {
1262 name: "hpexpiretime",
1263 arity: -5,
1264 flags: READ_FAST,
1265 first_key: 1,
1266 last_key: 1,
1267 step: 1,
1268 acl: AC_HASH_READ_FAST,
1269 since: "7.4.0",
1270 complexity: "O(N) with N the number of fields named",
1271 summary: "When hash fields fall due, in unix milliseconds.",
1272 group: "hash",
1273 },
1274 Spec {
1275 name: "hpersist",
1276 arity: -5,
1277 flags: WRITE_FAST,
1278 first_key: 1,
1279 last_key: 1,
1280 step: 1,
1281 acl: AC_HASH_WRITE_FAST,
1282 since: "7.4.0",
1283 complexity: "O(N) with N the number of fields named",
1284 summary: "Take the deadlines off hash fields.",
1285 group: "hash",
1286 },
1287 Spec {
1288 name: "hgetdel",
1289 arity: -5,
1290 flags: WRITE_FAST,
1291 first_key: 1,
1292 last_key: 1,
1293 step: 1,
1294 acl: AC_HASH_WRITE_FAST,
1295 since: "8.0.0",
1296 complexity: "O(N) with N the number of fields named",
1297 summary: "Read hash fields and delete them.",
1298 group: "hash",
1299 },
1300 Spec {
1301 name: "hgetex",
1302 arity: -5,
1303 flags: WRITE_FAST,
1304 first_key: 1,
1305 last_key: 1,
1306 step: 1,
1307 acl: AC_HASH_WRITE_FAST,
1308 since: "8.0.0",
1309 complexity: "O(N) with N the number of fields named",
1310 summary: "Read hash fields and set their deadlines.",
1311 group: "hash",
1312 },
1313 Spec {
1314 name: "hsetex",
1315 arity: -6,
1316 flags: WRITE_FAST_OOM,
1317 first_key: 1,
1318 last_key: 1,
1319 step: 1,
1320 acl: AC_HASH_WRITE_FAST,
1321 since: "8.0.0",
1322 complexity: "O(N) with N the number of fields being set",
1323 summary: "Set hash fields and their deadlines together.",
1324 group: "hash",
1325 },
1326 Spec {
1328 name: "lpush",
1329 arity: -3,
1330 flags: WRITE_FAST_OOM,
1331 first_key: 1,
1332 last_key: 1,
1333 step: 1,
1334 acl: AC_LIST_WRITE_FAST,
1335 since: "1.0.0",
1336 complexity: "O(N) with N the number of elements pushed",
1337 summary: "Push elements onto the head of a list.",
1338 group: "list",
1339 },
1340 Spec {
1341 name: "rpush",
1342 arity: -3,
1343 flags: WRITE_FAST_OOM,
1344 first_key: 1,
1345 last_key: 1,
1346 step: 1,
1347 acl: AC_LIST_WRITE_FAST,
1348 since: "1.0.0",
1349 complexity: "O(N) with N the number of elements pushed",
1350 summary: "Push elements onto the tail of a list.",
1351 group: "list",
1352 },
1353 Spec {
1354 name: "lpushx",
1355 arity: -3,
1356 flags: WRITE_FAST_OOM,
1357 first_key: 1,
1358 last_key: 1,
1359 step: 1,
1360 acl: AC_LIST_WRITE_FAST,
1361 since: "2.2.0",
1362 complexity: "O(N) with N the number of elements pushed",
1363 summary: "Push elements onto the head of a list that already exists.",
1364 group: "list",
1365 },
1366 Spec {
1367 name: "rpushx",
1368 arity: -3,
1369 flags: WRITE_FAST_OOM,
1370 first_key: 1,
1371 last_key: 1,
1372 step: 1,
1373 acl: AC_LIST_WRITE_FAST,
1374 since: "2.2.0",
1375 complexity: "O(N) with N the number of elements pushed",
1376 summary: "Push elements onto the tail of a list that already exists.",
1377 group: "list",
1378 },
1379 Spec {
1380 name: "lpop",
1381 arity: -2,
1382 flags: WRITE_FAST,
1383 first_key: 1,
1384 last_key: 1,
1385 step: 1,
1386 acl: AC_LIST_WRITE_FAST,
1387 since: "1.0.0",
1388 complexity: "O(N) with N the count asked for",
1389 summary: "Take elements off the head of a list.",
1390 group: "list",
1391 },
1392 Spec {
1393 name: "rpop",
1394 arity: -2,
1395 flags: WRITE_FAST,
1396 first_key: 1,
1397 last_key: 1,
1398 step: 1,
1399 acl: AC_LIST_WRITE_FAST,
1400 since: "1.0.0",
1401 complexity: "O(N) with N the count asked for",
1402 summary: "Take elements off the tail of a list.",
1403 group: "list",
1404 },
1405 Spec {
1406 name: "llen",
1407 arity: 2,
1408 flags: READ_FAST,
1409 first_key: 1,
1410 last_key: 1,
1411 step: 1,
1412 acl: AC_LIST_READ_FAST,
1413 since: "1.0.0",
1414 complexity: "O(1)",
1415 summary: "How many elements a list holds.",
1416 group: "list",
1417 },
1418 Spec {
1419 name: "lrange",
1420 arity: 4,
1421 flags: READ_SLOW,
1422 first_key: 1,
1423 last_key: 1,
1424 step: 1,
1425 acl: AC_LIST_READ_SLOW,
1426 since: "1.0.0",
1427 complexity: "O(S+N) with S the offset of the first element and N the range",
1428 summary: "Read a range of a list, both ends included.",
1429 group: "list",
1430 },
1431 Spec {
1432 name: "lindex",
1433 arity: 3,
1434 flags: READ_SLOW,
1435 first_key: 1,
1436 last_key: 1,
1437 step: 1,
1438 acl: AC_LIST_READ_SLOW,
1439 since: "1.0.0",
1440 complexity: "O(N) with N the distance to the index from the nearer end",
1441 summary: "Read one element of a list by index.",
1442 group: "list",
1443 },
1444 Spec {
1445 name: "lset",
1446 arity: 4,
1447 flags: WRITE_OOM,
1448 first_key: 1,
1449 last_key: 1,
1450 step: 1,
1451 acl: AC_LIST_WRITE_SLOW,
1452 since: "1.0.0",
1453 complexity: "O(N) with N the distance to the index from the nearer end",
1454 summary: "Replace one element of a list by index.",
1455 group: "list",
1456 },
1457 Spec {
1458 name: "linsert",
1459 arity: 5,
1460 flags: WRITE_OOM,
1461 first_key: 1,
1462 last_key: 1,
1463 step: 1,
1464 acl: AC_LIST_WRITE_SLOW,
1465 since: "2.2.0",
1466 complexity: "O(N) with N the distance to the pivot from the head",
1467 summary: "Insert an element before or after another one.",
1468 group: "list",
1469 },
1470 Spec {
1471 name: "lrem",
1472 arity: 4,
1473 flags: WRITE_SLOW,
1474 first_key: 1,
1475 last_key: 1,
1476 step: 1,
1477 acl: AC_LIST_WRITE_SLOW,
1478 since: "1.0.0",
1479 complexity: "O(N) with N the length of the list",
1480 summary: "Remove elements equal to a value from a list.",
1481 group: "list",
1482 },
1483 Spec {
1484 name: "ltrim",
1485 arity: 4,
1486 flags: WRITE_SLOW,
1487 first_key: 1,
1488 last_key: 1,
1489 step: 1,
1490 acl: AC_LIST_WRITE_SLOW,
1491 since: "1.0.0",
1492 complexity: "O(N) with N the number of elements thrown away",
1493 summary: "Keep a range of a list and throw the rest away.",
1494 group: "list",
1495 },
1496 Spec {
1497 name: "lpos",
1498 arity: -3,
1499 flags: READ_SLOW,
1500 first_key: 1,
1501 last_key: 1,
1502 step: 1,
1503 acl: AC_LIST_READ_SLOW,
1504 since: "6.0.6",
1505 complexity: "O(N) with N the length of the list",
1506 summary: "Find where a value sits in a list.",
1507 group: "list",
1508 },
1509 Spec {
1510 name: "rpoplpush",
1511 arity: 3,
1512 flags: WRITE_OOM,
1513 first_key: 1,
1514 last_key: 2,
1515 step: 1,
1516 acl: AC_LIST_WRITE_SLOW,
1517 since: "1.2.0",
1518 complexity: "O(1)",
1519 summary: "Move an element from the tail of one list to the head of another.",
1520 group: "list",
1521 },
1522 Spec {
1523 name: "lmove",
1524 arity: 5,
1525 flags: WRITE_OOM,
1526 first_key: 1,
1527 last_key: 2,
1528 step: 1,
1529 acl: AC_LIST_WRITE_SLOW,
1530 since: "6.2.0",
1531 complexity: "O(1)",
1532 summary: "Move an element from either end of one list to either end of another.",
1533 group: "list",
1534 },
1535 Spec {
1540 name: "lmpop",
1541 arity: -4,
1542 flags: &["write", "movablekeys"],
1543 first_key: 0,
1544 last_key: 0,
1545 step: 0,
1546 acl: AC_LIST_WRITE_SLOW,
1547 since: "7.0.0",
1548 complexity: "O(N+M) with N the number of keys and M the count popped",
1549 summary: "Pop from the first of several lists that has anything in it.",
1550 group: "list",
1551 },
1552 Spec {
1560 name: "blpop",
1561 arity: -3,
1562 flags: &["write", "blocking"],
1563 first_key: 1,
1564 last_key: -2,
1565 step: 1,
1566 acl: AC_LIST_WRITE_BLOCKING,
1567 since: "2.0.0",
1568 complexity: "O(N) with N the number of keys named",
1569 summary: "Pop the head of the first list that has anything, waiting if none does.",
1570 group: "list",
1571 },
1572 Spec {
1573 name: "brpop",
1574 arity: -3,
1575 flags: &["write", "blocking"],
1576 first_key: 1,
1577 last_key: -2,
1578 step: 1,
1579 acl: AC_LIST_WRITE_BLOCKING,
1580 since: "2.0.0",
1581 complexity: "O(N) with N the number of keys named",
1582 summary: "Pop the tail of the first list that has anything, waiting if none does.",
1583 group: "list",
1584 },
1585 Spec {
1588 name: "blmove",
1589 arity: 6,
1590 flags: &["write", "denyoom", "blocking"],
1591 first_key: 1,
1592 last_key: 2,
1593 step: 1,
1594 acl: AC_LIST_WRITE_BLOCKING,
1595 since: "6.2.0",
1596 complexity: "O(1)",
1597 summary: "Move an element between two lists, waiting for one to arrive.",
1598 group: "list",
1599 },
1600 Spec {
1601 name: "brpoplpush",
1602 arity: 4,
1603 flags: &["write", "denyoom", "blocking"],
1604 first_key: 1,
1605 last_key: 2,
1606 step: 1,
1607 acl: AC_LIST_WRITE_BLOCKING,
1608 since: "2.2.0",
1609 complexity: "O(1)",
1610 summary: "Move a tail element to another list's head, waiting for one to arrive.",
1611 group: "list",
1612 },
1613 Spec {
1615 name: "blmpop",
1616 arity: -5,
1617 flags: &["write", "blocking", "movablekeys"],
1618 first_key: 0,
1619 last_key: 0,
1620 step: 0,
1621 acl: AC_LIST_WRITE_BLOCKING,
1622 since: "7.0.0",
1623 complexity: "O(N+M) with N the number of keys and M the count popped",
1624 summary: "Pop from the first of several lists that has anything, waiting if none does.",
1625 group: "list",
1626 },
1627 Spec {
1629 name: "zadd",
1630 arity: -4,
1631 flags: WRITE_FAST_OOM,
1632 first_key: 1,
1633 last_key: 1,
1634 step: 1,
1635 acl: AC_ZSET_WRITE_FAST,
1636 since: "1.2.0",
1637 complexity: "O(log(N)) for each member added",
1638 summary: "Add members with scores, or move the scores of members already there.",
1639 group: "zset",
1640 },
1641 Spec {
1642 name: "zincrby",
1643 arity: 4,
1644 flags: WRITE_FAST_OOM,
1645 first_key: 1,
1646 last_key: 1,
1647 step: 1,
1648 acl: AC_ZSET_WRITE_FAST,
1649 since: "1.2.0",
1650 complexity: "O(log(N))",
1651 summary: "Add to a member's score, creating the member at zero if it is not there.",
1652 group: "zset",
1653 },
1654 Spec {
1655 name: "zcard",
1656 arity: 2,
1657 flags: READ_FAST,
1658 first_key: 1,
1659 last_key: 1,
1660 step: 1,
1661 acl: AC_ZSET_READ_FAST,
1662 since: "1.2.0",
1663 complexity: "O(1)",
1664 summary: "How many members a sorted set has.",
1665 group: "zset",
1666 },
1667 Spec {
1668 name: "zscore",
1669 arity: 3,
1670 flags: READ_FAST,
1671 first_key: 1,
1672 last_key: 1,
1673 step: 1,
1674 acl: AC_ZSET_READ_FAST,
1675 since: "1.2.0",
1676 complexity: "O(1)",
1677 summary: "A member's score, or nothing if it is not there.",
1678 group: "zset",
1679 },
1680 Spec {
1681 name: "zmscore",
1682 arity: -3,
1683 flags: READ_FAST,
1684 first_key: 1,
1685 last_key: 1,
1686 step: 1,
1687 acl: AC_ZSET_READ_FAST,
1688 since: "6.2.0",
1689 complexity: "O(N) with N the number of members asked about",
1690 summary: "The scores of several members in one round trip.",
1691 group: "zset",
1692 },
1693 Spec {
1694 name: "zrem",
1695 arity: -3,
1696 flags: WRITE_FAST,
1697 first_key: 1,
1698 last_key: 1,
1699 step: 1,
1700 acl: AC_ZSET_WRITE_FAST,
1701 since: "1.2.0",
1702 complexity: "O(M*log(N)) with M the number of members removed",
1703 summary: "Remove members, deleting the key if the last one goes.",
1704 group: "zset",
1705 },
1706 Spec {
1707 name: "zrank",
1708 arity: -3,
1709 flags: READ_FAST,
1710 first_key: 1,
1711 last_key: 1,
1712 step: 1,
1713 acl: AC_ZSET_READ_FAST,
1714 since: "2.0.0",
1715 complexity: "O(log(N))",
1716 summary: "Where a member sits counting up from the lowest score.",
1717 group: "zset",
1718 },
1719 Spec {
1720 name: "zrevrank",
1721 arity: -3,
1722 flags: READ_FAST,
1723 first_key: 1,
1724 last_key: 1,
1725 step: 1,
1726 acl: AC_ZSET_READ_FAST,
1727 since: "2.0.0",
1728 complexity: "O(log(N))",
1729 summary: "Where a member sits counting down from the highest score.",
1730 group: "zset",
1731 },
1732 Spec {
1733 name: "zcount",
1734 arity: 4,
1735 flags: READ_FAST,
1736 first_key: 1,
1737 last_key: 1,
1738 step: 1,
1739 acl: AC_ZSET_READ_FAST,
1740 since: "2.0.0",
1741 complexity: "O(log(N))",
1742 summary: "How many members have scores between two bounds.",
1743 group: "zset",
1744 },
1745 Spec {
1746 name: "zlexcount",
1747 arity: 4,
1748 flags: READ_FAST,
1749 first_key: 1,
1750 last_key: 1,
1751 step: 1,
1752 acl: AC_ZSET_READ_FAST,
1753 since: "2.8.9",
1754 complexity: "O(log(N))",
1755 summary: "How many members fall between two members, by name.",
1756 group: "zset",
1757 },
1758 Spec {
1759 name: "zrange",
1760 arity: -4,
1761 flags: READ_SLOW,
1762 first_key: 1,
1763 last_key: 1,
1764 step: 1,
1765 acl: AC_ZSET_READ_SLOW,
1766 since: "1.2.0",
1767 complexity: "O(log(N)+M) with M the number of members answered",
1768 summary: "A window of members, by rank or by score or by name, either way round.",
1769 group: "zset",
1770 },
1771 Spec {
1772 name: "zrevrange",
1773 arity: -4,
1774 flags: READ_SLOW,
1775 first_key: 1,
1776 last_key: 1,
1777 step: 1,
1778 acl: AC_ZSET_READ_SLOW,
1779 since: "1.2.0",
1780 complexity: "O(log(N)+M) with M the number of members answered",
1781 summary: "A window by rank, counting down from the highest score.",
1782 group: "zset",
1783 },
1784 Spec {
1785 name: "zrangebyscore",
1786 arity: -4,
1787 flags: READ_SLOW,
1788 first_key: 1,
1789 last_key: 1,
1790 step: 1,
1791 acl: AC_ZSET_READ_SLOW,
1792 since: "1.0.5",
1793 complexity: "O(log(N)+M) with M the number of members answered",
1794 summary: "The members whose scores fall between two bounds.",
1795 group: "zset",
1796 },
1797 Spec {
1798 name: "zrevrangebyscore",
1799 arity: -4,
1800 flags: READ_SLOW,
1801 first_key: 1,
1802 last_key: 1,
1803 step: 1,
1804 acl: AC_ZSET_READ_SLOW,
1805 since: "2.2.0",
1806 complexity: "O(log(N)+M) with M the number of members answered",
1807 summary: "The same window as ZRANGEBYSCORE, highest score first and named high end first.",
1808 group: "zset",
1809 },
1810 Spec {
1811 name: "zrangebylex",
1812 arity: -4,
1813 flags: READ_SLOW,
1814 first_key: 1,
1815 last_key: 1,
1816 step: 1,
1817 acl: AC_ZSET_READ_SLOW,
1818 since: "2.8.9",
1819 complexity: "O(log(N)+M) with M the number of members answered",
1820 summary: "The members that fall between two names, for a set where every score is the same.",
1821 group: "zset",
1822 },
1823 Spec {
1824 name: "zrevrangebylex",
1825 arity: -4,
1826 flags: READ_SLOW,
1827 first_key: 1,
1828 last_key: 1,
1829 step: 1,
1830 acl: AC_ZSET_READ_SLOW,
1831 since: "2.8.9",
1832 complexity: "O(log(N)+M) with M the number of members answered",
1833 summary: "The same window as ZRANGEBYLEX, backwards and named high end first.",
1834 group: "zset",
1835 },
1836 Spec {
1837 name: "zrangestore",
1838 arity: -5,
1839 flags: WRITE_OOM,
1840 first_key: 1,
1841 last_key: 2,
1842 step: 1,
1843 acl: AC_ZSET_WRITE_SLOW,
1844 since: "6.2.0",
1845 complexity: "O(log(N)+M) with M the number of members stored",
1846 summary: "Write a window of one sorted set into another key.",
1847 group: "zset",
1848 },
1849 Spec {
1850 name: "zremrangebyrank",
1851 arity: 4,
1852 flags: WRITE_SLOW,
1853 first_key: 1,
1854 last_key: 1,
1855 step: 1,
1856 acl: AC_ZSET_WRITE_SLOW,
1857 since: "2.0.0",
1858 complexity: "O(log(N)+M) with M the number of members removed",
1859 summary: "Remove the members in a range of ranks.",
1860 group: "zset",
1861 },
1862 Spec {
1863 name: "zremrangebyscore",
1864 arity: 4,
1865 flags: WRITE_SLOW,
1866 first_key: 1,
1867 last_key: 1,
1868 step: 1,
1869 acl: AC_ZSET_WRITE_SLOW,
1870 since: "1.2.0",
1871 complexity: "O(log(N)+M) with M the number of members removed",
1872 summary: "Remove the members whose scores fall between two bounds.",
1873 group: "zset",
1874 },
1875 Spec {
1876 name: "zremrangebylex",
1877 arity: 4,
1878 flags: WRITE_SLOW,
1879 first_key: 1,
1880 last_key: 1,
1881 step: 1,
1882 acl: AC_ZSET_WRITE_SLOW,
1883 since: "2.8.9",
1884 complexity: "O(log(N)+M) with M the number of members removed",
1885 summary: "Remove the members that fall between two names.",
1886 group: "zset",
1887 },
1888 Spec {
1889 name: "zunion",
1890 arity: -3,
1891 flags: READ_MOVABLE,
1892 first_key: 0,
1893 last_key: 0,
1894 step: 0,
1895 acl: AC_ZSET_READ_SLOW,
1896 since: "6.2.0",
1897 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1898 summary: "Every member of these sorted sets, with the scores combined.",
1899 group: "zset",
1900 },
1901 Spec {
1902 name: "zinter",
1903 arity: -3,
1904 flags: READ_MOVABLE,
1905 first_key: 0,
1906 last_key: 0,
1907 step: 0,
1908 acl: AC_ZSET_READ_SLOW,
1909 since: "6.2.0",
1910 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1911 summary: "Only the members all of these sorted sets have, with the scores combined.",
1912 group: "zset",
1913 },
1914 Spec {
1915 name: "zdiff",
1916 arity: -3,
1917 flags: READ_MOVABLE,
1918 first_key: 0,
1919 last_key: 0,
1920 step: 0,
1921 acl: AC_ZSET_READ_SLOW,
1922 since: "6.2.0",
1923 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1924 summary: "The members of the first that none of the rest have.",
1925 group: "zset",
1926 },
1927 Spec {
1928 name: "zunionstore",
1929 arity: -4,
1930 flags: WRITE_MOVABLE,
1931 first_key: 1,
1932 last_key: 1,
1933 step: 1,
1934 acl: AC_ZSET_WRITE_SLOW,
1935 since: "2.0.0",
1936 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1937 summary: "Store the union in another key and say how big it is.",
1938 group: "zset",
1939 },
1940 Spec {
1941 name: "zinterstore",
1942 arity: -4,
1943 flags: WRITE_MOVABLE,
1944 first_key: 1,
1945 last_key: 1,
1946 step: 1,
1947 acl: AC_ZSET_WRITE_SLOW,
1948 since: "2.0.0",
1949 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1950 summary: "Store the intersection in another key and say how big it is.",
1951 group: "zset",
1952 },
1953 Spec {
1954 name: "zdiffstore",
1955 arity: -4,
1956 flags: WRITE_MOVABLE,
1957 first_key: 1,
1958 last_key: 1,
1959 step: 1,
1960 acl: AC_ZSET_WRITE_SLOW,
1961 since: "6.2.0",
1962 complexity: "O(N)+O(M*log(M)) with N the total number of members and M the number in the answer",
1963 summary: "Store the difference in another key and say how big it is.",
1964 group: "zset",
1965 },
1966 Spec {
1967 name: "zintercard",
1968 arity: -3,
1969 flags: READ_MOVABLE,
1970 first_key: 0,
1971 last_key: 0,
1972 step: 0,
1973 acl: AC_ZSET_READ_SLOW,
1974 since: "7.0.0",
1975 complexity: "O(N*M) worst case, N the smallest input and M the number of inputs",
1976 summary: "How many members the intersection would have, without building it.",
1977 group: "zset",
1978 },
1979 Spec {
1980 name: "zrandmember",
1981 arity: -2,
1982 flags: READ_SLOW,
1983 first_key: 1,
1984 last_key: 1,
1985 step: 1,
1986 acl: AC_ZSET_READ_SLOW,
1987 since: "6.2.0",
1988 complexity: "O(N) with N the number of members drawn",
1989 summary: "Draw members at random, with or without replacement.",
1990 group: "zset",
1991 },
1992 Spec {
1993 name: "zscan",
1994 arity: -3,
1995 flags: READ_SLOW,
1996 first_key: 1,
1997 last_key: 1,
1998 step: 1,
1999 acl: AC_ZSET_READ_SLOW,
2000 since: "2.8.0",
2001 complexity: "O(1) per call, O(N) over a full walk",
2002 summary: "Walk the members and their scores a batch at a time.",
2003 group: "zset",
2004 },
2005 Spec {
2008 name: "zpopmin",
2009 arity: -2,
2010 flags: WRITE_FAST,
2011 first_key: 1,
2012 last_key: 1,
2013 step: 1,
2014 acl: AC_ZSET_WRITE_FAST,
2015 since: "5.0.0",
2016 complexity: "O(log(N)*M) with M the number of members popped",
2017 summary: "Take the lowest scoring members off and answer them.",
2018 group: "zset",
2019 },
2020 Spec {
2021 name: "zpopmax",
2022 arity: -2,
2023 flags: WRITE_FAST,
2024 first_key: 1,
2025 last_key: 1,
2026 step: 1,
2027 acl: AC_ZSET_WRITE_FAST,
2028 since: "5.0.0",
2029 complexity: "O(log(N)*M) with M the number of members popped",
2030 summary: "Take the highest scoring members off and answer them.",
2031 group: "zset",
2032 },
2033 Spec {
2036 name: "zmpop",
2037 arity: -4,
2038 flags: &["write", "movablekeys"],
2039 first_key: 0,
2040 last_key: 0,
2041 step: 0,
2042 acl: AC_ZSET_WRITE_SLOW,
2043 since: "7.0.0",
2044 complexity: "O(K) + O(M*log(N)) with K the keys named and M the count popped",
2045 summary: "Pop from the first of several sorted sets that has anything in it.",
2046 group: "zset",
2047 },
2048 Spec {
2051 name: "bzpopmin",
2052 arity: -3,
2053 flags: &["write", "blocking", "fast"],
2054 first_key: 1,
2055 last_key: -2,
2056 step: 1,
2057 acl: AC_ZSET_BLOCKING_FAST,
2058 since: "5.0.0",
2059 complexity: "O(log(N)) with N the size of the sorted set that answers",
2060 summary: "Take the lowest scoring member off the first sorted set that has one, waiting if none does.",
2061 group: "zset",
2062 },
2063 Spec {
2064 name: "bzpopmax",
2065 arity: -3,
2066 flags: &["write", "blocking", "fast"],
2067 first_key: 1,
2068 last_key: -2,
2069 step: 1,
2070 acl: AC_ZSET_BLOCKING_FAST,
2071 since: "5.0.0",
2072 complexity: "O(log(N)) with N the size of the sorted set that answers",
2073 summary: "Take the highest scoring member off the first sorted set that has one, waiting if none does.",
2074 group: "zset",
2075 },
2076 Spec {
2077 name: "bzmpop",
2078 arity: -5,
2079 flags: &["write", "blocking", "movablekeys"],
2080 first_key: 0,
2081 last_key: 0,
2082 step: 0,
2083 acl: AC_ZSET_BLOCKING_SLOW,
2084 since: "7.0.0",
2085 complexity: "O(K) + O(M*log(N)) with K the keys named and M the count popped",
2086 summary: "Pop from the first of several sorted sets that has anything, waiting if none does.",
2087 group: "zset",
2088 },
2089 Spec {
2091 name: "geoadd",
2092 arity: -5,
2093 flags: WRITE_OOM,
2094 first_key: 1,
2095 last_key: 1,
2096 step: 1,
2097 acl: AC_GEO_WRITE,
2098 since: "3.2.0",
2099 complexity: "O(log(N)) per point added",
2100 summary: "Add places to a geo key, which is a sorted set of position hashes.",
2101 group: "geo",
2102 },
2103 Spec {
2104 name: "geopos",
2105 arity: -2,
2106 flags: READ_SLOW,
2107 first_key: 1,
2108 last_key: 1,
2109 step: 1,
2110 acl: AC_GEO_READ,
2111 since: "3.2.0",
2112 complexity: "O(1) per member asked about",
2113 summary: "Answer where each member is, as a longitude and a latitude.",
2114 group: "geo",
2115 },
2116 Spec {
2117 name: "geodist",
2118 arity: -4,
2119 flags: READ_SLOW,
2120 first_key: 1,
2121 last_key: 1,
2122 step: 1,
2123 acl: AC_GEO_READ,
2124 since: "3.2.0",
2125 complexity: "O(1)",
2126 summary: "Answer how far apart two members are, in the unit asked for.",
2127 group: "geo",
2128 },
2129 Spec {
2130 name: "geohash",
2131 arity: -2,
2132 flags: READ_SLOW,
2133 first_key: 1,
2134 last_key: 1,
2135 step: 1,
2136 acl: AC_GEO_READ,
2137 since: "3.2.0",
2138 complexity: "O(1) per member asked about",
2139 summary: "Answer each member's position as a standard eleven character geohash.",
2140 group: "geo",
2141 },
2142 Spec {
2143 name: "geosearch",
2144 arity: -7,
2145 flags: READ_SLOW,
2146 first_key: 1,
2147 last_key: 1,
2148 step: 1,
2149 acl: AC_GEO_READ,
2150 since: "6.2.0",
2151 complexity: "O(N+log(M)) with N the members in the boxes searched",
2152 summary: "Find the members inside a circle or a rectangle around a point.",
2153 group: "geo",
2154 },
2155 Spec {
2156 name: "geosearchstore",
2157 arity: -8,
2158 flags: WRITE_OOM,
2159 first_key: 1,
2160 last_key: 2,
2161 step: 1,
2162 acl: AC_GEO_WRITE,
2163 since: "6.2.0",
2164 complexity: "O(N+log(M)) with N the members in the boxes searched",
2165 summary: "Run a search and write what it found into another key.",
2166 group: "geo",
2167 },
2168 Spec {
2169 name: "georadius",
2170 arity: -6,
2171 flags: WRITE_MOVABLE,
2172 first_key: 1,
2173 last_key: 1,
2174 step: 1,
2175 acl: AC_GEO_WRITE,
2176 since: "3.2.0",
2177 complexity: "O(N+log(M)) with N the members in the boxes searched",
2178 summary: "The older spelling of a circular search, which can also store.",
2179 group: "geo",
2180 },
2181 Spec {
2182 name: "georadius_ro",
2183 arity: -6,
2184 flags: READ_SLOW,
2185 first_key: 1,
2186 last_key: 1,
2187 step: 1,
2188 acl: AC_GEO_READ,
2189 since: "3.2.10",
2190 complexity: "O(N+log(M)) with N the members in the boxes searched",
2191 summary: "GEORADIUS without the store options, so a replica can serve it.",
2192 group: "geo",
2193 },
2194 Spec {
2195 name: "georadiusbymember",
2196 arity: -5,
2197 flags: WRITE_MOVABLE,
2198 first_key: 1,
2199 last_key: 1,
2200 step: 1,
2201 acl: AC_GEO_WRITE,
2202 since: "3.2.0",
2203 complexity: "O(N+log(M)) with N the members in the boxes searched",
2204 summary: "The same search centred on a member rather than on a point.",
2205 group: "geo",
2206 },
2207 Spec {
2208 name: "georadiusbymember_ro",
2209 arity: -5,
2210 flags: READ_SLOW,
2211 first_key: 1,
2212 last_key: 1,
2213 step: 1,
2214 acl: AC_GEO_READ,
2215 since: "3.2.10",
2216 complexity: "O(N+log(M)) with N the members in the boxes searched",
2217 summary: "GEORADIUSBYMEMBER without the store options.",
2218 group: "geo",
2219 },
2220 Spec {
2222 name: "g.nadd",
2223 arity: -3,
2224 flags: WRITE_FAST_OOM,
2225 first_key: 1,
2226 last_key: 1,
2227 step: 1,
2228 acl: AC_GRAPH_WRITE_FAST,
2229 since: "8.8.0",
2230 complexity: "O(N) with N the fields written",
2231 summary: "Write a node and its properties, creating it if it is new.",
2232 group: "graph",
2233 },
2234 Spec {
2235 name: "g.nget",
2236 arity: 3,
2237 flags: READ_FAST,
2238 first_key: 1,
2239 last_key: 1,
2240 step: 1,
2241 acl: AC_GRAPH_READ_FAST,
2242 since: "8.8.0",
2243 complexity: "O(N) with N the fields on the node",
2244 summary: "Every property on a node.",
2245 group: "graph",
2246 },
2247 Spec {
2248 name: "g.ndel",
2249 arity: 3,
2250 flags: WRITE_FAST,
2251 first_key: 1,
2252 last_key: 1,
2253 step: 1,
2254 acl: AC_GRAPH_WRITE_FAST,
2255 since: "8.8.0",
2256 complexity: "O(E) with E the edges on the node",
2257 summary: "Delete a node and every edge that touches it.",
2258 group: "graph",
2259 },
2260 Spec {
2261 name: "g.eadd",
2262 arity: -5,
2263 flags: WRITE_FAST_OOM,
2264 first_key: 1,
2265 last_key: 1,
2266 step: 1,
2267 acl: AC_GRAPH_WRITE_FAST,
2268 since: "8.8.0",
2269 complexity: "O(D) with D the outgoing degree under the label",
2270 summary: "Write an edge and its properties, creating either end if it is new.",
2271 group: "graph",
2272 },
2273 Spec {
2274 name: "g.edel",
2275 arity: 5,
2276 flags: WRITE_FAST,
2277 first_key: 1,
2278 last_key: 1,
2279 step: 1,
2280 acl: AC_GRAPH_WRITE_FAST,
2281 since: "8.8.0",
2282 complexity: "O(D) with D the outgoing degree under the label",
2283 summary: "Delete one edge between two nodes under a label.",
2284 group: "graph",
2285 },
2286 Spec {
2287 name: "g.out",
2288 arity: -4,
2289 flags: READ_FAST,
2290 first_key: 1,
2291 last_key: 1,
2292 step: 1,
2293 acl: AC_GRAPH_READ_FAST,
2294 since: "8.8.0",
2295 complexity: "O(N) with N the page asked for",
2296 summary: "Outgoing neighbours under a label, a page at a time.",
2297 group: "graph",
2298 },
2299 Spec {
2300 name: "g.in",
2301 arity: -4,
2302 flags: READ_FAST,
2303 first_key: 1,
2304 last_key: 1,
2305 step: 1,
2306 acl: AC_GRAPH_READ_FAST,
2307 since: "8.8.0",
2308 complexity: "O(N) with N the page asked for",
2309 summary: "Incoming neighbours under a label, a page at a time.",
2310 group: "graph",
2311 },
2312 Spec {
2313 name: "g.deg",
2314 arity: -4,
2315 flags: READ_FAST,
2316 first_key: 1,
2317 last_key: 1,
2318 step: 1,
2319 acl: AC_GRAPH_READ_FAST,
2320 since: "8.8.0",
2321 complexity: "O(1)",
2322 summary: "How many edges a node has under a label.",
2323 group: "graph",
2324 },
2325 Spec {
2326 name: "g.neigh",
2327 arity: -4,
2328 flags: READ_SLOW,
2329 first_key: 1,
2330 last_key: 1,
2331 step: 1,
2332 acl: AC_GRAPH_READ_SLOW,
2333 since: "8.8.0",
2334 complexity: "O(V + E) over the ball the depth reaches",
2335 summary: "Everything reachable within a depth, each node once.",
2336 group: "graph",
2337 },
2338 Spec {
2339 name: "g.path",
2340 arity: -4,
2341 flags: READ_SLOW,
2342 first_key: 1,
2343 last_key: 1,
2344 step: 1,
2345 acl: AC_GRAPH_READ_SLOW,
2346 since: "8.8.0",
2347 complexity: "O(b^(d/2)) with b the branching factor and d the distance",
2348 summary: "A shortest path between two nodes, searched from both ends.",
2349 group: "graph",
2350 },
2351 Spec {
2353 name: "arset",
2354 arity: -4,
2355 flags: WRITE_FAST_OOM,
2356 first_key: 1,
2357 last_key: 1,
2358 step: 1,
2359 acl: AC_ARRAY_WRITE_FAST,
2360 since: "8.8.0",
2361 complexity: "O(N) with N the number of values",
2362 summary: "Write values into consecutive positions from an index.",
2363 group: "array",
2364 },
2365 Spec {
2366 name: "armset",
2367 arity: -4,
2368 flags: WRITE_FAST_OOM,
2369 first_key: 1,
2370 last_key: 1,
2371 step: 1,
2372 acl: AC_ARRAY_WRITE_FAST,
2373 since: "8.8.0",
2374 complexity: "O(N) with N the number of pairs",
2375 summary: "Write index and value pairs, which need not be neighbours.",
2376 group: "array",
2377 },
2378 Spec {
2379 name: "arget",
2380 arity: 3,
2381 flags: READ_FAST,
2382 first_key: 1,
2383 last_key: 1,
2384 step: 1,
2385 acl: AC_ARRAY_READ_FAST,
2386 since: "8.8.0",
2387 complexity: "O(1)",
2388 summary: "The value at one index, or a null if nothing is there.",
2389 group: "array",
2390 },
2391 Spec {
2392 name: "armget",
2393 arity: -3,
2394 flags: READ_FAST,
2395 first_key: 1,
2396 last_key: 1,
2397 step: 1,
2398 acl: AC_ARRAY_READ_FAST,
2399 since: "8.8.0",
2400 complexity: "O(N) with N the number of indices",
2401 summary: "The values at the indices named, in the order named.",
2402 group: "array",
2403 },
2404 Spec {
2405 name: "argetrange",
2406 arity: 4,
2407 flags: READ_SLOW,
2408 first_key: 1,
2409 last_key: 1,
2410 step: 1,
2411 acl: AC_ARRAY_READ_SLOW,
2412 since: "8.8.0",
2413 complexity: "O(N) with N the length of the range",
2414 summary: "One reply per position between two indices, holes included.",
2415 group: "array",
2416 },
2417 Spec {
2418 name: "arlen",
2419 arity: 2,
2420 flags: READ_FAST,
2421 first_key: 1,
2422 last_key: 1,
2423 step: 1,
2424 acl: AC_ARRAY_READ_FAST,
2425 since: "8.8.0",
2426 complexity: "O(1)",
2427 summary: "The highest populated index plus one.",
2428 group: "array",
2429 },
2430 Spec {
2431 name: "arcount",
2432 arity: 2,
2433 flags: READ_FAST,
2434 first_key: 1,
2435 last_key: 1,
2436 step: 1,
2437 acl: AC_ARRAY_READ_FAST,
2438 since: "8.8.0",
2439 complexity: "O(1)",
2440 summary: "How many indices hold something.",
2441 group: "array",
2442 },
2443 Spec {
2444 name: "ardel",
2445 arity: -3,
2446 flags: WRITE_FAST,
2447 first_key: 1,
2448 last_key: 1,
2449 step: 1,
2450 acl: AC_ARRAY_WRITE_FAST,
2451 since: "8.8.0",
2452 complexity: "O(N) with N the number of indices",
2453 summary: "Empty the indices named and say how many held something.",
2454 group: "array",
2455 },
2456 Spec {
2457 name: "ardelrange",
2458 arity: -4,
2459 flags: WRITE_SLOW,
2460 first_key: 1,
2461 last_key: 1,
2462 step: 1,
2463 acl: AC_ARRAY_WRITE_SLOW,
2464 since: "8.8.0",
2465 complexity: "O(N) with N the elements touched, not the span asked for",
2466 summary: "Empty one or more ranges of indices.",
2467 group: "array",
2468 },
2469 Spec {
2470 name: "arinsert",
2471 arity: -3,
2472 flags: WRITE_FAST_OOM,
2473 first_key: 1,
2474 last_key: 1,
2475 step: 1,
2476 acl: AC_ARRAY_WRITE_FAST,
2477 since: "8.8.0",
2478 complexity: "O(N) with N the number of values",
2479 summary: "Append values at the insert cursor.",
2480 group: "array",
2481 },
2482 Spec {
2483 name: "arring",
2484 arity: -4,
2485 flags: WRITE_OOM,
2486 first_key: 1,
2487 last_key: 1,
2488 step: 1,
2489 acl: AC_ARRAY_WRITE_SLOW,
2490 since: "8.8.0",
2491 complexity: "O(N) with N the values, plus the ring size when it changes",
2492 summary: "Append values into a ring of the given size.",
2493 group: "array",
2494 },
2495 Spec {
2496 name: "arnext",
2497 arity: 2,
2498 flags: READ_FAST,
2499 first_key: 1,
2500 last_key: 1,
2501 step: 1,
2502 acl: AC_ARRAY_READ_FAST,
2503 since: "8.8.0",
2504 complexity: "O(1)",
2505 summary: "The index the next append would write to.",
2506 group: "array",
2507 },
2508 Spec {
2509 name: "arseek",
2510 arity: 3,
2511 flags: WRITE_FAST,
2512 first_key: 1,
2513 last_key: 1,
2514 step: 1,
2515 acl: AC_ARRAY_WRITE_FAST,
2516 since: "8.8.0",
2517 complexity: "O(1)",
2518 summary: "Point the insert cursor at an index.",
2519 group: "array",
2520 },
2521 Spec {
2522 name: "arlastitems",
2523 arity: -3,
2524 flags: READ_SLOW,
2525 first_key: 1,
2526 last_key: 1,
2527 step: 1,
2528 acl: AC_ARRAY_READ_SLOW,
2529 since: "8.8.0",
2530 complexity: "O(N) with N the count asked for",
2531 summary: "The newest positions from the insert cursor, holes included.",
2532 group: "array",
2533 },
2534 Spec {
2535 name: "arscan",
2536 arity: -4,
2537 flags: READ_SLOW,
2538 first_key: 1,
2539 last_key: 1,
2540 step: 1,
2541 acl: AC_ARRAY_READ_SLOW,
2542 since: "8.8.0",
2543 complexity: "O(N) with N the elements found, not the span asked for",
2544 summary: "Index and value pairs for what a range holds, skipping holes.",
2545 group: "array",
2546 },
2547 Spec {
2548 name: "argrep",
2549 arity: -6,
2550 flags: READ_SLOW,
2551 first_key: 1,
2552 last_key: 1,
2553 step: 1,
2554 acl: AC_ARRAY_READ_SLOW,
2555 since: "8.8.0",
2556 complexity: "O(P * C) with P the positions visited and C the cost of the predicates on one element",
2557 summary: "The indexes in a range whose elements answer a set of textual predicates.",
2558 group: "array",
2559 },
2560 Spec {
2561 name: "arop",
2562 arity: -5,
2563 flags: READ_SLOW,
2564 first_key: 1,
2565 last_key: 1,
2566 step: 1,
2567 acl: AC_ARRAY_READ_SLOW,
2568 since: "8.8.0",
2569 complexity: "O(N) with N the elements found, not the span asked for",
2570 summary: "One number out of a range, added up or compared or counted.",
2571 group: "array",
2572 },
2573 Spec {
2574 name: "arinfo",
2575 arity: -2,
2576 flags: READ_SLOW,
2577 first_key: 1,
2578 last_key: 1,
2579 step: 1,
2580 acl: AC_ARRAY_READ_SLOW,
2581 since: "8.8.0",
2582 complexity: "O(1), or O(N) with N the slices when FULL is given",
2583 summary: "The shape of the array, and what its slices look like.",
2584 group: "array",
2585 },
2586 Spec {
2588 name: "xadd",
2589 arity: -5,
2590 flags: WRITE_FAST_OOM,
2591 first_key: 1,
2592 last_key: 1,
2593 step: 1,
2594 acl: AC_STREAM_WRITE_FAST,
2595 since: "5.0.0",
2596 complexity: "O(1) for the append, plus what a trim removes.",
2597 summary: "Append an entry and answer with the ID it got.",
2598 group: "stream",
2599 },
2600 Spec {
2601 name: "xlen",
2602 arity: 2,
2603 flags: READ_FAST,
2604 first_key: 1,
2605 last_key: 1,
2606 step: 1,
2607 acl: AC_STREAM_READ_FAST,
2608 since: "5.0.0",
2609 complexity: "O(1)",
2610 summary: "How many entries the stream holds.",
2611 group: "stream",
2612 },
2613 Spec {
2614 name: "xdel",
2615 arity: -3,
2616 flags: WRITE_FAST,
2617 first_key: 1,
2618 last_key: 1,
2619 step: 1,
2620 acl: AC_STREAM_WRITE_FAST,
2621 since: "5.0.0",
2622 complexity: "O(1) per ID.",
2623 summary: "Remove entries by ID and say how many were there.",
2624 group: "stream",
2625 },
2626 Spec {
2627 name: "xdelex",
2628 arity: -5,
2629 flags: WRITE_FAST,
2630 first_key: 1,
2631 last_key: 1,
2632 step: 1,
2633 acl: AC_STREAM_WRITE_FAST,
2634 since: "8.2.0",
2635 complexity: "O(1) per ID.",
2636 summary: "Remove entries by ID, saying what to do about the groups.",
2637 group: "stream",
2638 },
2639 Spec {
2640 name: "xackdel",
2641 arity: -6,
2642 flags: WRITE_FAST,
2643 first_key: 1,
2644 last_key: 1,
2645 step: 1,
2646 acl: AC_STREAM_WRITE_FAST,
2647 since: "8.2.0",
2648 complexity: "O(1) per ID.",
2649 summary: "Acknowledge entries for a group and remove them.",
2650 group: "stream",
2651 },
2652 Spec {
2653 name: "xnack",
2654 arity: -7,
2655 flags: WRITE_FAST,
2656 first_key: 1,
2657 last_key: 1,
2658 step: 1,
2659 acl: AC_STREAM_WRITE_FAST,
2660 since: "8.8.0",
2661 complexity: "O(1) per ID.",
2662 summary: "Give entries back to the group for somebody else to claim.",
2663 group: "stream",
2664 },
2665 Spec {
2666 name: "xtrim",
2667 arity: -4,
2668 flags: WRITE_SLOW,
2669 first_key: 1,
2670 last_key: 1,
2671 step: 1,
2672 acl: AC_STREAM_WRITE_SLOW,
2673 since: "5.0.0",
2674 complexity: "O(N) in the entries removed.",
2675 summary: "Cut the stream down to a length or a minimum ID.",
2676 group: "stream",
2677 },
2678 Spec {
2679 name: "xrange",
2680 arity: -4,
2681 flags: READ_SLOW,
2682 first_key: 1,
2683 last_key: 1,
2684 step: 1,
2685 acl: AC_STREAM_READ_SLOW,
2686 since: "5.0.0",
2687 complexity: "O(N) in the entries returned.",
2688 summary: "The entries between two IDs, oldest first.",
2689 group: "stream",
2690 },
2691 Spec {
2692 name: "xrevrange",
2693 arity: -4,
2694 flags: READ_SLOW,
2695 first_key: 1,
2696 last_key: 1,
2697 step: 1,
2698 acl: AC_STREAM_READ_SLOW,
2699 since: "5.0.0",
2700 complexity: "O(N) in the entries returned.",
2701 summary: "The entries between two IDs, newest first.",
2702 group: "stream",
2703 },
2704 Spec {
2705 name: "xread",
2706 arity: -4,
2707 flags: READ_BLOCKING_MOVABLE,
2708 first_key: 0,
2709 last_key: 0,
2710 step: 0,
2711 acl: AC_STREAM_BLOCKING_READ,
2712 since: "5.0.0",
2713 complexity: "O(N) in the entries returned.",
2714 summary: "Read from one or more streams, waiting if asked to.",
2715 group: "stream",
2716 },
2717 Spec {
2718 name: "xreadgroup",
2719 arity: -7,
2720 flags: WRITE_BLOCKING_MOVABLE,
2721 first_key: 0,
2722 last_key: 0,
2723 step: 0,
2724 acl: AC_STREAM_BLOCKING_WRITE,
2725 since: "5.0.0",
2726 complexity: "O(N) in the entries returned.",
2727 summary: "Read as part of a consumer group, waiting if asked to.",
2728 group: "stream",
2729 },
2730 Spec {
2731 name: "xack",
2732 arity: -4,
2733 flags: WRITE_FAST,
2734 first_key: 1,
2735 last_key: 1,
2736 step: 1,
2737 acl: AC_STREAM_WRITE_FAST,
2738 since: "5.0.0",
2739 complexity: "O(1) per ID.",
2740 summary: "Drop entries from a group's pending list.",
2741 group: "stream",
2742 },
2743 Spec {
2744 name: "xsetid",
2745 arity: -3,
2746 flags: WRITE_FAST_OOM,
2747 first_key: 1,
2748 last_key: 1,
2749 step: 1,
2750 acl: AC_STREAM_WRITE_FAST,
2751 since: "5.0.0",
2752 complexity: "O(1)",
2753 summary: "Set the last ID, the entries added and the max deleted ID.",
2754 group: "stream",
2755 },
2756 Spec {
2757 name: "xgroup",
2758 arity: -2,
2759 flags: &[],
2760 first_key: 0,
2761 last_key: 0,
2762 step: 0,
2763 acl: AC_STREAM_CONTAINER,
2764 since: "5.0.0",
2765 complexity: "O(1) for all subcommands except DESTROY, which frees the group's pending list.",
2766 summary: "Make, move and unmake consumer groups.",
2767 group: "stream",
2768 },
2769 Spec {
2770 name: "xinfo",
2771 arity: -2,
2772 flags: &[],
2773 first_key: 0,
2774 last_key: 0,
2775 step: 0,
2776 acl: AC_STREAM_CONTAINER,
2777 since: "5.0.0",
2778 complexity: "O(1), or O(N) with N the entries and pending entries shown when FULL is given.",
2779 summary: "What a stream, its groups and its consumers look like.",
2780 group: "stream",
2781 },
2782 Spec {
2783 name: "xpending",
2784 arity: -3,
2785 flags: READ_SLOW,
2786 first_key: 1,
2787 last_key: 1,
2788 step: 1,
2789 acl: AC_STREAM_READ_SLOW,
2790 since: "5.0.0",
2791 complexity: "O(1) for the summary, O(N) in the entries returned for the list.",
2792 summary: "What a group has handed out and not had acknowledged.",
2793 group: "stream",
2794 },
2795 Spec {
2796 name: "xclaim",
2797 arity: -6,
2798 flags: WRITE_FAST,
2799 first_key: 1,
2800 last_key: 1,
2801 step: 1,
2802 acl: AC_STREAM_WRITE_FAST,
2803 since: "5.0.0",
2804 complexity: "O(1) per ID.",
2805 summary: "Move named pending entries to another consumer.",
2806 group: "stream",
2807 },
2808 Spec {
2809 name: "xautoclaim",
2810 arity: -6,
2811 flags: WRITE_FAST,
2812 first_key: 1,
2813 last_key: 1,
2814 step: 1,
2815 acl: AC_STREAM_WRITE_FAST,
2816 since: "6.2.0",
2817 complexity: "O(1) per entry claimed, plus what it skips getting there.",
2818 summary: "Sweep a group's pending list and take what has gone idle.",
2819 group: "stream",
2820 },
2821 Spec {
2823 name: "del",
2824 arity: -2,
2825 flags: &["write"],
2826 first_key: 1,
2827 last_key: -1,
2828 step: 1,
2829 acl: AC_KEY_WRITE_SLOW,
2830 since: "1.0.0",
2831 complexity: "O(N) in the number of keys.",
2832 summary: "Delete keys and say how many were there.",
2833 group: "keyspace",
2834 },
2835 Spec {
2836 name: "unlink",
2837 arity: -2,
2838 flags: &["write", "fast"],
2839 first_key: 1,
2840 last_key: -1,
2841 step: 1,
2842 acl: AC_KEY_WRITE_FAST,
2843 since: "4.0.0",
2844 complexity: "O(1) per key, since the freeing is not on this thread.",
2845 summary: "Delete keys and free them out of the way of the reply.",
2846 group: "keyspace",
2847 },
2848 Spec {
2849 name: "exists",
2850 arity: -2,
2851 flags: READ_FAST,
2852 first_key: 1,
2853 last_key: -1,
2854 step: 1,
2855 acl: AC_KEY_READ,
2856 since: "1.0.0",
2857 complexity: "O(N) in the number of keys.",
2858 summary: "Count how many of these keys are there, naming one twice counting twice.",
2859 group: "keyspace",
2860 },
2861 Spec {
2862 name: "type",
2863 arity: 2,
2864 flags: READ_FAST,
2865 first_key: 1,
2866 last_key: 1,
2867 step: 1,
2868 acl: AC_KEY_READ,
2869 since: "1.0.0",
2870 complexity: "O(1)",
2871 summary: "What kind of value is under a key, or none.",
2872 group: "keyspace",
2873 },
2874 Spec {
2875 name: "touch",
2876 arity: -2,
2877 flags: READ_FAST,
2878 first_key: 1,
2879 last_key: -1,
2880 step: 1,
2881 acl: AC_KEY_READ,
2882 since: "3.2.1",
2883 complexity: "O(N) in the number of keys.",
2884 summary: "Count how many of these keys are there, and move them up the eviction order.",
2885 group: "keyspace",
2886 },
2887 Spec {
2891 name: "scan",
2892 arity: -2,
2893 flags: &["readonly"],
2894 first_key: 0,
2895 last_key: 0,
2896 step: 0,
2897 acl: AC_KEY_READ_SLOW,
2898 since: "2.8.0",
2899 complexity: "O(1) a call, O(N) for a whole iteration",
2900 summary: "Walk part of the keyspace and say where to carry on from.",
2901 group: "keyspace",
2902 },
2903 Spec {
2904 name: "keys",
2905 arity: 2,
2906 flags: &["readonly"],
2907 first_key: 0,
2908 last_key: 0,
2909 step: 0,
2910 acl: AC_KEY_READ_ALL,
2911 since: "1.0.0",
2912 complexity: "O(N) in the number of keys.",
2913 summary: "Every key matching a pattern, in one reply.",
2914 group: "keyspace",
2915 },
2916 Spec {
2917 name: "randomkey",
2918 arity: 1,
2919 flags: &["readonly"],
2920 first_key: 0,
2921 last_key: 0,
2922 step: 0,
2923 acl: AC_KEY_READ_SLOW,
2924 since: "1.0.0",
2925 complexity: "O(1)",
2926 summary: "One key from the database, chosen at random.",
2927 group: "keyspace",
2928 },
2929 Spec {
2932 name: "rename",
2933 arity: 3,
2934 flags: &["write"],
2935 first_key: 1,
2936 last_key: 2,
2937 step: 1,
2938 acl: AC_KEY_WRITE_SLOW,
2939 since: "1.0.0",
2940 complexity: "O(1)",
2941 summary: "Move a key to another name, over whatever was there.",
2942 group: "keyspace",
2943 },
2944 Spec {
2945 name: "renamenx",
2946 arity: 3,
2947 flags: WRITE_FAST,
2948 first_key: 1,
2949 last_key: 2,
2950 step: 1,
2951 acl: AC_KEY_WRITE_FAST,
2952 since: "1.0.0",
2953 complexity: "O(1)",
2954 summary: "Move a key to another name, but only if that name is free.",
2955 group: "keyspace",
2956 },
2957 Spec {
2960 name: "copy",
2961 arity: -3,
2962 flags: &["write", "denyoom"],
2963 first_key: 1,
2964 last_key: 2,
2965 step: 1,
2966 acl: AC_KEY_WRITE_SLOW,
2967 since: "6.2.0",
2968 complexity: "O(N) in the size of the value.",
2969 summary: "Copy a value to another key, in this database or another one.",
2970 group: "keyspace",
2971 },
2972 Spec {
2977 name: "move",
2978 arity: 3,
2979 flags: WRITE_FAST,
2980 first_key: 1,
2981 last_key: 1,
2982 step: 1,
2983 acl: AC_KEY_WRITE_FAST,
2984 since: "1.0.0",
2985 complexity: "O(1)",
2986 summary: "Move a key to another database, if it is not already there.",
2987 group: "keyspace",
2988 },
2989 Spec {
2992 name: "wait",
2993 arity: 3,
2994 flags: &["blocking"],
2995 first_key: 0,
2996 last_key: 0,
2997 step: 0,
2998 acl: AC_WAIT,
2999 since: "3.0.0",
3000 complexity: "O(1)",
3001 summary: "Wait for this connection's writes to reach a number of replicas.",
3002 group: "keyspace",
3003 },
3004 Spec {
3005 name: "waitaof",
3006 arity: 4,
3007 flags: &["blocking"],
3008 first_key: 0,
3009 last_key: 0,
3010 step: 0,
3011 acl: AC_WAIT,
3012 since: "7.2.0",
3013 complexity: "O(1)",
3014 summary: "Wait for this connection's writes to reach the append only files.",
3015 group: "keyspace",
3016 },
3017 Spec {
3021 name: "dump",
3022 arity: 2,
3023 flags: READ_SLOW,
3024 first_key: 1,
3025 last_key: 1,
3026 step: 1,
3027 acl: AC_KEY_READ_SLOW,
3028 since: "2.6.0",
3029 complexity: "O(1) to find the key, then O(N) in the size of the value.",
3030 summary: "Serialize a value into a payload another server can load.",
3031 group: "keyspace",
3032 },
3033 Spec {
3034 name: "restore",
3035 arity: -4,
3036 flags: &["write", "denyoom"],
3037 first_key: 1,
3038 last_key: 1,
3039 step: 1,
3040 acl: AC_RESTORE,
3041 since: "2.6.0",
3042 complexity: "O(1) to find the key, then O(N) in the size of the payload.",
3043 summary: "Create a key from a payload produced by DUMP.",
3044 group: "keyspace",
3045 },
3046 Spec {
3051 name: "migrate",
3052 arity: -6,
3053 flags: MIGRATE_FLAGS,
3054 first_key: 3,
3055 last_key: 3,
3056 step: 1,
3057 acl: AC_RESTORE,
3058 since: "2.6.0",
3059 complexity: "A DUMP and a DEL here, a RESTORE there, and the bytes in between.",
3060 summary: "Move a key to another server.",
3061 group: "keyspace",
3062 },
3063 Spec {
3069 name: "sort",
3070 arity: -2,
3071 flags: WRITE_MOVABLE,
3072 first_key: 1,
3073 last_key: 1,
3074 step: 1,
3075 acl: AC_SORT_WRITE,
3076 since: "1.0.0",
3077 complexity: "O(N+M*log(M)) with N elements and M returned.",
3078 summary: "Sort a list, set or sorted set, optionally into another key.",
3079 group: "keyspace",
3080 },
3081 Spec {
3082 name: "sort_ro",
3083 arity: -2,
3084 flags: READ_MOVABLE,
3085 first_key: 1,
3086 last_key: 1,
3087 step: 1,
3088 acl: AC_SORT_READ,
3089 since: "7.0.0",
3090 complexity: "O(N+M*log(M)) with N elements and M returned.",
3091 summary: "Sort a list, set or sorted set, without the STORE option.",
3092 group: "keyspace",
3093 },
3094 Spec {
3097 name: "expire",
3098 arity: -3,
3099 flags: WRITE_FAST,
3100 first_key: 1,
3101 last_key: 1,
3102 step: 1,
3103 acl: AC_KEY_WRITE_FAST,
3104 since: "1.0.0",
3105 complexity: "O(1)",
3106 summary: "Put a deadline on a key, counted in seconds from now.",
3107 group: "keyspace",
3108 },
3109 Spec {
3110 name: "pexpire",
3111 arity: -3,
3112 flags: WRITE_FAST,
3113 first_key: 1,
3114 last_key: 1,
3115 step: 1,
3116 acl: AC_KEY_WRITE_FAST,
3117 since: "2.6.0",
3118 complexity: "O(1)",
3119 summary: "Put a deadline on a key, counted in milliseconds from now.",
3120 group: "keyspace",
3121 },
3122 Spec {
3123 name: "expireat",
3124 arity: -3,
3125 flags: WRITE_FAST,
3126 first_key: 1,
3127 last_key: 1,
3128 step: 1,
3129 acl: AC_KEY_WRITE_FAST,
3130 since: "1.2.0",
3131 complexity: "O(1)",
3132 summary: "Put a deadline on a key, as a unix time in seconds.",
3133 group: "keyspace",
3134 },
3135 Spec {
3136 name: "pexpireat",
3137 arity: -3,
3138 flags: WRITE_FAST,
3139 first_key: 1,
3140 last_key: 1,
3141 step: 1,
3142 acl: AC_KEY_WRITE_FAST,
3143 since: "2.6.0",
3144 complexity: "O(1)",
3145 summary: "Put a deadline on a key, as a unix time in milliseconds.",
3146 group: "keyspace",
3147 },
3148 Spec {
3149 name: "persist",
3150 arity: 2,
3151 flags: WRITE_FAST,
3152 first_key: 1,
3153 last_key: 1,
3154 step: 1,
3155 acl: AC_KEY_WRITE_FAST,
3156 since: "2.2.0",
3157 complexity: "O(1)",
3158 summary: "Take a key's deadline off, so it stops being temporary.",
3159 group: "keyspace",
3160 },
3161 Spec {
3162 name: "ttl",
3163 arity: 2,
3164 flags: READ_FAST,
3165 first_key: 1,
3166 last_key: 1,
3167 step: 1,
3168 acl: AC_KEY_READ,
3169 since: "1.0.0",
3170 complexity: "O(1)",
3171 summary: "How many seconds a key has left, -1 with no deadline, -2 if gone.",
3172 group: "keyspace",
3173 },
3174 Spec {
3175 name: "pttl",
3176 arity: 2,
3177 flags: READ_FAST,
3178 first_key: 1,
3179 last_key: 1,
3180 step: 1,
3181 acl: AC_KEY_READ,
3182 since: "2.6.0",
3183 complexity: "O(1)",
3184 summary: "How many milliseconds a key has left, -1 with no deadline, -2 if gone.",
3185 group: "keyspace",
3186 },
3187 Spec {
3188 name: "expiretime",
3189 arity: 2,
3190 flags: READ_FAST,
3191 first_key: 1,
3192 last_key: 1,
3193 step: 1,
3194 acl: AC_KEY_READ,
3195 since: "7.0.0",
3196 complexity: "O(1)",
3197 summary: "When a key falls due, as a unix time in seconds.",
3198 group: "keyspace",
3199 },
3200 Spec {
3201 name: "pexpiretime",
3202 arity: 2,
3203 flags: READ_FAST,
3204 first_key: 1,
3205 last_key: 1,
3206 step: 1,
3207 acl: AC_KEY_READ,
3208 since: "7.0.0",
3209 complexity: "O(1)",
3210 summary: "When a key falls due, as a unix time in milliseconds.",
3211 group: "keyspace",
3212 },
3213 Spec {
3217 name: "object",
3218 arity: -2,
3219 flags: &[],
3220 first_key: 0,
3221 last_key: 0,
3222 step: 0,
3223 acl: &["@slow"],
3224 since: "2.2.3",
3225 complexity: "O(1)",
3226 summary: "Look at the machinery under a key rather than at its value.",
3227 group: "keyspace",
3228 },
3229 Spec {
3233 name: "script",
3234 arity: -2,
3235 flags: &[],
3236 first_key: 0,
3237 last_key: 0,
3238 step: 0,
3239 acl: &["@slow"],
3240 since: "2.6.0",
3241 complexity: "O(1) for the subcommands that are here.",
3242 summary: "The script cache, which is empty and stays empty until M6.",
3243 group: "scripting",
3244 },
3245 Spec {
3246 name: "function",
3247 arity: -2,
3248 flags: &[],
3249 first_key: 0,
3250 last_key: 0,
3251 step: 0,
3252 acl: &["@slow"],
3253 since: "7.0.0",
3254 complexity: "O(1) for the subcommands that are here.",
3255 summary: "The function libraries, of which there are none until M6.",
3256 group: "scripting",
3257 },
3258 Spec {
3260 name: "ping",
3261 arity: -1,
3262 flags: &["fast"],
3263 first_key: 0,
3264 last_key: 0,
3265 step: 0,
3266 acl: AC_CONN,
3267 since: "1.0.0",
3268 complexity: "O(1)",
3269 summary: "Ask whether the server is answering.",
3270 group: "connection",
3271 },
3272 Spec {
3273 name: "echo",
3274 arity: 2,
3275 flags: &["loading", "stale", "fast"],
3276 first_key: 0,
3277 last_key: 0,
3278 step: 0,
3279 acl: AC_CONN,
3280 since: "1.0.0",
3281 complexity: "O(1)",
3282 summary: "Send a string back unchanged.",
3283 group: "connection",
3284 },
3285 Spec {
3286 name: "hello",
3287 arity: -1,
3288 flags: &[
3289 "noscript",
3290 "loading",
3291 "stale",
3292 "fast",
3293 "no_auth",
3294 "allow_busy",
3295 ],
3296 first_key: 0,
3297 last_key: 0,
3298 step: 0,
3299 acl: AC_CONN,
3300 since: "6.0.0",
3301 complexity: "O(1)",
3302 summary: "Agree on a protocol version and describe the server.",
3303 group: "connection",
3304 },
3305 Spec {
3306 name: "select",
3307 arity: 2,
3308 flags: &["loading", "stale", "fast"],
3309 first_key: 0,
3310 last_key: 0,
3311 step: 0,
3312 acl: AC_CONN,
3313 since: "1.0.0",
3314 complexity: "O(1)",
3315 summary: "Choose which database this connection works in.",
3316 group: "connection",
3317 },
3318 Spec {
3319 name: "reset",
3320 arity: 1,
3321 flags: &[
3322 "noscript",
3323 "loading",
3324 "stale",
3325 "fast",
3326 "no_auth",
3327 "allow_busy",
3328 ],
3329 first_key: 0,
3330 last_key: 0,
3331 step: 0,
3332 acl: AC_CONN,
3333 since: "6.2.0",
3334 complexity: "O(1)",
3335 summary: "Put the connection back the way it was opened.",
3336 group: "connection",
3337 },
3338 Spec {
3339 name: "quit",
3340 arity: -1,
3341 flags: &[
3342 "noscript",
3343 "loading",
3344 "stale",
3345 "fast",
3346 "no_auth",
3347 "allow_busy",
3348 ],
3349 first_key: 0,
3350 last_key: 0,
3351 step: 0,
3352 acl: AC_CONN,
3353 since: "1.0.0",
3354 complexity: "O(1)",
3355 summary: "Close the connection after the replies already queued.",
3356 group: "connection",
3357 },
3358 Spec {
3364 name: "command",
3365 arity: -1,
3366 flags: &["loading", "stale"],
3367 first_key: 0,
3368 last_key: 0,
3369 step: 0,
3370 acl: &["@slow", "@connection"],
3371 since: "2.8.13",
3372 complexity: "O(N) with N the number of commands",
3373 summary: "What this server can do, in the shape client libraries read.",
3374 group: "server",
3375 },
3376 Spec {
3377 name: "config",
3378 arity: -2,
3379 flags: &[],
3380 first_key: 0,
3381 last_key: 0,
3382 step: 0,
3383 acl: &["@slow"],
3384 since: "2.0.0",
3385 complexity: "Depends on the subcommand.",
3386 summary: "Read and change the settings a running server exposes.",
3387 group: "server",
3388 },
3389 Spec {
3390 name: "info",
3391 arity: -1,
3392 flags: &["loading", "stale"],
3393 first_key: 0,
3394 last_key: 0,
3395 step: 0,
3396 acl: &["@slow", "@dangerous"],
3397 since: "1.0.0",
3398 complexity: "O(1)",
3399 summary: "The server's own numbers, in sections.",
3400 group: "server",
3401 },
3402 Spec {
3403 name: "dbsize",
3404 arity: 1,
3405 flags: READ_FAST,
3406 first_key: 0,
3407 last_key: 0,
3408 step: 0,
3409 acl: AC_KEY_READ,
3410 since: "1.0.0",
3411 complexity: "O(1)",
3412 summary: "How many keys are in the database this connection is on.",
3413 group: "server",
3414 },
3415 Spec {
3416 name: "flushall",
3417 arity: -1,
3418 flags: &["write"],
3419 first_key: 0,
3420 last_key: 0,
3421 step: 0,
3422 acl: AC_KEY_FLUSH,
3423 since: "1.0.0",
3424 complexity: "O(N) in the number of keys in every database.",
3425 summary: "Empty every database.",
3426 group: "server",
3427 },
3428 Spec {
3429 name: "flushdb",
3430 arity: -1,
3431 flags: &["write"],
3432 first_key: 0,
3433 last_key: 0,
3434 step: 0,
3435 acl: AC_KEY_FLUSH,
3436 since: "1.0.0",
3437 complexity: "O(N) in the number of keys in this database.",
3438 summary: "Empty the database this connection is on.",
3439 group: "server",
3440 },
3441 Spec {
3445 name: "swapdb",
3446 arity: 3,
3447 flags: WRITE_FAST,
3448 first_key: 0,
3449 last_key: 0,
3450 step: 0,
3451 acl: AC_SWAPDB,
3452 since: "4.0.0",
3453 complexity: "O(N) in the number of clients watching or blocked on either.",
3454 summary: "Swap two databases, so every client on one sees the other.",
3455 group: "server",
3456 },
3457 Spec {
3461 name: "time",
3462 arity: 1,
3463 flags: &["loading", "stale", "fast"],
3464 first_key: 0,
3465 last_key: 0,
3466 step: 0,
3467 acl: &["@fast"],
3468 since: "2.6.0",
3469 complexity: "O(1)",
3470 summary: "The server's clock, as seconds and microseconds.",
3471 group: "server",
3472 },
3473];
3474
3475const MIN_LEN: usize = 3;
3481const MAX_LEN: usize = 20;
3482
3483const SLOTS: usize = 512;
3490
3491const FREE: u16 = u16::MAX;
3496
3497const MIX: u64 = 0xf9e1_1b95_048d_6851;
3520
3521const fn key_of(name: &[u8]) -> Option<u32> {
3543 if name.len() < MIN_LEN || name.len() > MAX_LEN {
3544 return None;
3545 }
3546 let last = name.len() - 1;
3547 Some(
3548 name.len() as u32
3549 | ((name[0] | 0x20) as u32) << 8
3550 | ((name[1] | 0x20) as u32) << 16
3551 | ((name[last] | 0x20) as u32) << 24,
3552 )
3553}
3554
3555const fn slot_of(key: u32) -> usize {
3557 ((key as u64).wrapping_mul(MIX) >> 55) as usize & (SLOTS - 1)
3558}
3559
3560const INDEX: [u16; SLOTS] = index();
3566
3567const fn index() -> [u16; SLOTS] {
3568 let mut out = [FREE; SLOTS];
3569 let mut i = 0;
3570 while i < COMMANDS.len() {
3571 let key = match key_of(COMMANDS[i].name.as_bytes()) {
3572 Some(key) => key,
3573 None => panic!("a command name is outside MIN_LEN..=MAX_LEN"),
3574 };
3575 let mut at = slot_of(key);
3576 while out[at] != FREE {
3577 at = (at + 1) & (SLOTS - 1);
3578 }
3579 out[at] = i as u16;
3580 i += 1;
3581 }
3582 out
3583}
3584
3585#[must_use]
3606pub fn lookup(name: &[u8]) -> Option<&'static Spec> {
3607 at(lookup_index(name))
3608}
3609
3610#[must_use]
3623pub fn lookup_index(name: &[u8]) -> u16 {
3624 let Some(key) = key_of(name) else {
3625 return FREE;
3626 };
3627 let mut at = slot_of(key);
3628 loop {
3629 let i = INDEX[at];
3630 if i == FREE {
3631 return FREE;
3632 }
3633 if COMMANDS[i as usize]
3634 .name
3635 .as_bytes()
3636 .eq_ignore_ascii_case(name)
3637 {
3638 return i;
3639 }
3640 at = (at + 1) & (SLOTS - 1);
3641 }
3642}
3643
3644#[must_use]
3649pub fn at(i: u16) -> Option<&'static Spec> {
3650 COMMANDS.get(i as usize)
3651}
3652
3653#[must_use]
3658pub const fn count() -> usize {
3659 COMMANDS.len()
3660}
3661
3662#[must_use]
3675pub fn index_of(spec: &'static Spec) -> usize {
3676 let front = COMMANDS.as_ptr().addr();
3677 let here = std::ptr::from_ref(spec).addr();
3678 (here - front) / size_of::<Spec>()
3679}
3680
3681#[must_use]
3688pub fn name_at(at: usize) -> &'static str {
3689 COMMANDS[at].name
3690}
3691
3692#[must_use]
3694pub fn arity_ok(spec: &Spec, n: usize) -> bool {
3695 let n = n as i32;
3696 if spec.arity >= 0 {
3697 n == spec.arity
3698 } else {
3699 n >= -spec.arity
3700 }
3701}
3702
3703#[cfg(test)]
3704mod tests {
3705 use super::*;
3706
3707 #[test]
3708 fn every_name_is_lower_case_and_appears_once() {
3709 let mut seen = std::collections::BTreeSet::new();
3710 for c in COMMANDS {
3711 assert_eq!(
3712 c.name,
3713 c.name.to_lowercase(),
3714 "{} is not lower case",
3715 c.name
3716 );
3717 assert!(seen.insert(c.name), "{} is in the table twice", c.name);
3718 }
3719 }
3720
3721 #[test]
3727 fn a_spec_knows_where_it_is_in_the_table() {
3728 assert_eq!(count(), COMMANDS.len());
3729 for (want, spec) in COMMANDS.iter().enumerate() {
3730 assert_eq!(index_of(spec), want, "{} is at the wrong index", spec.name);
3731 }
3732 assert_eq!(
3733 index_of(lookup(b"get").unwrap()),
3734 index_of(lookup(b"GET").unwrap())
3735 );
3736 }
3737
3738 #[test]
3739 fn lookup_ignores_case_and_does_not_match_a_prefix() {
3740 assert_eq!(lookup(b"GET").unwrap().name, "get");
3741 assert_eq!(lookup(b"gEt").unwrap().name, "get");
3742 assert!(lookup(b"ge").is_none());
3743 assert!(lookup(b"gets").is_none());
3744 }
3745
3746 #[test]
3753 fn every_command_is_findable_by_its_own_name() {
3754 for spec in COMMANDS {
3755 let found = lookup(spec.name.as_bytes()).expect(spec.name);
3756 assert_eq!(
3757 index_of(found),
3758 index_of(spec),
3759 "{} found the wrong spec",
3760 spec.name
3761 );
3762 assert_eq!(
3763 lookup(spec.name.to_ascii_uppercase().as_bytes()).map(index_of),
3764 Some(index_of(spec)),
3765 "{} is not found in upper case",
3766 spec.name,
3767 );
3768 }
3769 }
3770
3771 #[test]
3773 fn a_name_that_cannot_be_a_command_is_rejected_on_its_shape() {
3774 assert!(lookup(b"").is_none());
3775 assert!(key_of(b"").is_none());
3776 assert!(key_of(&[b'g'; 256]).is_none());
3777 assert!(lookup(&[b'g'; 256]).is_none());
3778 assert!(lookup(b"9et").is_none());
3779 }
3780
3781 #[test]
3783 fn a_key_folds_the_case_and_nothing_else() {
3784 assert_eq!(key_of(b"get"), key_of(b"GET"));
3785 assert_eq!(key_of(b"get"), key_of(b"gEt"));
3786 assert_ne!(key_of(b"get"), key_of(b"set"), "other first byte");
3787 assert_ne!(key_of(b"get"), key_of(b"gxt"), "other second byte");
3788 assert_ne!(key_of(b"get"), key_of(b"gex"), "other last byte");
3789 assert_ne!(key_of(b"get"), key_of(b"gett"), "other length");
3790 }
3791
3792 #[test]
3802 fn no_command_is_more_than_two_slots_from_where_it_wants_to_be() {
3803 let mut worst = 0;
3804 let mut total = 0;
3805 for spec in COMMANDS {
3806 let key = key_of(spec.name.as_bytes()).expect(spec.name);
3807 let home = slot_of(key);
3808 let mut at = home;
3809 let mut steps = 0;
3810 while INDEX[at] as usize != index_of(spec) {
3811 at = (at + 1) & (SLOTS - 1);
3812 steps += 1;
3813 assert!(steps < SLOTS, "{} is not in the index at all", spec.name);
3814 }
3815 worst = worst.max(steps);
3816 total += steps;
3817 }
3818 assert!(worst <= 2, "worst probe is {worst} slots");
3819 assert!(
3820 total <= 56,
3821 "{total} extra slots walked over the whole table"
3822 );
3823 }
3824
3825 #[test]
3827 fn the_index_is_not_full() {
3828 assert!(
3829 COMMANDS.len() < SLOTS,
3830 "the probe would never find an empty"
3831 );
3832 assert!(
3833 COMMANDS.len() < FREE as usize,
3834 "an index would collide with FREE"
3835 );
3836 let free = INDEX.iter().filter(|&&i| i == FREE).count();
3837 assert_eq!(free, SLOTS - COMMANDS.len());
3838 }
3839
3840 #[test]
3841 fn arity_counts_the_command_name() {
3842 let get = lookup(b"get").unwrap();
3843 assert!(!arity_ok(get, 1));
3844 assert!(arity_ok(get, 2));
3845 assert!(!arity_ok(get, 3));
3846
3847 let set = lookup(b"set").unwrap();
3849 assert!(!arity_ok(set, 2));
3850 assert!(arity_ok(set, 3));
3851 assert!(arity_ok(set, 9));
3852 }
3853
3854 #[test]
3857 fn the_pair_commands_step_two_keys_at_a_time() {
3858 for name in [b"mset".as_slice(), b"msetnx"] {
3859 let c = lookup(name).unwrap();
3860 assert_eq!((c.first_key, c.last_key, c.step), (1, -1, 2));
3861 }
3862 let mget = lookup(b"mget").unwrap();
3863 assert_eq!((mget.first_key, mget.last_key, mget.step), (1, -1, 1));
3864 let msetex = lookup(b"msetex").unwrap();
3867 assert_eq!((msetex.first_key, msetex.last_key, msetex.step), (0, 0, 0));
3868 assert!(msetex.flags.contains(&"movablekeys"));
3869 }
3870}