mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-17 06:30:50 +01:00
zwischenstand
This commit is contained in:
@ -1,13 +1,74 @@
|
||||
// database/core.rs
|
||||
use crate::database::DbConnection;
|
||||
use rusqlite::{Connection, OpenFlags};
|
||||
use serde_json::json;
|
||||
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
||||
use rusqlite::{
|
||||
types::{Value as RusqliteValue, ValueRef},
|
||||
Connection, OpenFlags, ToSql,
|
||||
};
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use tauri::State;
|
||||
// --- Hilfsfunktion: Konvertiert JSON Value zu etwas, das rusqlite versteht ---
|
||||
// Diese Funktion ist etwas knifflig wegen Ownership und Lifetimes.
|
||||
// Eine einfachere Variante ist oft, direkt rusqlite::types::Value zu erstellen.
|
||||
// Hier ein Beispiel, das owned Values erstellt (braucht evtl. Anpassung je nach rusqlite-Version/Nutzung)
|
||||
fn json_to_rusqlite_value(json_val: &JsonValue) -> Result<RusqliteValue, String> {
|
||||
match json_val {
|
||||
JsonValue::Null => Ok(RusqliteValue::Null),
|
||||
JsonValue::Bool(b) => Ok(RusqliteValue::Integer(*b as i64)), // SQLite hat keinen BOOLEAN
|
||||
JsonValue::Number(n) => {
|
||||
if let Some(i) = n.as_i64() {
|
||||
Ok(RusqliteValue::Integer(i))
|
||||
} else if let Some(f) = n.as_f64() {
|
||||
Ok(RusqliteValue::Real(f))
|
||||
} else {
|
||||
Err("Ungültiger Zahlenwert".to_string())
|
||||
}
|
||||
}
|
||||
JsonValue::String(s) => Ok(RusqliteValue::Text(s.clone())),
|
||||
JsonValue::Array(_) | JsonValue::Object(_) => {
|
||||
// SQLite kann Arrays/Objects nicht direkt speichern (außer als TEXT/BLOB)
|
||||
// Konvertiere sie zu JSON-Strings, wenn das gewünscht ist
|
||||
Ok(RusqliteValue::Text(
|
||||
serde_json::to_string(json_val).map_err(|e| e.to_string())?,
|
||||
))
|
||||
// Oder gib einen Fehler zurück, wenn Arrays/Objekte nicht erlaubt sind
|
||||
// Err("Arrays oder Objekte werden nicht direkt als Parameter unterstützt".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Tauri Command für INSERT/UPDATE/DELETE ---
|
||||
#[tauri::command]
|
||||
pub async fn execute(
|
||||
sql: String,
|
||||
params: Vec<JsonValue>,
|
||||
state: &State<'_, DbConnection>,
|
||||
) -> Result<usize, String> {
|
||||
// Gibt Anzahl betroffener Zeilen zurück
|
||||
|
||||
let params_converted: Vec<RusqliteValue> = params
|
||||
.iter()
|
||||
.map(json_to_rusqlite_value)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let params_sql: Vec<&dyn ToSql> = params_converted.iter().map(|v| v as &dyn ToSql).collect();
|
||||
|
||||
let db_lock = state
|
||||
.0
|
||||
.lock()
|
||||
.map_err(|e| format!("Mutex Lock Fehler: {}", e))?;
|
||||
let conn = db_lock.as_ref().ok_or("Keine Datenbankverbindung")?;
|
||||
|
||||
let affected_rows = conn
|
||||
.execute(&sql, ¶ms_sql[..])
|
||||
.map_err(|e| format!("SQL Execute Fehler: {}", e))?;
|
||||
|
||||
Ok(affected_rows)
|
||||
}
|
||||
|
||||
/// Führt SQL-Schreiboperationen (INSERT, UPDATE, DELETE, CREATE) ohne Berechtigungsprüfung aus
|
||||
pub async fn execute(
|
||||
/* pub async fn execute(
|
||||
sql: &str,
|
||||
params: &[String],
|
||||
state: &State<'_, DbConnection>,
|
||||
@ -26,14 +87,107 @@ pub async fn execute(
|
||||
"last_insert_id": last_id
|
||||
}))
|
||||
.map_err(|e| format!("JSON-Serialisierungsfehler: {}", e))?)
|
||||
} */
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn select(
|
||||
sql: String,
|
||||
params: Vec<JsonValue>, // Parameter als JSON Values empfangen
|
||||
state: &State<'_, DbConnection>,
|
||||
) -> Result<Vec<Vec<JsonValue>>, String> {
|
||||
// Ergebnis als Vec<RowObject>
|
||||
|
||||
// Konvertiere JSON Params zu rusqlite Values für die Abfrage
|
||||
// Wir sammeln sie als owned Values, da `params_from_iter` Referenzen braucht,
|
||||
// was mit lokalen Konvertierungen schwierig ist.
|
||||
let params_converted: Vec<RusqliteValue> = params
|
||||
.iter()
|
||||
.map(json_to_rusqlite_value)
|
||||
.collect::<Result<Vec<_>, _>>()?; // Sammle Ergebnisse, gibt Fehler weiter
|
||||
|
||||
// Konvertiere zu Slice von ToSql-Referenzen (erfordert, dass die Values leben)
|
||||
let params_sql: Vec<&dyn ToSql> = params_converted.iter().map(|v| v as &dyn ToSql).collect();
|
||||
|
||||
// Zugriff auf die Verbindung (blockierend, okay für SQLite in vielen Fällen)
|
||||
let db_lock = state
|
||||
.0
|
||||
.lock()
|
||||
.map_err(|e| format!("Mutex Lock Fehler: {}", e))?;
|
||||
let conn = db_lock.as_ref().ok_or("Keine Datenbankverbindung")?;
|
||||
|
||||
let mut stmt = conn
|
||||
.prepare(&sql)
|
||||
.map_err(|e| format!("SQL Prepare Fehler: {}", e))?;
|
||||
let column_names: Vec<String> = stmt
|
||||
.column_names()
|
||||
.into_iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
let num_columns = column_names.len();
|
||||
|
||||
let mut rows = stmt
|
||||
.query(¶ms_sql[..])
|
||||
.map_err(|e| format!("SQL Query Fehler: {}", e))?;
|
||||
let mut result_vec: Vec<Vec<JsonValue>> = Vec::new();
|
||||
|
||||
println!();
|
||||
println!();
|
||||
println!();
|
||||
println!();
|
||||
|
||||
while let Some(row) = rows.next().map_err(|e| format!("Row Next Fehler: {}", e))? {
|
||||
//let mut row_map = HashMap::new();
|
||||
let mut row_data: Vec<JsonValue> = Vec::with_capacity(num_columns);
|
||||
for i in 0..num_columns {
|
||||
let col_name = &column_names[i];
|
||||
|
||||
println!(
|
||||
"--- Processing Column --- Index: {}, Name: '{}'",
|
||||
i, col_name
|
||||
);
|
||||
let value_ref = row
|
||||
.get_ref(i)
|
||||
.map_err(|e| format!("Get Ref Fehler Spalte {}: {}", i, e))?;
|
||||
|
||||
// Wandle rusqlite ValueRef zurück zu serde_json Value
|
||||
let json_val = match value_ref {
|
||||
ValueRef::Null => JsonValue::Null,
|
||||
ValueRef::Integer(i) => JsonValue::Number(i.into()),
|
||||
ValueRef::Real(f) => JsonValue::Number(
|
||||
serde_json::Number::from_f64(f).unwrap_or(serde_json::Number::from(0)),
|
||||
), // Fallback für NaN/Infinity
|
||||
ValueRef::Text(t) => {
|
||||
let s = String::from_utf8_lossy(t).to_string();
|
||||
// Versuche, als JSON zu parsen, falls es ursprünglich ein Array/Objekt war
|
||||
//serde_json::from_str(&s).unwrap_or(JsonValue::String(s))
|
||||
JsonValue::String(s)
|
||||
}
|
||||
ValueRef::Blob(b) => {
|
||||
// BLOBs z.B. als Base64-String zurückgeben
|
||||
JsonValue::String(STANDARD.encode(b))
|
||||
}
|
||||
};
|
||||
println!(
|
||||
"new row: name: {} with value: {}",
|
||||
column_names[i].clone(),
|
||||
json_val,
|
||||
);
|
||||
row_data.push(json_val);
|
||||
//row_map.insert(column_names[i].clone(), json_val);
|
||||
}
|
||||
//result_vec.push(row_map);
|
||||
result_vec.push(row_data);
|
||||
}
|
||||
|
||||
Ok(result_vec)
|
||||
}
|
||||
|
||||
/// Führt SQL-Leseoperationen (SELECT) ohne Berechtigungsprüfung aus
|
||||
pub async fn select(
|
||||
/* pub async fn select(
|
||||
sql: &str,
|
||||
params: &[String],
|
||||
state: &State<'_, DbConnection>,
|
||||
) -> Result<Vec<Vec<String>>, String> {
|
||||
) -> Result<Vec<Vec<Option<String>>>, String> {
|
||||
let db = state.0.lock().map_err(|e| format!("Mutex-Fehler: {}", e))?;
|
||||
let conn = db.as_ref().ok_or("Keine Datenbankverbindung vorhanden")?;
|
||||
|
||||
@ -52,16 +206,20 @@ pub async fn select(
|
||||
{
|
||||
let mut row_data = Vec::new();
|
||||
for i in 0..columns {
|
||||
let value: String = row
|
||||
let value = row
|
||||
.get(i)
|
||||
.map_err(|e| format!("Datentypfehler in Spalte {}: {}", i, e))?;
|
||||
row_data.push(value);
|
||||
}
|
||||
/* println!(
|
||||
"Select Row Data: {}",
|
||||
&row_data.clone().join("").to_string()
|
||||
); */
|
||||
result.push(row_data);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
} */
|
||||
|
||||
/// Öffnet und initialisiert eine Datenbank mit Verschlüsselung
|
||||
pub fn open_and_init_db(path: &str, key: &str, create: bool) -> Result<Connection, String> {
|
||||
@ -75,6 +233,9 @@ pub fn open_and_init_db(path: &str, key: &str, create: bool) -> Result<Connectio
|
||||
conn.pragma_update(None, "key", key)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
conn.execute_batch("SELECT count(*) from haex_extensions")
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user