1pub mod from_value;
4pub mod marker;
5pub mod row_access;
6pub mod typed;
7
8pub use from_value::FromValue;
9pub use marker::ColumnMarker;
10pub use row_access::RowAccess;
11pub use typed::{Column, SelectColumns};
12
13#[cfg(test)]
14mod tests {
15 use super::*;
16 use crate::expr::Expr;
17 use crate::select::OrderDir;
18 use crate::value::Value;
19
20 #[test]
21 fn test_column_new() {
22 let col: Column<i64> = Column::new("users", "id");
23 assert_eq!(col.table(), "users");
24 assert_eq!(col.name(), "id");
25
26 let col: Column<String> = Column::new("users", "email");
27 assert_eq!(col.table(), "users");
28 assert_eq!(col.name(), "email");
29 }
30
31 #[test]
32 fn test_column_alias() {
33 let col: Column<i64> = Column::new("users", "id");
34 assert_eq!(col.alias(), "users__id");
35
36 let col: Column<String> = Column::new("posts", "title");
37 assert_eq!(col.alias(), "posts__title");
38 }
39
40 #[test]
41 fn test_column_marker() {
42 let col: Column<i64> = Column::new("users", "id");
43 let marker = col.marker();
44 assert_eq!(marker.table, "users");
45 assert_eq!(marker.name, "id");
46 }
47
48 #[test]
49 fn test_column_to_expr() {
50 let col: Column<i64> = Column::new("users", "id");
51 let expr: Expr = col.into();
52 assert_eq!(expr, Expr::Column("users__id".to_string()));
53 }
54
55 #[test]
56 fn test_eq_operator() {
57 let col: Column<i64> = Column::new("users", "id");
58 let expr = col.eq(42i64);
59 assert_eq!(
60 expr,
61 Expr::column("users__id").eq(Expr::param(Value::I64(42)))
62 );
63 }
64
65 #[test]
66 fn test_eq_operator_string() {
67 let col: Column<String> = Column::new("users", "email");
68 let expr = col.eq("test@example.com");
69 assert_eq!(
70 expr,
71 Expr::column("users__email")
72 .eq(Expr::param(Value::String("test@example.com".to_string())))
73 );
74 }
75
76 #[test]
77 fn test_desc_order() {
78 let col: Column<String> = Column::new("users", "email");
79 let order = col.desc();
80 assert_eq!(order.column, "users__email");
81 assert_eq!(order.direction, OrderDir::Desc);
82 }
83
84 #[test]
85 fn test_asc_order() {
86 let col: Column<i64> = Column::new("users", "id");
87 let order = col.asc();
88 assert_eq!(order.column, "users__id");
89 assert_eq!(order.direction, OrderDir::Asc);
90 }
91
92 #[test]
93 fn test_ends_with() {
94 let col: Column<String> = Column::new("users", "email");
95 let expr = col.ends_with("example.com");
96 assert_eq!(
97 expr,
98 Expr::column("users__email")
99 .like(Expr::param(Value::String("%example.com".to_string())))
100 );
101 }
102
103 #[test]
104 fn test_starts_with() {
105 let col: Column<String> = Column::new("users", "email");
106 let expr = col.starts_with("admin");
107 assert_eq!(
108 expr,
109 Expr::column("users__email").like(Expr::param(Value::String("admin%".to_string())))
110 );
111 }
112
113 #[test]
114 fn test_contains() {
115 let col: Column<String> = Column::new("users", "email");
116 let expr = col.contains("example");
117 assert_eq!(
118 expr,
119 Expr::column("users__email").like(Expr::param(Value::String("%example%".to_string())))
120 );
121 }
122
123 #[test]
124 fn test_from_value_i64() {
125 assert_eq!(i64::from_value(&Value::I64(42)).unwrap(), 42);
126 assert!(i64::from_value(&Value::Null).is_err());
127 assert!(i64::from_value(&Value::String("test".to_string())).is_err());
128 }
129
130 #[test]
131 fn test_from_value_string() {
132 assert_eq!(
133 String::from_value(&Value::String("test".to_string())).unwrap(),
134 "test"
135 );
136 assert!(String::from_value(&Value::Null).is_err());
137 assert!(String::from_value(&Value::I64(42)).is_err());
138 }
139
140 #[test]
141 fn test_from_value_bool() {
142 assert!(bool::from_value(&Value::Bool(true)).unwrap());
143 assert!(!bool::from_value(&Value::Bool(false)).unwrap());
144 assert!(bool::from_value(&Value::I64(1)).unwrap());
145 assert!(!bool::from_value(&Value::I64(0)).unwrap());
146 assert!(bool::from_value(&Value::Null).is_err());
147 assert!(bool::from_value(&Value::I64(2)).is_err());
148 }
149
150 #[test]
151 fn test_select_columns_single() {
152 let selection = (Column::<i64>::new("users", "id"),);
153 let columns = selection.columns();
154 assert_eq!(columns.len(), 1);
155 assert_eq!(columns[0].table, "users");
156 assert_eq!(columns[0].name, "id");
157 }
158
159 #[test]
160 fn test_select_columns_two() {
161 let selection = (
162 Column::<i64>::new("users", "id"),
163 Column::<String>::new("users", "email"),
164 );
165 let columns = selection.columns();
166 assert_eq!(columns.len(), 2);
167 assert_eq!(columns[0].table, "users");
168 assert_eq!(columns[0].name, "id");
169 assert_eq!(columns[1].table, "users");
170 assert_eq!(columns[1].name, "email");
171 }
172
173 #[test]
174 fn test_select_columns_multiple_tables() {
175 let selection = (
176 Column::<i64>::new("users", "id"),
177 Column::<String>::new("posts", "title"),
178 );
179 let columns = selection.columns();
180 assert_eq!(columns.len(), 2);
181 assert_eq!(columns[0].table, "users");
182 assert_eq!(columns[0].name, "id");
183 assert_eq!(columns[1].table, "posts");
184 assert_eq!(columns[1].name, "title");
185 }
186
187 #[test]
188 fn test_column_copy() {
189 let col1: Column<i64> = Column::new("users", "id");
190 let col2 = col1;
191 let col3 = col1;
192 assert_eq!(col1.name(), col2.name());
193 assert_eq!(col2.name(), col3.name());
194 }
195
196 #[test]
197 fn test_column_marker_from() {
198 let col: Column<i64> = Column::new("users", "id");
199 let marker: ColumnMarker = col.into();
200 assert_eq!(marker.table, "users");
201 assert_eq!(marker.name, "id");
202 }
203
204 #[test]
205 fn test_column_marker_alias() {
206 let marker = ColumnMarker::new("users", "id");
207 assert_eq!(marker.alias(), "users__id");
208
209 let marker = ColumnMarker::new("posts", "title");
210 assert_eq!(marker.alias(), "posts__title");
211 }
212
213 struct MockRow {
214 values: Vec<Value>,
215 }
216
217 impl<'row> RowAccess<'row> for MockRow {
218 fn get_by_pos(&'row self, idx: usize) -> Option<&'row Value> {
219 self.values.get(idx)
220 }
221
222 fn get(&'row self, _name: &str) -> Option<&'row Value> {
223 None
224 }
225
226 fn column_name(&'row self, _idx: usize) -> Option<&'row str> {
227 None
228 }
229
230 fn len(&self) -> usize {
231 self.values.len()
232 }
233 }
234
235 #[test]
236 fn test_select_columns_decode_single() {
237 let selection = (Column::<i64>::new("users", "id"),);
238 let mock_row = MockRow {
239 values: vec![Value::I64(42)],
240 };
241
242 let result = selection.decode(&mock_row).unwrap();
243 assert_eq!(result, (42,));
244 }
245
246 #[test]
247 fn test_select_columns_decode_two() {
248 let selection = (
249 Column::<i64>::new("users", "id"),
250 Column::<String>::new("users", "email"),
251 );
252 let mock_row = MockRow {
253 values: vec![
254 Value::I64(42),
255 Value::String("test@example.com".to_string()),
256 ],
257 };
258
259 let result = selection.decode(&mock_row).unwrap();
260 assert_eq!(result, (42, "test@example.com".to_string()));
261 }
262
263 #[test]
264 fn test_select_columns_decode_three() {
265 let selection = (
266 Column::<i64>::new("users", "id"),
267 Column::<String>::new("users", "email"),
268 Column::<bool>::new("users", "active"),
269 );
270 let mock_row = MockRow {
271 values: vec![
272 Value::I64(99),
273 Value::String("admin@example.com".to_string()),
274 Value::Bool(true),
275 ],
276 };
277
278 let result = selection.decode(&mock_row).unwrap();
279 assert_eq!(result, (99, "admin@example.com".to_string(), true));
280 }
281
282 #[test]
283 fn test_select_columns_decode_missing_column() {
284 let selection = (
285 Column::<i64>::new("users", "id"),
286 Column::<String>::new("users", "email"),
287 );
288 let mock_row = MockRow {
289 values: vec![Value::I64(42)],
290 };
291
292 let result = selection.decode(&mock_row);
293 assert!(result.is_err());
294 }
295
296 #[test]
297 fn test_select_columns_decode_type_error() {
298 let selection = (Column::<i64>::new("users", "id"),);
299 let mock_row = MockRow {
300 values: vec![Value::String("not a number".to_string())],
301 };
302
303 let result = selection.decode(&mock_row);
304 assert!(result.is_err());
305 }
306}