Expand description
Command 序列契约(方案 A 的「core 产出指令、Host 执行」边界)
core 不持有 MongoDB 驱动。读/写路径被拆成两步:
Host: plan = core.plan_query(gql, params, ctx) // 纯逻辑,产出命令
Host: for cmd in plan.commands { driver.execute(cmd) } // 唯一 IO 边界
Host: items = core.finalize(plan, items) // 回喂 core 做后处理命令 JSON 形状(语言无关,Node/Python 两侧共用):
source / database / schema / collection 为定位四元组,由生成该命令的 schema
一次填入(source 缺省 "default",database / schema 缺省 null = 连接自身默认库/schema;
schema 仅 PostgreSQL 落点携带非 null)。
Host 依据 cmd.source(而非 collection 反查)选择连接;database / schema 的用法见
multi-datasource-routing-plan.md(Mongo client 型 source / SQL qualified 表名)。
{ "kind": "find", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...}, "projection": {...}|null }
{ "kind": "aggregate", "source": "pg1", "database": "app_db", "schema": "app", "collection": "u", "pipeline": [ ... ] }
{ "kind": "countDocuments", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...} }
{ "kind": "findOne", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...}, "projection": {...}|null }
{ "kind": "insertOne", "source": "default", "database": null, "schema": null, "collection": "u", "doc": {...} }
{ "kind": "insertMany", "source": "default", "database": null, "schema": null, "collection": "u", "docs": [ ... ] }
{ "kind": "findOneAndUpdate", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...}, "update": {...}, "options": {...} }
{ "kind": "updateMany", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...}, "update": {...} }
{ "kind": "deleteMany", "source": "default", "database": null, "schema": null, "collection": "u", "filter": {...} }两阶段查询($lookup + $skip/$limit)的命令序列里,第二条 aggregate 的
$match._id.$in 为占位符 PHASE1_IDS,Host 需用第一条命令返回的
_id 数组(保持顺序)替换后再执行;执行完调用 restore_sort_order 还原排序。
写路径占位符:mutation 步骤间的父子依赖用 {{step.<N>._id}}
(step_id_placeholder)表达——第 N 步执行结果文档的 _id,Host 在该步
执行完成后回填到后续命令。需新生成的 _id 不用占位符:由 Host 供给
new_ids / new_id 参数,core 按序消费(core 无随机源)。
子模块划分:
- [
cmd]:命令构造 + 数值工具 - [
query]:读路径计划(分页 / 两阶段 / 排序还原) - [
count]:列表 + total 计划 write:插入与简单查询计划 + 写权限探针- [
mutate]:update / updateMany / remove / upsert / insertMany 计划 - [
mutation]:mutation 递归规划(父子文档步骤序列) - [
finalize]:结果回喂(后处理 / asyncFn 桥 / 剥离注入)
Structs§
- Count
Query Plan - Page
- Query
Plan - Write
Links - 一个写计划的链路解析结果。
Enums§
- Mode
- 读路径形态:决定 Host 如何执行命令序列
- Probe
- creator 写权限的探针状态:
NotProbed→ 尚未探查(可能返回需要探针的命令)NoResult→ 探针无结果(拒绝)Found→ 探针命中的{_id, createdBy}文档 - Write
Link Policy - 跨连接写策略。
Constants§
- ERR_
NO_ BATCH_ WRITE - ERR_
NO_ CONTEXT require_context开启时 ctx 缺失的拒绝哨兵(fail-secure;Host 按前缀识别, 一般映射为 500 配置/契约错误而非 403 —— 这是调用方合约违反,不是用户无权限)。- ERR_
NO_ DELETE - ERR_
NO_ WRITE - ERR_
PERMISSION - ERR_
PERM_ PREFIX - 权限拒绝哨兵:Host 需映射为各自的 PermissionError。
- ERR_
TEXT2QUERY - 档位拒绝哨兵:text2query 档命中硬限制/收缩项时的稳定前缀。
- ERR_
WRITE_ CROSS_ SOURCE_ PREFIX - 跨连接写同步的稳定错误前缀(宿主可按前缀识别)
- MAX_
PAGE_ SIZE - 读取上限(pageSize 封顶,防拖库)
- PHAS
E1_ IDS - 两阶段查询中由 Host 替换的阶段一
_id顺序数组 - T2Q_
MAX_ DEPTH - T2Q_
MAX_ FEDERATION_ ROWS - T2Q_
MAX_ ROWS - text2query 档硬限制(单点定义,Host 可读;取值严于 standard)
Functions§
- apply_
route_ override - 把计划内所有命令体的定位字段替换为
routeOverride声明。 - build_
plan - 由 AST 构建
QueryPlan:pipeline 用fetch_ast,后处理用post_ast。 - check_
readable_ relations - T2 / L1 / L2 / L5 / L6:递归校验 GQL 显式请求的关系可读性。
- check_
write_ perm - Schema 级写权限检查(对应 JS
_checkWritePerm): 拒写清单命中直接拒绝;非写授权时仅 creator 命中才放行(需 Host 先执行探针命令)。 - cmd_
aggregate - cmd_
count_ documents - cmd_
delete_ many - cmd_
find - cmd_
find_ one - cmd_
find_ one_ and_ update - cmd_
insert_ many - cmd_
insert_ one - cmd_
update_ many - ensure_
context - fail-secure 门禁:
require_context开启时拒绝ctx: None(默认关闭时零开销放行)。 - ensure_
profile_ ctx - text2query 档强制上下文(叠加于
ensure_context之上)。 - ensure_
route_ override_ allowed - text2query 档禁止携带
route_override(受信来源门禁)。 - err_
write_ cross_ source - 构造跨连接写拒绝错误(前缀 + schema 名 + source 列表)
- finalize_
query - 读路径尾部后处理(对应 JS
_postprocess三段时序) - forbid_
t2q - text2query 档禁用某项能力(standard 档放行)。
- forbid_
t2q_ shape - text2query 档功能收缩 Err(无
Registry场景:仅持Profile的形状校验函数用)。 - has_
pipeline - 用户
$pipeline直通探测:GQL 根参数声明了$pipeline且对应 params 值非 nullish。 - plan_
archive_ docs - 归档文档命令:源文档补
deletedAt后批量写入<collection>_deleted(对应 JSremove内的归档段;Host 仅在 find 有结果时调用)。 - plan_
count - 统计数量(对应 JS
count):filter 为 nullish 时用{} - plan_
exists - 判断存在性(对应 JS
exists) - plan_
insert - 生成插入命令(对应 JS
insert) - plan_
insert_ many - 批量插入(对应 JS
insertMany)。 - plan_
mutation - 规划一条 mutation(对应 JS
mutation的单条分支_mutationOne)。 - plan_
query - 生成读路径命令序列(对应 JS
query+_executePipeline的路径选择) - plan_
query_ ast_ mut - 由已解析的 AST 规划读路径(
plan_query_mut与联邦计划共用同一套语义) - plan_
query_ mut - 与
plan_query相同,但会把 owner 条件注入写回params(供 queryWithCount 复用) - plan_
query_ one - queryOne:语义为「取第一条」——用户 GQL 未显式给
$limit时强制下推$limit(1), 大集合不再全量取回后丢弃(对齐 MongoDBfindOne的 limit-1 语义)。 - plan_
query_ with_ count - 生成「列表 + total」命令序列(对应 JS
queryWithCount) - plan_
remove - 删除计划(对应 JS
remove): 归档表存在时返回 find 命令(Host 取源文档后调plan_archive_docs)+ deleteMany 命令。 - plan_
update - 更新一条(对应 JS
update,findOneAndUpdate+ returnDocument AFTER)。 - plan_
update_ many - 批量更新(对应 JS
updateMany)。拒写清单命中 / 无写授权直接拒绝,不走 creator 探针。 - plan_
upsert - 显式条件 upsert(对应 JS
upsert)。 - prepare_
query - finalize 第一阶段:逐条
process_node(补默认值 / 同步 fn / 递归下钻 / 权限裁剪), 并返回待 Host 执行的 asyncFn 回调标识(fnRef,已做 read 权限过滤)。 - resolve_
page - 分页参数解析(对应 JS
_resolvePage):page/pageSize 优先,否则由$skip/$limit反推 - resolve_
write_ links - 解析一个 schema 的写落点并做单连接判决。
- restore_
sort_ order - 两阶段查询后按阶段一
_id顺序重排(对应 JS_restoreSortOrder) - sorts_
by_ relation - pipeline 的
$sort是否引用关联表点号字段(如bidders.amount) - step_
id_ placeholder - mutation 第
idx步执行结果文档_id的占位符 - strip_
query - finalize 第三阶段:剥离 asyncFn 依赖注入的字段