安全关系型数据库查询新选择:Rust 语言的 rust-query 库深度解析
在当今这个数据驱动的时代,数据库作为信息存储和检索的核心组件,其重要性不言而喻。然而,对于开发者而言,如何在保证数据安全的前提下,高效地进行数据库操作却是一项挑战。传统的 SQL 查询虽然强大,但存在诸多不便,如易出错、难以维护等。幸运的是,随着 Rust 语言的崛起,一种全新的数据库交互方式应运而生——rust-query 库。本文将深入剖析 rust-query 的设计理念、核心特性以及实际应用,带您领略 Rust 语言在数据库领域的独特魅力。

Rust,作为一种系统级编程语言,以其高性能、内存安全和并发处理能力而广受开发者喜爱。然而,在与数据库的交互方面,Rust 的生态并不完善。传统的数据库交互库,如 Diesel、SQLx 等,虽然提供了丰富的功能,但在编译时检查、类型安全等方面仍存在不足。这导致开发者在编写数据库代码时,往往需要花费大量精力进行调试和维护。
正是基于对现有 Rust 数据库交互库的不满,LHolten 开发了 rust-query 库。作为一位对数据库有着深厚感情的开发者,他深知数据库操作的复杂性和潜在风险。因此,他希望通过 rust-query 为 Rust 开发者提供一种更安全、更直观、更高效的数据库交互方式。
一、rust-query 的核心特性
1、显式表别名
在 rust-query 中,表别名是显式的。当我们对表进行连接操作时,会返回一个代表该表的虚拟对象。例如:
let user = User::join(rows);
这种方式使得表之间的关系更加清晰,同时也减少了出错的可能性。
2、空值安全
在数据库查询中,空值(NULL)是一个常见的问题。为了避免空值带来的错误,rust-query 将查询中的可选值类型设置为 Option。这意味着开发者需要特别注意处理这些可选值,从而确保程序的健壮性。
3、直观的聚合操作
聚合操作是数据库查询中的重要组成部分。在 rust-query 中,聚合操作被设计得非常直观。例如,我们可以轻松地计算每个故事的平均评分:
let avg_rating = aggregate(|rows| {let rating = Rating::join(rows);rows.filter_on(rating.story(), &story);rows.avg(rating.stars().as_float())});
这种方式不仅简化了代码,还提高了查询的可读性和可维护性。
4、类型安全的外键导航
在关系型数据库中,外键约束是保证数据完整性的重要手段。rust-query 充分利用 Rust 的类型系统,实现了类型安全的外键导航。例如,我们可以通过以下方式获取专辑的艺术家名称:
track.album().artist().name()
这种链式调用不仅简洁明了,还能在编译时检查类型错误,确保查询的正确性。
5、类型安全的唯一查找
在数据库中,唯一约束是一种常见的约束类型。rust-query 提供了类型安全的唯一查找功能。例如,我们可以获取某个用户对某篇故事的评分:
let rating = Rating::unique(my_user, my_story);
这种方式不仅简化了代码,还能在编译时检查唯一性约束,避免潜在的冲突。
6、多版本模式支持
随着业务的发展,数据库模式可能会发生变化。为了应对这种情况,rust-query 支持多版本模式。开发者可以轻松地定义不同版本的模式,并在迁移过程中保持数据的完整性。
7、类型安全的迁移
在数据库应用中,模式迁移是一项常见的任务。rust-query 提供了类型安全的迁移功能。开发者可以使用任意的 Rust 代码来处理行数据,从而实现复杂的迁移逻辑。例如:
let m = m.migrate(v1::update::Schema {user: Box::new(|old_user| {Alter::new(v1::update::UserMigration {email: old_user.name().map_dummy(|name| format!("{}@example.com", name)),})}),});
这种方式不仅提高了迁移的安全性,还使得迁移过程更加灵活和可控。
8、行引用与事务生命周期绑定
在 rust-query 中,行引用与事务的生命周期紧密绑定。这意味着只有在行数据被保证存在的情况下,我们才能使用对应的行引用。这种方式有效地避免了因行数据被删除或修改而导致的错误。
9、封装的类型化行 ID
为了保护数据的隐私和安全,rust-query 封装了实际的行号。开发者无需关心具体的行号,只需通过库提供的 API 进行操作即可。这种方式不仅简化了代码逻辑,还提高了数据的安全性。
二、实战演练:使用 rust-query 进行数据库操作
接下来,我们将通过一个简单的示例来演示如何使用 rust-query 进行数据库操作。假设我们有一个包含用户、故事和评分三个表的模式:
#[schema]enum Schema {User { name: String },Story { author: User, title: String, content: String },#[unique(user, story)]Rating { user: User, story: Story, stars: i64 },}
首先,我们需要插入一些数据:
fn insert_data(txn: &mut TransactionMut<Schema>) {let alice = txn.insert(User { name: "Alice" });let bob = txn.insert(User { name: "Bob" });let dream = txn.insert(Story { author: alice, title: "My Crazy Dream", content: "A dinosaur and a bird..." });let rating = txn.try_insert(Rating { user: bob, story: dream, stars: 5 }).expect("no rating for this user and story exists yet");}
然后,我们可以查询这些数据并计算平均评分:
fn query_data(txn: &Transaction<Schema>) {let results = txn.query(|rows| {let story = Story::join(rows);let avg_rating = aggregate(|rows| {let rating = Rating::join(rows);rows.filter_on(rating.story(), &story);rows.avg(rating.stars().as_float())});rows.into_vec((story.title(), avg_rating))});for (title, avg_rating) in results {println!("Story '{}' has avg rating {}", title, avg_rating.unwrap_or(0.0));}}
通过这个示例,我们可以看到 rust-query 的强大功能和简洁语法。无论是插入数据还是查询数据,rust-query 都能提供类型安全、直观易用的 API,让开发者能够轻松地完成各种数据库操作。
三、模式演进与迁移
随着业务的发展,数据库模式可能会发生变化。为了应对这种情况,rust-query 提供了强大的模式演进和迁移功能。开发者可以通过定义新的模式版本和编写迁移逻辑来实现模式的平滑升级。
例如,假设我们需要为每个用户添加一个电子邮件地址字段。我们可以先定义一个新的模式版本:
#[schema]#[version(0..=1)]enum Schema {User { name: String, #[version(1..)] email: String },// ... rest of schema ...}
然后,我们可以编写迁移逻辑来更新现有数据:
let m = m.migrate(v1::update::Schema {user: Box::new(|old_user| {Alter::new(v1::update::UserMigration {email: old_user.name().map_dummy(|name| format!("{}@example.com", name)),})}),});
通过这种方式,我们可以确保在模式升级过程中数据的完整性和一致性。
rust-query 作为 Rust 语言中的一款新型数据库交互库,以其安全、直观和高效的特点吸引了众多开发者的关注。它充分利用 Rust 的类型系统和编译时检查能力,为开发者提供了一种全新的数据库操作方式。
通过本文的介绍和分析,我们可以看到 rust-query 在数据库操作方面的强大功能和简洁语法。无论是插入数据、查询数据还是进行模式迁移,rust-query 都能提供类型安全、直观易用的 API,让开发者能够轻松地完成各种数据库操作。
然而,我们也需要注意到 rust-query 目前仍处于开发阶段,其功能和性能还有待进一步完善和优化。因此,在实际应用中,我们可能需要结合具体的业务需求和场景来选择合适的数据库交互方式。
展望未来,随着 Rust 语言生态的不断完善和数据库技术的不断发展,我们有理由相信 rust-query 将会在未来的数据库应用中发挥更加重要的作用。同时,我们也期待更多的开发者能够关注和使用 rust-query,共同推动 Rust 语言在数据库领域的应用和发展。
科技脉搏,每日跳动。
——敖行客Allthinker与您共享未来之声

