ZRANGE key start stop — returns members in rank range [start, stop] (0-based).
(
cmd: &RespCommand,
session: &RespSession,
state: &SharedState,
)
| 140 | |
| 141 | /// ZRANGE key start stop — returns members in rank range [start, stop] (0-based). |
| 142 | pub(super) async fn handle_zrange( |
| 143 | cmd: &RespCommand, |
| 144 | session: &RespSession, |
| 145 | state: &SharedState, |
| 146 | ) -> RespValue { |
| 147 | if cmd.argc() < 2 { |
| 148 | return RespValue::err("ERR wrong number of arguments for 'zrange' command"); |
| 149 | } |
| 150 | |
| 151 | let start = cmd.arg_i64(0).unwrap_or(0); |
| 152 | let stop = cmd.arg_i64(1).unwrap_or(-1); |
| 153 | |
| 154 | // Fetch enough entries to cover the range. |
| 155 | // ZRANGE uses 0-based inclusive indices; negative means from end. |
| 156 | // We'll fetch top_k with k = stop + 1 (or all if stop is negative). |
| 157 | let k = if stop < 0 { |
| 158 | u32::MAX |
| 159 | } else { |
| 160 | (stop + 1) as u32 |
| 161 | }; |
| 162 | |
| 163 | let plan = PhysicalPlan::Kv(KvOp::SortedIndexTopK { |
| 164 | index_name: session.collection.clone(), |
| 165 | k, |
| 166 | }); |
| 167 | |
| 168 | match dispatch_kv(state, session, plan).await { |
| 169 | Ok(resp) if resp.status == Status::Ok => { |
| 170 | let rows: Vec<serde_json::Value> = |
| 171 | sonic_rs::from_slice(&resp.payload).unwrap_or_default(); |
| 172 | let total = rows.len() as i64; |
| 173 | |
| 174 | let actual_start = if start < 0 { |
| 175 | (total + start).max(0) as usize |
| 176 | } else { |
| 177 | start as usize |
| 178 | }; |
| 179 | let actual_stop = if stop < 0 { |
| 180 | (total + stop).max(0) as usize |
| 181 | } else { |
| 182 | (stop as usize).min(rows.len().saturating_sub(1)) |
| 183 | }; |
| 184 | |
| 185 | if actual_start > actual_stop || actual_start >= rows.len() { |
| 186 | return RespValue::array(vec![]); |
| 187 | } |
| 188 | |
| 189 | let items: Vec<RespValue> = rows[actual_start..=actual_stop] |
| 190 | .iter() |
| 191 | .filter_map(|row| { |
| 192 | row.get("key") |
| 193 | .and_then(|v| v.as_str()) |
| 194 | .map(|k| RespValue::bulk(k.as_bytes().to_vec())) |
| 195 | }) |
| 196 | .collect(); |
| 197 | RespValue::array(items) |
| 198 | } |
| 199 | Ok(_) => RespValue::array(vec![]), |
no test coverage detected