chore: align infrastructure with go/file and go/cast (v1.0.11) (by AI)
This commit is contained in:
parent
9cdcdaeecd
commit
b2136e170e
10
CHANGELOG.md
10
CHANGELOG.md
@ -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`)中的包装引号。
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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")
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
18
TEST.md
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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")
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user