- 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 虚拟连接
DuckDB Schema Dialect
DuckDB schema dialect 为 DuckDB 数据库提供了 DDL (Data Definition Language) 操作支持。
功能特性
- ✅ 创建表 (CREATE TABLE)
- ✅ 添加列 (ALTER TABLE ADD COLUMN)
- ✅ 修改列 (ALTER TABLE ALTER COLUMN)
- ✅ 删除列 (ALTER TABLE DROP COLUMN)
- ✅ 删除表 (DROP TABLE)
- ✅ 重命名表 (ALTER TABLE RENAME TO)
- ✅ 表注释 (COMMENT ON TABLE)
- ✅ 列注释 (通过 Comment 属性)
- ✅ 自增主键 (SERIAL/BIGSERIAL)
- ✅ 查询表是否存在
- ✅ 获取表的列列表
支持的数据类型
| Schema 类型 | DuckDB 类型 | 说明 |
|---|---|---|
| char | CHAR(n) | 固定长度字符 |
| string | VARCHAR(n) | 可变长度字符串 |
| text | TEXT | 长文本 |
| integer | INTEGER | 整数 |
| bigInteger | BIGINT | 大整数 |
| smallInteger | SMALLINT | 小整数 |
| tinyInteger | TINYINT | 微整数 |
| decimal | DECIMAL(m,d) | 定点数 |
| boolean | BOOLEAN | 布尔值 |
| json | JSON | JSON 数据 |
| binary | BLOB | 二进制数据 |
| datetime | TIMESTAMP | 日期时间 |
| timestamp | TIMESTAMP | 时间戳 |
| date | DATE | 日期 |
| time | TIME | 时间 |
| uuid | UUID | UUID |
使用示例
package main
import (
"git.fsdpf.net/go/db/engine"
"git.fsdpf.net/go/db/schema"
_ "git.fsdpf.net/go/db/dialect/duckdb"
_ "git.fsdpf.net/go/db/schema/dialect/duckdb"
_ "github.com/marcboeker/go-duckdb"
)
func main() {
// 创建数据库连接
db := engine.Open(map[string]engine.DBConfig{
"duckdb": engine.NewDBConfig("duckdb",
engine.WithDuckDBFile("mydb.duckdb"), // 或者 "" 表示内存数据库
),
}).Connection("duckdb")
// 获取 schema 实现
s := schema.GetSchemaDialect(db)
// 创建表
bp := schema.NewBlueprint("users")
bp.Create()
bp.BigIncrements("id").AutoIncrement().Comment("用户ID")
bp.String("name", 50).Comment("用户名")
bp.String("email", 100).Comment("邮箱")
bp.Integer("age").Nullable().Comment("年龄")
bp.Boolean("active").Default("1").Comment("是否激活")
bp.Timestamp("created_at").UseCurrent().Comment("创建时间")
bp.Timestamp("updated_at").UseCurrent().Comment("更新时间")
// 编译并执行
sqls := s.CompileCreate(bp)
for _, sql := range sqls {
db.Exec(sql)
}
// 添加新列
bp2 := schema.NewBlueprint("users")
bp2.String("phone", 20).Nullable().Comment("电话")
sqls = s.CompileAdd(bp2)
for _, sql := range sqls {
db.Exec(sql)
}
}
DuckDB 特性说明
自增主键
DuckDB 使用 SERIAL 类型系列实现自增:
SERIAL- 对应 INTEGER 自增BIGSERIAL- 对应 BIGINT 自增SMALLSERIAL- 对应 SMALLINT 自增
bp.BigIncrements("id").AutoIncrement()
// 生成: "id" BIGSERIAL NOT NULL PRIMARY KEY
列修改
DuckDB 的 ALTER COLUMN 操作需要分别执行:
bp.String("name", 100).Change("username")
// 生成多条 SQL:
// 1. ALTER TABLE "users" RENAME COLUMN "name" TO "username"
// 2. ALTER TABLE "users" ALTER COLUMN "username" TYPE VARCHAR(100)
// 3. ALTER TABLE "users" ALTER COLUMN "username" SET NOT NULL
表注释和列注释
DuckDB 使用标准 SQL 的 COMMENT ON 语法:
bp := schema.NewBlueprint("users")
bp.Comment = "用户表"
// 生成: COMMENT ON TABLE "users" IS '用户表'
列注释暂时不支持单独的 COMMENT ON COLUMN 语句。
标识符引用
DuckDB 使用双引号引用标识符 (PostgreSQL 风格):
CREATE TABLE "users" (
"id" BIGSERIAL NOT NULL PRIMARY KEY,
"name" VARCHAR(50) NOT NULL
)
测试
运行测试:
# 运行所有测试
go test ./schema/dialect/duckdb/...
# 运行示例测试
go test -v ./schema/dialect/duckdb/... -run Example
# 运行特定测试
go test -v ./schema/dialect/duckdb/... -run TestCompileCreate
注意事项
- DuckDB 是分析型数据库,主要用于 OLAP 场景
- 内存数据库性能优异,适合测试和临时数据处理
- 支持 PostgreSQL 兼容的大部分语法
- 不支持所有的 MySQL 特性 (如 UNSIGNED、AUTO_INCREMENT 等)