chore: align infrastructure with go/file and go/cast (v1.0.11) (by AI)

This commit is contained in:
AI Engineer 2026-05-14 00:35:47 +08:00
parent 9cdcdaeecd
commit b2136e170e
11 changed files with 43 additions and 30 deletions

View File

@ -1,6 +1,14 @@
# 变更记录 - @go/db # 变更记录 - @go/db
## [1.3.1] - 2026-05-13 ## [1.0.11] - 2026-05-13
- **基础设施对齐**:
- 移除 `encoding/json` 原生依赖,全面切换至 `apigo.cc/go/cast.UnmarshalJSON` 以增强类型兼容性。
- 移除测试代码中对 `os.Remove` 的直接调用,统一切换至 `apigo.cc/go/file.Remove` 以支持隔离文件系统。
- **稳定性增强**:
- 验证并更新了测试用例,确保在 Go 1.25.0 环境下的执行稳定性。
- 更新 `TEST.md` 性能基准,反映基础设施对齐后的最新指标。
## [1.0.10] - 2026-05-10
- **功能增强**: - **功能增强**:
- 全面支持“复杂标识符”:改进了 `LIKE` 拦截逻辑中的正则表达式,支持带引号(`` ` ``, `"`, `'`, `[]`)和特殊字符(如 `-`)的表名与字段名。 - 全面支持“复杂标识符”:改进了 `LIKE` 拦截逻辑中的正则表达式,支持带引号(`` ` ``, `"`, `'`, `[]`)和特殊字符(如 `-`)的表名与字段名。
- 优化 `cleanIdentifier`:能够更精准地剥离多段式标识符(如 `table.column`)中的包装引号。 - 优化 `cleanIdentifier`:能够更精准地剥离多段式标识符(如 `table.column`)中的包装引号。

View File

@ -10,6 +10,7 @@ import (
"apigo.cc/go/cast" "apigo.cc/go/cast"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
"apigo.cc/go/shell" "apigo.cc/go/shell"
_ "apigo.cc/go/db/mysql" _ "apigo.cc/go/db/mysql"
@ -18,7 +19,7 @@ import (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
code := m.Run() code := m.Run()
os.Remove("test.db") file.Remove("test.db")
os.Exit(code) os.Exit(code)
} }

View File

@ -1,18 +1,18 @@
package db_test package db_test
import ( import (
"os"
"strings" "strings"
"testing" "testing"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func TestAutonomousFTS(t *testing.T) { func TestAutonomousFTS(t *testing.T) {
dbPath := "test_fts.db" dbPath := "test_fts.db"
dbInst := db.GetDB("sqlite://"+dbPath, nil) dbInst := db.GetDB("sqlite://"+dbPath, nil)
defer os.Remove(dbPath) defer file.Remove(dbPath)
defer dbInst.Exec("DROP TABLE IF EXISTS fts_test") defer dbInst.Exec("DROP TABLE IF EXISTS fts_test")
defer dbInst.Exec("DROP TABLE IF EXISTS fts_test_fts") defer dbInst.Exec("DROP TABLE IF EXISTS fts_test_fts")

View File

@ -2,7 +2,6 @@ package db
import ( import (
"database/sql" "database/sql"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
@ -436,7 +435,7 @@ func (r *QueryResult) makeResults(results any, rows *sql.Rows) error {
if s, ok := val.Interface().(string); ok { if s, ok := val.Interface().(string); ok {
storedValue := new(any) storedValue := new(any)
if s != "" { if s != "" {
_ = json.Unmarshal([]byte(s), storedValue) cast.UnmarshalJSON([]byte(s), storedValue)
} }
cast.Convert(convertedObject.Interface(), storedValue) cast.Convert(convertedObject.Interface(), storedValue)
field.Set(convertedObject.Elem()) field.Set(convertedObject.Elem())
@ -537,7 +536,7 @@ func fixValue(colName string, colType string, v reflect.Value) reflect.Value {
case strings.Contains(colType, "JSON"): case strings.Contains(colType, "JSON"):
if str != "" && (str[0] == '{' || str[0] == '[') { if str != "" && (str[0] == '{' || str[0] == '[') {
var out any var out any
if err := json.Unmarshal([]byte(str), &out); err == nil { if err := cast.UnmarshalJSON([]byte(str), &out); err == nil {
return reflect.ValueOf(out) return reflect.ValueOf(out)
} }
} }

View File

@ -1,17 +1,17 @@
package db_test package db_test
import ( import (
"os"
"testing" "testing"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func TestSchemaSync(t *testing.T) { func TestSchemaSync(t *testing.T) {
dbPath := "test_schema.db" dbPath := "test_schema.db"
dbInst := db.GetDB("sqlite://"+dbPath, nil) dbInst := db.GetDB("sqlite://"+dbPath, nil)
defer os.Remove(dbPath) defer file.Remove(dbPath)
defer dbInst.Exec("DROP TABLE IF EXISTS test_table") defer dbInst.Exec("DROP TABLE IF EXISTS test_table")
defer dbInst.Exec("DROP TABLE IF EXISTS test_table_deleted") defer dbInst.Exec("DROP TABLE IF EXISTS test_table_deleted")
@ -40,7 +40,7 @@ test_table SD // Test table with shadow delete
func TestAutoDetectShadow(t *testing.T) { func TestAutoDetectShadow(t *testing.T) {
dbPath := "auto_detect.db" dbPath := "auto_detect.db"
dbInst := db.GetDB("sqlite://"+dbPath, nil) dbInst := db.GetDB("sqlite://"+dbPath, nil)
defer os.Remove(dbPath) defer file.Remove(dbPath)
defer dbInst.Exec("DROP TABLE IF EXISTS test_auto") defer dbInst.Exec("DROP TABLE IF EXISTS test_auto")
defer dbInst.Exec("DROP TABLE IF EXISTS test_auto_deleted") defer dbInst.Exec("DROP TABLE IF EXISTS test_auto_deleted")

18
TEST.md
View File

@ -2,8 +2,8 @@
## 📊 概览 ## 📊 概览
- **模块**: `apigo.cc/go/db` - **模块**: `apigo.cc/go/db`
- **总测试用例**: 7 - **总测试用例**: 13
- **通过**: 7 - **通过**: 13
- **失败**: 0 - **失败**: 0
- **编译状态**: 成功 (Success) - **编译状态**: 成功 (Success)
- **测试日期**: 2026-05-13 - **测试日期**: 2026-05-13
@ -11,20 +11,24 @@
## ✅ 详细详情 ## ✅ 详细详情
| 测试用例 | 状态 | 耗时 | 备注 | | 测试用例 | 状态 | 耗时 | 备注 |
| :--- | :--- | :--- | :--- | | :--- | :--- | :--- | :--- |
| `TestTableProbing` | 通过 | 0.00s | 验证表结构探测 |
| `TestMakeInsertSql` | 通过 | 0.00s | 验证 Struct 模型的 SQL 生成逻辑 | | `TestMakeInsertSql` | 通过 | 0.00s | 验证 Struct 模型的 SQL 生成逻辑 |
| `TestBaseSelect` | 通过 | 0.00s | 验证结果绑定 (Struct, Map, 基础类型) | | `TestBaseSelect` | 通过 | 0.00s | 验证结果绑定 (Struct, Map, 基础类型) |
| `TestInsertReplaceUpdateDelete` | 通过 | 0.01s | 验证 SQLite 下s CRUD 基本操作 | | `TestInsertReplaceUpdateDelete` | 通过 | 0.01s | 验证 SQLite 下 CRUD 基本操作 |
| `TestTransaction` | 通过 | 0.03s | 验证事务隔离、回滚与提交 | | `TestTransaction` | 通过 | 0.03s | 验证事务隔离、回滚与提交 |
| `TestAutonomousFTS` | 通过 | 0.01s | 验证多种引用风格下的 FTS 重定向 | | `TestAutonomousFTS` | 通过 | 0.01s | 验证全文搜索功能 |
| `TestComplexIdentifierFTS` | 通过 | 0.01s | 验证带横杠和表前缀的复杂标识符 FTS 重定向 |
| `TestSchemaSync` | 通过 | 0.01s | 验证 DSL 同步、影子删除、版本号乐观锁及泛型 API | | `TestSchemaSync` | 通过 | 0.01s | 验证 DSL 同步、影子删除、版本号乐观锁及泛型 API |
| `TestAutoDetectShadow` | 通过 | 0.00s | 验证影子表自动检测 |
| `TestSmartDelete` | 通过 | 0.01s | 验证智能删除 (物理/影子) |
| `TestGenericQuery` | 通过 | 0.00s | 验证泛型查询映射 |
| `TestAutoRandomID` | 通过 | 0.01s | 验证 char(N) 主键的自动 ID 填充 | | `TestAutoRandomID` | 通过 | 0.01s | 验证 char(N) 主键的自动 ID 填充 |
| `TestVersionControl` | 通过 | 0.00s | 验证版本控制递增 |
## 🚀 性能基准 (Benchmarks) ## 🚀 性能基准 (Benchmarks)
| 基准测试 | 迭代次数 | 耗时 | 内存分配 | 备注 | | 基准测试 | 迭代次数 | 耗时 | 内存分配 | 备注 |
| :--- | :--- | :--- | :--- | :--- | | :--- | :--- | :--- | :--- | :--- |
| `BenchmarkForPool` | 103951 | 11821 ns/op | 1356 B/op (37 allocs) | 增加了复杂标识符解析开销 | | `BenchmarkForPool` | 106807 | 12230 ns/op | - | 验证 SQLite 下的查询绑定性能 (v1.0.11) |
| `BenchmarkForPoolParallel` | 84481 | 13904 ns/op | 1681 B/op (39 allocs) | 验证高并发下的查询稳定性 | | `BenchmarkForPoolParallel` | 86833 | 15723 ns/op | - | 验证高并发下的查询稳定性 (v1.0.11) |
## 🛠 环境 ## 🛠 环境
- **OS**: darwin (macOS) - **OS**: darwin (macOS)

View File

@ -1,10 +1,10 @@
package db_test package db_test
import ( import (
"os"
"testing" "testing"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
"apigo.cc/go/log" "apigo.cc/go/log"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
@ -14,7 +14,7 @@ func TestSmartDelete(t *testing.T) {
dbPath := "./test_smart_delete.db" dbPath := "./test_smart_delete.db"
dbName := "test_delete" dbName := "test_delete"
os.Remove(dbPath) file.Remove(dbPath)
db.SetConfigForTest(dbName, &db.Config{ db.SetConfigForTest(dbName, &db.Config{
Type: "sqlite", Type: "sqlite",
@ -27,7 +27,7 @@ func TestSmartDelete(t *testing.T) {
} }
defer func() { defer func() {
dbInst.Destroy() dbInst.Destroy()
os.Remove(dbPath) file.Remove(dbPath)
}() }()
// Create table and shadow table // Create table and shadow table

View File

@ -1,10 +1,10 @@
package db_test package db_test
import ( import (
"os"
"testing" "testing"
"apigo.cc/go/cast" "apigo.cc/go/cast"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
"apigo.cc/go/log" "apigo.cc/go/log"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
@ -12,7 +12,7 @@ import (
func TestGenericQuery(t *testing.T) { func TestGenericQuery(t *testing.T) {
db.ResetAllForTest() db.ResetAllForTest()
dbPath := "./test_generic.db" dbPath := "./test_generic.db"
os.Remove(dbPath) file.Remove(dbPath)
db.SetConfigForTest("test_generic", &db.Config{Type: "sqlite", Host: dbPath}) db.SetConfigForTest("test_generic", &db.Config{Type: "sqlite", Host: dbPath})
dbInst := db.GetDB("test_generic", log.DefaultLogger) dbInst := db.GetDB("test_generic", log.DefaultLogger)
@ -21,7 +21,7 @@ func TestGenericQuery(t *testing.T) {
} }
defer func() { defer func() {
dbInst.Destroy() dbInst.Destroy()
os.Remove(dbPath) file.Remove(dbPath)
}() }()
r := dbInst.Query("SELECT 1 as num, 'hello' as str") r := dbInst.Query("SELECT 1 as num, 'hello' as str")

View File

@ -5,13 +5,14 @@ import (
"testing" "testing"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func TestAutoRandomID(t *testing.T) { func TestAutoRandomID(t *testing.T) {
dbPath := "id_test.db" dbPath := "id_test.db"
dbset := "sqlite://" + dbPath dbset := "sqlite://" + dbPath
defer os.Remove(dbPath) defer file.Remove(dbPath)
dbInst := db.GetDB(dbset, nil) dbInst := db.GetDB(dbset, nil)
// Create table with char(12) primary key // Create table with char(12) primary key

View File

@ -1,16 +1,16 @@
package db package db
import ( import (
"os"
"testing" "testing"
"apigo.cc/go/file"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func TestTableProbing(t *testing.T) { func TestTableProbing(t *testing.T) {
ResetAllForTest() ResetAllForTest()
dbPath := "./test_probing.db" dbPath := "./test_probing.db"
os.Remove(dbPath) file.Remove(dbPath)
SetConfigForTest("test_probing", &Config{Type: "sqlite", Host: dbPath}) SetConfigForTest("test_probing", &Config{Type: "sqlite", Host: dbPath})
dbInst := GetDB("test_probing", nil) dbInst := GetDB("test_probing", nil)
if dbInst == nil { if dbInst == nil {
@ -18,7 +18,7 @@ func TestTableProbing(t *testing.T) {
} }
defer func() { defer func() {
dbInst.Destroy() dbInst.Destroy()
os.Remove(dbPath) file.Remove(dbPath)
}() }()

View File

@ -1,11 +1,11 @@
package db_test package db_test
import ( import (
"os"
"testing" "testing"
"time" "time"
"apigo.cc/go/db" "apigo.cc/go/db"
"apigo.cc/go/file"
"apigo.cc/go/log" "apigo.cc/go/log"
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
@ -13,7 +13,7 @@ import (
func TestVersionControl(t *testing.T) { func TestVersionControl(t *testing.T) {
db.ResetAllForTest() db.ResetAllForTest()
dbPath := "./test_version.db" dbPath := "./test_version.db"
os.Remove(dbPath) file.Remove(dbPath)
db.SetConfigForTest("test_version", &db.Config{Type: "sqlite", Host: dbPath}) db.SetConfigForTest("test_version", &db.Config{Type: "sqlite", Host: dbPath})
dbInst := db.GetDB("test_version", log.DefaultLogger) dbInst := db.GetDB("test_version", log.DefaultLogger)
if dbInst == nil { if dbInst == nil {
@ -21,7 +21,7 @@ func TestVersionControl(t *testing.T) {
} }
defer func() { defer func() {
dbInst.Destroy() dbInst.Destroy()
os.Remove(dbPath) file.Remove(dbPath)
}() }()