(
&mut self,
task: &ExecutionTask,
tid: u64,
collection: &str,
field: &str,
lower: Option<&[u8]>,
upper: Option<&[u8]>,
limit: usize,
| 106 | |
| 107 | #[allow(clippy::too_many_arguments)] |
| 108 | pub(in crate::data::executor) fn execute_range_scan( |
| 109 | &mut self, |
| 110 | task: &ExecutionTask, |
| 111 | tid: u64, |
| 112 | collection: &str, |
| 113 | field: &str, |
| 114 | lower: Option<&[u8]>, |
| 115 | upper: Option<&[u8]>, |
| 116 | limit: usize, |
| 117 | ) -> Response { |
| 118 | debug!(core = self.core_id, %collection, %field, limit, "range scan"); |
| 119 | |
| 120 | // Try index-backed range scan first. |
| 121 | let results = match self |
| 122 | .sparse |
| 123 | .range_scan(tid, collection, field, lower, upper, limit) |
| 124 | { |
| 125 | Ok(r) => r, |
| 126 | Err(e) => { |
| 127 | warn!(core = self.core_id, error = %e, "sparse range scan failed"); |
| 128 | return self.response_error( |
| 129 | task, |
| 130 | ErrorCode::Internal { |
| 131 | detail: e.to_string(), |
| 132 | }, |
| 133 | ); |
| 134 | } |
| 135 | }; |
| 136 | |
| 137 | // If the index returned nothing, fall back to full scan + sort. |
| 138 | // This handles collections without a secondary index on `field`. |
| 139 | if results.is_empty() { |
| 140 | let scan_result = self.scan_collection(tid, collection, limit.max(1000)); |
| 141 | match scan_result { |
| 142 | Ok(mut docs) => { |
| 143 | super::super::document::sort::sort_rows( |
| 144 | &mut docs, |
| 145 | &[(field.to_string(), true)], |
| 146 | ); |
| 147 | docs.truncate(limit); |
| 148 | // Raw msgpack passthrough — no decode/re-encode. |
| 149 | let rows: Vec<_> = docs |
| 150 | .iter() |
| 151 | .map(|(id, val)| { |
| 152 | let mp = super::super::super::doc_format::json_to_msgpack(val); |
| 153 | (id.clone(), mp) |
| 154 | }) |
| 155 | .collect(); |
| 156 | match super::super::super::response_codec::encode_raw_document_rows(&rows) { |
| 157 | Ok(payload) => return self.response_with_payload(task, payload), |
| 158 | Err(e) => { |
| 159 | return self.response_error( |
| 160 | task, |
| 161 | ErrorCode::Internal { |
| 162 | detail: e.to_string(), |
| 163 | }, |
| 164 | ); |
| 165 | } |
no test coverage detected