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,
9};
10
11///
12/// GroupedRow
13///
14/// One grouped public output row: ordered grouping key values plus ordered
15/// aggregate outputs. Group and aggregate vectors preserve query declaration
16/// order at the outward API boundary.
17///
18
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub struct GroupedRow {
21    group_key: Vec<OutputValue>,
22    aggregate_values: Vec<OutputValue>,
23}
24
25impl GroupedRow {
26    /// Construct one grouped output row payload.
27    #[must_use]
28    pub fn new<I, J, K, L>(group_key: I, aggregate_values: J) -> Self
29    where
30        I: IntoIterator<Item = K>,
31        J: IntoIterator<Item = L>,
32        K: Into<OutputValue>,
33        L: Into<OutputValue>,
34    {
35        Self {
36            group_key: group_key.into_iter().map(Into::into).collect(),
37            aggregate_values: aggregate_values.into_iter().map(Into::into).collect(),
38        }
39    }
40
41    /// Borrow grouped key values.
42    #[must_use]
43    pub const fn group_key(&self) -> &[OutputValue] {
44        self.group_key.as_slice()
45    }
46
47    /// Borrow aggregate output values.
48    #[must_use]
49    pub const fn aggregate_values(&self) -> &[OutputValue] {
50        self.aggregate_values.as_slice()
51    }
52}
53
54///
55/// PagedGroupedExecution
56///
57/// Cursor-paged grouped execution payload with optional continuation cursor bytes.
58///
59
60#[derive(Clone, Debug)]
61pub struct PagedGroupedExecution {
62    rows: Vec<GroupedRow>,
63    continuation_cursor: Option<Vec<u8>>,
64}
65
66impl PagedGroupedExecution {
67    /// Construct one grouped paged execution payload.
68    #[must_use]
69    pub const fn new(rows: Vec<GroupedRow>, continuation_cursor: Option<Vec<u8>>) -> Self {
70        Self {
71            rows,
72            continuation_cursor,
73        }
74    }
75
76    /// Borrow grouped rows.
77    #[must_use]
78    pub const fn rows(&self) -> &[GroupedRow] {
79        self.rows.as_slice()
80    }
81
82    /// Borrow optional continuation cursor bytes.
83    #[must_use]
84    pub fn continuation_cursor(&self) -> Option<&[u8]> {
85        self.continuation_cursor.as_deref()
86    }
87
88    /// Consume into grouped rows and continuation cursor bytes.
89    #[must_use]
90    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>) {
91        (self.rows, self.continuation_cursor)
92    }
93}
94
95///
96/// PagedGroupedExecutionWithTrace
97///
98/// Cursor-paged grouped execution payload plus optional route/execution trace.
99///
100
101#[derive(Clone, Debug)]
102pub struct PagedGroupedExecutionWithTrace {
103    rows: Vec<GroupedRow>,
104    continuation_cursor: Option<Vec<u8>>,
105    execution_trace: Option<ExecutionTrace>,
106}
107
108impl PagedGroupedExecutionWithTrace {
109    /// Construct one traced grouped paged execution payload.
110    #[must_use]
111    pub const fn new(
112        rows: Vec<GroupedRow>,
113        continuation_cursor: Option<Vec<u8>>,
114        execution_trace: Option<ExecutionTrace>,
115    ) -> Self {
116        Self {
117            rows,
118            continuation_cursor,
119            execution_trace,
120        }
121    }
122
123    /// Borrow grouped rows.
124    #[must_use]
125    pub const fn rows(&self) -> &[GroupedRow] {
126        self.rows.as_slice()
127    }
128
129    /// Borrow optional continuation cursor bytes.
130    #[must_use]
131    pub fn continuation_cursor(&self) -> Option<&[u8]> {
132        self.continuation_cursor.as_deref()
133    }
134
135    /// Borrow optional execution trace details.
136    #[must_use]
137    pub const fn execution_trace(&self) -> Option<&ExecutionTrace> {
138        self.execution_trace.as_ref()
139    }
140
141    /// Borrow compact execution metrics derived from the optional execution trace.
142    #[must_use]
143    pub fn execution_metrics(&self) -> Option<ExecutionMetrics> {
144        self.execution_trace.as_ref().map(ExecutionTrace::metrics)
145    }
146
147    /// Consume payload and drop trace details.
148    #[must_use]
149    pub fn into_execution(self) -> PagedGroupedExecution {
150        PagedGroupedExecution {
151            rows: self.rows,
152            continuation_cursor: self.continuation_cursor,
153        }
154    }
155
156    /// Consume into grouped rows, continuation cursor bytes, and optional trace.
157    #[must_use]
158    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>, Option<ExecutionTrace>) {
159        (self.rows, self.continuation_cursor, self.execution_trace)
160    }
161}