马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
前言
这篇就来看看插件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_url和migrations
比如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语句的封装。
等用于为前端提供了数据库毗连和实行的接口。
|