- 智慧链接 思想协作 -
相关文章:
安全关系型数据库查询新选择:Rust 语言的 rust-query 库深度解析
在当今这个数据驱动的时代,数据库作为信息存储和检索的核心组件,其重要性不言而喻。然而,对于开发者而言,如何在保证数据安全的前提下,高效地进行数据库操作却是一项挑战。传统的 SQL 查询虽然强大,但存在诸…...
《C++ 模型训练之早停法:有效预防过拟合的关键策略》
在 C 模型开发的复杂世界里,过拟合犹如一个潜藏的陷阱,常常使我们精心构建的模型在实际应用中表现大打折扣。而早停法(Early Stopping)作为一种行之有效的策略,能够帮助我们及时察觉模型训练过程中的异常,避…...
5.11【数据库】第一次实验
民宿预定,至少有不同的民宿,民宿下面有不同的房间(面积,房间编号) 房间类型,单价, 可预订以及不可预订 游客信息 订单信息 公司有很多课程, 学生,课程 每位学生每期…...
【CSS in Depth 2 精译_062】第 10 章 CSS 中的容器查询(@container)概述 + 10.1 容器查询的一个简单示例
当前内容所在位置(可进入专栏查看其他译好的章节内容) 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 ✔️ 10.1.1 容器尺寸查询的用法 ✔️ 10.2 深入理解容器10.3 与容器相关的单位10.4 容器样式查询的用法10.5 本章小结 文章目录 第 10…...
蓝桥杯每日真题 - 第23天
题目:(直线) 题目描述(12届 C&C B组C题) 解题思路: 题目理解: 在平面直角坐标系中,从给定的点集中确定唯一的直线。 两点确定一条直线,判断两条直线是否相同,可通过…...
# Vue 入门级教程三
在前两篇 Vue 入门教程中,我们已经熟悉了 Vue 的基础语法、数据绑定、指令以及组件化开发等核心概念。在本教程中,我们将进一步探索 Vue 的高级特性,包括过滤器、自定义指令、过渡效果以及 Vue 与后端数据交互等内容,让你能够构建…...
hint: Updates were rejected because the tip of your current branch is behind!
问题 本地仓库往远段仓库推代码时候提示: error: failed to push some refs to 192.168.2.1:java-base/java-cloud.git hint: Updates were rejected because the tip of your current branch is behind! refs/heads/master:refs/heads/master [rejected] (…...
PHP 方头像转为圆图
业务需要把创建海报上的用户头像由方形转为圆形,前端的样式设置不能用。 故采用GD的函数来对方图进行裁剪处理为圆图。 目录 裁剪函数 本地图片 远程图片 效果 参考文章 总结 裁剪函数 从网上找的一个裁剪图片的函数。 代码如下: /* * 将图片切…...
centos 7 离线安装postgis插件
前一段时间记录了下如何在centos7中离线安装postgresql,因为工作需要,我不仅要安装postgresql,还需要安装postgis插件,这篇文章记录下postgis插件的安装过程。 1. 安装前的参考 如下的链接都是官网上的链接,对你安装p…...
pyinstaller打包的时候将ffmpeg也加进包中(包括打包文件夹的方法)
在使用 PyInstaller 打包包含 pydub 的 Python 应用程序时,由于 pydub 需要依赖 ffmpeg,你需要确保 ffmpeg 被正确包含进打包后的程序。以下是操作步骤: 1. 准备 ffmpeg 首先,确保你已经下载并安装了 ffmpeg。可以通过以下方式获取…...
JVM面试知识点1
内存结构(掌握内存结构划分、熟知各区域结构功能) 经典的JVM内存结构: 按照线程是否共享来划分: Heap (堆区) 1. 堆区的介绍 堆是 OOM 故障最主要的发生区域。它是内存区域中最大的一块区域,被所有线程共…...
wordpress
2024年自己建网站的步骤,新手自学建站教程 – 奶爸建站笔记 超详细图解:从 0 搭建一个个人网站,也太简单了吧 - 王一白 - 博客园 如何使用插件或者自定义页面创建一个WordPress着陆页 - 闪电博...
Day33 动态规划part02
62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。 代码随想录 视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili class Solution {public int uniquePaths(int m, int n) {int dp[][] = new int[m][n];//初…...
渗透测试之Web基础之Linux病毒编写——泷羽sec
声明: 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章。本文只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频 (bilibili.com)https://space.bilibili.com/350329294 导读: 时刻…...
jmeter基础07_组件的层级
课程大纲 1. 优先级/执行顺序(一般情况) 同级组件:按组件先后顺序执行。如:同一层的线程组、同一层的http请求。 上下级组件:先执行外层(上级),再执行内层(下级ÿ…...
Nginx反向代理和负载均衡配置
一、疑问 在苍穹外卖里,浏览器发送的请求,比如登录,其url为http://localhost/api/employee/login, 而后端的路径是http://localhost:8080/admin/employee/login 两者不一致,数据是如何准确传输的呢? 二、…...
【379】基于springboot的防疫物资管理信息系统
摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装防疫物资管理信息系统软件来发挥其高效地信息处理的作用&am…...
Linux 各个目录作用
刚毕业的时候学习Linux基础知识,发现了一份特别好的文档快乐的 Linux 命令行,翻译者是happypeter,作者当年也在慕课录制了react等前端相关的视频,通俗易懂,十分推荐 关于Linux的目录,多数博客已有详细介绍…...
【Linux】文件操作的艺术——从基础到精通
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚前言:一切皆文件 📚一、C语言的文件接口 📖1.文件打…...
java中的运算符
大家好,今天来看看java中运算符的一些知识点,理解好运算符是我们在写代码的一大重点,那么我们就来看看吧。 运算符:对操作数进行操作时的符号.,不同运算筹操作的含义不同. 一、算术算片. 1、基本四则运算符:加减乘除模(一*/%) 注意:都是二元…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
