1mod page_bytes;
4
5pub use page_bytes::PageBytes;
6
7pub const HEAD_FENCE_MISMATCH_GROUP: &str = "depot";
8pub const HEAD_FENCE_MISMATCH_CODE: &str = "head_fence_mismatch";
9
10pub fn is_head_fence_mismatch(group: &str, code: &str) -> bool {
11 group == HEAD_FENCE_MISMATCH_GROUP && code == HEAD_FENCE_MISMATCH_CODE
12}
13
14pub const TRANSACTION_TOO_LARGE_GROUP: &str = "sqlite";
17pub const TRANSACTION_TOO_LARGE_CODE: &str = "transaction_too_large";
18
19pub fn is_transaction_too_large(group: &str, code: &str) -> bool {
20 group == TRANSACTION_TOO_LARGE_GROUP && code == TRANSACTION_TOO_LARGE_CODE
21}
22
23pub fn storage_overload_retry_after_ms(group: &str, code: &str, message: &str) -> Option<u64> {
27 if group != "depot" || code != "overloaded" {
28 return None;
29 }
30 let hint = message.split_once("retry_after_ms=").and_then(|(_, rest)| {
31 let end = rest
32 .find(|c: char| !c.is_ascii_digit())
33 .unwrap_or(rest.len());
34 rest[..end].parse::<u64>().ok()
35 });
36 Some(hint.unwrap_or(100))
37}
38
39pub const SHARD_SIZE: u32 = 64;
43
44pub const COMMIT_SEGMENT_MAX_SHARDS: u32 = 5;
46
47pub const MAX_COMMIT_DIRTY_PAGES: usize = 32_768;
51
52pub fn segment_start_for_page(pgno: u32) -> u32 {
54 pgno / SHARD_SIZE * SHARD_SIZE
55}
56
57pub fn cut_page_segments<T>(pages: &[T], pgno_of: impl Fn(&T) -> u32) -> Vec<(u32, &[T])> {
65 let mut segments = Vec::new();
66 let mut start = 0;
67 while start < pages.len() {
68 let first_shard = pgno_of(&pages[start]) / SHARD_SIZE;
69 let shard_limit = first_shard.saturating_add(COMMIT_SEGMENT_MAX_SHARDS);
72 let end = pages[start..]
73 .iter()
74 .position(|page| pgno_of(page) / SHARD_SIZE >= shard_limit)
75 .map_or(pages.len(), |offset| start + offset);
76 segments.push((first_shard * SHARD_SIZE, &pages[start..end]));
77 start = end;
78 }
79
80 segments
81}
82
83#[derive(Clone, Debug, PartialEq)]
84pub enum BindParam {
85 Null,
86 Integer(i64),
87 Float(f64),
88 Text(String),
89 Blob(Vec<u8>),
90}
91
92#[derive(Clone, Debug, PartialEq)]
93pub struct ExecResult {
94 pub changes: i64,
95}
96
97#[derive(Clone, Debug, PartialEq)]
98pub struct QueryResult {
99 pub columns: Vec<String>,
100 pub rows: Vec<Vec<ColumnValue>>,
101}
102
103#[derive(Clone, Debug, PartialEq)]
104pub struct ExecuteResult {
105 pub columns: Vec<String>,
106 pub rows: Vec<Vec<ColumnValue>>,
107 pub changes: i64,
108 pub last_insert_row_id: Option<i64>,
109}
110
111impl ExecuteResult {
112 pub fn into_query_result(self) -> QueryResult {
113 QueryResult {
114 columns: self.columns,
115 rows: self.rows,
116 }
117 }
118
119 pub fn into_exec_result(self) -> ExecResult {
120 ExecResult {
121 changes: self.changes,
122 }
123 }
124}
125
126#[derive(Clone, Debug, PartialEq)]
127pub enum ColumnValue {
128 Null,
129 Integer(i64),
130 Float(f64),
131 Text(String),
132 Blob(Vec<u8>),
133}