Skip to main content

icydb_core/db/query/fluent/load/
result.rs

1use crate::{
2    db::{EntityResponse, PagedGroupedExecutionWithTrace, query::intent::QueryError},
3    traits::EntityKind,
4};
5
6///
7/// LoadQueryResult
8///
9/// Unified fluent load execution payload for scalar and grouped query shapes.
10/// Scalar queries materialize typed entity rows.
11/// Grouped queries materialize grouped rows plus continuation metadata.
12///
13#[derive(Debug)]
14pub enum LoadQueryResult<E: EntityKind> {
15    Rows(EntityResponse<E>),
16    Grouped(PagedGroupedExecutionWithTrace),
17}
18
19impl<E: EntityKind> LoadQueryResult<E> {
20    // Shared constructors keep the outward fluent load result contract owned
21    // by this facade instead of open-coding enum variants in session helpers.
22    pub(crate) const fn rows(rows: EntityResponse<E>) -> Self {
23        Self::Rows(rows)
24    }
25
26    pub(crate) const fn grouped(grouped: PagedGroupedExecutionWithTrace) -> Self {
27        Self::Grouped(grouped)
28    }
29
30    // Grouped results expose row slices, so count conversion must saturate at
31    // the fluent facade boundary instead of leaking usize into the API.
32    fn grouped_count(grouped: &PagedGroupedExecutionWithTrace) -> u32 {
33        u32::try_from(grouped.rows().len()).unwrap_or(u32::MAX)
34    }
35
36    // Shared grouped-vs-scalar mismatch errors keep the user-facing result
37    // contract owned by this facade instead of rebuilding messages per method.
38    fn grouped_rows_required_error() -> QueryError {
39        QueryError::unsupported_query(
40            "grouped queries return grouped rows; call execute() and inspect the grouped result",
41        )
42    }
43
44    fn scalar_rows_required_error() -> QueryError {
45        QueryError::unsupported_query(
46            "scalar queries return entity rows; grouped results are not available",
47        )
48    }
49
50    /// Return the number of emitted rows or groups.
51    #[must_use]
52    pub fn count(&self) -> u32 {
53        match self {
54            Self::Rows(rows) => rows.count(),
55            Self::Grouped(grouped) => Self::grouped_count(grouped),
56        }
57    }
58
59    /// Return whether no rows or groups were emitted.
60    #[must_use]
61    pub fn is_empty(&self) -> bool {
62        self.count() == 0
63    }
64
65    /// Consume this result and require scalar entity rows.
66    pub fn into_rows(self) -> Result<EntityResponse<E>, QueryError> {
67        match self {
68            Self::Rows(rows) => Ok(rows),
69            Self::Grouped(_) => Err(Self::grouped_rows_required_error()),
70        }
71    }
72
73    /// Consume this result and require grouped rows.
74    pub fn into_grouped(self) -> Result<PagedGroupedExecutionWithTrace, QueryError> {
75        match self {
76            Self::Grouped(grouped) => Ok(grouped),
77            Self::Rows(_) => Err(Self::scalar_rows_required_error()),
78        }
79    }
80}