• 如何使用sqlx将Rust与SQLite无缝集成
  • 发布于 2个月前
  • 775 热度
    0 评论
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();
    // 堆代码 duidaima.com
    // 在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及其功能。
用户评论