【Tauri2】035——sql和sqlx

前言

这篇就来看看插件sql

SQL | Taurihttps://tauri.app/plugin/sql/

正文

准备

添加依赖

tauri-plugin-sql = {version = "2.2.0",features = ["sqlite"]}

features可以是mysql、sqlite、postsql

进去features看看

sqlite = [
    "sqlx/sqlite",
    "sqlx/runtime-tokio",
]

可以发现本质使用的是sqlx

sqlx - Rusthttps://docs.rs/sqlx/latest/sqlx/注册插件

        .plugin(tauri_plugin_sql::Builder::default().build())

并不像其他插件一样,有init方法,因为需要一些配置,比如连接数据库。

配置

要想配置数据库,如果数据库里面有东西,比如表,需要用到如下函数add_migrations

    pub fn add_migrations(mut self,
                          db_url: &str, 
                          migrations: Vec<Migration>) -> Self 

需要传入db_urlmigrations

比如db_url可以设置sqlite:start.db

migrations是个Vec,元素类型是Migration

Migration的定义如下

#[derive(Debug)]
pub struct Migration {
    pub version: i64,
    pub description: &'static str,
    pub sql: &'static str,
    pub kind: MigrationKind,
}

 MigrationKind是指定迁移的类型

#[derive(Debug)]
pub enum MigrationKind {
    Up,
    Down,
}

项目结构如下 

在migration.rs中

use tauri_plugin_sql::{Migration,MigrationKind};
pub fn get_migration()->Vec<Migration>{
    vec![
        // Define your migrations here
        Migration {
            version: 1,
            description: "Create book table",
            sql: r"
                     CREATE TABLE book (
                        id INTEGER PRIMARY KEY,
                        author TEXT,
                        title TEXT,
                        published_date date
                            );
                ",
            kind: MigrationKind::Up,
        }
    ] 
}

 创建了一张表

注册

       .plugin(tauri_plugin_sql::Builder::default()
            .add_migrations("sqlite:start.db",get_migration())
            .build())

 想要在后端使用

怎么在后端使用,这确实是个问题,笔者发现好像没有在后端使用的东西,全都是前端调用

比如说

    pub(crate) async fn connect<R: Runtime>(
        conn_url: &str,
        _app: &AppHandle<R>,
    ) -> Result<Self, crate::Error> 

按道理来说,connect应该可以使用,但是这是私有的,只在crate内部公开,

笔者也没找到怎么使用,

看看内部的通信函数

#[command]
pub(crate) async fn load<R: Runtime>(
    app: AppHandle<R>,
    db_instances: State<'_, DbInstances>,
    migrations: State<'_, Migrations>,
    db: String,
) -> Result<String, crate::Error> {
    let pool = DbPool::connect(&db, &app).await?;

    if let Some(migrations) = migrations.0.lock().await.remove(&db) {
        let migrator = Migrator::new(migrations).await?;
        pool.migrate(&migrator).await?;
    }

    db_instances.0.write().await.insert(db.clone(), pool);

    Ok(db)
}
impl DbPool {
    pub(crate) async fn connect
    pub(crate) async fn migrate

    pub(crate) async fn close(&self) 
    pub(crate) async fn execute
    }

可以看出使用了DbInstances和Migrations,两个State

要先连接 DbPool::connect,但是这个connect没公开,其他方法也没有公开

看来这个插件就是写在前端的。后端无法使用。

要么使用sqlx,要么修改源码。额,都很麻烦。

笔者不在后端使用这个插件。直接使用sqlx

sqlx

暂时丢掉插件,简单使用一下这个crate

创建一个数据库和book表


添加依赖

sqlx = { version = "0.8.5", features = ["sqlite", "runtime-tokio"] }

 

在connect.rs中,定义DbInstances ,然后将其注册成State

use sqlx::sqlite::SqlitePoolOptions;
use sqlx::Sqlite;
use sqlx::Pool;
use tauri::{command, AppHandle, State};
async fn connect()-> Pool<Sqlite> {
    SqlitePoolOptions::new()
        .connect("sqlite:start.db").await.unwrap()

}
pub struct DbInstances {
    pub db: Pool<Sqlite>
}
impl DbInstances {
    pub async fn new() -> Self {
        Self {
            db: connect().await
        }
    }
}

通信函数 

use sqlx::Executor;
use crate::sql::connect::DbInstances;
use tauri::{command, AppHandle, State};
use tauri::Result;

#[command]
pub async fn insert_one(state: State<'_, DbInstances>)->Result<()> {
    let db=state.db.clone();
    db.execute(r"
        INSERT INTO book (id, author, title, published_date) VALUES (2, 'gg', 'good', '2024-04-20');
    "
    ).await.unwrap();
    Ok(())

}

注册State通信函数之后。

执行后

成功。简单地使用了一下sqlx

