2 个稳定版本

2.0.0 2024 年 8 月 14 日
1.0.0 2024 年 8 月 10 日

#271 in 数据库接口

Download history 91/week @ 2024-08-05 154/week @ 2024-08-12

245 每月下载量
3 crates 中使用

LGPL-3.0-only

77KB
1.5K SLoC

Criterium

Criterium 是一个微型框架,旨在使实现动态条件和数据库查询变得更加容易。

它通过提供可以编译成 SQL 的所需数据结构以及一系列值或直接与给定值匹配的值来实现这一点。

还可以使用布尔逻辑(链)组合多个标准。

动态还意味着可配置的,Criterium 与 Serde 集成

它目前与 rusqlite 集成。

它是如何工作的?

另请参阅 概念文档

通常在构建数据库查询时,从一个相对简单的函数开始

fn fetch_bookmark_information(
	is_favorite: Option<bool>,
	name_contains: Option<String>,
	tags: Vec<String>,
	but_not_tags: Vec<String>,
	//
) -> Vec<Bookmark>;

但正如您从这个简单的例子中可以看到:这不会很好地扩展,手动编写 SQL 生成器是一个繁琐的噩梦(即使切换到结构体也是如此)。

而且大多数时候,人们甚至不需要所有可用的选项。这就是 Criterium 的用武之地。

使用 Criterium,您有一个枚举,它描述了针对数据类型的所有可能的查询。

enum BookmarkCriterium {
	IsFavorite(BooleanCriterium),
	Name(StringCriterium),
	HasTag(StringCriterium),
	//
}

impl ToRusqliteQuery for BookmarkCriterium {
	fn get_sql_where(&self) -> String {
		match self {
			Self::IsFavorite(c) => c.get_sql_where("favorite".to_string()),
			Self::Name(c) => c.get_sql_where("name".to_string()),
		}
	}

	fn get_where_values(&self) -> Vec<Value> {
		match self {
			Self::IsFavorite(c) => c.get_where_values(),
			Self::Name(c) => c.get_where_values(),
		}
	}
}

注意:示例中并非所有数据类型都已实现,但它们应该在 Criterium 之外很容易实现。

然后使用 CriteriumChain 将这些组合起来

let chain_builder: CriteriumChainBuilder<BookmarkCriterium> =
	CriteriumChainBuilder::and(true);
	
chain_builder.add_criterium(
	BookmarkCriterium::IsFavorite(true.into()));
chain_builder.add_criterium(
	BookmarkCriterium::HasTag("tag".into()));
chain_builder.add_criterium(
	BookmarkCriterium::HasTag(StringCriterium::HasPrefix("useful:")));
chain_builder.add_criterium(
	BookmarkCriterium::Name(StringCriterium::Contains("foo")));

let bookmarks = database.query_bookmarks(chain_builder.to_chain());

虽然乍一看这可能看起来更冗长(确实是),但这可以在动态组装,并且更灵活(注意我在那里是如何紧凑地匹配标签的?)。

后台的 SQL 简单地有一个 WHERE,后面紧跟 chain.get_sql_where() 的输出,并从 chain.get_where_values() 中获取值,您只需提供 Criterium 依赖的 SQL 查询中的值即可。

如您所见,当需要查询很多东西时,这很有用,同时也相当具有个人意见,它可能或可能不适合您的项目。

这不是像 django 中的对象关系模型 (ORM) 吗?

是的,有点像。但非常轻量级和基础……并且编译器可以为您验证其中大部分内容。

功能标志

默认情况下,所有需要外部包的集成都被禁用。更多集成将很快推出™。

  • rusqlite - 启用 rusqlite 集成(将条件编译成 SQL)
  • chrono - 启用 chrono 集成(用数字代替 DateTime
  • serde - 启用使用 serde 序列化和反序列化 criteium-chains 和默认条件。
  • full - 启用所有功能,用于构建文档,对于依赖项,您应该明确启用所需的所有功能。

这里有什么?

注意:如果您是从 Rust 文档中阅读的,则链接已损坏。

依赖项

~0–4MB
~72K SLoC