* This function handles ZRANGE and ZRANGESTORE, and also the deprecated * Z[REV]RANGE[BYPOS|BYLEX] commands. * * The simple ZRANGE and ZRANGESTORE can take _AUTO in rangetype and direction, * other command pass explicit value. * * The argc_start points to the src key argument, so following syntax is like: * [BYSCORE | BYLEX] [REV] [WITHSCORES] [LIMIT offset count] */
| 3568 | * <src> <min> <max> [BYSCORE | BYLEX] [REV] [WITHSCORES] [LIMIT offset count] |
| 3569 | */ |
| 3570 | void zrangeGenericCommand(zrange_result_handler *handler, int argc_start, int store, |
| 3571 | zrange_type rangetype, zrange_direction direction) |
| 3572 | { |
| 3573 | client *c = handler->client; |
| 3574 | robj *key = c->argv[argc_start]; |
| 3575 | robj_roptr zobj; |
| 3576 | zrangespec range; |
| 3577 | zlexrangespec lexrange; |
| 3578 | int minidx = argc_start + 1; |
| 3579 | int maxidx = argc_start + 2; |
| 3580 | |
| 3581 | /* Options common to all */ |
| 3582 | long opt_start = 0; |
| 3583 | long opt_end = 0; |
| 3584 | int opt_withscores = 0; |
| 3585 | long opt_offset = 0; |
| 3586 | long opt_limit = -1; |
| 3587 | |
| 3588 | /* Step 1: Skip the <src> <min> <max> args and parse remaining optional arguments. */ |
| 3589 | for (int j=argc_start + 3; j < c->argc; j++) { |
| 3590 | int leftargs = c->argc-j-1; |
| 3591 | if (!store && !strcasecmp(szFromObj(c->argv[j]),"withscores")) { |
| 3592 | opt_withscores = 1; |
| 3593 | } else if (!strcasecmp(szFromObj(c->argv[j]),"limit") && leftargs >= 2) { |
| 3594 | if ((getLongFromObjectOrReply(c, c->argv[j+1], &opt_offset, NULL) != C_OK) || |
| 3595 | (getLongFromObjectOrReply(c, c->argv[j+2], &opt_limit, NULL) != C_OK)) |
| 3596 | { |
| 3597 | return; |
| 3598 | } |
| 3599 | j += 2; |
| 3600 | } else if (direction == ZRANGE_DIRECTION_AUTO && |
| 3601 | !strcasecmp(szFromObj(c->argv[j]),"rev")) |
| 3602 | { |
| 3603 | direction = ZRANGE_DIRECTION_REVERSE; |
| 3604 | } else if (rangetype == ZRANGE_AUTO && |
| 3605 | !strcasecmp(szFromObj(c->argv[j]),"bylex")) |
| 3606 | { |
| 3607 | rangetype = ZRANGE_LEX; |
| 3608 | } else if (rangetype == ZRANGE_AUTO && |
| 3609 | !strcasecmp(szFromObj(c->argv[j]),"byscore")) |
| 3610 | { |
| 3611 | rangetype = ZRANGE_SCORE; |
| 3612 | } else { |
| 3613 | addReplyErrorObject(c,shared.syntaxerr); |
| 3614 | return; |
| 3615 | } |
| 3616 | } |
| 3617 | |
| 3618 | /* Use defaults if not overriden by arguments. */ |
| 3619 | if (direction == ZRANGE_DIRECTION_AUTO) |
| 3620 | direction = ZRANGE_DIRECTION_FORWARD; |
| 3621 | if (rangetype == ZRANGE_AUTO) |
| 3622 | rangetype = ZRANGE_RANK; |
| 3623 | |
| 3624 | /* Check for conflicting arguments. */ |
| 3625 | if (opt_limit != -1 && rangetype == ZRANGE_RANK) { |
| 3626 | addReplyError(c,"syntax error, LIMIT is only supported in combination with either BYSCORE or BYLEX"); |
| 3627 | return; |
no test coverage detected