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