SQL 拦截器(实体过滤器)
有些条件应该对某实体的所有查询生效——软删除(排除已删行)、多租户、行级权限。手写进每个查询容易漏;FilterManager 把它做成机制:注册一次,自动注入所有查询。
沙盒真实演示:软删除 task
示例数据中有 task 表(id/title/deleted_at,含一行已软删除),下面的完整示例可直接运行:
// ① 导入:model/prop/dto 建模型;FilterManager 从 @ts-grm/sql 导入;
// createFilteredClient 是示例提供的 client 工厂(仅可带 filterManager)
import { model, prop, dto } from '@ts-grm/core'
import { FilterManager } from '@ts-grm/sql'
import { createFilteredClient, sqlClient } from './infra/sql-client'
// ② 模型:task 含 deletedAt(时间戳;非空 = 已软删除)
const Task = model("Task", "id", class {
id = prop.i64()
title = prop.str(50)
deletedAt = prop.dt().nullable()
})
// ③ 注册软删除过滤器:谓词 = deleted_at is null
const filterManager = new FilterManager()
filterManager.add(Task, t => t.deletedAt.isNull())
// ④ 用带过滤器的 client 查询:所有 task 查询自动 AND deleted = false
const client = createFilteredClient({ filterManager })
const tasks = await client.createQuery(Task, (q, t) => {
return q.select(t.fetch(dto.view(Task, c => [c.id, c.title])))
}).fetchList()
console.log('过滤器 client(自动排除已删):')
console.log(tasks)
// ⑤ 对照:默认 client 无过滤器,能看到全部(含已删行)
const all = await sqlClient.createQuery(Task, (q, t) => {
return q.select(t.fetch(dto.view(Task, c => [c.id, c.title])))
}).fetchList()
console.log('默认 client(含已删行):', all)
运行结果:过滤器 client 只返回未删除的 2 行(“旧需求”被自动排除),默认 client 返回 3 行含已删——同一个模型,有无拦截器带来不同查询语义。
机制
const filterManager = new FilterManager()
filterManager.add(MODEL, table => 谓词) // Filter = (table) => Predicate | undefined
const client = newSqlClient(driver, { filterManager }) // 挂到 client 即全量生效
- 谓词与查询内
q.where(...)AND 叠加,对 findMany/createQuery/子查询/计数全部生效; - 返回
undefined表示该查询不附加约束(可选过滤); - 示例工作区提供了
createFilteredClient(仅透传filterManager);真实项目直接用newSqlClient的filterManager选项。
典型场景
| 场景 | 过滤器谓词 |
|---|---|
| 软删除 | row => row.deletedAt.isNull() |
| 多租户行隔离 | row => row.tenantId.eq(currentTenant) |
| 行级权限 | row => row.ownerId.in(currentUserVisibleIds) |
| 默认数据范围 | row => row.status.ne("ARCHIVED") |
把"惯例"沉淀成拦截器后,新写查询天然合规——少一个忘记过滤的坑。要临时放行(管理后台看已删数据)就注册时为"默认 client"与"管理 client"分别配置过滤器,而不是绕过规则。
下一步
SQL 后端七页收束:驱动 → 命名 → 事务 → 方言 → 日志 → 模式创建 → 拦截器。「API 参考」提供速查。