feat: 新增 DuckDB 方言支持及 SQLite3 自动注册 IF 函数

- 新增 dialect/duckdb 方言,支持 DuckDB SQL 语法
- 新增 schema/dialect/duckdb DDL 操作支持
- dialect/sqlite3: 注册 sqlite3_with_if 驱动,连接时自动注册 IF() 函数
- engine: MakeConnection 对 sqlite3 自动使用带 IF 支持的驱动
- engine: 新增 DBConfig DuckDB 配置项及相关 Option 函数
- 统一各方言测试引用路径
This commit is contained in:
2026-04-16 10:14:46 +08:00
parent c4590cf592
commit 2221ca0ddb
19 changed files with 1270 additions and 62 deletions
+76
View File
@@ -68,6 +68,14 @@ type DBConfig struct {
KeepAlive int
Dsn string
}
DuckDB struct {
File string
AccessMode string
Threads int
MaxMemory string
Dsn string
}
}
// Option 配置选项类型
@@ -84,6 +92,8 @@ func (c *DBConfig) ToDSN() string {
return c.toSQLiteDSN()
case "sqlserver":
return c.toSQLServerDSN()
case "duckdb":
return c.toDuckDBDSN()
default:
panic(fmt.Sprintf("Unsupported driver for DSN generation: %s", c.Driver))
}
@@ -279,6 +289,32 @@ func (c *DBConfig) toSQLServerDSN() string {
return "sqlserver://" + c.Username + ":" + url.QueryEscape(c.Password) + "@" + host + ":" + c.Port + "?" + params.Encode()
}
// toDuckDBDSN 生成 DuckDB DSN
func (c *DBConfig) toDuckDBDSN() string {
if c.DuckDB.Dsn != "" {
return c.DuckDB.Dsn
}
// DuckDB 可以使用内存数据库或文件数据库
dsn := c.DuckDB.File
if dsn == "" {
dsn = "" // 空字符串表示内存数据库
}
params := url.Values{}
if c.DuckDB.AccessMode != "" {
params.Add("access_mode", c.DuckDB.AccessMode)
}
if c.DuckDB.Threads > 0 {
params.Add("threads", fmt.Sprintf("%d", c.DuckDB.Threads))
}
if c.DuckDB.MaxMemory != "" {
params.Add("max_memory", c.DuckDB.MaxMemory)
}
if len(params) > 0 {
dsn += "?" + params.Encode()
}
return dsn
}
// NewDBConfig 创建新的 DBConfig 实例,检查关键参数
func NewDBConfig(driver string, options ...Option) DBConfig {
if driver == "" {
@@ -291,6 +327,7 @@ func NewDBConfig(driver string, options ...Option) DBConfig {
"pgsql": true,
"sqlite3": true,
"sqlserver": true,
"duckdb": true,
}
if !validDrivers[driver] {
panic(fmt.Sprintf("Unsupported driver: %s", driver))
@@ -330,6 +367,8 @@ func NewDBConfig(driver string, options ...Option) DBConfig {
if config.SQLite.File == "" {
panic("File is required for sqlite3 driver")
}
case "duckdb":
// DuckDB 文件参数可选,空字符串表示内存数据库
}
return *config
@@ -447,3 +486,40 @@ func WithSQLServerInstance(instance string) Option {
c.SQLServer.Instance = instance
}
}
// DuckDB 专用选项
func WithDuckDBFile(file string) Option {
return func(c *DBConfig) {
if c.Driver != "duckdb" {
panic("WithDuckDBFile is only valid for duckdb driver")
}
c.DuckDB.File = file
}
}
func WithDuckDBAccessMode(accessMode string) Option {
return func(c *DBConfig) {
if c.Driver != "duckdb" {
panic("WithDuckDBAccessMode is only valid for duckdb driver")
}
c.DuckDB.AccessMode = accessMode
}
}
func WithDuckDBThreads(threads int) Option {
return func(c *DBConfig) {
if c.Driver != "duckdb" {
panic("WithDuckDBThreads is only valid for duckdb driver")
}
c.DuckDB.Threads = threads
}
}
func WithDuckDBMaxMemory(maxMemory string) Option {
return func(c *DBConfig) {
if c.Driver != "duckdb" {
panic("WithDuckDBMaxMemory is only valid for duckdb driver")
}
c.DuckDB.MaxMemory = maxMemory
}
}