Skip to main content

Module command

Module command 

Source
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§

CountQueryPlan
Page
QueryPlan
WriteLinks
一个写计划的链路解析结果。

Enums§

Mode
读路径形态:决定 Host 如何执行命令序列
Probe
creator 写权限的探针状态: NotProbed → 尚未探查(可能返回需要探针的命令) NoResult → 探针无结果(拒绝) Found → 探针命中的 {_id, createdBy} 文档
WriteLinkPolicy
跨连接写策略。

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 封顶,防拖库)
PHASE1_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 (对应 JS remove 内的归档段;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), 大集合不再全量取回后丢弃(对齐 MongoDB findOne 的 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 依赖注入的字段