Skip to main content

sz_orm_core/
sql_buffer.rs

1//! SQL 构造缓冲区抽象
2//!
3//! 当 `perf-smallstring` feature 启用时,使用 `CompactString` 作为内部缓冲区,
4//! 短字符串(≤ 23 字节)内联存储,减少堆分配。
5//! 当 feature 关闭时,退化为 `String`,零额外开销。
6
7#[cfg(feature = "perf-smallstring")]
8mod inner {
9    use compact_str::CompactString;
10
11    /// SQL 构造缓冲区
12    pub struct SqlBuffer {
13        buf: CompactString,
14    }
15
16    impl SqlBuffer {
17        /// 创建空缓冲区
18        pub fn new() -> Self {
19            Self {
20                buf: CompactString::with_capacity(0),
21            }
22        }
23
24        /// 从字符串切片创建
25        #[allow(clippy::should_implement_trait)]
26        pub fn from_str(s: &str) -> Self {
27            Self {
28                buf: CompactString::from(s),
29            }
30        }
31
32        /// 追加字符串切片
33        pub fn push_str(&mut self, s: &str) {
34            self.buf.push_str(s);
35        }
36
37        /// 追加单个字符
38        pub fn push(&mut self, c: char) {
39            self.buf.push(c);
40        }
41
42        /// 返回字符串切片
43        pub fn as_str(&self) -> &str {
44            &self.buf
45        }
46
47        /// 判断是否为空
48        pub fn is_empty(&self) -> bool {
49            self.buf.is_empty()
50        }
51
52        /// 消耗缓冲区,返回 `String`
53        pub fn into_string(self) -> String {
54            self.buf.to_string()
55        }
56
57        /// 返回已存储的字节数
58        pub fn len(&self) -> usize {
59            self.buf.len()
60        }
61    }
62
63    impl Default for SqlBuffer {
64        fn default() -> Self {
65            Self::new()
66        }
67    }
68
69    impl std::fmt::Write for SqlBuffer {
70        fn write_str(&mut self, s: &str) -> std::fmt::Result {
71            self.push_str(s);
72            Ok(())
73        }
74    }
75}
76
77#[cfg(not(feature = "perf-smallstring"))]
78mod inner {
79    /// SQL 构造缓冲区(退化为 String)
80    pub struct SqlBuffer {
81        buf: String,
82    }
83
84    impl SqlBuffer {
85        /// 创建空缓冲区
86        pub fn new() -> Self {
87            Self { buf: String::new() }
88        }
89
90        /// 从字符串切片创建
91        #[allow(clippy::should_implement_trait)]
92        pub fn from_str(s: &str) -> Self {
93            Self { buf: s.to_string() }
94        }
95
96        /// 追加字符串切片
97        pub fn push_str(&mut self, s: &str) {
98            self.buf.push_str(s);
99        }
100
101        /// 追加单个字符
102        pub fn push(&mut self, c: char) {
103            self.buf.push(c);
104        }
105
106        /// 返回字符串切片
107        pub fn as_str(&self) -> &str {
108            &self.buf
109        }
110
111        /// 判断是否为空
112        pub fn is_empty(&self) -> bool {
113            self.buf.is_empty()
114        }
115
116        /// 消耗缓冲区,返回 `String`
117        pub fn into_string(self) -> String {
118            self.buf
119        }
120
121        /// 返回已存储的字节数
122        pub fn len(&self) -> usize {
123            self.buf.len()
124        }
125    }
126
127    impl Default for SqlBuffer {
128        fn default() -> Self {
129            Self::new()
130        }
131    }
132
133    impl std::fmt::Write for SqlBuffer {
134        fn write_str(&mut self, s: &str) -> std::fmt::Result {
135            self.push_str(s);
136            Ok(())
137        }
138    }
139}
140
141pub use inner::SqlBuffer;
142
143#[cfg(test)]
144mod tests {
145    use super::SqlBuffer;
146
147    #[test]
148    fn test_sql_buffer_basic() {
149        let mut buf = SqlBuffer::new();
150        buf.push_str("SELECT ");
151        buf.push_str("* FROM users");
152        assert_eq!(buf.as_str(), "SELECT * FROM users");
153        assert!(!buf.is_empty());
154        assert_eq!(buf.len(), 19);
155    }
156
157    #[test]
158    fn test_sql_buffer_from_str() {
159        let buf = SqlBuffer::from_str("SELECT * FROM users");
160        assert_eq!(buf.as_str(), "SELECT * FROM users");
161        let s = buf.into_string();
162        assert_eq!(s, "SELECT * FROM users");
163    }
164
165    #[test]
166    fn test_sql_buffer_push_char() {
167        let mut buf = SqlBuffer::new();
168        buf.push('A');
169        buf.push('B');
170        buf.push('C');
171        assert_eq!(buf.as_str(), "ABC");
172    }
173
174    #[test]
175    fn test_sql_buffer_empty() {
176        let buf = SqlBuffer::new();
177        assert!(buf.is_empty());
178        assert_eq!(buf.len(), 0);
179    }
180
181    #[test]
182    fn test_sql_buffer_into_string() {
183        let mut buf = SqlBuffer::new();
184        buf.push_str("INSERT INTO users (name) VALUES ('test')");
185        let sql = buf.into_string();
186        assert_eq!(sql, "INSERT INTO users (name) VALUES ('test')");
187    }
188
189    #[test]
190    fn test_sql_buffer_write_fmt() {
191        use std::fmt::Write;
192        let mut buf = SqlBuffer::new();
193        let cols = "id, name";
194        let table = "users";
195        write!(buf, "SELECT {cols} FROM {table}").unwrap();
196        assert_eq!(buf.as_str(), "SELECT id, name FROM users");
197    }
198}