List all GSIs declared for a collection.
(&self, tenant_id: u64, collection: &str)
| 268 | |
| 269 | /// List all GSIs declared for a collection. |
| 270 | pub fn list_indexes(&self, tenant_id: u64, collection: &str) -> crate::Result<Vec<GsiMeta>> { |
| 271 | let prefix = format!("{tenant_id}:{collection}:"); |
| 272 | let end = format!("{tenant_id}:{collection}:\u{ffff}"); |
| 273 | |
| 274 | let read_txn = self.db.begin_read().map_err(|e| crate::Error::Storage { |
| 275 | engine: "gsi".into(), |
| 276 | detail: format!("read: {e}"), |
| 277 | })?; |
| 278 | let table = read_txn |
| 279 | .open_table(GSI_META) |
| 280 | .map_err(|e| crate::Error::Storage { |
| 281 | engine: "gsi".into(), |
| 282 | detail: format!("open meta: {e}"), |
| 283 | })?; |
| 284 | |
| 285 | let range = |
| 286 | table |
| 287 | .range(prefix.as_str()..end.as_str()) |
| 288 | .map_err(|e| crate::Error::Storage { |
| 289 | engine: "gsi".into(), |
| 290 | detail: format!("range: {e}"), |
| 291 | })?; |
| 292 | |
| 293 | let mut result = Vec::new(); |
| 294 | for entry in range { |
| 295 | let entry = entry.map_err(|e| crate::Error::Storage { |
| 296 | engine: "gsi".into(), |
| 297 | detail: format!("entry: {e}"), |
| 298 | })?; |
| 299 | match zerompk::from_msgpack::<GsiMeta>(entry.1.value()) { |
| 300 | Ok(meta) => result.push(meta), |
| 301 | Err(e) => { |
| 302 | tracing::warn!( |
| 303 | key = %entry.0.value(), |
| 304 | error = %e, |
| 305 | "GSI metadata deserialization failed, skipping entry" |
| 306 | ); |
| 307 | } |
| 308 | } |
| 309 | } |
| 310 | Ok(result) |
| 311 | } |
| 312 | |
| 313 | /// Check if a GSI covers all projected columns (covering index query). |
| 314 | /// |