SQLite是一个c语言库,它实现了一个小型、快速、自包含、高可靠性、全功能的SQL数据库引擎,与Rust的安全性和性能非常匹配。
sqlx crate是一个很棒的工具,可以提供到各种数据库(包括SQLite)的异步连接。sqlx的美妙之处在于它可以在编译时检查SQL查询语句以及它与Rust异步特性的兼容。
在这篇文章中,我们将探索如何使用sqlx将Rust与SQLite无缝集成;我们还将探索Rust中异步编程的复杂性,确保你在将来的项目中能够很好地处理数据库操作。在文章的最后,你将拥有一个使用Rust创建和操作数据库的工作示例,同时包含异步编程。
使用如下命令创建一个Rust新项目:
cargo new rust-sqlx-sqlite
在Cargo.toml文件中,加入以下依赖项:
[dependencies]
sqlx ={ version = "0.7.3", features = ["runtime-async-std-native-tls", "sqlite"]}
async-std ={ version = "1.6", features = ["attributes"]}
futures = "0.3.18"
首先导入必要的crate和模块,如数据库操作的sqlx和处理操作结果的std::result::Result。
use std::result::Result;
use sqlx::{sqlite::SqliteQueryResult, Sqlite, SqlitePool, migrate::MigrateDatabase};
定义create_schema异步函数,用于在SQLite数据库中创建一个新的schema。它以数据库URL作为输入,并尝试使用SqlitePool::connect连接到数据库。在建立连接之后,执行SQL命令以启用外键并创建两个表:settings和project,其中project具有对settings的外键引用。代码如下:
// 传入db_url,它期望返回一个SqliteQueryResult
async fn create_schema(db_url:&str) -> Result<SqliteQueryResult, sqlx::Error> {
// 创建一个连接到db_url的连接池
let pool = SqlitePool::connect(db_url).await?;
// 定义数据库表
let qry =
"PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS settings
(
settings_id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
created_on DATETIME DEFAULT (datetime('now', 'localtime')),
updated_on DATETIME DEFAULT (datetime('now', 'localtime')),
done BOOLEAN NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS project
(
project_id INTEGER PRIMARY KEY AUTOINCREMENT,
product_name TEXT,
created_on DATETIME DEFAULT (datetime('now', 'localtime')),
updated_on DATETIME DEFAULT (datetime('now', 'localtime')),
img_directory TEXT NOT NULL,
out_directory TEXT NOT NULL,
status TEXT NOT NULL,
settings_id INTEGER NOT NULL DEFAULT 1,
FOREIGN KEY (settings_id) REFERENCES settings (settings_id) ON UPDATE SET NULL ON DELETE SET NULL
);";
// 运行
let result = sqlx::query(qry).execute(&pool).await;
// 关闭连接池
pool.close().await;
result
}
async Main函数是程序的异步入口点,它首先使用Sqlite::database_exists检查数据库是否存在,如果不存在,则使用Sqlite::create_database创建数据库。然后,调用create_schema来设置数据库模式。在模式创建之后,再次连接到数据库,在settings表中插入一条testing记录。
#[async_std::main]
async fn main() {
// 在项目根目录下创建一个数据库名为'sqlite.db'文件
let db_url = String::from("sqlite://sqlite.db");
// 如果数据库不存在,则创建它。
if !Sqlite::database_exists(&db_url).await.unwrap_or(false){
Sqlite::create_database(&db_url).await.unwrap();
//如果存在,则调用create_schema
match create_schema(&db_url).await {
// 如果一切顺利,打印OK…否则panic
Ok(_) => println!("database created succesfully"),
Err(e) => panic!("{}", e)
}
}
// 连接数据库
let instances = SqlitePool::connect(&db_url).await.unwrap();
// 在settings表的description字段插入"testing"
let qry = "INSERT INTO settings (description) VALUES($1)";
let result = sqlx::query(qry).bind("testing").execute(&instances).await;
// 关闭数据库
instances.close().await;
println!("{:?}", result);
}
运行结果如下:
database created succesfully
Ok(SqliteQueryResult { changes: 1, last_insert_rowid: 1 })
将Rust与SQLite集成仅仅是个开始,你可以尝试执行不同的sql语句,深入了解sqlx及其功能。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8