Skip to content

[finding][drivers] DriverQuery 已经存在,但几处驱动调用方仍在用 as any / as QueryAST 兜住冗余的 object —— 连带把 where/orderBy/fields 的检查一起关掉 #6231

Description

@os-zhuang

#6075(PR #6210)做下游消费半径清扫时实测发现,记录备查。观察类,不挂 pm:queue,请分诊轮定级。

现状

#5181DriverQuery 的动机之一,就是消灭「调用方手上只有 where,却叫不出类型的名字,于是 as any」这个口子 —— 它那条 changeset 记过代价:cloud#1053 实测 20 处,cloud#1030 的 $like 就是从这里活到运行时的。

DriverQuery 现在有了(#6076 已合),#6075 也让五个驱动的实现跟上了。但仍有几处调用方保持原样,因为它们藏在 cast 后面、编译器看不见(全仓 pnpm typecheck 125/125 全绿的前提下依然存在):

位置 现状
packages/metadata/src/loaders/database-loader.ts:233 this.driver!.find(table, { object: table, ...query } as any)
packages/metadata/src/loaders/database-loader.ts:240 this.driver!.findOne(table, { object: table, ...query } as any)
packages/metadata/src/loaders/database-loader.ts:247 this.driver!.count(table, { object: table, ...query } as any)
packages/objectql/src/engine.ts:3317 secretDriver.find('sys_secret', { object: 'sys_secret', where: { id } } as QueryAST)
packages/objectql/src/lifecycle/lifecycle-service.ts:772 driver.count(obj.name, { object: obj.name })(无 cast,靠形参松)

(行号取自 origin/main @ 80f7dc6 之后的分支,会漂。)

为什么是一笔账

两层,第二层才是重点:

  1. 冗余:第一个实参已经是对象名,object 又写一遍 —— 就是 [spec] IDataDriver 的 query 参数要求 QueryAST.object 与第一实参重复 —— 下游被迫 as any(20 处实测),提议 Omit/optional 化 #5181 消掉的那个冗余,只是它活在 cast 后面躲过了 TS2353
  2. as any 把整个 query 的检查关掉:不只是 objectwhere / orderBy / fields 一并失去检查。这正是 [spec] IDataDriver 的 query 参数要求 QueryAST.object 与第一实参重复 —— 下游被迫 as any(20 处实测),提议 Omit/optional 化 #5181 的 changeset 点名的那笔账,而 database-loader 是元数据加载的主读路径。

as QueryAST(engine.ts:3317)好一些但同理:它只是为了满足 object 必填而存在,删掉键之后这个 cast 本身也就不需要了。

不是缺陷,别当缺陷派

今天没有人踩:这些站点传的 object 与第一个实参逐字相同(已逐处核对),且 git grep 'query\.object' -- 'packages/drivers/*/src'main 上仍是零命中,没有任何驱动读它。所以这是休眠的冗余 + 自愿放弃的检查,不是活体缺陷。

如果要做

database-loader 那三处大概是这个形状(query 本身若已是 DriverQuery 形,连展开都不需要):

// FROM
return this.driver!.find(table, { object: table, ...query } as any);
// TO —— 键和 cast 一起消失,where/orderBy/fields 重新受检
return this.driver!.find(table, query);

⚠️ 逐处核对相等性,别无脑 sweep。 同一次扫描里还撞到一个故意不相等的站点:packages/objectql/src/engine-unknown-option.test.ts:183engine.find('task', { object: 'person' } as any) 是一条拒绝测试,按「见 object: 就删」的批量清扫会直接毁掉它。另外 expand 条目里的 object 命名的是关联对象、以及 syncSchemasBatch([{ object, schema }]) 里的 object 是被真实读取的必填键,两者都不能删。

参考 PR #6210 里的删键办法:用带反向引用的模式,只在值与第一个实参逐字相同时才匹配,等价性由模式本身保证。

会话:session_01WyvqvKMG6asi9aXjKE6xtx#6075 下游清扫期间发现,未认领)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions