feat: 完善扫描器、exec 及 schema 相关功能
- exec/scanner: 用 *interface{} 替换 **json.RawMessage 扫描目标,兼容 DuckDB 返回 map[string]interface{} 的场景;新增 toJSONRawMessage 转换函数
- exec/scanner: ScanVal 支持结构体指针,通过 JSON 中间层转换(DuckDB STRUCT 列)
- exec/scanner: 将 *sql.RawBytes 和 *[]byte 的处理从 ScanValContext 移入 scanner.ScanVal
- exec/query_executor: 简化 ScanValContext,移除私有 scan 方法
- exec: 补充 scanner 级别 ScanVal 测试用例
- internal/util/reflect: 重写 SafeSetVarValue,修复非指针 src 及 nil 指针字段的 panic
- internal/util/column_map: 恢复非匿名带标签结构体字段的展开逻辑
- schema: 新增 vector 列类型支持
- engine: 补充 DuckDB 相关配置
- dialect/sqlite3/vtab: 完善虚拟表适配器
- 各方言测试改用 sqlmock 虚拟连接
This commit is contained in:
@@ -1,32 +1,16 @@
|
||||
package sqlite3_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.fsdpf.net/go/db"
|
||||
"git.fsdpf.net/go/db/engine"
|
||||
"git.fsdpf.net/go/db/schema"
|
||||
sqlmock "github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var (
|
||||
tableName = "entry"
|
||||
|
||||
dropTable = "DROP TABLE IF EXISTS `entry`;"
|
||||
|
||||
createTable = "CREATE TABLE IF NOT EXISTS `entry` (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
"`int` INT NOT NULL ," +
|
||||
"`float` FLOAT NOT NULL ," +
|
||||
"`string` VARCHAR(255) NOT NULL ," +
|
||||
"`time` DATETIME NOT NULL ," +
|
||||
"`bool` TINYINT NOT NULL ," +
|
||||
"`bytes` BLOB NOT NULL" +
|
||||
");"
|
||||
)
|
||||
var tableName = "entry"
|
||||
|
||||
type sqlite3Test struct {
|
||||
suite.Suite
|
||||
@@ -38,18 +22,28 @@ func TestSqlite3Suite(t *testing.T) {
|
||||
}
|
||||
|
||||
func (t *sqlite3Test) SetupSuite() {
|
||||
db := engine.Open(map[string]engine.DBConfig{
|
||||
"test-sqlite3": engine.NewDBConfig("sqlite3",
|
||||
engine.WithSQLiteFile(os.Getenv("DB_FILE")),
|
||||
),
|
||||
mockDB, mock, _ := sqlmock.New()
|
||||
|
||||
// TestGetColumnListing: PRAGMA table_info(entry)
|
||||
mock.ExpectQuery("PRAGMA table_info").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"cid", "name", "type", "notnull", "dflt_value", "pk"}).
|
||||
AddRow(0, "id", "INTEGER", 1, nil, 1).
|
||||
AddRow(1, "int", "INT", 1, nil, 0).
|
||||
AddRow(2, "float", "FLOAT", 1, nil, 0).
|
||||
AddRow(3, "string", "VARCHAR(255)", 1, nil, 0).
|
||||
AddRow(4, "time", "DATETIME", 1, nil, 0).
|
||||
AddRow(5, "bool", "TINYINT", 1, nil, 0).
|
||||
AddRow(6, "bytes", "BLOB", 1, nil, 0))
|
||||
|
||||
// TestTableExists: SELECT COUNT(*) FROM sqlite_master WHERE ...
|
||||
mock.ExpectQuery("SELECT.*COUNT.*sqlite_master").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(1))
|
||||
|
||||
conn := engine.Mock(map[string]engine.MockDBConfig{
|
||||
"test-sqlite3": {Driver: "sqlite3", Mock: mockDB},
|
||||
}).Connection("test-sqlite3")
|
||||
|
||||
t.schema = schema.GetSchemaDialect(db)
|
||||
|
||||
// db.Exec(dropTable)
|
||||
if _, err := db.Exec(createTable); err != nil {
|
||||
t.Require().NoError(err)
|
||||
}
|
||||
t.schema = schema.GetSchemaDialect(conn)
|
||||
}
|
||||
|
||||
func (t *sqlite3Test) TestTableExists() {
|
||||
@@ -123,14 +117,14 @@ func (t *sqlite3Test) TestCompileChange() {
|
||||
|
||||
sql := t.schema.CompileChange(bp)
|
||||
t.Equal(len([]string{
|
||||
"ALTER TABLE `users` ADD COLUMN `name_1742738970482105700` varchar(50) NOT NULL",
|
||||
"UPDATE `users` SET `name_1742738970482105700`=`name`",
|
||||
"ALTER TABLE `users` ADD COLUMN `name_tmp` varchar(50) NOT NULL",
|
||||
"UPDATE `users` SET `name_tmp`=`name`",
|
||||
"ALTER TABLE `users` DROP COLUMN `name`",
|
||||
"ALTER TABLE `users` RENAME COLUMN `name_1742738970482105700` TO `username`",
|
||||
"ALTER TABLE `users` ADD COLUMN `age_1742738970482151800` smallint(4) NOT NULL DEFAULT '19'",
|
||||
"UPDATE `users` SET `age_1742738970482151800`=`age`",
|
||||
"ALTER TABLE `users` RENAME COLUMN `name_tmp` TO `username`",
|
||||
"ALTER TABLE `users` ADD COLUMN `age_tmp` smallint(4) NOT NULL DEFAULT '19'",
|
||||
"UPDATE `users` SET `age_tmp`=`age`",
|
||||
"ALTER TABLE `users` DROP COLUMN `age`",
|
||||
"ALTER TABLE `users` RENAME COLUMN `age_1742738970482151800` TO `age`",
|
||||
"ALTER TABLE `users` RENAME COLUMN `age_tmp` TO `age`",
|
||||
}), len(sql))
|
||||
|
||||
t.T().Log(sql)
|
||||
@@ -195,9 +189,9 @@ func (t *sqlite3Test) TestCompileCreate_HiddenColumn() {
|
||||
"CREATE TABLE IF NOT EXISTS `api_users` (\n" +
|
||||
"`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT\n" +
|
||||
"`name` varchar(100) NULL\n" +
|
||||
"`age` INTEGER(0) NOT NULL\n" +
|
||||
"`age` INTEGER NOT NULL\n" +
|
||||
"`token` varchar(255) HIDDEN\n" +
|
||||
"`page_size` INTEGER(0) HIDDEN\n" +
|
||||
"`page_size` INTEGER HIDDEN\n" +
|
||||
")",
|
||||
}, sql)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user