[−][src]Crate rql
Description
RQL (Rusty Query Language) is a library design to bring sql-like logic to Rust. However, bear in mind that there is no traditional database here, just some traits and adapters applied to iterators and hashmaps.
Important Note
rql
does not provide a real database. All data is stored in memory. This
pseudo-database can be saved to and loaded from the disk via serialization and
deserialization from serde
. A number of serialization protocols are supported
so that you may choose one to suit your speed, size, and backward-compatibility
needs.
Schema
To use an rql
database, you must first define some schema. Every table is defined
by a struct representing a single entry. In this example, we will define three tables:
User, Group, and Member.
use rql::prelude::*; #[derive(Serialize, Deserialize)] struct User { name: String, age: u8, } #[derive(Serialize, Deserialize)] struct Group { name: String, } #[derive(Serialize, Deserialize)] struct Member { user_id: Id<User>, group_id: Id<Group>, permission: bool, }
Unique id fields are not necessary, as every entry is automatically
given a unique identifier. References to entries in other tables
are denoted with Id<T>
.
To make the actual schema, use the schema!
macro:
schema! { MySchema { user: User, group: Group, member: Member, } }
Database operations
Below are a few simple ways of interfacing with the database.
// Create a new database with the previously defined schema // We pass a folder name for the database files as well as a representation type let db = MySchema::new("test_database_example", HumanReadable).unwrap(); // Insert values into the database // Insertion returns the new row's id let dan = db.user_mut().insert(User { name: "Dan".into(), age: 25 }); let steve = db.user_mut().insert(User { name: "Steve".into(), age: 39 }); let mary = db.user_mut().insert(User { name: "Mary".into(), age: 31 }); let admin = db.group_mut().insert(Group { name: "Admin".into() }); let normal = db.group_mut().insert(Group { name: "Normal User".into() }); db.member_mut().insert(Member { user_id: dan, group_id: admin, permission: true }); db.member_mut().insert(Member { user_id: steve, group_id: normal, permission: true }); db.member_mut().insert(Member { user_id: mary, group_id: normal, permission: false }); // Data can easily be looked up by id db.user_mut().get_mut(dan).unwrap().age += 1; let dan_age = db.user().get(dan).unwrap().age; assert_eq!(dan_age, 26); // Data can be selected from a table let ages: Vec<u8> = db.user().select(|user| user.age).collect(); // Use `wher` to filter entries let can_run_for_president: Vec<String> = db.user() .wher(|user| user.age >= 35) .select(|user| user.name.clone()) .collect(); // Table intersections are done using `relate` // A function relating the tables is required for (user, permission) in db.user() .relate( &*db.member(), |user, member| user.id == member.user_id && member.group_id == normal ) .select(|(user, member)| (&user.data.name, member.permission)) { println!("{} is a normal user with permission = {}", user, permission); } // Rows can be updated with `update` for mut user in db.user_mut().update() { user.age += 1; } // Rows can be deleted in a few ways // By id db.user_mut().delete_one(steve); // With a where clause db.member_mut().delete_where(|member| member.permission); // With an iterator over ids db.user_mut().delete_iter(|_| vec![dan, mary]); // Changes to the database are automatically saved, so they can be loaded again let db_copy = MySchema::new("test_database_example", HumanReadable).unwrap(); assert_eq!(db.user().len(), db_copy.user().len() ); assert_eq!(db.group().len(), db_copy.group().len() ); assert_eq!(db.member().len(), db_copy.member().len());
Re-exports
pub use crate::repr::*; |
Modules
example_schema | Example schema generated by the |
prelude | A prelude for commonly used imports |
repr | Ways of serializing/deserializing data |
Macros
schema | Macro for generating a schema |
Structs
Id | An id for indexing rows |
OwnedRow | An row of owned data cloned from a |
Relate | A relationship between two tables |
Row | A row in a |
RowIter | An iterator over rows in a |
RowIterMut | An mutable iterator over rows in a |
RowMut | A mutable row in a |
Select | An adaptor for selecting data |
Table | A table abstraction akin to a table in a real schema |
TableGuard | An immutable guard to a |
TableGuardMut | A mutable guard to a |
Where | A clause for searching through rows and limiting
the returned values, similar to a sql |
Enums
Error | An error type for |
Traits
HasRows | A trait for accessing rows |
HasRowsMut | A trait for mutably accessing rows |
Idd | A trait for getting row |
Type Definitions
Result | A result type for |