Expand description
§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
schema!
macro - prelude
- A prelude for commonly used imports
- repr
- Ways of serializing/deserializing data
Macros§
- schema
- Macro for generating a schema
struct
Structs§
- Id
- An id for indexing rows
- Owned
Row - An row of owned data cloned from a
Table
- Relate
- A relationship between two tables
- Row
- A row in a
Table
- RowIter
- An iterator over rows in a
Table
- RowIter
Mut - An mutable iterator over rows in a
Table
- RowMut
- A mutable row in a
Table
- Select
- An adaptor for selecting data
- Table
- A table abstraction akin to a table in a real schema
- Table
Guard - An immutable guard to a
Table
- Table
Guard Mut - A mutable guard to a
Table
- Where
- A clause for searching through rows and limiting
the returned values, similar to a sql
WHERE
Enums§
- Error
- An error type for
rql
Traits§
- HasRows
- A trait for accessing rows
- HasRows
Mut - A trait for mutably accessing rows
- Idd
- A trait for getting row
Id
s
Type Aliases§
- Result
- A result type for
rql