feat(sqlite): create empty database file on connect if missing

This commit is contained in:
t8y2
2026-06-16 13:55:44 +08:00
parent db7b730dd3
commit 558b9301a2
11 changed files with 53 additions and 3 deletions
@@ -2000,6 +2000,24 @@ async function createDuckDbFilePath() {
form.value.host = path;
}
function ensureSqliteFileExtension(path: string): string {
return /\.(db|sqlite|sqlite3)$/i.test(path) ? path : `${path}.db`;
}
async function createSqliteFilePath() {
if (!isTauriRuntime()) return;
const { save } = await import("@tauri-apps/plugin-dialog");
const selected = await save({
title: t("connection.createSqliteFile"),
defaultPath: "database.db",
filters: [{ name: "SQLite", extensions: ["db", "sqlite", "sqlite3"] }],
});
if (!selected) return;
const path = ensureSqliteFileExtension(selected);
form.value.host = path;
}
async function browseJdbcDriverPaths() {
if (!isTauriRuntime()) return;
const { open } = await import("@tauri-apps/plugin-dialog");
@@ -2371,6 +2389,14 @@ function openExternalUrl(url: string) {
</TooltipTrigger>
<TooltipContent>{{ t("connection.createDuckDbFile") }}</TooltipContent>
</Tooltip>
<Tooltip v-if="isDesktop && form.db_type === 'sqlite'">
<TooltipTrigger as-child>
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" @click="createSqliteFilePath">
<FilePlus2 class="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>{{ t("connection.createSqliteFile") }}</TooltipContent>
</Tooltip>
</div>
<p v-if="supportsMemoryDatabasePath" class="text-xs text-muted-foreground">
{{ t("connection.memoryDatabasePathHint") }}
+1
View File
@@ -144,6 +144,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "H2 file path cannot be empty",
createDuckDbFile: "Create DuckDB file",
createSqliteFile: "Create SQLite database",
memoryDatabasePathHint: "Use :memory: to create an in-memory SQLite or DuckDB database.",
sqliteExtensions: "SQLite Extensions",
sqliteExtensionsPlaceholder: "/path/to/regexp.dylib\n/path/to/text.dylib|sqlite3_text_init",
+1
View File
@@ -142,6 +142,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "La ruta del archivo H2 no puede estar vacía",
createDuckDbFile: "Crear archivo DuckDB",
createSqliteFile: "Crear base de datos SQLite",
user: "Usuario",
password: "Contraseña",
database: "Base de datos",
+1
View File
@@ -142,6 +142,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "Il percorso del file H2 non può essere vuoto",
createDuckDbFile: "Crea file DuckDB",
createSqliteFile: "Crea database SQLite",
memoryDatabasePathHint: "Usa :memory: per creare un database SQLite o DuckDB in memoria.",
sqliteExtensions: "Estensioni SQLite",
sqliteExtensionsPlaceholder: "/percorso/per/regexp.dylib\n/percorso/per/text.dylib|sqlite3_text_init",
+1
View File
@@ -143,6 +143,7 @@ export default {
h2TcpMode: "TCP",
h2FilePathRequired: "H2ファイルパスを指定してください",
createDuckDbFile: "DuckDBファイルを作成",
createSqliteFile: "SQLiteデータベースを作成",
memoryDatabasePathHint: "インメモリのSQLiteまたはDuckDBデータベースを作成するには :memory: を使用してください。",
sqliteExtensions: "SQLite拡張",
sqliteExtensionsPlaceholder: "/path/to/regexp.dylib\n/path/to/text.dylib|sqlite3_text_init",
+1
View File
@@ -142,6 +142,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "O caminho do arquivo H2 não pode ficar vazio",
createDuckDbFile: "Criar arquivo DuckDB",
createSqliteFile: "Criar banco de dados SQLite",
memoryDatabasePathHint: "Use :memory: para criar um banco de dados SQLite ou DuckDB na memória.",
sqliteExtensions: "Extensões SQLite",
sqliteExtensionsPlaceholder: "/caminho/para/regexp.dylib\n/caminho/para/text.dylib|sqlite3_text_init",
+1
View File
@@ -145,6 +145,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "H2 文件路径不能为空",
createDuckDbFile: "新建 DuckDB 文件",
createSqliteFile: "新建 SQLite 数据库",
memoryDatabasePathHint: "输入 :memory: 可创建 SQLite 或 DuckDB 内存数据库。",
sqliteExtensions: "SQLite 扩展库",
sqliteExtensionsPlaceholder: "/path/to/regexp.dylib\n/path/to/text.dylib|sqlite3_text_init",
+1
View File
@@ -142,6 +142,7 @@
h2TcpMode: "TCP",
h2FilePathRequired: "H2 檔案路徑不能為空",
createDuckDbFile: "建立 DuckDB 檔案",
createSqliteFile: "建立 SQLite 資料庫",
memoryDatabasePathHint: "輸入 :memory: 可建立 SQLite 或 DuckDB 記憶體資料庫。",
sqliteExtensions: "SQLite 擴充庫",
sqliteExtensionsPlaceholder: "/path/to/regexp.dylib\n/path/to/text.dylib|sqlite3_text_init",
+5 -1
View File
@@ -447,7 +447,11 @@ impl AppState {
})
.collect();
PoolKind::Sqlite(
db::sqlite::connect_path_with_extensions(&expand_tilde(&db_config.host), extensions).await?,
db::sqlite::connect_path_create_if_missing_with_extensions(
&expand_tilde(&db_config.host),
extensions,
)
.await?,
)
}
DatabaseType::Rqlite => {
+7
View File
@@ -46,6 +46,13 @@ pub async fn connect_path_create_if_missing(path: &str) -> Result<SqliteHandle,
connect_path_with_options(path, true, Vec::new()).await
}
pub async fn connect_path_create_if_missing_with_extensions(
path: &str,
extensions: Vec<SqliteExtensionSpec>,
) -> Result<SqliteHandle, String> {
connect_path_with_options(path, true, extensions).await
}
async fn connect_path_with_options(
path: &str,
create_if_missing: bool,
+8 -2
View File
@@ -320,7 +320,12 @@ pub async fn test_connection(state: State<'_, Arc<AppState>>, config: Connection
extension
})
.collect();
match db::sqlite::connect_path_with_extensions(&expand_tilde(&config.host), extensions).await {
match db::sqlite::connect_path_create_if_missing_with_extensions(
&expand_tilde(&config.host),
extensions,
)
.await
{
Ok(_) => Ok("Connection successful".to_string()),
Err(e) => Err(e),
}
@@ -539,7 +544,8 @@ pub async fn connect_db(state: State<'_, Arc<AppState>>, config: ConnectionConfi
})
.collect();
PoolKind::Sqlite(
db::sqlite::connect_path_with_extensions(&expand_tilde(&db_config.host), extensions).await?,
db::sqlite::connect_path_create_if_missing_with_extensions(&expand_tilde(&db_config.host), extensions)
.await?,
)
}
DatabaseType::Redis => {