fixed drizzle rust logic

This commit is contained in:
2025-10-21 16:29:13 +02:00
parent e268947593
commit 9ea057e943
13 changed files with 151 additions and 112 deletions

View File

@ -164,7 +164,9 @@ pub fn execute(
if has_returning { if has_returning {
// Use prepare + query for RETURNING statements // Use prepare + query for RETURNING statements
let mut stmt = conn.prepare(&sql).map_err(|e| DatabaseError::PrepareError { let mut stmt = conn
.prepare(&sql)
.map_err(|e| DatabaseError::PrepareError {
reason: e.to_string(), reason: e.to_string(),
})?; })?;
@ -183,10 +185,10 @@ pub fn execute(
let mut row_values: Vec<JsonValue> = Vec::with_capacity(num_columns); let mut row_values: Vec<JsonValue> = Vec::with_capacity(num_columns);
for i in 0..num_columns { for i in 0..num_columns {
let value_ref = row.get_ref(i).map_err(|e| { let value_ref =
DatabaseError::RowProcessingError { row.get_ref(i)
.map_err(|e| DatabaseError::RowProcessingError {
reason: format!("Failed to get column {}: {}", i, e), reason: format!("Failed to get column {}: {}", i, e),
}
})?; })?;
let json_val = convert_value_ref_to_json(value_ref)?; let json_val = convert_value_ref_to_json(value_ref)?;
@ -274,6 +276,16 @@ pub fn select(
}) })
} }
pub fn select_with_crdt(
sql: String,
params: Vec<JsonValue>,
connection: &DbConnection,
) -> Result<Vec<Vec<JsonValue>>, DatabaseError> {
with_connection(&connection, |conn| {
SqlExecutor::select_internal(conn, &sql, &params)
})
}
/// Konvertiert rusqlite ValueRef zu JSON /// Konvertiert rusqlite ValueRef zu JSON
pub fn convert_value_ref_to_json(value_ref: ValueRef) -> Result<JsonValue, DatabaseError> { pub fn convert_value_ref_to_json(value_ref: ValueRef) -> Result<JsonValue, DatabaseError> {
let json_val = match value_ref { let json_val = match value_ref {

View File

@ -43,6 +43,15 @@ pub fn sql_execute(
core::execute(sql, params, &state.db) core::execute(sql, params, &state.db)
} }
#[tauri::command]
pub fn sql_select_with_crdt(
sql: String,
params: Vec<JsonValue>,
state: State<'_, AppState>,
) -> Result<Vec<Vec<JsonValue>>, DatabaseError> {
core::select_with_crdt(sql, params, &state.db)
}
#[tauri::command] #[tauri::command]
pub fn sql_execute_with_crdt( pub fn sql_execute_with_crdt(
sql: String, sql: String,

View File

@ -167,7 +167,6 @@ impl ExtensionManager {
Ok(specific_extension_dir) Ok(specific_extension_dir)
} }
pub fn add_production_extension(&self, extension: Extension) -> Result<(), ExtensionError> { pub fn add_production_extension(&self, extension: Extension) -> Result<(), ExtensionError> {
if extension.id.is_empty() { if extension.id.is_empty() {
return Err(ExtensionError::ValidationError { return Err(ExtensionError::ValidationError {
@ -223,10 +222,11 @@ impl ExtensionManager {
name: &str, name: &str,
) -> Result<Option<(String, Extension)>, ExtensionError> { ) -> Result<Option<(String, Extension)>, ExtensionError> {
// 1. Check dev extensions first (higher priority) // 1. Check dev extensions first (higher priority)
let dev_extensions = self.dev_extensions.lock().map_err(|e| { let dev_extensions =
ExtensionError::MutexPoisoned { self.dev_extensions
.lock()
.map_err(|e| ExtensionError::MutexPoisoned {
reason: e.to_string(), reason: e.to_string(),
}
})?; })?;
for (id, ext) in dev_extensions.iter() { for (id, ext) in dev_extensions.iter() {
@ -236,10 +236,11 @@ impl ExtensionManager {
} }
// 2. Check production extensions // 2. Check production extensions
let prod_extensions = self.production_extensions.lock().map_err(|e| { let prod_extensions =
ExtensionError::MutexPoisoned { self.production_extensions
.lock()
.map_err(|e| ExtensionError::MutexPoisoned {
reason: e.to_string(), reason: e.to_string(),
}
})?; })?;
for (id, ext) in prod_extensions.iter() { for (id, ext) in prod_extensions.iter() {
@ -262,11 +263,7 @@ impl ExtensionManager {
.map(|(_, ext)| ext)) .map(|(_, ext)| ext))
} }
pub fn remove_extension( pub fn remove_extension(&self, public_key: &str, name: &str) -> Result<(), ExtensionError> {
&self,
public_key: &str,
name: &str,
) -> Result<(), ExtensionError> {
let (id, _) = self let (id, _) = self
.find_extension_id_by_public_key_and_name(public_key, name)? .find_extension_id_by_public_key_and_name(public_key, name)?
.ok_or_else(|| ExtensionError::NotFound { .ok_or_else(|| ExtensionError::NotFound {
@ -276,10 +273,11 @@ impl ExtensionManager {
// Remove from dev extensions first // Remove from dev extensions first
{ {
let mut dev_extensions = self.dev_extensions.lock().map_err(|e| { let mut dev_extensions =
ExtensionError::MutexPoisoned { self.dev_extensions
.lock()
.map_err(|e| ExtensionError::MutexPoisoned {
reason: e.to_string(), reason: e.to_string(),
}
})?; })?;
if dev_extensions.remove(&id).is_some() { if dev_extensions.remove(&id).is_some() {
return Ok(()); return Ok(());
@ -288,10 +286,11 @@ impl ExtensionManager {
// Remove from production extensions // Remove from production extensions
{ {
let mut prod_extensions = self.production_extensions.lock().map_err(|e| { let mut prod_extensions =
ExtensionError::MutexPoisoned { self.production_extensions
.lock()
.map_err(|e| ExtensionError::MutexPoisoned {
reason: e.to_string(), reason: e.to_string(),
}
})?; })?;
prod_extensions.remove(&id); prod_extensions.remove(&id);
} }
@ -316,7 +315,10 @@ impl ExtensionManager {
})?; })?;
eprintln!("DEBUG: Removing extension with ID: {}", extension.id); eprintln!("DEBUG: Removing extension with ID: {}", extension.id);
eprintln!("DEBUG: Extension name: {}, version: {}", extension_name, extension_version); eprintln!(
"DEBUG: Extension name: {}, version: {}",
extension_name, extension_version
);
// Lösche Permissions und Extension-Eintrag in einer Transaktion // Lösche Permissions und Extension-Eintrag in einer Transaktion
with_connection(&state.db, |conn| { with_connection(&state.db, |conn| {
@ -327,12 +329,11 @@ impl ExtensionManager {
})?; })?;
// Lösche alle Permissions mit extension_id // Lösche alle Permissions mit extension_id
eprintln!("DEBUG: Deleting permissions for extension_id: {}", extension.id); eprintln!(
PermissionManager::delete_permissions_in_transaction( "DEBUG: Deleting permissions for extension_id: {}",
&tx, extension.id
&hlc_service, );
&extension.id, PermissionManager::delete_permissions_in_transaction(&tx, &hlc_service, &extension.id)?;
)?;
// Lösche Extension-Eintrag mit extension_id // Lösche Extension-Eintrag mit extension_id
let sql = format!("DELETE FROM {} WHERE id = ?", TABLE_EXTENSIONS); let sql = format!("DELETE FROM {} WHERE id = ?", TABLE_EXTENSIONS);
@ -573,6 +574,7 @@ impl ExtensionManager {
app_handle: &AppHandle, app_handle: &AppHandle,
state: &State<'_, AppState>, state: &State<'_, AppState>,
) -> Result<Vec<String>, ExtensionError> { ) -> Result<Vec<String>, ExtensionError> {
// Clear existing data
self.production_extensions self.production_extensions
.lock() .lock()
.map_err(|e| ExtensionError::MutexPoisoned { .map_err(|e| ExtensionError::MutexPoisoned {
@ -592,19 +594,22 @@ impl ExtensionManager {
})? })?
.clear(); .clear();
// Schritt 1: Alle Daten aus der Datenbank in einem Rutsch laden. // Lade alle Daten aus der Datenbank
let extensions = with_connection(&state.db, |conn| { let extensions = with_connection(&state.db, |conn| {
let sql = format!( let sql = format!(
"SELECT id, name, version, author, entry, icon, public_key, signature, homepage, description, enabled FROM {}", "SELECT id, name, version, author, entry, icon, public_key, signature, homepage, description, enabled FROM {}",
TABLE_EXTENSIONS TABLE_EXTENSIONS
); );
eprintln!("DEBUG: SQL Query before transformation: {}", sql); eprintln!("DEBUG: SQL Query before transformation: {}", sql);
// select_internal gibt jetzt Vec<Vec<JsonValue>> zurück
let results = SqlExecutor::select_internal(conn, &sql, &[])?; let results = SqlExecutor::select_internal(conn, &sql, &[])?;
eprintln!("DEBUG: Query returned {} results", results.len()); eprintln!("DEBUG: Query returned {} results", results.len());
let mut data = Vec::new(); let mut data = Vec::new();
for result in results { for row in results {
let id = result["id"] // Wir erwarten die Werte in der Reihenfolge der SELECT-Anweisung
let id = row[0]
.as_str() .as_str()
.ok_or_else(|| DatabaseError::SerializationError { .ok_or_else(|| DatabaseError::SerializationError {
reason: "Missing id field".to_string(), reason: "Missing id field".to_string(),
@ -612,31 +617,31 @@ impl ExtensionManager {
.to_string(); .to_string();
let manifest = ExtensionManifest { let manifest = ExtensionManifest {
name: result["name"] name: row[1]
.as_str() .as_str()
.ok_or_else(|| DatabaseError::SerializationError { .ok_or_else(|| DatabaseError::SerializationError {
reason: "Missing name field".to_string(), reason: "Missing name field".to_string(),
})? })?
.to_string(), .to_string(),
version: result["version"] version: row[2]
.as_str() .as_str()
.ok_or_else(|| DatabaseError::SerializationError { .ok_or_else(|| DatabaseError::SerializationError {
reason: "Missing version field".to_string(), reason: "Missing version field".to_string(),
})? })?
.to_string(), .to_string(),
author: result["author"].as_str().map(String::from), author: row[3].as_str().map(String::from),
entry: result["entry"].as_str().unwrap_or("index.html").to_string(), entry: row[4].as_str().unwrap_or("index.html").to_string(),
icon: result["icon"].as_str().map(String::from), icon: row[5].as_str().map(String::from),
public_key: result["public_key"].as_str().unwrap_or("").to_string(), public_key: row[6].as_str().unwrap_or("").to_string(),
signature: result["signature"].as_str().unwrap_or("").to_string(), signature: row[7].as_str().unwrap_or("").to_string(),
permissions: ExtensionPermissions::default(), permissions: ExtensionPermissions::default(),
homepage: result["homepage"].as_str().map(String::from), homepage: row[8].as_str().map(String::from),
description: result["description"].as_str().map(String::from), description: row[9].as_str().map(String::from),
}; };
let enabled = result["enabled"] let enabled = row[10]
.as_bool() .as_bool()
.or_else(|| result["enabled"].as_i64().map(|v| v != 0)) .or_else(|| row[10].as_i64().map(|v| v != 0))
.unwrap_or(false); .unwrap_or(false);
data.push(ExtensionDataFromDb { data.push(ExtensionDataFromDb {
@ -684,10 +689,7 @@ impl ExtensionManager {
continue; continue;
} }
eprintln!( eprintln!("DEBUG: Extension loaded successfully: {}", extension_id);
"DEBUG: Extension loaded successfully: {}",
extension_id
);
let extension = Extension { let extension = Extension {
id: extension_id.clone(), id: extension_id.clone(),

View File

@ -5,6 +5,8 @@ use crate::crdt::transformer::CrdtTransformer;
use crate::crdt::trigger; use crate::crdt::trigger;
use crate::database::core::{convert_value_ref_to_json, parse_sql_statements, ValueConverter}; use crate::database::core::{convert_value_ref_to_json, parse_sql_statements, ValueConverter};
use crate::database::error::DatabaseError; use crate::database::error::DatabaseError;
use crate::database::DbConnection;
use rusqlite::Connection;
use rusqlite::{params_from_iter, types::Value as SqliteValue, ToSql, Transaction}; use rusqlite::{params_from_iter, types::Value as SqliteValue, ToSql, Transaction};
use serde_json::Value as JsonValue; use serde_json::Value as JsonValue;
use sqlparser::ast::{Insert, Statement, TableObject}; use sqlparser::ast::{Insert, Statement, TableObject};
@ -423,10 +425,10 @@ impl SqlExecutor {
/// Führt SELECT aus (mit CRDT-Transformation) - OHNE Permission-Check /// Führt SELECT aus (mit CRDT-Transformation) - OHNE Permission-Check
pub fn select_internal( pub fn select_internal(
conn: &rusqlite::Connection, conn: &Connection,
sql: &str, sql: &str,
params: &[JsonValue], params: &[JsonValue],
) -> Result<Vec<JsonValue>, DatabaseError> { ) -> Result<Vec<Vec<JsonValue>>, DatabaseError> {
// Parameter validation // Parameter validation
let total_placeholders = sql.matches('?').count(); let total_placeholders = sql.matches('?').count();
if total_placeholders != params.len() { if total_placeholders != params.len() {
@ -457,42 +459,40 @@ impl SqlExecutor {
let sql_params = ValueConverter::convert_params(params)?; let sql_params = ValueConverter::convert_params(params)?;
let transformer = CrdtTransformer::new(); let transformer = CrdtTransformer::new();
let last_statement = ast_vec.pop().unwrap(); let mut stmt_to_execute = ast_vec.pop().unwrap();
let mut stmt_to_execute = last_statement;
transformer.transform_select_statement(&mut stmt_to_execute)?; transformer.transform_select_statement(&mut stmt_to_execute)?;
let transformed_sql = stmt_to_execute.to_string(); let transformed_sql = stmt_to_execute.to_string();
let mut prepared_stmt = let mut prepared_stmt = conn.prepare(&transformed_sql)?;
conn.prepare(&transformed_sql) let num_columns = prepared_stmt.column_count();
.map_err(|e| DatabaseError::ExecutionError {
sql: transformed_sql.clone(),
reason: e.to_string(),
table: None,
})?;
let column_names: Vec<String> = prepared_stmt let mut rows = prepared_stmt
.column_names() .query(params_from_iter(sql_params.iter()))
.into_iter()
.map(|s| s.to_string())
.collect();
let rows = prepared_stmt
.query_map(params_from_iter(sql_params.iter()), |row| {
crate::extension::database::row_to_json_value(row, &column_names)
})
.map_err(|e| DatabaseError::QueryError { .map_err(|e| DatabaseError::QueryError {
reason: e.to_string(), reason: e.to_string(),
})?; })?;
let mut results = Vec::new(); let mut result_vec: Vec<Vec<JsonValue>> = Vec::new();
for row_result in rows {
results.push(row_result.map_err(|e| DatabaseError::RowProcessingError { while let Some(row) = rows.next().map_err(|e| DatabaseError::RowProcessingError {
reason: e.to_string(), reason: format!("Row iteration error: {}", e),
})?); })? {
let mut row_values: Vec<JsonValue> = Vec::with_capacity(num_columns);
for i in 0..num_columns {
let value_ref = row
.get_ref(i)
.map_err(|e| DatabaseError::RowProcessingError {
reason: format!("Failed to get column {}: {}", i, e),
})?;
let json_val = convert_value_ref_to_json(value_ref)?;
row_values.push(json_val);
}
result_vec.push(row_values);
} }
Ok(results) Ok(result_vec)
} }
/// Führt SQL mit CRDT-Transformation aus und gibt RETURNING-Ergebnisse zurück /// Führt SQL mit CRDT-Transformation aus und gibt RETURNING-Ergebnisse zurück

View File

@ -70,15 +70,16 @@ pub fn run() {
database::delete_vault, database::delete_vault,
database::list_vaults, database::list_vaults,
database::open_encrypted_database, database::open_encrypted_database,
database::sql_execute,
database::sql_execute_with_crdt, database::sql_execute_with_crdt,
database::sql_execute,
database::sql_query_with_crdt, database::sql_query_with_crdt,
database::sql_select_with_crdt,
database::sql_select, database::sql_select,
database::vault_exists, database::vault_exists,
extension::database::extension_sql_execute, extension::database::extension_sql_execute,
extension::database::extension_sql_select, extension::database::extension_sql_select,
extension::get_all_extensions,
extension::get_all_dev_extensions, extension::get_all_dev_extensions,
extension::get_all_extensions,
extension::get_extension_info, extension::get_extension_info,
extension::install_extension_with_permissions, extension::install_extension_with_permissions,
extension::is_extension_installed, extension::is_extension_installed,

View File

@ -17,6 +17,7 @@
class="w-full h-full" class="w-full h-full"
@swiper="onSwiperInit" @swiper="onSwiperInit"
@slide-change="onSlideChange" @slide-change="onSlideChange"
direction="vertical"
> >
<SwiperSlide <SwiperSlide
v-for="workspace in workspaces" v-for="workspace in workspaces"

View File

@ -52,7 +52,7 @@
<p <p
v-if="extension.description" v-if="extension.description"
class="text-sm text-gray-600 dark:text-gray-300 mt-2 line-clamp-2" class="hidden @lg:flex text-sm text-gray-600 dark:text-gray-300 mt-2 line-clamp-2"
> >
{{ extension.description }} {{ extension.description }}
</p> </p>
@ -67,7 +67,9 @@
> >
<UIcon name="i-heroicons-check-circle-solid" /> <UIcon name="i-heroicons-check-circle-solid" />
<span v-if="!extension.installedVersion">{{ t('installed') }}</span> <span v-if="!extension.installedVersion">{{ t('installed') }}</span>
<span v-else>{{ t('installedVersion', { version: extension.installedVersion }) }}</span> <span v-else>{{
t('installedVersion', { version: extension.installedVersion })
}}</span>
</div> </div>
<div <div
v-if="extension.downloads" v-if="extension.downloads"
@ -114,10 +116,16 @@
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
<UButton <UButton
:label="getInstallButtonLabel()" :label="getInstallButtonLabel()"
:color="extension.isInstalled && !extension.installedVersion ? 'neutral' : 'primary'" :color="
extension.isInstalled && !extension.installedVersion
? 'neutral'
: 'primary'
"
:disabled="extension.isInstalled && !extension.installedVersion" :disabled="extension.isInstalled && !extension.installedVersion"
:icon=" :icon="
extension.isInstalled && !extension.installedVersion ? 'i-heroicons-check' : 'i-heroicons-arrow-down-tray' extension.isInstalled && !extension.installedVersion
? 'i-heroicons-check'
: 'i-heroicons-arrow-down-tray'
" "
size="sm" size="sm"
@click.stop="$emit('install')" @click.stop="$emit('install')"

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="flex flex-col h-full"> <div class="flex flex-col h-full bg-default">
<!-- Header with Actions --> <!-- Header with Actions -->
<div <div
class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 p-6 border-b border-gray-200 dark:border-gray-800" class="flex flex-col @lg:flex-row @lg:items-center justify-between gap-4 p-6 border-b border-gray-200 dark:border-gray-800"
> >
<div> <div>
<h1 class="text-2xl font-bold"> <h1 class="text-2xl font-bold">
@ -14,14 +14,14 @@
</div> </div>
<div <div
class="flex flex-col sm:flex-row items-stretch sm:items-center gap-3" class="flex flex-col @lg:flex-row items-stretch @lg:items-center gap-3"
> >
<!-- Marketplace Selector --> <!-- Marketplace Selector -->
<USelectMenu <USelectMenu
v-model="selectedMarketplace" v-model="selectedMarketplace"
:items="marketplaces" :items="marketplaces"
value-key="id" value-key="id"
class="w-full sm:w-48" class="w-full @lg:w-48"
> >
<template #leading> <template #leading>
<UIcon name="i-heroicons-building-storefront" /> <UIcon name="i-heroicons-building-storefront" />
@ -34,13 +34,14 @@
icon="i-heroicons-arrow-up-tray" icon="i-heroicons-arrow-up-tray"
color="neutral" color="neutral"
@click="onSelectExtensionAsync" @click="onSelectExtensionAsync"
block
/> />
</div> </div>
</div> </div>
<!-- Search and Filters --> <!-- Search and Filters -->
<div <div
class="flex flex-col sm:flex-row items-stretch sm:items-center gap-4 p-6 border-b border-gray-200 dark:border-gray-800" class="flex flex-col @lg:flex-row items-stretch @lg:items-center gap-4 p-6 border-b border-gray-200 dark:border-gray-800"
> >
<UInput <UInput
v-model="searchQuery" v-model="searchQuery"
@ -53,7 +54,7 @@
:items="categories" :items="categories"
:placeholder="t('filter.category')" :placeholder="t('filter.category')"
value-key="id" value-key="id"
class="w-full sm:w-48" class="w-full @lg:w-48"
> >
<template #leading> <template #leading>
<UIcon name="i-heroicons-tag" /> <UIcon name="i-heroicons-tag" />
@ -65,7 +66,7 @@
<div class="flex-1 overflow-auto p-6"> <div class="flex-1 overflow-auto p-6">
<div <div
v-if="filteredExtensions.length" v-if="filteredExtensions.length"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" class="grid grid-cols-1 @md:grid-cols-2 @2xl:grid-cols-3 gap-4"
> >
<!-- Marketplace Extension Card --> <!-- Marketplace Extension Card -->
<HaexExtensionMarketplaceCard <HaexExtensionMarketplaceCard

View File

@ -1,8 +1,6 @@
<template> <template>
<div> <div class="w-full h-full bg-default">
<div <div class="grid grid-cols-2 p-2">
class="grid grid-rows-2 sm:grid-cols-2 sm:gap-2 p-2 max-w-2xl w-full h-fit"
>
<div class="p-2">{{ t('language') }}</div> <div class="p-2">{{ t('language') }}</div>
<div><UiDropdownLocale @select="onSelectLocaleAsync" /></div> <div><UiDropdownLocale @select="onSelectLocaleAsync" /></div>
@ -34,6 +32,8 @@
@change="onUpdateDeviceNameAsync" @change="onUpdateDeviceNameAsync"
/> />
</div> </div>
<div class="h-full"></div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -5,7 +5,7 @@
:class="[ :class="[
'absolute bg-default/80 backdrop-blur-xl rounded-xl shadow-2xl overflow-hidden isolate', 'absolute bg-default/80 backdrop-blur-xl rounded-xl shadow-2xl overflow-hidden isolate',
'border border-gray-200 dark:border-gray-700 transition-all ease-out duration-600 ', 'border border-gray-200 dark:border-gray-700 transition-all ease-out duration-600 ',
'flex flex-col', 'flex flex-col @container',
{ 'select-none': isResizingOrDragging }, { 'select-none': isResizingOrDragging },
isActive ? 'z-50' : 'z-10', isActive ? 'z-50' : 'z-10',
]" ]"
@ -208,6 +208,7 @@ useDrag(
} }
} }
globalThis.getSelection()?.removeAllRanges()
emit('positionChanged', x.value, y.value) emit('positionChanged', x.value, y.value)
emit('sizeChanged', width.value, height.value) emit('sizeChanged', width.value, height.value)
emit('dragEnd') emit('dragEnd')

View File

@ -2,7 +2,7 @@
<UCard <UCard
class="cursor-pointer transition-all h-32 w-72 shrink-0 group duration-500" class="cursor-pointer transition-all h-32 w-72 shrink-0 group duration-500"
:class="[ :class="[
workspace.position === currentWorkspaceIndex workspace.id === currentWorkspace?.id
? 'ring-2 ring-secondary bg-secondary/10' ? 'ring-2 ring-secondary bg-secondary/10'
: 'hover:ring-2 hover:ring-gray-300', : 'hover:ring-2 hover:ring-gray-300',
]" ]"
@ -31,5 +31,5 @@ defineProps<{ workspace: IWorkspace }>()
const workspaceStore = useWorkspaceStore() const workspaceStore = useWorkspaceStore()
const { currentWorkspaceIndex } = storeToRefs(workspaceStore) const { currentWorkspace } = storeToRefs(workspaceStore)
</script> </script>

View File

@ -38,6 +38,7 @@ export const useWorkspaceStore = defineStore('workspaceStore', () => {
.from(haexWorkspaces) .from(haexWorkspaces)
.orderBy(asc(haexWorkspaces.position)) .orderBy(asc(haexWorkspaces.position))
console.log('loadWorkspacesAsync', items)
workspaces.value = items workspaces.value = items
// Create default workspace if none exist // Create default workspace if none exist

View File

@ -142,7 +142,10 @@ const drizzleCallback = (async (
if (isSelectQuery(sql)) { if (isSelectQuery(sql)) {
// SELECT statements // SELECT statements
rows = await invoke<unknown[]>('sql_select', { sql, params }).catch((e) => { rows = await invoke<unknown[]>('sql_select_with_crdt', {
sql,
params,
}).catch((e) => {
console.error('SQL select Error:', e, sql, params) console.error('SQL select Error:', e, sql, params)
return [] return []
}) })
@ -164,9 +167,9 @@ const drizzleCallback = (async (
console.error('SQL execute with CRDT Error:', e, sql, params, rows) console.error('SQL execute with CRDT Error:', e, sql, params, rows)
return [] return []
}) })
return { rows: undefined }
} }
console.log('drizzle found', rows)
if (method === 'get') { if (method === 'get') {
return { rows: rows.length > 0 ? [rows[0]] : [] } return { rows: rows.length > 0 ? [rows[0]] : [] }
} else { } else {