前端使用插件sql

既然这个插件是为前端服务的,就在前端简单使用一下。

添加依赖

pnpm add @tauri-apps/plugin-sql

后端注册完成后,简单的代码如下 

import Database,{QueryResult}  from '@tauri-apps/plugin-sql';
export async function useSql(){
    const db = await Database.load('sqlite:start.db');
    let a=await db.execute("INSERT INTO book (id, author, title, published_date) VALUES (22, 'gg', 'good', '2024-04-20');");
    console.log(a)
    let b=await db.select("select * from book")
    console.log(b)
    db.close()
}

所有的通信函数都在这里。 

使用load方法和execuct方法,需要配置权限

    "sql:default",
    "sql:allow-execute"

 通信函数load

#[command]
pub(crate) async fn load<R: Runtime>(
    app: AppHandle<R>,
    db_instances: State<'_, DbInstances>,
    migrations: State<'_, Migrations>,
    db: String,
) -> Result<String, crate::Error> {
    let pool = DbPool::connect(&db, &app).await?;

    if let Some(migrations) = migrations.0.lock().await.remove(&db) {
        let migrator = Migrator::new(migrations).await?;
        pool.migrate(&migrator).await?;
    }

    db_instances.0.write().await.insert(db.clone(), pool);

    Ok(db)
}

先连接,看看DbPool::connect方法

 match conn_url
            .split_once(':')
            .ok_or_else(|| crate::Error::InvalidDbUrl(conn_url.to_string()))?
            .0
        {
            #[cfg(feature = "sqlite")]
            "sqlite" => {
                let app_path = _app
                    .path()
                    .app_config_dir()
                    .expect("No App config path was found!");

                create_dir_all(&app_path).expect("Couldn't create app config dir");

                let conn_url = &path_mapper(app_path, conn_url);

                if !Sqlite::database_exists(conn_url).await.unwrap_or(false) {
                    Sqlite::create_database(conn_url).await?;
                }
                Ok(Self::Sqlite(Pool::connect(conn_url).await?))
            }
fn path_mapper(mut app_path: std::path::PathBuf, connection_string: &str) -> String {
    app_path.push(
        connection_string
            .split_once(':')
            .expect("Couldn't parse the connection string for DB!")
            .1,
    );

对于sqlite:start.db可以发现位置其实是在app_config_dir+start.db

笔者是Window系统,位置如下

写相当路径会相对 app_config_dir。

可以写绝对路径,比如

const db = await Database.load('sqlite:D:/start/start.db');

当然,需要有表,结果如下

从官网的案例中可以发现

const result = await db.execute(
"UPDATE todos SET title = $1, status = $2 WHERE id = $3",
[todos.title, todos.status, todos.id],
);

 可以在sql语句中使用占位符。基本操作。

预加载

可以在配置文件中提前配置。不重要

  "plugins": {
    "sql": {
      "preload": ["sqlite:start.db"]
    }
  },

总结

这个插件实际上感觉就是对sqlx的封装。也不是很完全的封装,也没有对sql语句的封装。

等用于为前端提供了数据库连接和执行的接口。

### Tauri 2 开源项目详情 Tauri 是一个用于构建安全、快速小型二进制文件的应用程序框架,允许开发者创建桌面应用程序并将其打包为原生可执行文件。Tauri 使用 Rust 编写核心逻辑,并支持多种前端技术栈来开发用户界面[^1]。 对于 Tauri 2 版本而言,此版本引入了许多改进特性以及性能优化措施,在保持原有优势的基础上进一步增强了安全性与易用性。具体来说: - 改进了 API 设计以更好地适应现代 Web 技术的发展趋势; - 提升了应用启动速度及运行效率; - 增加了更多平台的支持选项; ```rust use tauri::App; fn main() { App::new("com.tauri.example") .setup(|app| { /* ... */ }) .run(); } ``` ### 贡献方式 有兴趣参与到 Tauri 社区中的个人可以通过以下几种途径做出贡献: - **报告 Bug 或提出功能请求**:通过 GitHub Issues 页面提交遇到的问题或是希望看到的新特性。 - **修复现有问题**:浏览仓库中的 open issues 列表寻找可以解决的任务,并按照指南提交 Pull Request 进行代码修改。 - **文档编写**:帮助完善官方文档或其他形式的学习资料,使新用户更容易上手使用该工具。 - **社区交流支持**:加入 Discord 频道与其他成员互动讨论,分享经验技巧的同时也为他人提供必要的指导建议。 ### 最新进展 目前关于 Tauri 的最新动态主要集中在持续迭代完善其生态系统方面的工作之上。团队正在积极努力确保稳定性兼容性的基础上不断推出新的特性增强功能。此外,还特别关注如何简化初次使用者入门流程,降低学习成本,提高整体用户体验水平[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值