7 个版本 (破坏性更新)
0.7.0 | 2023年8月30日 |
---|---|
0.6.2 | 2023年8月29日 |
0.5.0 | 2023年7月25日 |
0.4.0 | 2023年6月8日 |
0.1.0 | 2023年5月18日 |
#647 在 数据库接口
每月72次下载
73KB
1K SLoC
pg-worm
PostgreSQL 的 Worst ORM
pg-worm
是一个简单的、完全类型化的、异步的 PostgreSQL ORM 和查询构建器。好吧,至少这是目标。
功能/为什么选择 pg-worm
?
-
现有的 ORM 不是
async
,需要你编写迁移或使用 cli。pg-worm
的明确目标是 简单,并且只需定义你的类型,无需设置。 -
pg-worm
还具有 内置连接池 和 简洁的语法。 -
pg-worm
不会阻碍你 - 在享受其他功能的同时,可以轻松地包含原始查询。
用法
这个库基于 tokio_postgres
,并打算与 tokio
一起使用。
幸运的是,使用 pg-worm
非常简单。
只需为你的类型派生 Model
特性,连接到你的数据库,你就可以出发了!
以下是一个快速示例
// Import the prelude to get started quickly
use pg_worm::prelude::*;
#[derive(Model)]
struct Book {
// An auto-generated primary key
#[column(primary_key, auto)]
id: i64,
title: String,
author_id: i64
}
#[derive(Model)]
struct Author {
#[column(primary_key, auto)]
id: i64,
name: String
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// First create a connection. This can be only done once.
Connection::build("postgres://postgres:postgres@localhost:5432").connect()?;
// Then, create tables for your models.
// Use `try_create_table!` if you want to fail if a
// table with the same name already exists.
//
// `force_create_table` drops the old table,
// which is useful for development.
//
// If your tables already exist, skip this part.
force_create_table!(Author, Book).await?;
// Next, insert some data.
// This works by passing values for all
// fields which aren't autogenerated.
Author::insert("Stephen King").await?;
Author::insert("Martin Luther King").await?;
Author::insert("Karl Marx").await?;
Book::insert("Foo - Part I", 1).await?;
Book::insert("Foo - Part II", 2).await?;
Book::insert("Foo - Part III", 3).await?;
// Let's start with a simple query for all books:
let books = Book::select().await?; // Vec<Book>
assert_eq!(books.len(), 3);
// You can also search for a specific book.
// Adding a `WHERE` clause is as simple as
// calling a method on the respective field:
let book = Book::select_one()
.where_(Book::title.eq(&"Foo - Part I".to_string()))
.await?; // Option<Book>
assert!(book.is_some());
// Or update exsisting records:
let books_updated = Book::update()
.set(Book::title, &"Foo - Part III".to_string())
.where_(Book::title.eq(&"Foo - Part II".to_string()))
.await?; // u64
assert_eq!(books_updated, 1);
// Or delete a book, you don't like:
let books_deleted = Book::delete()
.where_(Book::title.eq(&"Foo - Part III".to_string()))
.await?; // u64
assert_eq!(books_deleted, 2);
Ok(())
}
如果你想查看更多代码示例,请查看 测试目录。
查询构建器
如上所示,pg-worm
允许你通过在所谓的 '构建器' 上链式调用方法来构建查询。对于每种查询类型,pg-worm
都提供相应的构建器(除了 INSERT
,它以不同的方式处理)。
这些构建器公开了一组用于构建查询的方法。以下是他们中的几个
方法 | 描述 | 可用性 |
---|---|---|
where_ |
将 WHERE 子句附加到查询。 |
所有构建器(Select 、Update 、Delete ) |
where_raw |
与 where_ 相同,但你可以传递原始 SQL。 |
所有构建器(Select 、Update 、Delete ) |
set |
SET 列的值。注意:必须在执行查询之前至少调用此方法一次。 |
Update |
limit 、offset |
将 LIMIT 或 OFFSET 附加到查询。 |
Select |
使用 WHERE
进行过滤
.where_()
可用于轻松地将 WHERE
子句包含在查询中。
这是通过传递一个由调用相应列的方法构建的 Where
对象来完成的。 pg-worm
会自动为你的 Model
的每个字段构造一个常量。
一个实际例子可能看起来像这样
let where_: Where<'_> = MyModel::my_field.eq(&5);
可用方法
目前,已实现了以下方法
函数 | 描述 | 可用性 |
---|---|---|
eq |
检查相等。 | 任何类型 |
gt 、gte 、lt 、lte |
检查此列的值是否大于或等于某个其他值。 | 实现 PartialOrd 的任何类型。注意:并不能保证Postgres支持类型为 PartialOrd 的操作符。在使用之前,请务必检查Postgres文档。 |
null 、not_null |
检查列是否为 NULL 。 |
任何 Option<T> 。所有其他类型都不是可空类型,因此保证不为 NULL 。 |
contains 、contains_not 、contains_all 、conatains_none 、contains_any |
数组操作。检查此列的数组是否包含一个值、一个 不 包含的值或另一个数组的任意/所有/无值。 | 任何 Vec<T> 。 |
布尔逻辑
您还可以使用标准布尔逻辑链接/修改这些过滤器
Book::select()
.where_(!Book::id.eq(&1) & Book::id.gt(&3))
.await?;
操作符/方法 | 描述 |
---|---|
! 、.not() |
使用逻辑 NOT 取消一个过滤器的过滤。 |
& 、.and() |
使用逻辑 AND 结合两个过滤器。 |
|| 、.or() |
使用逻辑 OR 结合两个过滤器。 |
执行查询
构建完查询后,您只需调用 .await
。这将把构建器转换为 Query
对象,然后异步执行。
执行查询总是会返回一个 Result
。
原始查询
虽然这些功能很棒,但它们并不适用于所有应用程序。这就是为什么您可以轻松地执行自定义查询,同时仍然利用自动解析等优势。
// NOTE: You have to pass the exact type that PostgreSQL is
// expecting. Doing otherwise will result in a runtime error.
let king_books = Book::query(r#"
SELECT * FROM book
JOIN author ON author.id = book.author_id
WHERE POSITION(? in author.name) > 0
"#,
vec![&"King".to_string()]
).await?;
assert_eq!(king_books.len(), 2);
有关查询构建器上的 .where_raw
,请参阅相关内容,您可以通过它传递一个原始条件,而无需自己编写整个查询。
事务
pg-worm
也支持事务。您可以在 Transaction
中轻松执行任何查询,并且只有在您满意时才提交。
当事务被丢弃时,事务会自动回滚,除非它们之前已被提交。
以下是一个示例
use pg_worm::prelude::*;
#[derive(Model)]
struct Foo {
bar: i64
}
async fn foo() -> Result<(), Box<dyn std::error::Error>> {
// Easily create a new transaction
let transaction = Transaction::begin().await?;
// Execute any query inside the transaction
let all_foo = transaction.execute(
Foo::select()
).await?;
// Commit the transaction when done.
// If not committed, transaction are rolled back
// when dropped.
transaction.commit().await?;
}
支持类型
以下是一个支持(Rust)类型及其映射到PostgreSQL类型的列表。
Rust类型 | PostgreSQL类型 |
---|---|
bool |
BOOL |
i16 |
INT2 |
i32 |
INT4 |
i64 |
INT8 |
f32 |
FLOAT4 |
f64 |
FLOAT8 |
String |
TEXT |
Option<T> * |
T (但列变为 NULLABLE ) |
Vec<T> * |
T[] |
*T
必须是另一个支持类型。嵌套和混合 Option
/Vec
目前不支持。
JSON、时间戳等
也是支持的。要使用它们,请激活相应的功能,如下所示
# Cargo.toml
[dependencies]
pg-worm = { version = "latest-version", features = ["foo"] }
以下是一个支持的功能/类型及其相应的PostgreSQL类型的列表
-
"serde-json"
用于serde_json
v1.0
Rust类型 PostgreSQL类型 Value
JSONB
-
"time"
用于time
v3.0
Rust类型 PostgreSQL类型 Date
DATE
Time
TIME
PrimitiveDateTime
TIMESTAMP
OffsetDateTime
TIMESTAMP WITH TIME ZONE
-
"uuid"
用于uuid
v1.0
Rust类型 PostgreSQL类型 Uuid
UUID
derive
选项
您可以为您 Model
配置一些选项。这是通过使用 pg-worm
暴露的两个属性之一来完成的。
属性 #[table]
属性 #[table]
可以用来向 Model
传递配置,该配置影响相应的表本身。
use pg_worm::prelude::*;
#[derive(Model)]
#[table(table_name = "book_list")]
struct Book {
id: i64
}
Option | 含义 | 用法 | 默认 |
---|---|---|---|
table_name |
设置表的名称 | table_name= "new_table_name" |
使用 这个包 将结构体名称转换为蛇形命名法。 |
属性 #[column]
属性 #[column]
可以用来向 Model
的字段传递配置,该配置影响相应的列。
use pg_worm::prelude::*;
#[derive(Model)]
struct Book {
#[column(primary_key, auto)]
id: i64
}
Option | 含义 | 用法 | 默认 |
---|---|---|---|
column_name |
设置此列的名称。 | #[column(column_name= "new_column_name")] |
使用 这个包 将字段名称转换为蛇形命名法。 |
primary_key |
将此列设置为主键。每个 Model 只能使用一次。如果希望此列自动生成,请使用 auto 。 |
#[column(primary_key)] |
false |
auto |
使此列自动生成。仅适用于 i16 、i32 和 i64 ,以及 Uuid 如果 已启用 "uuid" 功能 并且 您使用 PostgreSQL 版本 13 或更高版本。 |
#[column(auto)] |
false |
MSRV
最低支持的 Rust 版本是 1.70
,因为此 crate 使用了最近引入的 OnceLock
。
许可协议
此项目在 MIT 和 Apache 2.0 许可协议下双授权。
依赖项
~8–18MB
~256K SLoC