@@ -2848,7 +2848,7 @@ typedef enum {
2848
2848
2849
2849
typedef struct zrange_result_handler zrange_result_handler ;
2850
2850
2851
- typedef void (* zrangeResultBeginFunction )(zrange_result_handler * c );
2851
+ typedef void (* zrangeResultBeginFunction )(zrange_result_handler * c , long length );
2852
2852
typedef void (* zrangeResultFinalizeFunction )(
2853
2853
zrange_result_handler * c , size_t result_count );
2854
2854
typedef void (* zrangeResultEmitCBufferFunction )(
@@ -2876,8 +2876,22 @@ struct zrange_result_handler {
2876
2876
zrangeResultEmitLongLongFunction emitResultFromLongLong ;
2877
2877
};
2878
2878
2879
- /* Result handler methods for responding the ZRANGE to clients. */
2880
- static void zrangeResultBeginClient (zrange_result_handler * handler ) {
2879
+ /* Result handler methods for responding the ZRANGE to clients.
2880
+ * length can be used to provide the result length in advance (avoids deferred reply overhead).
2881
+ * length can be set to -1 if the result length is not know in advance.
2882
+ */
2883
+ static void zrangeResultBeginClient (zrange_result_handler * handler , long length ) {
2884
+ if (length > 0 ) {
2885
+ /* In case of WITHSCORES, respond with a single array in RESP2, and
2886
+ * nested arrays in RESP3. We can't use a map response type since the
2887
+ * client library needs to know to respect the order. */
2888
+ if (handler -> withscores && (handler -> client -> resp == 2 )) {
2889
+ length *= 2 ;
2890
+ }
2891
+ addReplyArrayLen (handler -> client , length );
2892
+ handler -> userdata = NULL ;
2893
+ return ;
2894
+ }
2881
2895
handler -> userdata = addReplyDeferredLen (handler -> client );
2882
2896
}
2883
2897
@@ -2912,6 +2926,9 @@ static void zrangeResultEmitLongLongToClient(zrange_result_handler *handler,
2912
2926
static void zrangeResultFinalizeClient (zrange_result_handler * handler ,
2913
2927
size_t result_count )
2914
2928
{
2929
+ /* If the reply size was know at start there's nothing left to do */
2930
+ if (!handler -> userdata )
2931
+ return ;
2915
2932
/* In case of WITHSCORES, respond with a single array in RESP2, and
2916
2933
* nested arrays in RESP3. We can't use a map response type since the
2917
2934
* client library needs to know to respect the order. */
@@ -2923,8 +2940,9 @@ static void zrangeResultFinalizeClient(zrange_result_handler *handler,
2923
2940
}
2924
2941
2925
2942
/* Result handler methods for storing the ZRANGESTORE to a zset. */
2926
- static void zrangeResultBeginStore (zrange_result_handler * handler )
2943
+ static void zrangeResultBeginStore (zrange_result_handler * handler , long length )
2927
2944
{
2945
+ UNUSED (length );
2928
2946
handler -> dstobj = createZsetListpackObject ();
2929
2947
}
2930
2948
@@ -3019,18 +3037,19 @@ void genericZrangebyrankCommand(zrange_result_handler *handler,
3019
3037
if (end < 0 ) end = llen + end ;
3020
3038
if (start < 0 ) start = 0 ;
3021
3039
3022
- handler -> beginResultEmission (handler );
3023
3040
3024
3041
/* Invariant: start >= 0, so this test will be true when end < 0.
3025
3042
* The range is empty when start > end or start >= length. */
3026
3043
if (start > end || start >= llen ) {
3044
+ handler -> beginResultEmission (handler , 0 );
3027
3045
handler -> finalizeResultEmission (handler , 0 );
3028
3046
return ;
3029
3047
}
3030
3048
if (end >= llen ) end = llen - 1 ;
3031
3049
rangelen = (end - start )+ 1 ;
3032
3050
result_cardinality = rangelen ;
3033
3051
3052
+ handler -> beginResultEmission (handler , rangelen );
3034
3053
if (zobj -> encoding == OBJ_ENCODING_LISTPACK ) {
3035
3054
unsigned char * zl = zobj -> ptr ;
3036
3055
unsigned char * eptr , * sptr ;
@@ -3124,7 +3143,7 @@ void genericZrangebyscoreCommand(zrange_result_handler *handler,
3124
3143
int reverse ) {
3125
3144
unsigned long rangelen = 0 ;
3126
3145
3127
- handler -> beginResultEmission (handler );
3146
+ handler -> beginResultEmission (handler , -1 );
3128
3147
3129
3148
/* For invalid offset, return directly. */
3130
3149
if (offset > 0 && offset >= (long )zsetLength (zobj )) {
@@ -3409,7 +3428,7 @@ void genericZrangebylexCommand(zrange_result_handler *handler,
3409
3428
{
3410
3429
unsigned long rangelen = 0 ;
3411
3430
3412
- handler -> beginResultEmission (handler );
3431
+ handler -> beginResultEmission (handler , -1 );
3413
3432
3414
3433
if (zobj -> encoding == OBJ_ENCODING_LISTPACK ) {
3415
3434
unsigned char * zl = zobj -> ptr ;
@@ -3647,7 +3666,7 @@ void zrangeGenericCommand(zrange_result_handler *handler, int argc_start, int st
3647
3666
zobj = lookupKeyRead (c -> db , key );
3648
3667
if (zobj == NULL ) {
3649
3668
if (store ) {
3650
- handler -> beginResultEmission (handler );
3669
+ handler -> beginResultEmission (handler , -1 );
3651
3670
handler -> finalizeResultEmission (handler , 0 );
3652
3671
} else {
3653
3672
addReply (c , shared .emptyarray );
0 commit comments