Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugins/sql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ time = "0.3"
tokio = { version = "1", features = ["sync"] }
indexmap = { version = "2", features = ["serde"] }
uuid = "1"
strum = { version = "0.28", features = ["derive"] }

[features]
sqlite = ["sqlx/sqlite", "sqlx/runtime-tokio"]
Expand Down
97 changes: 62 additions & 35 deletions plugins/sql/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

import { invoke } from '@tauri-apps/api/core'
import { invoke } from '@tauri-apps/api/core';

export interface QueryResult {
/** The number of rows affected by the query. */
rowsAffected: number
rowsAffected: number;
/**
* The last inserted `id`.
*
Expand All @@ -15,7 +15,12 @@ export interface QueryResult {
* must be used, with a `RETURNING` clause
* (`INSERT INTO todos (title) VALUES ($1) RETURNING id`).
*/
lastInsertId?: number
lastInsertId?: number;
}

export interface ErrorInfo {
kind: 'Sql' | 'Migration' | 'InvalidDbUrl' | 'DatabaseNotLoaded' | 'UnsupportedDatatype' | (string & {});
message: string;
}

/**
Expand All @@ -25,9 +30,9 @@ export interface QueryResult {
* communicating with the rust side of the sql plugin.
*/
export default class Database {
path: string
path: string;
constructor(path: string) {
this.path = path
this.path = path;
}

/**
Expand All @@ -45,12 +50,19 @@ export default class Database {
* const db = await Database.load("sqlite:test.db");
* ```
*/
static async load(path: string): Promise<Database> {
const _path = await invoke<string>('plugin:sql|load', {
db: path
})
static async load(path: string, applyMigrations = true): Promise<Database | ErrorInfo> {
try {
const _path = await invoke<string>('plugin:sql|load', {
db: path,
applyMigrations: applyMigrations,
});

return new Database(_path);
}
catch (err) {
return err as ErrorInfo;
}

return new Database(_path)
}

/**
Expand All @@ -70,7 +82,7 @@ export default class Database {
* ```
*/
static get(path: string): Database {
return new Database(path)
return new Database(path);
}

/**
Expand Down Expand Up @@ -105,18 +117,23 @@ export default class Database {
* );
* ```
*/
async execute(query: string, bindValues?: unknown[]): Promise<QueryResult> {
const [rowsAffected, lastInsertId] = await invoke<[number, number]>(
'plugin:sql|execute',
{
db: this.path,
query,
values: bindValues ?? []
}
)
return {
lastInsertId,
rowsAffected
async execute(query: string, bindValues?: unknown[]): Promise<QueryResult | ErrorInfo> {
try {
const [rowsAffected, lastInsertId] = await invoke<[number, number]>(
'plugin:sql|execute',
{
db: this.path,
query,
values: bindValues ?? []
}
);
return {
lastInsertId,
rowsAffected
};
}
catch (err) {
return err as ErrorInfo;
}
}

Expand All @@ -138,14 +155,19 @@ export default class Database {
* );
* ```
*/
async select<T>(query: string, bindValues?: unknown[]): Promise<T> {
const result = await invoke<T>('plugin:sql|select', {
db: this.path,
query,
values: bindValues ?? []
})
async select<T>(query: string, bindValues?: unknown[]): Promise<T | ErrorInfo> {
try {
const result = await invoke<T>('plugin:sql|select', {
db: this.path,
query,
values: bindValues ?? []
});

return result
return result;
}
catch (err) {
return err as ErrorInfo;
}
}

/**
Expand All @@ -159,10 +181,15 @@ export default class Database {
* ```
* @param db - Optionally state the name of a database if you are managing more than one. Otherwise, all database pools will be in scope.
*/
async close(db?: string): Promise<boolean> {
const success = await invoke<boolean>('plugin:sql|close', {
db
})
return success
async close(db?: string): Promise<boolean | ErrorInfo> {
try {
const success = await invoke<boolean>('plugin:sql|close', {
db
});
return success;
}
catch (err) {
return err as ErrorInfo;
}
}
}
9 changes: 6 additions & 3 deletions plugins/sql/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ pub(crate) async fn load<R: Runtime>(
db_instances: State<'_, DbInstances>,
migrations: State<'_, Migrations>,
db: String,
apply_migrations: bool,
) -> 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?;
if apply_migrations {
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);
Expand Down
16 changes: 14 additions & 2 deletions plugins/sql/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use serde::{Serialize, Serializer};

#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, strum::AsRefStr)]
pub enum Error {
#[error(transparent)]
Sql(#[from] sqlx::Error),
Expand All @@ -18,11 +18,23 @@ pub enum Error {
UnsupportedDatatype(String),
}

#[derive(serde::Serialize)]
pub struct ErrorInfo {
kind: String,
message: String,
}

impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
let error_kind = self.as_ref().to_string();
let error_message = self.to_string();
let error_info = ErrorInfo {
kind: error_kind,
message: error_message,
};
error_info.serialize(serializer)
}
}