From 82f57deec840cd65612d93f5bbc23229af236e72 Mon Sep 17 00:00:00 2001 From: what Date: Thu, 20 Aug 2026 16:47:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=A1=A5=E5=85=85=20README=EF=BC=8C?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=95=B4=E4=BD=93=E6=9E=B6=E6=9E=84=E4=B8=8E?= =?UTF-8?q?=20v1-legacy=20=E5=88=86=E6=94=AF=E7=9A=84=E5=85=B3=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 老代码库(git.fsdpf.net/go/db 现在的 master)用的是链式字符串拼接的 db.Builder, 这个仓库是另开的新项目,架构 fork 自 doug-martin/goqu(表达式树 + 方言渲染), 两边历史不相关。记录当前仓库的整体能力(SelectDataset 系列、exp 表达式树、 engine 连接管理、schema 建表迁移),并说明还在用老 API 的项目应该去 v1-legacy 分支。 --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e9c2e0..d21fe28 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,50 @@ -## Credits -https://github.com/doug-martin/goqu \ No newline at end of file +# git.fsdpf.net/go/db(master) + +数据库访问层,架构上 fork 自 [doug-martin/goqu](https://github.com/doug-martin/goqu):不是链式 +拼字符串的 Builder,而是先构造一棵 `exp` 表达式树,再由方言(dialect)相关的 `sqlgen` 渲染成 +具体 SQL + 绑定参数。配合 `req-v2`/`orm-v2` 等 "-v2" 系列项目使用。 + +## 这个仓库有什么 + +### 查询构造:`SelectDataset`/`InsertDataset`/`UpdateDataset`/`DeleteDataset` + +- `db.From(table ...interface{}) *SelectDataset`:起一个查询,`.Select(...)`/`.Where(...)`/ + `.Join(...)`/`.GroupBy(...)`/`.Order(...)` 等链式方法都是在往同一棵表达式树上追加/替换子句 + (`Clauses`),不是拼字符串,所以中间状态可以安全地复制、按条件分支修改。 +- `Executor()`/`ScanStructs`/`ScanStruct`/`GetRecords()`:真正执行查询、把结果扫进结构体或 + `map[string]any`。`ToSQL()` 只生成 SQL 文本,不落库,方便测试断言/调试。 +- `.WithHook(hook)`:给这次查询挂一个 `exec.Hooks` 实现(`Before`/`After` 两个阶段),这是 + `req-v2/resx` 包用来做字段级脱敏、行级权限过滤、变更留痕的挂载点——`db-v2` 本身不关心权限, + 只提供"查询执行前后可以介入改写"这个机制。 + +### 表达式树:`exp` 包 + +- `exp.IdentifierExpression`(`db.I`/`db.C`/`db.T`,标识符:列/表/schema)、 + `exp.LiteralExpression`(`db.L`/`db.V`,字面量/原样 SQL 片段)、 + `exp.AliasedExpression`(`.As(...)`)、`exp.SQLFunctionExpression`(`db.Func`/`db.COUNT`/ + `db.COALESCE` 等聚合与常用函数)、`exp.CaseExpression`(`db.Case()`)、 + `exp.WindowExpression`(`db.W()`,窗口函数)。 +- 这棵树是 immutable/copy-on-write 风格的:每次链式调用返回新的(或者原地更新的)`Clauses`, + 不会有隐式的跨查询共享状态问题。 + +### 连接与方言 + +- `engine.Engine`:多连接管理,`engine.Open(cfgs map[string]DBConfig)` 从配置建立连接池, + `engine.Mock(cfgs map[string]MockDBConfig)` 用 `sqlmock` 建 mock 连接(测试专用); + `Engine.Connection(name string) *db.Database` 按连接名取出可以直接 `.From(...)` 发查询的 + `*db.Database`。 +- `dialect/mysql`/`dialect/sqlite3`/`dialect/duckdb`:具体方言实现,通过 `import _ + "git.fsdpf.net/go/db/dialect/mysql"` 这种匿名 import 注册进 `sqlgen`,不用的方言不用编译进去。 +- `dialect/sqlite3/vtab`:SQLite 虚拟表(Virtual Table)支持,给需要把非关系数据源伪装成表的 + 场景用(`sqlite3`/`vtable` build tag 控制是否编译)。 + +### 建表/迁移:`schema` 包 + +- `schema.Blueprint`/`ColumnDefinition`:描述表结构(列类型、长度、默认值、可空性等), + `schema/dialect/*` 按方言生成 `CREATE TABLE`/`ALTER TABLE` 语句。 + +## 分支状态 + +`master` 是持续开发中的新架构,**跟老仓库 `v1-legacy` 分支历史不相关**(`db-v2` 是另开的新 +项目,不是从老代码库演化过来的),API 完全不兼容。还在用老版 `db.Builder`(`Table`/`Find`/ +`Paginate`/`Chunk` 那一套)的老项目,参见 `v1-legacy` 分支。