Skip to main content

infinite_db/infinitedb_core/
query.rs

1use serde::{Deserialize, Serialize};
2use super::address::{DimensionVector, RevisionId, SpaceId};
3use super::snapshot::SnapshotId;
4
5/// An axis-aligned bounding box in N-dimensional space.
6/// Records whose point lies within [min, max] on every axis are included.
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct SpatialRange {
9    pub min: DimensionVector,
10    pub max: DimensionVector,
11}
12
13impl SpatialRange {
14    /// Create an axis-aligned range with inclusive bounds.
15    pub fn new(min: DimensionVector, max: DimensionVector) -> Self {
16        assert_eq!(min.dims(), max.dims(), "Range bounds must have equal dimensions");
17        Self { min, max }
18    }
19}
20
21/// A read query against a snapshot.
22/// Queries are pure descriptors — the storage layer executes them.
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct Query {
25    pub space: SpaceId,
26    pub snapshot: SnapshotId,
27    /// Spatial bounds to filter records by. None = all records in the space.
28    pub range: Option<SpatialRange>,
29    /// Precomputed Hilbert key interval [min, max] for block pruning.
30    /// Takes precedence over `range` when set; None falls back to `range`.
31    pub key_range: Option<(u128, u128)>,
32    /// Only return records at or before this revision.
33    /// Defaults to the snapshot's own revision when None.
34    pub as_of: Option<RevisionId>,
35    /// Include tombstoned (deleted) records in results.
36    pub include_tombstones: bool,
37}
38
39impl Query {
40    /// Build a query pinned to a specific space and snapshot.
41    pub fn new(space: SpaceId, snapshot: SnapshotId) -> Self {
42        Self {
43            space,
44            snapshot,
45            range: None,
46            key_range: None,
47            as_of: None,
48            include_tombstones: false,
49        }
50    }
51
52    /// Add a spatial range filter.
53    pub fn with_range(mut self, range: SpatialRange) -> Self {
54        self.range = Some(range);
55        self
56    }
57
58    /// Set a precomputed Hilbert key interval, taking precedence over `range`.
59    pub fn with_key_range(mut self, lo: u128, hi: u128) -> Self {
60        self.key_range = Some((lo, hi));
61        self
62    }
63
64    /// Restrict results to records at or before `revision`.
65    pub fn as_of(mut self, revision: RevisionId) -> Self {
66        self.as_of = Some(revision);
67        self
68    }
69
70    /// Include tombstoned records in query results.
71    pub fn include_tombstones(mut self) -> Self {
72        self.include_tombstones = true;
73        self
74    }
75
76    /// Convenience helper to set range bounds from raw coordinate vectors.
77    pub fn with_bounds(self, min: Vec<u32>, max: Vec<u32>) -> Self {
78        self.with_range(SpatialRange::new(
79            DimensionVector::new(min),
80            DimensionVector::new(max),
81        ))
82    }
83}