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