1pub mod types;
8pub mod storage;
9pub mod query;
10pub mod index;
11pub mod transaction;
12pub mod persistence;
13
14pub use types::{DbValue, DataType, Column, TableSchema, DbError, DbResult};
15pub use storage::{MemoryEngine, PersistedEngine, StorageEngine, Row, RowId};
16pub use query::{QueryBuilder, UpdateBuilder, DeleteBuilder, Order, JoinType};
17pub use transaction::Transaction;
18
19use std::sync::{Arc, RwLock};
20use std::path::Path;
21
22pub enum DatabaseEngine {
24 Memory(Arc<RwLock<MemoryEngine>>),
26 Persisted(Arc<RwLock<PersistedEngine>>),
28}
29
30pub struct Database {
34 engine: DatabaseEngine,
35}
36
37impl Database {
38 pub fn new() -> Self {
40 Database {
41 engine: DatabaseEngine::Memory(Arc::new(RwLock::new(MemoryEngine::new()))),
42 }
43 }
44
45 pub fn open(path: &Path) -> DbResult<Self> {
47 let engine = PersistedEngine::open(path)?;
48 Ok(Database {
49 engine: DatabaseEngine::Persisted(Arc::new(RwLock::new(engine))),
50 })
51 }
52
53 pub fn create(path: &Path) -> DbResult<Self> {
55 let engine = PersistedEngine::create(path)?;
56 Ok(Database {
57 engine: DatabaseEngine::Persisted(Arc::new(RwLock::new(engine))),
58 })
59 }
60
61 pub fn create_table(&self, name: &str, columns: Vec<Column>) -> DbResult<()> {
63 let schema = TableSchema::new(name, columns);
64 match &self.engine {
65 DatabaseEngine::Memory(engine) => {
66 let mut e = engine.write().unwrap();
67 e.create_table(schema)
68 }
69 DatabaseEngine::Persisted(engine) => {
70 let mut e = engine.write().unwrap();
71 e.create_table(schema)
72 }
73 }
74 }
75
76 pub fn drop_table(&self, name: &str) -> DbResult<()> {
78 match &self.engine {
79 DatabaseEngine::Memory(engine) => {
80 let mut e = engine.write().unwrap();
81 e.drop_table(name)
82 }
83 DatabaseEngine::Persisted(engine) => {
84 let mut e = engine.write().unwrap();
85 e.drop_table(name)
86 }
87 }
88 }
89
90 pub fn has_table(&self, name: &str) -> bool {
92 match &self.engine {
93 DatabaseEngine::Memory(engine) => {
94 let e = engine.read().unwrap();
95 e.has_table(name)
96 }
97 DatabaseEngine::Persisted(engine) => {
98 let e = engine.read().unwrap();
99 e.has_table(name)
100 }
101 }
102 }
103
104 pub fn insert(&self, table: &str, values: Vec<(&str, DbValue)>) -> DbResult<RowId> {
106 match &self.engine {
107 DatabaseEngine::Memory(engine) => {
108 let mut e = engine.write().unwrap();
109 Self::insert_with_schema(&mut *e, table, values)
110 }
111 DatabaseEngine::Persisted(engine) => {
112 let mut e = engine.write().unwrap();
113 Self::insert_with_schema(&mut *e, table, values)
114 }
115 }
116 }
117
118 fn insert_with_schema<E: StorageEngine>(
120 engine: &mut E,
121 table: &str,
122 values: Vec<(&str, DbValue)>,
123 ) -> DbResult<RowId> {
124 let schema = engine.get_schema(table)?.clone();
126
127 let mut row = Row::new();
129 for (name, value) in values {
130 row.insert(name.to_string(), value);
131 }
132
133 let values_ref: Vec<(String, DbValue)> = row.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
135 schema.validate(&values_ref)?;
136
137 engine.insert(table, row)
138 }
139
140 pub fn get(&self, table: &str, row_id: RowId) -> DbResult<Option<Row>> {
142 match &self.engine {
143 DatabaseEngine::Memory(engine) => {
144 let e = engine.read().unwrap();
145 e.get(table, row_id)
146 }
147 DatabaseEngine::Persisted(engine) => {
148 let e = engine.read().unwrap();
149 e.get(table, row_id)
150 }
151 }
152 }
153
154 pub fn query(&self, table: &str) -> QueryBuilder {
159 match &self.engine {
160 DatabaseEngine::Memory(engine) => {
161 QueryBuilder::new(table.to_string(), Arc::clone(engine))
162 }
163 DatabaseEngine::Persisted(engine) => {
164 let e = engine.read().unwrap();
166 QueryBuilder::new(table.to_string(), e.inner_arc())
167 }
168 }
169 }
170
171 pub fn update(&self, table: &str) -> UpdateBuilder {
176 match &self.engine {
177 DatabaseEngine::Memory(engine) => {
178 UpdateBuilder::new(table.to_string(), Arc::clone(engine))
179 }
180 DatabaseEngine::Persisted(engine) => {
181 let e = engine.read().unwrap();
183 UpdateBuilder::new(table.to_string(), e.inner_arc())
184 }
185 }
186 }
187
188 pub fn delete(&self, table: &str) -> DeleteBuilder {
193 match &self.engine {
194 DatabaseEngine::Memory(engine) => {
195 DeleteBuilder::new(table.to_string(), Arc::clone(engine))
196 }
197 DatabaseEngine::Persisted(engine) => {
198 let e = engine.read().unwrap();
200 DeleteBuilder::new(table.to_string(), e.inner_arc())
201 }
202 }
203 }
204
205 pub fn transaction<F, T>(&self, f: F) -> DbResult<T>
211 where
212 F: FnOnce(&mut Transaction<'_>) -> DbResult<T>,
213 {
214 match &self.engine {
215 DatabaseEngine::Memory(engine) => {
216 let mut e = engine.write().unwrap();
217 let mut tx = Transaction::new(&mut *e as &mut dyn StorageEngine);
219 let result = f(&mut tx)?;
220 tx.commit()?;
221 Ok(result)
222 }
223 DatabaseEngine::Persisted(engine) => {
224 let mut e = engine.write().unwrap();
225 let mut tx = Transaction::new(&mut *e as &mut dyn StorageEngine);
227 let result = f(&mut tx)?;
228 tx.commit()?;
229 Ok(result)
230 }
231 }
232 }
233
234 pub fn create_index(&self, table: &str, column: &str) -> DbResult<()> {
236 match &self.engine {
237 DatabaseEngine::Memory(engine) => {
238 let mut e = engine.write().unwrap();
239 e.create_index(table, column)
240 }
241 DatabaseEngine::Persisted(engine) => {
242 let mut e = engine.write().unwrap();
243 e.create_index(table, column)
244 }
245 }
246 }
247
248 pub fn create_composite_index(&self, table: &str, columns: &[&str]) -> DbResult<()> {
250 match &self.engine {
251 DatabaseEngine::Memory(engine) => {
252 let mut e = engine.write().unwrap();
253 e.create_composite_index(table, columns)
254 }
255 DatabaseEngine::Persisted(engine) => {
256 let mut e = engine.write().unwrap();
257 e.create_composite_index(table, columns)
258 }
259 }
260 }
261
262 pub fn create_unique_index(&self, table: &str, columns: &[&str]) -> DbResult<()> {
264 match &self.engine {
265 DatabaseEngine::Memory(engine) => {
266 let mut e = engine.write().unwrap();
267 e.create_unique_index(table, columns)
268 }
269 DatabaseEngine::Persisted(engine) => {
270 let mut e = engine.write().unwrap();
271 e.create_unique_index(table, columns)
272 }
273 }
274 }
275
276 pub fn drop_index(&self, table: &str, column: &str) -> DbResult<bool> {
278 match &self.engine {
279 DatabaseEngine::Memory(engine) => {
280 let mut e = engine.write().unwrap();
281 e.drop_index(table, column)
282 }
283 DatabaseEngine::Persisted(engine) => {
284 let mut e = engine.write().unwrap();
285 e.drop_index(table, column)
286 }
287 }
288 }
289
290 pub fn drop_composite_index(&self, table: &str, columns: &[&str]) -> DbResult<bool> {
292 match &self.engine {
293 DatabaseEngine::Memory(engine) => {
294 let mut e = engine.write().unwrap();
295 e.drop_composite_index(table, columns)
296 }
297 DatabaseEngine::Persisted(engine) => {
298 let mut e = engine.write().unwrap();
299 e.drop_composite_index(table, columns)
300 }
301 }
302 }
303
304 pub fn has_index(&self, table: &str, column: &str) -> bool {
306 match &self.engine {
307 DatabaseEngine::Memory(engine) => {
308 let e = engine.read().unwrap();
309 e.has_index(table, column)
310 }
311 DatabaseEngine::Persisted(engine) => {
312 let e = engine.read().unwrap();
313 e.has_index(table, column)
314 }
315 }
316 }
317
318 pub fn has_composite_index(&self, table: &str, columns: &[&str]) -> bool {
320 match &self.engine {
321 DatabaseEngine::Memory(engine) => {
322 let e = engine.read().unwrap();
323 e.has_composite_index(table, columns)
324 }
325 DatabaseEngine::Persisted(engine) => {
326 let e = engine.read().unwrap();
327 e.has_composite_index(table, columns)
328 }
329 }
330 }
331}
332
333impl Default for Database {
334 fn default() -> Self {
335 Self::new()
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn test_create_table() {
345 let db = Database::new();
346 let columns = vec![
347 Column::new("id", DataType::integer()).primary_key(),
348 Column::new("name", DataType::text()),
349 Column::new("age", DataType::integer()),
350 ];
351
352 assert!(db.create_table("users", columns).is_ok());
353 assert!(db.has_table("users"));
354 }
355
356 #[test]
357 fn test_insert_and_query() {
358 let db = Database::new();
359 let columns = vec![
360 Column::new("id", DataType::integer()).primary_key(),
361 Column::new("name", DataType::text()),
362 Column::new("age", DataType::integer()),
363 ];
364 db.create_table("users", columns).unwrap();
365
366 db.insert("users", vec![
367 ("id", DbValue::integer(1)),
368 ("name", DbValue::text("Alice")),
369 ("age", DbValue::integer(25)),
370 ]).unwrap();
371
372 db.insert("users", vec![
373 ("id", DbValue::integer(2)),
374 ("name", DbValue::text("Bob")),
375 ("age", DbValue::integer(30)),
376 ]).unwrap();
377
378 match &db.engine {
380 DatabaseEngine::Memory(engine) => {
381 let e = engine.read().unwrap();
382 let rows = e.scan("users").unwrap();
383 assert_eq!(rows.len(), 2);
384 }
385 _ => {}
386 }
387 }
388
389 #[test]
390 fn test_transaction_basic() {
391 let db = Database::new();
392 db.create_table("users", vec![
393 Column::new("id", DataType::integer()),
394 Column::new("name", DataType::text()),
395 ]).unwrap();
396
397 let result = db.transaction(|tx| {
398 tx.insert("users", vec![("id", DbValue::integer(1)), ("name", DbValue::text("Alice"))])?;
399 tx.insert("users", vec![("id", DbValue::integer(2)), ("name", DbValue::text("Bob"))])?;
400 Ok(())
401 });
402
403 assert!(result.is_ok());
404
405 match &db.engine {
407 DatabaseEngine::Memory(engine) => {
408 let e = engine.read().unwrap();
409 let rows = e.scan("users").unwrap();
410 assert_eq!(rows.len(), 2);
411 }
412 _ => {}
413 }
414 }
415
416 #[test]
417 fn test_transaction_rollback() {
418 let db = Database::new();
419 db.create_table("users", vec![
420 Column::new("id", DataType::integer()),
421 Column::new("name", DataType::text()),
422 ]).unwrap();
423
424 db.insert("users", vec![
426 ("id", DbValue::integer(1)),
427 ("name", DbValue::text("Alice")),
428 ]).unwrap();
429
430 let result = db.transaction(|tx| {
432 tx.insert("users", vec![("id", DbValue::integer(2)), ("name", DbValue::text("Bob"))])?;
433 tx.rollback()?;
435 Ok(())
436 });
437
438 assert!(result.is_ok());
439
440 match &db.engine {
442 DatabaseEngine::Memory(engine) => {
443 let e = engine.read().unwrap();
444 let rows = e.scan("users").unwrap();
445 assert_eq!(rows.len(), 1);
446 assert_eq!(rows[0].1.get("name").unwrap().as_text(), Some("Alice"));
447 }
448 _ => {}
449 }
450 }
451}