Skip to main content

icydb_core/db/response/
grouped.rs

1//! Module: response::grouped
2//! Responsibility: grouped paged response payload contracts.
3//! Does not own: grouped execution evaluation, route policy, or cursor token protocol.
4//! Boundary: grouped DTOs returned by session/query execution APIs.
5
6use crate::{
7    db::diagnostics::{ExecutionMetrics, ExecutionTrace},
8    value::{OutputValue, Value},
9};
10
11///
12/// RuntimeGroupedRow
13///
14/// Internal grouped runtime row carrier with ordered key and aggregate values.
15/// This stays on runtime `Value` until the session boundary materializes the
16/// public grouped output DTO.
17///
18
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub(in crate::db) struct RuntimeGroupedRow {
21    group_key: Vec<Value>,
22    aggregate_values: Vec<Value>,
23}
24
25impl RuntimeGroupedRow {
26    /// Construct one grouped runtime row payload.
27    #[must_use]
28    pub(in crate::db) const fn new(group_key: Vec<Value>, aggregate_values: Vec<Value>) -> Self {
29        Self {
30            group_key,
31            aggregate_values,
32        }
33    }
34
35    /// Borrow grouped runtime key values.
36    #[must_use]
37    pub(in crate::db) const fn group_key(&self) -> &[Value] {
38        self.group_key.as_slice()
39    }
40
41    /// Borrow grouped runtime aggregate values.
42    #[must_use]
43    pub(in crate::db) const fn aggregate_values(&self) -> &[Value] {
44        self.aggregate_values.as_slice()
45    }
46}
47
48///
49/// GroupedRow
50///
51/// One grouped public output row: ordered grouping key values plus ordered
52/// aggregate outputs. Group and aggregate vectors preserve query declaration
53/// order at the outward API boundary.
54///
55
56#[derive(Clone, Debug, Eq, PartialEq)]
57pub struct GroupedRow {
58    group_key: Vec<OutputValue>,
59    aggregate_values: Vec<OutputValue>,
60}
61
62impl GroupedRow {
63    /// Construct one grouped output row payload.
64    #[must_use]
65    pub fn new<I, J, K, L>(group_key: I, aggregate_values: J) -> Self
66    where
67        I: IntoIterator<Item = K>,
68        J: IntoIterator<Item = L>,
69        K: Into<OutputValue>,
70        L: Into<OutputValue>,
71    {
72        Self {
73            group_key: group_key.into_iter().map(Into::into).collect(),
74            aggregate_values: aggregate_values.into_iter().map(Into::into).collect(),
75        }
76    }
77
78    /// Materialize one grouped output row from the runtime grouped carrier.
79    #[must_use]
80    pub(in crate::db) fn from_runtime_row(row: RuntimeGroupedRow) -> Self {
81        Self::new(row.group_key, row.aggregate_values)
82    }
83
84    /// Borrow grouped key values.
85    #[must_use]
86    pub const fn group_key(&self) -> &[OutputValue] {
87        self.group_key.as_slice()
88    }
89
90    /// Borrow aggregate output values.
91    #[must_use]
92    pub const fn aggregate_values(&self) -> &[OutputValue] {
93        self.aggregate_values.as_slice()
94    }
95}
96
97///
98/// PagedGroupedExecution
99///
100/// Cursor-paged grouped execution payload with optional continuation cursor bytes.
101///
102
103#[derive(Clone, Debug)]
104pub struct PagedGroupedExecution {
105    rows: Vec<GroupedRow>,
106    continuation_cursor: Option<Vec<u8>>,
107}
108
109impl PagedGroupedExecution {
110    /// Construct one grouped paged execution payload.
111    #[must_use]
112    pub const fn new(rows: Vec<GroupedRow>, continuation_cursor: Option<Vec<u8>>) -> Self {
113        Self {
114            rows,
115            continuation_cursor,
116        }
117    }
118
119    /// Borrow grouped rows.
120    #[must_use]
121    pub const fn rows(&self) -> &[GroupedRow] {
122        self.rows.as_slice()
123    }
124
125    /// Borrow optional continuation cursor bytes.
126    #[must_use]
127    pub fn continuation_cursor(&self) -> Option<&[u8]> {
128        self.continuation_cursor.as_deref()
129    }
130
131    /// Consume into grouped rows and continuation cursor bytes.
132    #[must_use]
133    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>) {
134        (self.rows, self.continuation_cursor)
135    }
136}
137
138///
139/// PagedGroupedExecutionWithTrace
140///
141/// Cursor-paged grouped execution payload plus optional route/execution trace.
142///
143
144#[derive(Clone, Debug)]
145pub struct PagedGroupedExecutionWithTrace {
146    rows: Vec<GroupedRow>,
147    continuation_cursor: Option<Vec<u8>>,
148    execution_trace: Option<ExecutionTrace>,
149}
150
151impl PagedGroupedExecutionWithTrace {
152    /// Construct one traced grouped paged execution payload.
153    #[must_use]
154    pub const fn new(
155        rows: Vec<GroupedRow>,
156        continuation_cursor: Option<Vec<u8>>,
157        execution_trace: Option<ExecutionTrace>,
158    ) -> Self {
159        Self {
160            rows,
161            continuation_cursor,
162            execution_trace,
163        }
164    }
165
166    /// Borrow grouped rows.
167    #[must_use]
168    pub const fn rows(&self) -> &[GroupedRow] {
169        self.rows.as_slice()
170    }
171
172    /// Borrow optional continuation cursor bytes.
173    #[must_use]
174    pub fn continuation_cursor(&self) -> Option<&[u8]> {
175        self.continuation_cursor.as_deref()
176    }
177
178    /// Borrow optional execution trace details.
179    #[must_use]
180    pub const fn execution_trace(&self) -> Option<&ExecutionTrace> {
181        self.execution_trace.as_ref()
182    }
183
184    /// Borrow compact execution metrics derived from the optional execution trace.
185    #[must_use]
186    pub fn execution_metrics(&self) -> Option<ExecutionMetrics> {
187        self.execution_trace.as_ref().map(ExecutionTrace::metrics)
188    }
189
190    /// Consume payload and drop trace details.
191    #[must_use]
192    pub fn into_execution(self) -> PagedGroupedExecution {
193        PagedGroupedExecution {
194            rows: self.rows,
195            continuation_cursor: self.continuation_cursor,
196        }
197    }
198
199    /// Consume into grouped rows, continuation cursor bytes, and optional trace.
200    #[must_use]
201    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>, Option<ExecutionTrace>) {
202        (self.rows, self.continuation_cursor, self.execution_trace)
203    }
204}