A general relational execution core for MoonBit: typed plans, per-node cardinality, and verifiable contracts with minimal witnesses.
v0.2.4 preview:从 JoinWitness(单点等值关联预检)扩展而来。v0.1 只回答“这一对表 join 会不会扇出”;v0.2 回答“这条管道在哪一步、因为哪个键、扇出了多少行”。 对初审意见的逐条回应(改了什么、证据在哪、什么还没做)见 docs/REJECTION_RESPONSE.md。
| 它不是 | 为什么 |
|---|---|
| 不是 DataFrame 门面 | 不提供链式 df.filter().group_by() API;门面可以建在 Relcore 之上,Relcore 只做执行层 |
| 不是 SQL 引擎 | 不实现 SQL 方言、不做解析器;入口是 plan IR,未来可由 SQL AST 生成 |
| 不是单表校验器 | 不做规则市场、不做 schema 迁移;契约挂在执行计划的结果与 join 节点上 |
let orders = @relcore.read_csv(orders_text, "orders")
let customers = @relcore.read_csv(customers_text, "customers")
let result = @relcore.execute(
@relcore.Join(
@relcore.Scan(orders),
@relcore.Scan(customers),
["customer", "tenant"],
["customer", "tenant"],
@relcore.Inner,
),
)
let violations = @relcore.check_contracts(result.batch, result.stats, [
@relcore.JoinCardinality(["many_to_one"]),
])node bin/relcore.mjs examples/plan-tenant-fanout.json --md# Relcore report
- rows: 7
- contracts: **fail**
## Plan stages
| stage | rows in | rows out | fanout | cardinality |
| --- | --- | --- | --- | --- |
| scan | 5 | 5 | 0 | - |
| scan | 4 | 4 | 0 | - |
| join:inner | 9 | 7 | 2 | many_to_many |
## Violations
- **JOIN_CARDINALITY**: join cardinality many_to_many is outside the allowed set
- `worst_key=3:i:9|`
- `left_rows=3,4`
- `right_rows=2,3`node bin/relcore.mjs examples/compare-tenant-keys.json{
"ok": false,
"baseline_rows": 7,
"candidate_rows": 5,
"row_diff": { "retained": 5, "lost": 2, "gained": 0 },
"first_divergence": {
"index": 2,
"baseline_op": "join:inner",
"candidate_op": "join:inner",
"baseline_rows": 7,
"candidate_rows": 5
}
}| 层 | 已实现(v0.2 preview) | 计划中 |
|---|---|---|
| 数据模型 | Schema / Field / DataType / Column / Batch(列式) | 分块(chunk)与字典编码 |
| 类型 | null / bool / int64 / float64 / text | decimal / date / time |
| 输入 | CSV、JSONL、内存 Batch | Arrow IPC、Parquet |
| 算子 | scan filter project join(inner/left/right/full/semi/anti) aggregate sort limit union distinct | with_columns、窗口、explode |
| 计划 | 逻辑计划 IR、JSON 序列化、tag 节点、explain() 树形输出 | join 谓词拆分、投影裁剪 |
| 优化 | 常量折叠、filter 下推 project/sort、limit 下推 project | join 谓词拆分、投影裁剪、代价模型 |
| 契约 | row_count / unique / no_null / join_cardinality;可挂在根或 tag 节点 | foreign_key / accepted_values |
| 证据 | 最坏键、左右行号、fanout、未匹配数 | 自动最小化到最小行集 |
| 对比 | 两条计划逐阶段对比 + retained/lost/gained | 多候选对比、回归基线库 |
| 接口 | MoonBit 库、JSON 计划、Node CLI、JS 构建 | 浏览器工作台、SQL AST 适配 |
| 契约 | 参数 | 检查位置 | 违约证据 |
|---|---|---|---|
| row_count | min, max | 根或 tag 节点 | 实际行数 |
| unique | columns | 根或 tag 节点 | 重复键 + 前 5 组行号 |
| no_null | columns | 根或 tag 节点 | 列名 + 前 5 个空值行号 |
| join_cardinality | allowed | 每个 join 节点 | 节点、形态、最坏键、fanout、左右行号 |
| 左键唯一 | 右键唯一 | 形态 |
|---|---|---|
| 是 | 是 | one_to_one |
| 是 | 否 | one_to_many |
| 否 | 是 | many_to_one |
| 否 | 否 | many_to_many |
| 维度 | JoinWitness v0.1 | Relcore v0.2 |
|---|---|---|
| 输入格式 | 1(私有 JSON) | 3(CSV / JSONL / 内存) |
| 类型 | 4(text/int32/bool/null) | 5(+ int64/float64) |
| 算子 | 1(equi-join) | 9,可任意组合 |
| 计划 | 无 | 逻辑计划 IR + JSON + tag |
| 契约作用域 | 仅 join | 任意 tag 节点 + 每个 join 节点 |
| 规模 | 硬上限 1 万行/表 | 单进程内存;max_rows / max_join_rows 可配,超限 BUDGET_EXCEEDED |
| 调用方式 | CLI | 库 / CLI / JS |
| 生态对接 | 无 | CSV / JSONL(Arrow 在路线图) |
| 计划对比 | 无 | 逐阶段分叉 + 行对差异 |
| 项目 | 它做什么 | 重叠 | Relcore 的差异 |
|---|---|---|---|
| MoonFrame | Polars 风格 DataFrame 门面 | 列式表、join、group_by、sort | 不提供门面;提供 plan IR、节点契约、基数形态、witness、计划对比 |
| moonsql | 嵌入式关系 SQL 引擎 | 关系算子执行 | 不做 SQL 方言;plan IR 是数据,可被 SQL 前端消费 |
| mbitsv | CSV/TSV 校验、profile、单表 diff | CSV、校验、diff | 契约挂在执行计划与 join 节点上;证据是基数与行对 |
| moon-data-contract | schema 治理、迁移规划 | “contract” 一词 | 元数据层 vs 执行层,不是同一层的东西 |
| JoinWitness | 单算子预检(作者前作) | join、基数、证据 | 本期扩展:9 算子、3 输入、节点契约、计划对比;旧仓库保留为原型 |
relcore/
├── types.mbt # DataType / Value / Schema / Batch
├── csv.mbt # RFC-4180 风格 CSV 读取与类型推断
├── expr.mbt # 表达式树与三值逻辑
├── exec.mbt # 逻辑计划 + 算子执行 + 节点统计 + 证据
├── contract.mbt # 契约检查、节点契约、witness
├── wire.mbt # JSON 计划/对比解析、JSONL 读取
├── api.mbt # run / run_markdown / compare
├── api/ # JS 导出层
├── bin/relcore.mjs # Node CLI
└── examples/ # 可复现计划与对比moon check --target all --deny-warn
moon test --deny-warn # 32 项
moon test --target js --deny-warn # 32 项
moon fmt --check
moon run examples/embed --deny-warn # 库 API 消费者
node scripts/build.mjs
node --test tests/cli.test.mjs # 8 项
python tests/oracle.py # 4 组 SQLite 差分校验| 日期 | 目标 |
|---|---|
| 10/24 | 内核骨架、CSV/JSONL、9 算子、4 契约、节点契约、计划对比、CLI(已完成) |
| 10/25 | 表达式补全、保守优化器(常量折叠/filter/limit 下推)、explain()(已完成) |
| 10/26 | 分块执行;预算参数已完成(BUDGET_EXCEEDED) |
| 10/27 | Arrow IPC 只读适配、浏览器工作台 |
| 10/28 | DuckDB/Polars 差分 oracle、基准 |
| 10/29 | CI 矩阵、API 文档、发布 Mooncakes |
| 10/30 | 申报书与提交 |
| 10/31 | buffer |
pub(all) struct NodeStat {
op : String
rows_in : Int
rows_out : Int
matched_left : Int
unmatched_left : Int
unmatched_right : Int
max_fanout : Int
left_unique : Bool
right_unique : Bool
worst_key : String?
worst_count : Int
evidence : JoinEvidence?
} derive(Eq)pub(all) enum Plan {
Scan(Batch)
Filter(Expr, Plan)
Project(Array[(String, Expr)], Plan)
Join(Plan, Plan, Array[String], Array[String], JoinKind)
Aggregate(Array[String], Array[AggSpec], Plan)
Sort(Array[(String, Bool)], Plan)
Limit(Int, Plan)
Union(Plan, Plan)
Distinct(Array[String], Plan)
Tag(String, Plan)
}fn compare(source : String) -> Stringfn explain(source : String) -> Stringfn run(source : String) -> Stringfn run_markdown(source : String) -> StringInstall
Download zipA general relational execution core for MoonBit: typed plans, per-node cardinality, and verifiable contracts with minimal witnesses.