#table #schema #in-memory #sql #orm

rql

一个内存中的虚拟数据库,提供管理虚拟关系表及其模式的功能

8个版本 (4个重大更新)

0.5.2 2020年4月25日
0.5.1 2019年9月5日
0.5.0 2019年8月21日
0.4.0 2019年8月1日
0.1.0 2019年4月16日

#2364 in 数据库接口

每月下载量 35次

MIT 许可证

37KB
927

描述

rql 是一个Rust的内存虚拟数据库。它提供了管理虚拟关系表及其模式的功能。

更多信息,请查看文档


lib.rs:

描述

RQL (Rusty Query Language) 是一个库,旨在将类似SQL的逻辑引入Rust。然而,请注意,这里没有传统的数据库,只有一些应用于迭代器和哈希表的特性和适配器。

重要提示

rql 不提供真正的数据库。所有数据都存储在内存中。这个虚拟数据库可以通过从serde进行序列化和反序列化来保存到磁盘和从磁盘加载。支持多种序列化协议,以便您可以选择一个适合您速度、大小和向后兼容性需求的一个。

模式

要使用rql数据库,您必须首先定义一些模式。每个表都由一个表示单个条目的结构体定义。在这个例子中,我们将定义三个表:User,Group和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,
}

唯一ID字段不是必需的,因为每个条目都会自动分配一个唯一标识符。对其他表中条目的引用用Id<T>表示。

使用schema!宏来创建实际的模式

schema! {
MySchema {
user: User,
group: Group,
member: Member,
}
}

数据库操作

以下是一些与数据库交互的简单方法。



// 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());

依赖关系

~2.8–4MB
~79K SLoC