mirror of
https://github.com/patarapolw/cjdic2.git
synced 2026-11-09 17:39:35 +00:00
(feat) sql runner for the frontend invoke
This commit is contained in:
1 parent
d6f2b145c3
commit
cbef2046fd
5 files changed
+83
-8
No files matched your search
+1
-1
@@ -5,7 +5,7 @@ mod util;
|
||||
|
||||
pub use db::{YomitanRow, YomitanZipImportProgress, YomitanZipImportResult, ZipSource};
|
||||
pub use error::CJDicError;
|
||||
pub use service::AppService;
|
||||
pub use service::{AppService, SqlParam};
|
||||
pub use util::Timer;
|
||||
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
|
||||
+65
-3
@@ -3,11 +3,11 @@ use std::{
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use rusqlite::Connection;
|
||||
use serde::Serialize;
|
||||
use rusqlite::{Connection, params_from_iter};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
ZipSource,
|
||||
Timer, ZipSource,
|
||||
db::{
|
||||
Database, YOMITAN_DBFILE, YomitanRow, YomitanWriter, YomitanZipImportProgress,
|
||||
YomitanZipImportResult,
|
||||
@@ -21,6 +21,16 @@ pub struct LoadYomitanZipDirResult {
|
||||
pub to_be_removed_dicts: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum SqlParam {
|
||||
Null,
|
||||
Integer(i64),
|
||||
Real(f64),
|
||||
Text(String),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
pub struct AppService {
|
||||
db: Database,
|
||||
}
|
||||
@@ -31,6 +41,58 @@ impl AppService {
|
||||
Ok(Self { db })
|
||||
}
|
||||
|
||||
pub fn execute_sql(
|
||||
&self,
|
||||
sql: String,
|
||||
params: Vec<SqlParam>,
|
||||
) -> Result<serde_json::Value, CJDicError> {
|
||||
let _timer = Timer::new(sql.to_string());
|
||||
|
||||
let conn = self.db.conn.lock().unwrap();
|
||||
let converted_params: Vec<_> = params
|
||||
.into_iter()
|
||||
.map(|p| match p {
|
||||
SqlParam::Null => rusqlite::types::Value::Null,
|
||||
SqlParam::Integer(i) => rusqlite::types::Value::Integer(i),
|
||||
SqlParam::Real(n) => rusqlite::types::Value::Real(n),
|
||||
SqlParam::Text(s) => rusqlite::types::Value::Text(s),
|
||||
SqlParam::Bool(b) => rusqlite::types::Value::Integer(b as i64),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut stmt = conn.prepare(&sql)?;
|
||||
|
||||
if stmt.column_count() == 0 {
|
||||
let affected = stmt.execute(params_from_iter(converted_params))?;
|
||||
return Ok(serde_json::Value::Number(affected.into()));
|
||||
}
|
||||
|
||||
let column_names: Vec<String> = stmt.column_names().iter().map(|s| s.to_string()).collect();
|
||||
let rows = stmt.query_map(params_from_iter(converted_params), |row| {
|
||||
let mut obj = serde_json::Map::new();
|
||||
|
||||
for (i, name) in column_names.iter().enumerate() {
|
||||
let value = match row.get_ref(i)? {
|
||||
rusqlite::types::ValueRef::Null => serde_json::Value::Null,
|
||||
rusqlite::types::ValueRef::Integer(i) => serde_json::Value::Number(i.into()),
|
||||
// Boolean are also rendered as an integer.
|
||||
rusqlite::types::ValueRef::Real(n) => serde_json::Number::from_f64(n)
|
||||
.map(serde_json::Value::Number)
|
||||
.unwrap_or(serde_json::Value::Null),
|
||||
rusqlite::types::ValueRef::Text(t) => {
|
||||
serde_json::Value::String(String::from_utf8_lossy(t).into())
|
||||
}
|
||||
_ => serde_json::Value::Null,
|
||||
};
|
||||
obj.insert(name.clone(), value);
|
||||
}
|
||||
return Ok(serde_json::Value::Object(obj));
|
||||
})?;
|
||||
|
||||
let result: Result<Vec<_>, _> = rows.collect();
|
||||
Ok(serde_json::Value::Array(result?))
|
||||
}
|
||||
|
||||
pub fn search_yomitan(
|
||||
&self,
|
||||
q_term: &str,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { toHiragana } from "wanakana";
|
||||
import { toKana } from "wanakana";
|
||||
|
||||
import {
|
||||
Box,
|
||||
@@ -145,7 +145,7 @@ function SearchPage() {
|
||||
|
||||
function onSearchboxChange(q: string) {
|
||||
if (isAutoKana) {
|
||||
q = toHiragana(q, { useObsoleteKana: true, IMEMode: true });
|
||||
q = toKana(q, { useObsoleteKana: true, IMEMode: true });
|
||||
}
|
||||
|
||||
setQ(q);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{borrow::Cow, path::PathBuf};
|
||||
|
||||
use cjdic2_core::{AppService, CJDicError, YomitanRow, ZipSource};
|
||||
use cjdic2_core::{AppService, CJDicError, SqlParam, YomitanRow, ZipSource};
|
||||
use tauri::{AppHandle, Emitter, Manager, Runtime, path::BaseDirectory};
|
||||
use tauri_plugin_fs::FsExt;
|
||||
|
||||
@@ -104,3 +104,12 @@ pub async fn search_yomitan(
|
||||
) -> Result<Vec<YomitanRow>, CJDicError> {
|
||||
state.search_yomitan(q_term, q_reading, limit, offset)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn execute_sql(
|
||||
sql: String,
|
||||
params: Vec<SqlParam>,
|
||||
state: tauri::State<'_, AppService>,
|
||||
) -> Result<serde_json::Value, CJDicError> {
|
||||
state.execute_sql(sql, params)
|
||||
}
|
||||
@@ -25,7 +25,11 @@ pub fn run() {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![init_yomitan, search_yomitan])
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
init_yomitan,
|
||||
search_yomitan,
|
||||
execute_sql
|
||||
])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while running tauri application")
|
||||
.run(|_app_handle, event| match event {
|
||||
|
||||
Reference in new issue
Block a user