From 33faa6f722777ab4f6a741069fb80aa100c5ba6d Mon Sep 17 00:00:00 2001 From: black Date: Tue, 14 Apr 2026 09:47:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(database):=20=E6=B7=BB=E5=8A=A0=20SQLite?= =?UTF-8?q?=20=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9B=AE=E5=BD=95=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=88=9B=E5=BB=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 SQLite 数据库添加数据库文件目录自动创建逻辑 - 实现 ensureSQLiteDirectory 方法解析数据库路径并创建必要目录 - 支持从 config.Name 或 config.Link 中提取 SQLite 文件路径 - 添加对 SQLite 链接格式 sqlite::@file(path) 的路径解析支持 - 在数据库表迁移前确保 SQLite 数据库文件目录存在 - 新增 sqlitecgo 驱动包实现 SQLite 数据库驱动支持 --- database/drivers/sqlitecgo/sqlitecgo.go | 6 ++++ database/gdb_migration_auto.go | 47 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/database/drivers/sqlitecgo/sqlitecgo.go b/database/drivers/sqlitecgo/sqlitecgo.go index 39d456f..f7e6434 100644 --- a/database/drivers/sqlitecgo/sqlitecgo.go +++ b/database/drivers/sqlitecgo/sqlitecgo.go @@ -50,3 +50,9 @@ func (d *Driver) New(core *database.Core, node *database.ConfigNode) (database.D func (d *Driver) GetChars() (charLeft string, charRight string) { return quoteChar, quoteChar } + +// GetMigration returns a Migration instance implementing the Migration interface. +// Note: sqlitecgo driver does not have migration support yet, returns nil. +func (d *Driver) GetMigration() database.Migration { + return nil +} diff --git a/database/gdb_migration_auto.go b/database/gdb_migration_auto.go index 045bd3d..b31bcda 100644 --- a/database/gdb_migration_auto.go +++ b/database/gdb_migration_auto.go @@ -9,6 +9,8 @@ package database import ( "context" "fmt" + "os" + "path/filepath" "reflect" "strings" "time" @@ -46,6 +48,13 @@ func (am *AutoMigrateCore) migrateEntity(ctx context.Context, entity any) error return fmt.Errorf("no columns found for table %s", tableName) } + // For SQLite, ensure the database file directory exists + if am.db.GetConfig().Type == "sqlite" { + if err := am.ensureSQLiteDirectory(); err != nil { + return fmt.Errorf("failed to prepare SQLite database: %w", err) + } + } + // Check if table exists hasTable, err := am.db.HasTable(ctx, tableName) if err != nil { @@ -450,3 +459,41 @@ func IsZeroValue(v any) bool { } return false } + +// ensureSQLiteDirectory ensures the SQLite database file directory exists. +func (am *AutoMigrateCore) ensureSQLiteDirectory() error { + config := am.db.GetConfig() + if config.Type != "sqlite" { + return nil + } + + // Get the database file path from config.Name or config.Link + dbPath := config.Name + if dbPath == "" && config.Link != "" { + // Parse link format: sqlite::@file(./data/company.db) + if strings.Contains(config.Link, "@file(") { + start := strings.Index(config.Link, "@file(") + 6 + end := strings.Index(config.Link[start:], ")") + if end > 0 { + dbPath = config.Link[start : start+end] + } + } + } + + if dbPath == "" { + return fmt.Errorf("SQLite database path is empty") + } + + // Get directory path + dir := filepath.Dir(dbPath) + + // Check if directory exists + if _, err := os.Stat(dir); os.IsNotExist(err) { + // Create directory with all parents + if err := os.MkdirAll(dir, 0755); err != nil { + return fmt.Errorf("failed to create directory %s: %w", dir, err) + } + } + + return nil +}