depot_client_types/
lib.rs1pub const HEAD_FENCE_MISMATCH_GROUP: &str = "depot";
4pub const HEAD_FENCE_MISMATCH_CODE: &str = "head_fence_mismatch";
5
6pub fn is_head_fence_mismatch(group: &str, code: &str) -> bool {
7 group == HEAD_FENCE_MISMATCH_GROUP && code == HEAD_FENCE_MISMATCH_CODE
8}
9
10pub const SHARD_SIZE: u32 = 64;
14
15pub const COMMIT_SEGMENT_MAX_SHARDS: u32 = 5;
17
18pub const MAX_COMMIT_DIRTY_PAGES: usize = 32_768;
34
35pub fn segment_start_for_page(pgno: u32) -> u32 {
37 pgno / SHARD_SIZE * SHARD_SIZE
38}
39
40pub fn cut_page_segments<T>(pages: &[T], pgno_of: impl Fn(&T) -> u32) -> Vec<(u32, &[T])> {
49 let mut segments = Vec::new();
50 let mut start = 0;
51 while start < pages.len() {
52 let first_shard = pgno_of(&pages[start]) / SHARD_SIZE;
53 let shard_limit = first_shard.saturating_add(COMMIT_SEGMENT_MAX_SHARDS);
56 let end = pages[start..]
57 .iter()
58 .position(|page| pgno_of(page) / SHARD_SIZE >= shard_limit)
59 .map_or(pages.len(), |offset| start + offset);
60 segments.push((first_shard * SHARD_SIZE, &pages[start..end]));
61 start = end;
62 }
63
64 segments
65}
66
67#[derive(Clone, Debug, PartialEq)]
68pub enum BindParam {
69 Null,
70 Integer(i64),
71 Float(f64),
72 Text(String),
73 Blob(Vec<u8>),
74}
75
76#[derive(Clone, Debug, PartialEq)]
77pub struct ExecResult {
78 pub changes: i64,
79}
80
81#[derive(Clone, Debug, PartialEq)]
82pub struct QueryResult {
83 pub columns: Vec<String>,
84 pub rows: Vec<Vec<ColumnValue>>,
85}
86
87#[derive(Clone, Debug, PartialEq)]
88pub struct ExecuteResult {
89 pub columns: Vec<String>,
90 pub rows: Vec<Vec<ColumnValue>>,
91 pub changes: i64,
92 pub last_insert_row_id: Option<i64>,
93}
94
95impl ExecuteResult {
96 pub fn into_query_result(self) -> QueryResult {
97 QueryResult {
98 columns: self.columns,
99 rows: self.rows,
100 }
101 }
102
103 pub fn into_exec_result(self) -> ExecResult {
104 ExecResult {
105 changes: self.changes,
106 }
107 }
108}
109
110#[derive(Clone, Debug, PartialEq)]
111pub enum ColumnValue {
112 Null,
113 Integer(i64),
114 Float(f64),
115 Text(String),
116 Blob(Vec<u8>),
117}
118
119#[cfg(test)]
120mod tests {
121 use super::{ColumnValue, ExecuteResult};
122
123 #[test]
124 fn execute_result_preserves_result_and_route_metadata() {
125 let result = ExecuteResult {
126 columns: vec!["id".to_owned(), "name".to_owned()],
127 rows: vec![vec![
128 ColumnValue::Integer(7),
129 ColumnValue::Text("alpha".to_owned()),
130 ]],
131 changes: 3,
132 last_insert_row_id: Some(42),
133 };
134
135 assert_eq!(result.columns, vec!["id", "name"]);
136 assert_eq!(
137 result.rows,
138 vec![vec![
139 ColumnValue::Integer(7),
140 ColumnValue::Text("alpha".to_owned())
141 ]]
142 );
143 assert_eq!(result.changes, 3);
144 assert_eq!(result.last_insert_row_id, Some(42));
145 }
146
147 #[test]
148 fn execute_result_projects_query_and_exec_results() {
149 let result = ExecuteResult {
150 columns: vec!["count".to_owned()],
151 rows: vec![vec![ColumnValue::Integer(9)]],
152 changes: 2,
153 last_insert_row_id: Some(10),
154 };
155
156 let query_result = result.clone().into_query_result();
157 assert_eq!(query_result.columns, vec!["count"]);
158 assert_eq!(query_result.rows, vec![vec![ColumnValue::Integer(9)]]);
159
160 let exec_result = result.into_exec_result();
161 assert_eq!(exec_result.changes, 2);
162 }
163}