reifydb_store_multi/hot/sqlite/
query.rs1use std::ops::Bound;
17
18use reifydb_core::common::CommitVersion;
19use rusqlite::{Result as SqliteResult, ToSql, types};
20
21#[inline]
22pub(super) fn version_to_bytes(version: CommitVersion) -> [u8; 8] {
23 version.0.to_be_bytes()
24}
25
26pub(super) fn build_versioned_range_query(
37 table_name: &str,
38 start: Bound<&[u8]>,
39 end: Bound<&[u8]>,
40 version: CommitVersion,
41 reverse: bool,
42 limit: usize,
43) -> (String, Vec<QueryParam>) {
44 let mut conditions = Vec::new();
45 let mut params: Vec<QueryParam> = Vec::new();
46
47 match start {
48 Bound::Included(v) => {
49 conditions.push(format!("key >= ?{}", params.len() + 1));
50 params.push(QueryParam::Blob(v.to_vec()));
51 }
52 Bound::Excluded(v) => {
53 conditions.push(format!("key > ?{}", params.len() + 1));
54 params.push(QueryParam::Blob(v.to_vec()));
55 }
56 Bound::Unbounded => {}
57 }
58
59 match end {
60 Bound::Included(v) => {
61 conditions.push(format!("key <= ?{}", params.len() + 1));
62 params.push(QueryParam::Blob(v.to_vec()));
63 }
64 Bound::Excluded(v) => {
65 conditions.push(format!("key < ?{}", params.len() + 1));
66 params.push(QueryParam::Blob(v.to_vec()));
67 }
68 Bound::Unbounded => {}
69 }
70
71 conditions.push(format!("version <= ?{}", params.len() + 1));
72 params.push(QueryParam::Version(version_to_bytes(version)));
73
74 let where_clause = format!(" WHERE {}", conditions.join(" AND "));
75
76 let order = if reverse {
77 "DESC"
78 } else {
79 "ASC"
80 };
81
82 let query = format!(
84 "SELECT key, version, value FROM (\
85 SELECT key, version, value, \
86 ROW_NUMBER() OVER (PARTITION BY key ORDER BY version DESC) as rn \
87 FROM \"{}\"{}\
88 ) WHERE rn = 1 ORDER BY key {} LIMIT {}",
89 table_name, where_clause, order, limit
90 );
91
92 (query, params)
93}
94
95#[derive(Debug, Clone)]
97pub(super) enum QueryParam {
98 Blob(Vec<u8>),
99 Version([u8; 8]),
100}
101
102impl ToSql for QueryParam {
103 fn to_sql(&self) -> SqliteResult<types::ToSqlOutput<'_>> {
104 match self {
105 QueryParam::Blob(v) => v.to_sql(),
106 QueryParam::Version(v) => v.as_slice().to_sql(),
107 }
108 }
109}