在 Rust 中使用 SQLX 集成 SQLite 數據庫
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 和模塊
首先導入必要的 crate 和模塊,如數據庫操作的 sqlx 和處理操作結果的 std::result::Result。
use std::result::Result;
use sqlx::{sqlite::SqliteQueryResult, Sqlite, SqlitePool, migrate::MigrateDatabase};
第二步,創建數據庫 Schema
定義 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
}
第三步,main 函數
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 })
注意
-
**關閉連接:**在 create_schema 函數和 main 程序中,完成操作後,都使用 pool.close().await 顯式關閉數據庫連接。
-
**錯誤處理:**該程序包括基本的錯誤處理。在 create_schema 和 main 函數中,使用 Rust 的模式匹配來處理異步操作的結果,打印成功消息或在出現錯誤時 panic。
-
**運行程序:**要運行此程序,需要一個異步運行時。在這裏由#[async_std::main] 屬性表示,指定使用 async-std crate 的運行時。
將 Rust 與 SQLite 集成僅僅是個開始,你可以嘗試執行不同的 sql 語句,深入瞭解 sqlx 及其功能。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/u6Heoqi4c28Uk5Sxp1kz0Q