From 38e520c3003777a2c0b04d69f128f083e960c9bf Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Mon, 8 Jun 2026 20:47:32 +0800 Subject: [PATCH] feat: add SetConfig for dynamic configuration (by AI) --- CHANGELOG.md | 6 +++- DB.go | 97 +++++++++++++++++++++++++++++----------------------- README.md | 4 ++- go.mod | 6 ++-- go.sum | 22 ++++-------- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e54c9f1..6b937d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # 变更记录 - @go/db -## [1.5.1] - 2026-06-04 +## [1.5.3] - 2026-06-08 +- **新增**: `SetConfig(name, setting string)` 方法,支持动态配置数据库连接(不依赖配置文件),方便通过别名获取连接。 +- **优化**: 重构配置加载逻辑,支持动态配置与 `config/db.yaml` 配置文件配置共存。 + +## [1.5.2] - 2026-06-05 - **架构重构: 两阶段 (Two-Pass) 索引命名生成**: - 重构了 `CheckTable` 中的 Schema 同步逻辑,从“边解析边生成”改为两阶段处理。现在多列联合索引(无论是 Unique, Index 还是 Fulltext)的名字会根据包含的**字段名称自动拼接生成**(如 `uk_user_name_phone`),替代了以前难以溯源的分组号(如 `uk_user_1`),极大提升了 DBA 在数据库维护时的可读性与直观性。 - **超长防断机制**: 当生成的索引名称超过 60 个字符时,自动进行截断,并在末尾追加原完整名称的 6 位 MD5 Hash,完美规避了各种 RDBMS 对标识符 64 字符长度限制引发的建表错误。 diff --git a/DB.go b/DB.go index a9a4b3d..90582b1 100644 --- a/DB.go +++ b/DB.go @@ -412,6 +412,59 @@ func Begin() *Tx { return d.Begin() } +func SetConfig(name, setting string) { + loadConfigs(nil) + conf := new(Config) + conf.ConfigureBy(setting) + dbConfigsLock.Lock() + dbConfigs[name] = conf + dbConfigsLock.Unlock() +} + +func loadConfigs(logger *log.Logger) { + once.Do(func() { + if logger == nil { + logger = log.DefaultLogger + } + dbConfigs1 := make(map[string]*Config) + if err := config.Load(&dbConfigs1, "db"); err == nil { + for k, v := range dbConfigs1 { + if v.Host != "" { + dbConfigsLock.Lock() + dbConfigs[k] = v + dbConfigsLock.Unlock() + } + } + } else { + logger.Error(err.Error()) + } + dbConfigs2 := make(map[string]string) + if err := config.Load(&dbConfigs2, "db"); err == nil { + for k, v := range dbConfigs2 { + if strings.Contains(v, "://") { + v2 := new(Config) + v2.ConfigureBy(v) + if v2.Host != "" { + v2.logger = logger + dbConfigsLock.Lock() + dbConfigs[k] = v2 + dbConfigsLock.Unlock() + } + } else { + dbConfigsLock.Lock() + v2 := dbConfigs[v] + if v2 != nil && v2.Host != "" { + dbConfigs[k] = v2 + } + dbConfigsLock.Unlock() + } + } + } else { + logger.Error(err.Error()) + } + }) +} + func getDB(name string, logger *log.Logger, useCache bool) *DB { if logger == nil { logger = log.DefaultLogger @@ -432,49 +485,7 @@ func getDB(name string, logger *log.Logger, useCache bool) *DB { conf.logger = logger conf.ConfigureBy(name) } else { - dbConfigsLock.RLock() - n := len(dbConfigs) - dbConfigsLock.RUnlock() - if n == 0 { - once.Do(func() { - dbConfigs1 := make(map[string]*Config) - if err := config.Load(&dbConfigs1, "db"); err == nil { - for k, v := range dbConfigs1 { - if v.Host != "" { - dbConfigsLock.Lock() - dbConfigs[k] = v - dbConfigsLock.Unlock() - } - } - } else { - logger.Error(err.Error()) - } - dbConfigs2 := make(map[string]string) - if err := config.Load(&dbConfigs2, "db"); err == nil { - for k, v := range dbConfigs2 { - if strings.Contains(v, "://") { - v2 := new(Config) - v2.ConfigureBy(v) - if v2.Host != "" { - v2.logger = logger - dbConfigsLock.Lock() - dbConfigs[k] = v2 - dbConfigsLock.Unlock() - } - } else { - dbConfigsLock.Lock() - v2 := dbConfigs[v] - if v2 != nil && v2.Host != "" { - dbConfigs[k] = v2 - } - dbConfigsLock.Unlock() - } - } - } else { - logger.Error(err.Error()) - } - }) - } + loadConfigs(logger) dbConfigsLock.RLock() conf = dbConfigs[name] dbConfigsLock.RUnlock() diff --git a/README.md b/README.md index 4e4680c..db1f504 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,10 @@ go get apigo.cc/go/db ## 🛠 API 指南 ### 1. 核心方法 +- **`SetConfig(name, setting string)`** + - 动态设置数据库配置(不依赖配置文件),可通过别名获取连接。 - **`GetDB(name string, logger *log.Logger) *DB`** - - 获取数据库连接实例。`name` 可以是 `db.json` 中的配置名,也可以是标准 DSN(如 `mysql://user:pwd@host:port/db` 或 `sqlite://test.db`)。 + - 获取数据库连接实例。`name` 可以是别名、`db.json` 中的配置名,也可以是标准 DSN(如 `mysql://user:pwd@host:port/db` 或 `sqlite://test.db`)。 - **`Sync(schema string) error`** - 解析 DSL 并同步数据库表结构。用于创建表(包括 `_deleted` 表)和索引。详见 [架构 DSL 指南](./DSL.md)。 diff --git a/go.mod b/go.mod index 13e7a43..7ee3275 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/go-sql-driver/mysql v1.10.0 github.com/jackc/pgx/v5 v5.9.2 github.com/mitchellh/mapstructure v1.5.0 - modernc.org/sqlite v1.50.0 + modernc.org/sqlite v1.51.0 ) require ( @@ -29,7 +29,7 @@ require ( github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect golang.org/x/crypto v0.52.0 // indirect @@ -37,7 +37,7 @@ require ( golang.org/x/sys v0.45.0 // indirect golang.org/x/text v0.37.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.72.0 // indirect + modernc.org/libc v1.72.5 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect ) diff --git a/go.sum b/go.sum index 251beae..43345dc 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,7 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= @@ -74,7 +73,6 @@ golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= @@ -87,30 +85,24 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/cc/v4 v4.27.3 h1:uNCgn37E5U09mTv1XgskEVUJ8ADKpmFMPxzGJ0TSo+U= -modernc.org/cc/v4 v4.27.3/go.mod h1:3YjcbCqhoTTHPycJDRl2WZKKFj0nwcOIPBfEZK0Hdk8= -modernc.org/ccgo/v4 v4.32.4 h1:L5OB8rpEX4ZsXEQwGozRfJyJSFHbbNVOoQ59DU9/KuU= -modernc.org/ccgo/v4 v4.32.4/go.mod h1:lY7f+fiTDHfcv6YlRgSkxYfhs+UvOEEzj49jAn2TOx0= +modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY= +modernc.org/ccgo/v4 v4.34.2 h1:mxsy2FdrB6+qG3NfXefz1AmWv0ehOSDO4jxgxd7h9yo= modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= -modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/gc/v3 v3.1.3 h1:6QAplYyVO+KdPW3pGnqmJDUxtkec8ooEWvks/hhU3lc= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.72.0 h1:IEu559v9a0XWjw0DPoVKtXpO2qt5NVLAnFaBbjq+n8c= -modernc.org/libc v1.72.0/go.mod h1:tTU8DL8A+XLVkEY3x5E/tO7s2Q/q42EtnNWda/L5QhQ= +modernc.org/libc v1.72.5 h1:m2OGx9Ser1VvTS4Z9ZJlWs+CBMxutLaTiAWkNz+NB9U= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM= -modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew= +modernc.org/sqlite v1.51.0 h1:aH/MMSoayAIhozZ7uJbVTT9QO/VhzBf0J9tymmmuC/U= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=