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    /// Borrow grouped rows.
68    #[must_use]
69    pub const fn rows(&self) -> &[GroupedRow] {
70        self.rows.as_slice()
71    }
72
73    /// Borrow optional continuation cursor bytes.
74    #[must_use]
75    pub fn continuation_cursor(&self) -> Option<&[u8]> {
76        self.continuation_cursor.as_deref()
77    }
78
79    /// Consume into grouped rows and continuation cursor bytes.
80    #[must_use]
81    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>) {
82        (self.rows, self.continuation_cursor)
83    }
84}
85
86///
87/// PagedGroupedExecutionWithTrace
88///
89/// Cursor-paged grouped execution payload plus optional route/execution trace.
90///
91
92#[derive(Clone, Debug)]
93pub struct PagedGroupedExecutionWithTrace {
94    rows: Vec<GroupedRow>,
95    continuation_cursor: Option<Vec<u8>>,
96    execution_trace: Option<ExecutionTrace>,
97}
98
99impl PagedGroupedExecutionWithTrace {
100    /// Construct one traced grouped paged execution payload.
101    #[must_use]
102    pub const fn new(
103        rows: Vec<GroupedRow>,
104        continuation_cursor: Option<Vec<u8>>,
105        execution_trace: Option<ExecutionTrace>,
106    ) -> Self {
107        Self {
108            rows,
109            continuation_cursor,
110            execution_trace,
111        }
112    }
113
114    /// Borrow grouped rows.
115    #[must_use]
116    pub const fn rows(&self) -> &[GroupedRow] {
117        self.rows.as_slice()
118    }
119
120    /// Borrow optional continuation cursor bytes.
121    #[must_use]
122    pub fn continuation_cursor(&self) -> Option<&[u8]> {
123        self.continuation_cursor.as_deref()
124    }
125
126    /// Borrow optional execution trace details.
127    #[must_use]
128    pub const fn execution_trace(&self) -> Option<&ExecutionTrace> {
129        self.execution_trace.as_ref()
130    }
131
132    /// Borrow compact execution metrics derived from the optional execution trace.
133    #[must_use]
134    pub fn execution_metrics(&self) -> Option<ExecutionMetrics> {
135        self.execution_trace.as_ref().map(ExecutionTrace::metrics)
136    }
137
138    /// Consume payload and drop trace details.
139    #[must_use]
140    pub fn into_execution(self) -> PagedGroupedExecution {
141        PagedGroupedExecution {
142            rows: self.rows,
143            continuation_cursor: self.continuation_cursor,
144        }
145    }
146
147    /// Consume into grouped rows, continuation cursor bytes, and optional trace.
148    #[must_use]
149    pub fn into_parts(self) -> (Vec<GroupedRow>, Option<Vec<u8>>, Option<ExecutionTrace>) {
150        (self.rows, self.continuation_cursor, self.execution_trace)
151    }
152}