配合 v1-legacy 维护分支的拆分,记录 master 这条线(Condition/ConditionExpr 表达式树、TokenValue、JSON 序列化、engine 规则引擎)目前有哪些能力,跟 v1-legacy 分支做区分;顺带记一下 engine.go 那个已知的 nil user 问题。
55 lines
3.2 KiB
Markdown
55 lines
3.2 KiB
Markdown
# git.fsdpf.net/go/condition(master)
|
||
|
||
条件表达式 DSL:把一组条件(等值/比较/模糊匹配/IN 等)组织成可嵌套的 `AND`/`OR` 树,渲染成
|
||
`db-v2` 的表达式(`db.Expression`),供权限过滤、规则引擎等场景复用同一套条件描述。配合
|
||
"-v2" 系列项目使用。
|
||
|
||
## 这个仓库有什么
|
||
|
||
### `Condition`/`ConditionExpr`
|
||
|
||
- `Condition`:条件树的节点,`AppendTo`/`SetCondition`/`SetExpr` 组装子条件/表达式,
|
||
`ToSql(m TokenValue) db.Expression` 渲染成 `db-v2` 的表达式树——内部用
|
||
`exp.NewExpressionList(this.typ, conditions...)` 构造,不是手工拼 SQL 字符串。
|
||
`ConditionType` 是 `exp.ExpressionListType`(`AND`/`OR`)的类型别名。
|
||
- `ConditionExpr`:单个表达式(字段 + 操作符 + 值),`ConditionOperator` 是
|
||
`exp.BooleanOperation` 的类型别名(`EQ`/`NE`/`GT`/`LIKE`/`IN` 等),跟 `db-v2` 的操作符
|
||
体系直接对齐,不用自己维护一份字符串常量再转换。
|
||
- `util.go`:`ToConditionOperator(op string) ConditionOperator` 把字符串(比如从配置/请求
|
||
参数解析出来的)转成 `ConditionOperator`。
|
||
|
||
### `TokenValue`(`token_value.go`)
|
||
|
||
条件渲染时取值用的接口:`GetParam(k string) valuex.Accessor`(配合 `reflux/valuex` 统一属性
|
||
访问方式)+ `User() req.User`。`NewTokenValue(x valuex.Accessor, opts ...tValueOpt)` 构造,
|
||
`WithUser(user)` 显式指定用户;不传时会尝试从 `x` 上探测 `User()` 方法,两者都拿不到会
|
||
panic——`TokenValue` 必须绑定一个具体用户,不支持匿名/无用户场景。
|
||
|
||
### JSON 序列化(`condition_json.go`)
|
||
|
||
`Condition`/`ConditionExpr` 都实现了 `MarshalJSON`/`UnmarshalJSON`(内部过一层 DTO 结构避免
|
||
递归),`FromMap(m map[string]any) (*Condition, error)` 直接从已解析好的 map 构造,不用先转
|
||
成 JSON 字符串再解析一遍——典型场景是权限配置、规则条件存在数据库的 JSON 列里,读出来直接
|
||
反序列化成 `Condition` 用。
|
||
|
||
### `engine` 子包:规则引擎
|
||
|
||
`Engine[T any]`:按 `Case(cond *condition.Condition, cb func(data T, g req.GlobalParams) error)`
|
||
注册一组"条件 -> 回调"规则,`Execute(data T)` 对传入数据求值,命中第一个条件为真的分支就
|
||
调用对应回调(`Default(cb)` 兜底)。内部通过 `db/engine`(sqlite3 内存库)把 `data`(用
|
||
`reflux.R` 包装)当成一行虚拟数据跑 SQL 判断条件是否成立,不用自己写一套表达式求值器。
|
||
`EngineOption`(`Debug()`/`Relation(...)`)控制调试日志和关联字段展开。
|
||
|
||
## 已知问题
|
||
|
||
`engine.go` 在调用方没有显式传 `GlobalParams` 时,会用 `nil` user 构造一个兜底值,这跟
|
||
`TokenValue` 现在强制要求非 nil user 冲突,`TestEngine` 目前会 panic——待 `Engine.Execute`
|
||
支持显式传 user 时一并解决,暂时未修。
|
||
|
||
## 分支状态
|
||
|
||
`master` 是持续开发中的新架构,**跟老仓库 `v1-legacy` 分支不兼容**——`Condition.ToSql` 从手工
|
||
拼 SQL 字符串换成了 `db-v2` 表达式树,`TokenValue` 从 `req.GlobalParams` 换成了
|
||
`reflux/valuex`,`engine` 包的连接管理也换成了 `db/engine`。还在用老版 API 的老项目,参见
|
||
`v1-legacy` 分支。
|