Files
condition/README.md
T
what dcfd2f42da docs: 补充 README,说明当前分支的能力范围
配合 v1-legacy 维护分支的拆分,记录 master 这条线(Condition/ConditionExpr
表达式树、TokenValue、JSON 序列化、engine 规则引擎)目前有哪些能力,跟
v1-legacy 分支做区分;顺带记一下 engine.go 那个已知的 nil user 问题。
2026-08-21 09:03:29 +08:00

55 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# git.fsdpf.net/go/conditionmaster
条件表达式 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` 分支。