Sign in

    moonsqlitefile

    Pure MoonBit read-only SQLite file format parser and inspector

    sqlite
    parser
    database
    inspector
    Download zip
    Author
    Version
    0.7.0
    License
    Apache-2.0
    Last updated
    9 days ago
    Downloads
    145

    #MoonSQLiteFile

    CI Mooncakes License

    纯 MoonBit 的 SQLite 文件解析与检查库

    MoonSQLiteFile 直接读取 SQLite 3 数据库的磁盘格式,提供文件头、页面、schema 和原始记录的只读 API。适合构建离线数据库浏览器、文件结构检查工具,以及 SQLite 存储格式的教学演示。

    核心库只依赖 MoonBit 标准库,支持 Wasm、WasmGC、JavaScript 和 native,无需 SQLite 引擎或 FFI。文件 I/O 由宿主提供;随附的 Node.js CLI 可直接检查本地数据库快照。

    #功能

    • 文件与页面解析:100 字节文件头、512–65536 字节页面、四类 B-tree 页、完整 cell/freeblock 空间覆盖与碎片计数校验。
    • 记录解码:1–9 字节 varint、标准 serial types、64 位整数、浮点、NULL、BLOB,以及 UTF-8、UTF-16LE、UTF-16BE 文本。
    • 表与索引读取:多层 rowid 表、索引内部页记录、WITHOUT ROWID 表、overflow 链及 sqlite_schema。
    • 有界扫描:逐条回调、提前停止、完成状态,以及记录数、树深度、页数和 payload 预算。
    • 结构检查:单树检查和全局页归属报告,检测跨对象重复占页、freelist 冲突、未认领页及 auto-vacuum Ptrmap 不一致。
    • WAL 快照:两种 checksum 字节序、salt 与提交边界校验、只读覆盖数据源和最新已提交页版本;CLI 显式接收 db/WAL 一致副本。
    • 宿主集成与展示:Bytes 输入、第三方同步 PageSource / RangeSource、空间与位置报告、中文/JSON CLI,独立异步 JS 范围源、背压与取消,以及单文件 Blob/WAL 页面导航。

    当前版本为 v0.7.0,从 v0.5.0 直接升级:包含同步 64 位范围读取、独立异步 JS 适配包、无 I/O 核心游标与 Blob/WAL 浏览器分块检查。v0.6.0 仅作为内部开发里程碑,未单独发布。契约及迁移方法见范围读取、异步范围读取和v0.7.0 升级说明。

    #安装

    使用 MoonBit release 工具链,在现有项目中运行:

    moon add prowk/moonsqlitefile@0.7.0

    在消费包的 moon.pkg 中添加导入:

    import {
    "prowk/moonsqlitefile" @sqlite,
    }

    #快速上手

    宿主读取数据库文件后,将完整字节传入 open_database。以下示例读取普通 rowid 表的前 10 行:

    fn read_rows(data : Bytes) -> Array[@sqlite.Row] raise @sqlite.SqliteError {
    let db = @sqlite.open_database(data)
    db.table_rows("samples", limit=10)
    }

    Row 提供 rowid、values 和所在 page_number。值类型包括 Null、Integer(Int64)、Real(Double)、Text(String) 和 Blob(Bytes)。

    对于 WITHOUT ROWID 表或索引,使用原始记录 API:

    fn read_records(data : Bytes) -> Array[@sqlite.BTreeRecord] raise @sqlite.SqliteError {
    let db = @sqlite.open_database(data)
    db.table_records("keyed", limit=10)
    }

    fn read_index(data : Bytes) -> Array[@sqlite.BTreeRecord] raise @sqlite.SqliteError {
    let db = @sqlite.open_database(data)
    db.index_records("mixed_index", limit=10)
    }

    BTreeRecord 额外提供 cell_offset;索引和 WITHOUT ROWID 记录的 rowid 为 None。这两个示例对应仓库中的 fixtures/btree.sqlite。

    #逐条扫描

    用 scan_btree 消费记录,可避免在库中收集整个结果数组。根页号可从 db.schema() 的条目获取:

    fn scan_records(
    data : Bytes,
    root_page : Int,
    consume : (@sqlite.BTreeRecord) -> Bool raise @sqlite.SqliteError,
    ) -> @sqlite.ScanSummary raise @sqlite.SqliteError {
    let db = @sqlite.open_database(data)
    db.scan_btree(root_page, consume, limit=1000, max_total_payload_bytes=8388608UL)
    }

    回调返回 false 时停止扫描。检查 ScanSummary.completion,区分 Complete(已遍历全部记录)、RecordLimit(达到记录上限)和 VisitorStopped(回调主动停止)。结果还提供已读取的记录数、页数及累计 payload 字节数。

    #按需读取

    open_source(&PageSource) 接收宿主实现的数据源,初始化时仅读取文件头,后续按范围读取字节。接口同步返回 Bytes,数据源必须在整个读取期间保持同一份静态快照。接口定义和资源限额见 架构说明。

    #检查数据库结构

    fn inspect_file(data : Bytes) -> @sqlite.DatabaseInspection raise @sqlite.SqliteError {
    let db = @sqlite.open_database(data)
    db.inspect_database(max_total_payload_bytes=67108864UL, max_issues=100)
    }

    报告提供每页的用途、对象、根页和父页,以及冲突双方、未认领页和 Ptrmap 不一致等诊断。status 区分 Complete、Incomplete 和 Failed;ownership_complete 表示归属遍历完成,ptrmap_checked 表示反向指针检查完成或不适用,diagnostics_truncated 表示诊断已截断。达到资源限额时会保留已完成的结果;未完成根页发现时,不把未知页判定为孤儿。

    只检查一棵树时使用 db.inspect_btree(root_page);读取原始反向指针时使用 db.ptrmap_entries()。结构检查范围与各标记的含义详见 架构说明。

    #读取 WAL 快照

    fn read_committed(db_bytes : Bytes, wal_bytes : Bytes) -> @sqlite.Database raise @sqlite.SqliteError {
    @sqlite.open_wal_database(db_bytes, wal_bytes)
    }

    inspect_wal 提供帧/提交报告;WalSource::new 可包装第三方同步源,再用 open_wal_source 打开。默认拒绝异常尾部,显式 UseValidPrefix 才读取异常前的完整提交;帧预算不足不能当作最新快照成功。输入必须是同一时刻的一致静态副本,详见 WAL 契约和升级说明。

    #命令行工具

    CLI 需要 MoonBit release 工具链和 Node.js 22 或更新版本,无 npm 依赖:

    git clone https://github.com/prowk/MoonSQLiteFile.git cd MoonSQLiteFile moon build --target js cmd/inspect node tools/inspect.cjs fixtures/core.sqlite schema node tools/inspect.cjs fixtures/core.sqlite rows samples 10 node tools/inspect.cjs fixtures/btree.sqlite index mixed_index 5 node tools/inspect.cjs fixtures/btree.sqlite inspect node tools/inspect.cjs fixtures/btree.sqlite summary

    将样本路径替换为自己的静态数据库副本即可检查实际文件。所有命令的格式为 node tools/inspect.cjs <file> <command> [arguments]:

    命令用途
    header读取数据库文件头
    schema列出 schema 条目及根页号
    page <number>检查指定 B-tree 页
    page-inspect <number>返回 B-tree 页空间统计与错误位置
    rows <table> [limit]读取普通 rowid 表
    records <table> [limit]读取普通表或 WITHOUT ROWID 表的原始记录
    index <name> [limit]读取索引原始记录
    scan <root> [limit]扫描指定根页,输出记录和扫描状态
    freelist检查空闲页链
    inspect输出全局页归属、Ptrmap 校验及结构化诊断
    tree-inspect <root> [limit]输出单树检查进度和失败位置
    inspect-details输出全局报告及各条诊断的位置
    summary中文检查摘要、页面分类、对象占页及诊断
    summary-json精简 JSON 汇总,适合展示层消费
    viewer-data同一次扫描的文件头、汇总、详细诊断与导航数据
    wal-inspect输入为 WAL 文件,输出连续有效帧和提交边界
    wal-info配合 --wal 输出帧报告、最新快照页数与尾部策略

    除 summary 输出中文文本外,成功时 stdout 输出一行 JSON;参数、初始化或读取错误写入 stderr,并返回非零退出码。能够构造报告的检查与摘要命令始终将报告写入 stdout:退出码 0 表示完整、1 表示失败、2 表示未完成,诊断与覆盖范围保留在报告中。整数和 rowid 输出为十进制字符串,BLOB 输出为十六进制字符串,避免 JavaScript 丢失 64 位整数精度。rows 默认上限为 100000 行,显式传入 0 返回空数组。

    WAL 输入格式为 node tools/inspect.cjs DB --wal WAL [--wal-prefix] COMMAND [arguments]。选项放在命令前;原有命令都读取同一已提交覆盖视图。不提供 --wal 时继续只读主文件,不自动加载相邻日志。wal-inspect 直接接收 WAL 文件并以 0/1/2 区分 EOF/异常尾部/帧预算不足。示例:

    node tools/inspect.cjs snapshot.wal wal-inspect node tools/inspect.cjs snapshot.db --wal snapshot.wal wal-info node tools/inspect.cjs snapshot.db --wal snapshot.wal inspect-details

    #离线页面导航

    当前源码先执行 moon build --target js --deny-warn 和 python tools/build_viewer.py,生成 _build/moonsqlitefile-viewer.html。界面支持静态 db/WAL、对象/父子/overflow 页导航、空间分布、cell 和原始字节;File/Blob 交给 Worker 按需分块读取,取消或预算耗尽显示部分结果。默认累计 payload 64 MiB、检查时间 120 秒,预算可调整,文件长度不再限制为 64 MiB。单文件没有外部资源,真实 Chrome 验收已覆盖本机页面载入后断网;直接 file:// 打开按本次交付范围保留为未验收项。详见离线示例。

    v0.7.0 Release 提供可下载的单文件 HTML 和异步 JS 包 tarball。HTML 可通过本机静态 HTTP 服务载入后断网使用;直接 file:// 打开尚未验收。

    独立异步包尚未发布 npm;下载 Release 中的 prowk-moonsqlitefile-async-0.7.0.tgz 后可执行 npm install ./prowk-moonsqlitefile-async-0.7.0.tgz,也可本地执行 python tools/build_async.py,使用 _build/async-adapter。它提供 Node 22 与 Blob 源、异步迭代器/visitor 背压、取消和详细检查,运行时没有第三方依赖,使用方式见适配契约。

    #支持范围与限制

    v0.4.0 补齐所访问 B-tree 页的空间覆盖与碎片计数校验,提供单页统计、详细树/全局诊断位置、对象占页汇总与离线导航。使用 inspect_page、inspect_btree_details、inspect_database_details 或 DatabaseInspection.summarize()。页面验证比 v0.3.0 更严格,升级前请阅读升级说明。

    MoonSQLiteFile 返回磁盘存储值,字段保留磁盘顺序,不推断 SQL 列名、默认值或类型亲和性。普通表的 INTEGER PRIMARY KEY 字段通常存为 Null,其真实值位于 Row.rowid;WITHOUT ROWID 表按主键优先存储字段,索引记录可能附带 rowid 或主键字段。

    当前版本只读静态数据库文件及最新已提交 WAL 覆盖快照,不执行 SQL、不写数据库、不执行 checkpoint、不获取在线并发快照,也不读取 shm 或提供任意历史事务。尚未验证索引排序与 collation、表与索引记录的一致性,也不提供 SQL 列映射;旧同步 PageSource 使用 Int 偏移;v0.7.0 合入原 v0.6.0 里程碑的 RangeSource、CachedSource 和 RangeWalSource,支持 64 位长度/偏移与 db/WAL 按需读取,页号最多为 2147483647。v0.7.0 在独立 JS 包提供异步 I/O;全局报告及 WAL 索引仍须独立预算,见范围读取契约及异步契约。

    扫描或检查结果为 Complete 只表示其覆盖范围内的工作完成,不等同于 SQLite integrity_check。解析错误通过 SqliteError 返回,分为 Invalid、Unsupported 和 LimitExceeded;检查 API 将错误保留在报告中。

    #开发与测试

    检出源码后,运行纯库示例:

    moon run --target js examples/basic

    预期输出:

    page_size=512, pages=1 schema entries=0

    完整验证需要 MoonBit release、Node 22、Python 3.13;SQLite 引擎仅用于样本生成和结果对照。真实浏览器测试先按 CI 安装 Playwright 1.62.1 和 Chromium,或用 MOONSQLITE_PLAYWRIGHT / MOONSQLITE_BROWSER 指向已有包和浏览器。浏览器脚本使用本机临时 HTTP,载入后断网;不将其记为 file:// 验收:

    moon check --target all --deny-warn moon build --target all --deny-warn moon test --target all --deny-warn moon fmt --check python tools/verify_api.py python tools/generate_fixtures.py --check python tools/verify_oracle.py python tools/generate_btree_fixtures.py --check python tools/verify_btree_oracle.py python tools/verify_inspection.py python tools/verify_wal_oracle.py python tools/verify_review.py node tools/verify_range_io.cjs node tools/verify_wide_wal.cjs python tools/verify_large_payload.py python tools/benchmark_io.py moon run --target js examples/basic python tools/verify_consumer.py python tools/build_viewer.py node tools/verify_viewer.cjs python tools/build_async.py node tools/verify_async.mjs python tools/verify_async_package.py python tools/verify_async_wal.py python tools/generate_browser_fixtures.py node tools/verify_browser.cjs node tools/fuzz.cjs --seed 20261003 --iterations 512

    v0.7.0 四后端各 121 项核心回归,v0.3.0 的 85 项、v0.4.0 的 123 项、v0.5.0 的 160 项和 v0.6.0 的 199 项公开声明继续兼容检查;发布包在外部消费目录四后端运行,独立异步包另外通过实际 npm tarball 消费。同步验收继续覆盖 54 组 SQLite SQL 操作、2 GiB 主文件/WAL 范围、超过 64 MiB 的预算、1063 行普通表、4407 条索引/WITHOUT ROWID 记录及 2412 页归属。异步验收比较六组数据库所有根页和详细报告,并核对 29 组 WAL 快照、5470 条恢复记录;真实浏览器覆盖选文件、WAL、Worker、导航、取消、切换、释放和大库预算。Linux CI 要求 dbstat,远程验证以该提交对应的 GitHub CI 为准,不沿用旧提交的结果。CI 运行 512 次主文件/WAL 混合变更,每日任务 5000 次,失败时保存配对输入。详见异步验收、模糊测试与重放、WAL 对照及样本说明。

    问题反馈或改进建议请提交到 GitHub Issues。报告解析问题时,请附上复现步骤、错误输出及可公开的最小数据库样本。

    #许可证

    采用 Apache-2.0 许可证。实现依据 SQLite 官方磁盘格式规范,未移植第三方解析器;详见 来源说明。

    PageSource

    pub(open) trait PageSource {
    fn byte_length(Self) -> Int
    fn read_range(Self, Int, Int) -> Bytes raise SqliteError
    }

    源必须在 Database 的使用期间保持同一份静态快照;不提供并发锁或事务语义。

    RangeSource

    pub(open) trait RangeSource {
    fn byte_length64(Self) -> Int64
    fn read_range64(Self, Int64, Int) -> Bytes raise SourceError
    }

    长度和偏移为有符号 64 位;单次读取长度仍为 Int,必须精确返回请求长度。

    SourceError

    pub(all) suberror SourceError {
    HostFailure(String)
    ShortRead(String)
    RangeOutOfBounds(String)
    }

    宿主错误与文件格式错误分离;所有数据源须提供不可变的静态快照。

    SqliteError

    pub(all) suberror SqliteError {
    Invalid(String)
    Unsupported(String)
    LimitExceeded(String)
    } derive(
    Debug
    )

    BTreeCursor

    pub struct BTreeCursor {
    // private fields
    }

    BTreeCursor::location

    BTreeCursor::next

    fn BTreeCursor::next(self : BTreeCursor) -> ScanEvent raise SqliteError

    连续 next 在尚未供页时重复同一请求;错误后游标不可继续使用。

    BTreeCursor::progress

    fn BTreeCursor::progress(self : BTreeCursor) -> ScanProgress

    BTreeCursor::provide_page

    fn BTreeCursor::provide_page(self : BTreeCursor, number : Int, bytes : Bytes) -> Unit raise SqliteError

    仅允许供应当前请求的完整页面;宿主须在调用前自行分类短读和读取失败。

    BTreeCursor::stop

    fn BTreeCursor::stop(self : BTreeCursor) -> ScanSummary

    提前终止并释放当前路径和未完成的 payload;不再请求页面。

    BTreeInspection

    pub(all) struct BTreeInspection {
    root_page : Int
    status : InspectionStatus
    records_decoded : Int
    summary : ScanSummary?
    error : SqliteError?
    } derive(
    Debug
    )

    不保存记录数组;发生错误时仍保留此前成功解码的记录数。

    BTreeInspectionDetails

    pub(all) struct BTreeInspectionDetails {
    inspection : BTreeInspection
    location : DiagnosticLocation?
    } derive(
    Debug
    )

    BTreeRecord

    pub(all) struct BTreeRecord {
    rowid : Int64?
    values : Array[Value]
    page_number : Int
    cell_offset : Int
    } derive(
    Debug
    )

    原始存储记录;index B-tree 没有独立 rowid,字段按磁盘顺序保留。

    BytesSource

    pub struct BytesSource {
    data : Bytes
    }

    BytesSource::byte_length

    fn BytesSource::byte_length(self : BytesSource) -> Int

    BytesSource::byte_length64

    fn BytesSource::byte_length64(self : BytesSource) -> Int64

    BytesSource::new

    fn BytesSource::new(data : Bytes) -> BytesSource

    BytesSource::read_range

    fn BytesSource::read_range(self : BytesSource, offset : Int, count : Int) -> Bytes raise SqliteError

    BytesSource::read_range64

    fn BytesSource::read_range64(self : BytesSource, offset : Int64, count : Int) -> Bytes raise SourceError

    CacheStatistics

    pub(all) struct CacheStatistics {
    hits : Int64
    misses : Int64
    bytes_read : Int64
    resident_pages : Int
    } derive(
    Debug
    )

    CachedSource

    pub struct CachedSource {
    // private fields
    }

    按固定块缓存,FIFO 淘汰;缓存与扫描状态、归属报告、WAL 索引预算互相独立。

    CachedSource::byte_length64

    fn CachedSource::byte_length64(self : CachedSource) -> Int64

    CachedSource::new

    fn CachedSource::new(source : &RangeSource, block_size? : Int, max_pages? : Int) -> CachedSource raise SqliteError

    CachedSource::read_range64

    fn CachedSource::read_range64(self : CachedSource, offset : Int64, count : Int) -> Bytes raise SourceError

    CachedSource::statistics

    fn CachedSource::statistics(self : CachedSource) -> CacheStatistics

    Database

    pub struct Database {
    source : &PageSource
    header : Header
    page_count : Int
    limits : Limits
    // private fields
    }

    Database::freelist

    fn Database::freelist(self : Database) -> Array[Int] raise SqliteError

    返回 freelist 中的 trunk 与 leaf 页号,并校验计数与循环。

    Database::header

    fn Database::header(self : Database) -> Header

    Database::index_records

    fn Database::index_records(self : Database, name : String, limit? : Int) -> Array[BTreeRecord] raise SqliteError

    Database::inspect_btree

    fn Database::inspect_btree(self : Database, root : Int, limit? : Int, max_total_payload_bytes? : UInt64) -> BTreeInspection

    检查单棵 B-tree,保留完成状态或原始错误;资源不足不判为格式损坏。

    Database::inspect_btree_details

    fn Database::inspect_btree_details(self : Database, root : Int, limit? : Int, max_total_payload_bytes? : UInt64) -> BTreeInspectionDetails

    与 inspect_btree 使用相同扫描和状态语义,额外保留失败上下文。

    Database::inspect_database

    fn Database::inspect_database(self : Database, max_total_payload_bytes? : UInt64, max_issues? : Int) -> DatabaseInspection

    扫描 schema、独立 B-tree 和 freelist,使用整个检查过程共享的预算。

    Database::inspect_database_details

    fn Database::inspect_database_details(self : Database, max_total_payload_bytes? : UInt64, max_issues? : Int) -> DatabaseInspectionDetails

    Database::inspect_page

    fn Database::inspect_page(self : Database, number : Int) -> PageInspection

    Database::inspection_cursor

    fn Database::inspection_cursor(self : Database, max_total_payload_bytes? : UInt64, max_issues? : Int) -> InspectionCursor

    Database::page

    fn Database::page(self : Database, number : Int) -> Page raise SqliteError

    Database::page_count

    fn Database::page_count(self : Database) -> Int

    Database::ptrmap_entries

    fn Database::ptrmap_entries(self : Database) -> Array[PtrmapEntry] raise SqliteError

    读取 auto-vacuum 反向指针;与真实页归属对照请使用 inspect_database。

    Database::read_btree

    fn Database::read_btree(self : Database, root : Int, limit? : Int, max_total_payload_bytes? : UInt64) -> Array[BTreeRecord] raise SqliteError

    Database::read_index

    fn Database::read_index(self : Database, root : Int, limit? : Int) -> Array[BTreeRecord] raise SqliteError

    Database::read_page

    fn Database::read_page(self : Database, number : Int) -> Bytes raise SqliteError

    Database::read_table

    fn Database::read_table(self : Database, root : Int, limit? : Int) -> Array[Row] raise SqliteError

    以 rowid 顺序读取普通表;保留首版接口与原始存储值语义。

    Database::scan_btree

    fn Database::scan_btree(self : Database, root : Int, visit : (BTreeRecord) -> Bool raise SqliteError, limit? : Int, max_total_payload_bytes? : UInt64) -> ScanSummary raise SqliteError

    按 B-tree 顺序逐条回调,返回 false 可停止;无需在库中保存所有结果。

    Database::scan_cursor

    fn Database::scan_cursor(self : Database, root : Int, limit? : Int, max_total_payload_bytes? : UInt64, table_only? : Bool) -> BTreeCursor raise SqliteError

    创建可恢复的扫描,不读取根页;next 返回需要的页面或一条记录。

    Database::schema

    fn Database::schema(self : Database) -> Array[SchemaEntry] raise SqliteError

    Database::source64

    fn Database::source64(self : Database) -> &RangeSource

    返回用于完整读取的 64 位源;旧 source 字段保持 v0.5 的 Int 契约。

    Database::table_records

    fn Database::table_records(self : Database, name : String, limit? : Int) -> Array[BTreeRecord] raise SqliteError

    返回普通表或 WITHOUT ROWID 表的原始存储记录,不推断 SQL 列顺序。

    Database::table_rows

    fn Database::table_rows(self : Database, name : String, limit? : Int) -> Array[Row] raise SqliteError

    DatabaseInspection

    pub(all) struct DatabaseInspection {
    status : InspectionStatus
    ownership_complete : Bool
    ptrmap_checked : Bool
    diagnostics_truncated : Bool
    roots_inspected : Int
    records_decoded : Int
    payload_bytes : UInt64
    pages : Array[PageOwnership]
    unclaimed_pages : Array[Int]
    issues : Array[DatabaseIssue]
    } derive(
    Debug
    )

    只检查逻辑数据库页;完整页归属不等价于 SQL 完整性检查。

    DatabaseInspection::summarize

    不读取数据源、不解码记录;未完成报告的统计只表示已观察到的页。

    DatabaseInspectionDetails

    pub(all) struct DatabaseInspectionDetails {
    inspection : DatabaseInspection
    issues : Array[LocatedDatabaseIssue]
    } derive(
    Debug
    )

    issues 与 inspection.issues 同序同长度,位置来自同一次检查,不重新读取源。

    DatabaseIssue

    pub(all) enum DatabaseIssue {
    ScanError(Int?, SqliteError)
    PageConflict(PageOwnership, PageOwnership)
    UnclaimedPage(Int)
    UnsupportedFeature(String)
    PtrmapMismatch(PtrmapEntry, PageOwnership)
    } derive(
    Debug
    )

    DiagnosticLocation

    pub(all) struct DiagnosticLocation {
    phase : DiagnosticPhase
    page_number : Int?
    byte_offset : Int?
    cell_index : Int?
    page_diagnostic : PageDiagnostic?
    } derive(
    Debug
    )

    偏移从页面起点计数,下标从零计数;不能确定位置时保留 None。

    DiagnosticPhase

    pub(all) enum DiagnosticPhase {
    Configuration
    ReadPage
    PageLayout
    TreeTraversal
    CellPayload
    OverflowChain
    RecordDecode
    SchemaDecode
    FreelistCheck
    PtrmapCheck
    PageOwnershipCheck
    } derive(Eq,
    Debug
    )

    失败发生的检查阶段;读取失败不能仅凭 SqliteError 判断为格式损坏。

    DiagnosticPhase::equal

    DiagnosticPhase::not_equal

    fn DiagnosticPhase::not_equal(x : DiagnosticPhase, y : DiagnosticPhase) -> Bool

    pub(all) struct Header {
    page_size : Int
    usable_size : Int
    write_version : Int
    read_version : Int
    change_counter : UInt
    declared_pages : UInt
    freelist_trunk : UInt
    freelist_pages : UInt
    schema_cookie : UInt
    schema_format : Int
    largest_root_page : UInt
    incremental_vacuum : Bool
    text_encoding : Int
    user_version : UInt
    application_id : UInt
    version_valid_for : UInt
    sqlite_version : UInt
    } derive(Eq,
    Debug
    )

    Header::equal

    fn Header::equal(Header, Header) -> Bool

    Header::not_equal

    fn Header::not_equal(x : Header, y : Header) -> Bool

    Header::to_repr

    InspectionCursor

    pub struct InspectionCursor {
    // private fields
    }

    InspectionCursor::location

    InspectionCursor::next

    InspectionCursor::progress

    InspectionCursor::provide_page

    fn InspectionCursor::provide_page(self : InspectionCursor, number : Int, bytes : Bytes) -> Unit raise SqliteError

    InspectionCursor::reject_page

    fn InspectionCursor::reject_page(self : InspectionCursor, reason : SqliteError) -> Unit raise SqliteError

    将本次页读取失败送回状态机,其他可独立检查的对象仍可继续。

    InspectionCursor::stop

    宿主失败或取消保留观察结果,并明确标记检查未完成。

    InspectionEvent

    pub(all) enum InspectionEvent {
    NeedInspectionPage(Int)
    InspectionProgress(ScanProgress)
    InspectionFinished(DatabaseInspectionDetails)
    } derive(
    Debug
    )

    全库检查按需请求页面,进度事件允许宿主让出执行权和取消。

    InspectionStatus

    pub(all) enum InspectionStatus {
    Complete
    Incomplete
    Failed
    } derive(Eq,
    Debug
    )

    仅描述指定根页的扫描结果,不代表整个数据库的完整性结论。

    InspectionStatus::equal

    InspectionStatus::not_equal

    fn InspectionStatus::not_equal(x : InspectionStatus, y : InspectionStatus) -> Bool

    InspectionSummary

    pub(all) struct InspectionSummary {
    claimed_pages : Int
    unclaimed_pages : Int
    page_kinds : Array[PageKindCount]
    objects : Array[ObjectPageCount]
    } derive(Eq,
    Debug
    )

    对已有报告的纯汇总;完整程度、诊断及 payload 请求总量仍以原报告为准。

    InspectionSummary::equal

    InspectionSummary::not_equal

    fn InspectionSummary::not_equal(x : InspectionSummary, y : InspectionSummary) -> Bool

    Limits

    pub(all) struct Limits {
    max_rows : Int
    max_payload_bytes : Int
    max_pages : Int
    max_depth : Int
    } derive(
    Debug
    )

    Limits::default

    fn Limits::default() -> Limits

    Limits::to_repr

    LocatedDatabaseIssue

    pub(all) struct LocatedDatabaseIssue {
    issue : DatabaseIssue
    location : DiagnosticLocation?
    } derive(
    Debug
    )

    ObjectPageCount

    pub(all) struct ObjectPageCount {
    root_page : Int
    object_name : String?
    btree_pages : Int
    overflow_pages : Int
    } derive(Eq,
    Debug
    )

    仅统计已经认领的页,不把冲突引用重复计入另一个对象。

    ObjectPageCount::equal

    ObjectPageCount::not_equal

    fn ObjectPageCount::not_equal(x : ObjectPageCount, y : ObjectPageCount) -> Bool

    Page

    pub(all) struct Page {
    number : Int
    kind : PageType
    first_freeblock : Int
    cell_count : Int
    content_start : Int
    fragmented_bytes : Int
    right_child : Int?
    cell_offsets : Array[Int]
    } derive(
    Debug
    )

    Page::to_repr

    PageDiagnostic

    pub(all) struct PageDiagnostic {
    code : PageDiagnosticCode
    page_number : Int
    byte_offset : Int?
    cell_index : Int?
    error : SqliteError
    } derive(
    Debug
    )

    byte_offset 从页面起点计数;cell_index 从零计数。位置指向检查失败的字段或区间。

    PageDiagnosticCode

    pub(all) enum PageDiagnosticCode {
    PageRead
    PageTypeTag
    PageHeader
    CellPointer
    CellFormat
    Freeblock
    SpaceOverlap
    UntrackedSpace
    FragmentCount
    ChildPointer
    } derive(Eq,
    Debug
    )

    页内格式错误的分类;PageRead 表示输入或宿主读取失败。

    PageDiagnosticCode::equal

    PageDiagnosticCode::not_equal

    PageInspection

    pub(all) struct PageInspection {
    status : InspectionStatus
    page : Page?
    statistics : PageStatistics?
    diagnostic : PageDiagnostic?
    } derive(
    Debug
    )

    仅检查指定 B-tree 页的布局;失败时不返回可能误导的部分统计。

    PageKind

    pub(all) enum PageKind {
    BtreeRoot
    BtreeChild
    OverflowFirst
    OverflowContinuation
    FreelistTrunk
    FreelistLeaf
    PointerMap
    LockByte
    } derive(Eq,
    Debug
    )

    PageKind::equal

    fn PageKind::equal(PageKind, PageKind) -> Bool

    PageKind::not_equal

    fn PageKind::not_equal(x : PageKind, y : PageKind) -> Bool

    PageKind::to_repr

    PageKindCount

    pub(all) struct PageKindCount {
    kind : PageKind
    pages : Int
    } derive(Eq,
    Debug
    )

    PageKindCount::equal

    PageKindCount::not_equal

    fn PageKindCount::not_equal(x : PageKindCount, y : PageKindCount) -> Bool

    PageOwnership

    pub(all) struct PageOwnership {
    page_number : Int
    kind : PageKind
    root_page : Int?
    object_name : String?
    parent_page : Int?
    } derive(Eq,
    Debug
    )

    PageOwnership::equal

    PageOwnership::not_equal

    fn PageOwnership::not_equal(x : PageOwnership, y : PageOwnership) -> Bool

    PageSourceAdapter

    pub struct PageSourceAdapter {
    source : &PageSource
    }

    PageSourceAdapter::byte_length64

    fn PageSourceAdapter::byte_length64(self : PageSourceAdapter) -> Int64

    PageSourceAdapter::new

    PageSourceAdapter::read_range64

    fn PageSourceAdapter::read_range64(self : PageSourceAdapter, offset : Int64, count : Int) -> Bytes raise SourceError

    PageStatistics

    pub(all) struct PageStatistics {
    database_header_bytes : Int
    btree_header_bytes : Int
    pointer_bytes : Int
    unallocated_bytes : Int
    cell_bytes : Int
    freeblock_bytes : Int
    fragmented_bytes : Int
    reserved_bytes : Int
    payload_bytes : UInt64
    local_payload_bytes : UInt64
    max_payload_bytes : Int
    overflow_cells : Int
    } derive(
    Debug
    )

    空间项互不重叠,总和等于页面大小;payload 计数是 cell 声明值,不验证 overflow 链。

    PageType

    pub(all) enum PageType {
    TableLeaf
    TableInterior
    IndexLeaf
    IndexInterior
    } derive(Eq,
    Debug
    )

    PageType::equal

    fn PageType::equal(PageType, PageType) -> Bool

    PageType::not_equal

    fn PageType::not_equal(x : PageType, y : PageType) -> Bool

    PageType::to_repr

    PtrmapEntry

    pub(all) struct PtrmapEntry {
    page_number : Int
    map_page : Int
    kind : PtrmapType
    parent_page : Int
    } derive(Eq,
    Debug
    )

    PtrmapEntry::equal

    fn PtrmapEntry::equal(PtrmapEntry, PtrmapEntry) -> Bool

    PtrmapEntry::not_equal

    fn PtrmapEntry::not_equal(x : PtrmapEntry, y : PtrmapEntry) -> Bool

    PtrmapType

    pub(all) enum PtrmapType {
    RootPage
    FreePage
    FirstOverflow
    NextOverflow
    NonRootBtree
    } derive(Eq,
    Debug
    )

    PtrmapType::equal

    fn PtrmapType::equal(PtrmapType, PtrmapType) -> Bool

    PtrmapType::not_equal

    fn PtrmapType::not_equal(x : PtrmapType, y : PtrmapType) -> Bool

    RangeWalCommit

    pub(all) struct RangeWalCommit {
    frame_index : Int
    database_pages : UInt
    } derive(Eq,
    Debug
    )

    RangeWalCommit::equal

    RangeWalCommit::not_equal

    fn RangeWalCommit::not_equal(x : RangeWalCommit, y : RangeWalCommit) -> Bool

    RangeWalFrame

    pub(all) struct RangeWalFrame {
    index : Int
    byte_offset : Int64
    page_number : UInt
    database_pages : UInt
    checksum1 : UInt
    checksum2 : UInt
    } derive(Eq,
    Debug
    )

    RangeWalFrame::equal

    RangeWalFrame::not_equal

    fn RangeWalFrame::not_equal(x : RangeWalFrame, y : RangeWalFrame) -> Bool

    RangeWalInspection

    pub(all) struct RangeWalInspection {
    header : WalHeader?
    frames : Array[RangeWalFrame]
    commits : Array[RangeWalCommit]
    committed_frames : Int
    database_pages : UInt?
    stop_reason : WalStopReason
    stop_offset : Int64
    trailing_bytes : Int64
    } derive(
    Debug
    )

    RangeWalSource

    pub struct RangeWalSource {
    // private fields
    }

    RangeWalSource::byte_length64

    fn RangeWalSource::byte_length64(self : RangeWalSource) -> Int64

    RangeWalSource::from_cursor

    fn RangeWalSource::from_cursor(base : &RangeSource, wal : &RangeSource, cursor : WalCursor, tail_policy? : WalTailPolicy, max_overlay_pages? : Int) -> RangeWalSource raise SqliteError

    使用已经完成的供帧游标创建索引;游标输入必须来自相同的不可变 WAL。

    RangeWalSource::inspection

    RangeWalSource::new

    fn RangeWalSource::new(base : &RangeSource, wal : &RangeSource, tail_policy? : WalTailPolicy, max_frames? : Int, max_overlay_pages? : Int) -> RangeWalSource raise SqliteError

    只读最新已提交快照;调用者负责提供同一数据库、同一时刻的不可变副本。

    RangeWalSource::page_count

    fn RangeWalSource::page_count(self : RangeWalSource) -> Int

    RangeWalSource::page_range

    fn RangeWalSource::page_range(self : RangeWalSource, number : Int) -> SnapshotPageRange raise SqliteError

    RangeWalSource::read_range64

    fn RangeWalSource::read_range64(self : RangeWalSource, offset : Int64, count : Int) -> Bytes raise SourceError

    Row

    pub(all) struct Row {
    rowid : Int64
    values : Array[Value]
    page_number : Int
    } derive(
    Debug
    )

    Row::to_repr

    ScanCompletion

    pub(all) enum ScanCompletion {
    Complete
    RecordLimit
    VisitorStopped
    } derive(Eq,
    Debug
    )

    ScanCompletion::equal

    ScanCompletion::not_equal

    fn ScanCompletion::not_equal(x : ScanCompletion, y : ScanCompletion) -> Bool

    ScanEvent

    pub(all) enum ScanEvent {
    NeedPage(Int)
    RecordReady(BTreeRecord)
    ScanFinished(ScanSummary)
    } derive(
    Debug
    )

    页面由调用者提供;游标不执行 I/O,记录之间可暂停以实现异步背压。

    ScanProgress

    pub(all) struct ScanProgress {
    records_read : Int
    pages_read : Int
    payload_bytes : UInt64
    } derive(Eq,
    Debug
    )

    已完成的记录和已认领页面进度,不表示整个扫描已完成。

    ScanProgress::equal

    ScanProgress::not_equal

    fn ScanProgress::not_equal(x : ScanProgress, y : ScanProgress) -> Bool

    ScanSummary

    pub(all) struct ScanSummary {
    records_read : Int
    pages_read : Int
    payload_bytes : UInt64
    completion : ScanCompletion
    } derive(
    Debug
    )

    SchemaEntry

    pub(all) struct SchemaEntry {
    object_type : String
    name : String
    table_name : String
    root_page : Int
    sql : String?
    } derive(
    Debug
    )

    SnapshotPageRange

    pub(all) enum SnapshotPageRange {
    MainPage(Int64)
    WalPage(Int64)
    } derive(Eq,
    Debug
    )

    异步适配器使用同一个核心覆盖索引确定页来源,不重复实现提交或缩小语义。

    SnapshotPageRange::equal

    SnapshotPageRange::not_equal

    fn SnapshotPageRange::not_equal(x : SnapshotPageRange, y : SnapshotPageRange) -> Bool

    Value

    pub(all) enum Value {
    Null
    Integer(Int64)
    Real(Double)
    Text(String)
    Blob(Bytes)
    } derive(Eq,
    Debug
    )

    SQLite 记录中的原始值,保留整数、浮点数与二进制数据的区别。

    Value::equal

    fn Value::equal(Value, Value) -> Bool

    Value::not_equal

    fn Value::not_equal(x : Value, y : Value) -> Bool

    Value::to_repr

    WalChecksumOrder

    pub(all) enum WalChecksumOrder {
    LittleEndianChecksum
    BigEndianChecksum
    } derive(Eq,
    Debug
    )

    WalChecksumOrder::equal

    WalChecksumOrder::not_equal

    fn WalChecksumOrder::not_equal(x : WalChecksumOrder, y : WalChecksumOrder) -> Bool

    WalCommit

    pub(all) struct WalCommit {
    frame_index : Int
    database_pages : UInt
    } derive(Eq,
    Debug
    )

    WalCommit::equal

    fn WalCommit::equal(WalCommit, WalCommit) -> Bool

    WalCommit::not_equal

    fn WalCommit::not_equal(x : WalCommit, y : WalCommit) -> Bool

    WalCursor

    pub struct WalCursor {
    // private fields
    }

    WalCursor::close

    fn WalCursor::close(self : WalCursor) -> Unit

    取消后释放缓冲和索引;不能把此前的提交当成最新快照返回。

    WalCursor::frames_read

    fn WalCursor::frames_read(self : WalCursor) -> Int

    WalCursor::new

    fn WalCursor::new(size : Int64, max_frames? : Int) -> WalCursor raise SqliteError

    WalCursor::next

    fn WalCursor::next(self : WalCursor) -> WalReadEvent raise SqliteError

    未供给数据时重复同一请求,成功接受一帧后才推进 offset 和 checksum。

    WalCursor::provide

    fn WalCursor::provide(self : WalCursor, offset : Int64, bytes : Bytes) -> Unit raise SqliteError

    只接受当前请求,调用者须先分类宿主短读、越界与读取失败。

    WalFrame

    pub(all) struct WalFrame {
    index : Int
    byte_offset : Int
    page_number : UInt
    database_pages : UInt
    checksum1 : UInt
    checksum2 : UInt
    } derive(Eq,
    Debug
    )

    WalFrame::equal

    fn WalFrame::equal(WalFrame, WalFrame) -> Bool

    WalFrame::not_equal

    fn WalFrame::not_equal(x : WalFrame, y : WalFrame) -> Bool

    WalFrame::to_repr

    WalHeader

    pub(all) struct WalHeader {
    checksum_order : WalChecksumOrder
    version : UInt
    page_size : Int
    checkpoint_sequence : UInt
    salt1 : UInt
    salt2 : UInt
    checksum1 : UInt
    checksum2 : UInt
    } derive(Eq,
    Debug
    )

    WalHeader::equal

    fn WalHeader::equal(WalHeader, WalHeader) -> Bool

    WalHeader::not_equal

    fn WalHeader::not_equal(x : WalHeader, y : WalHeader) -> Bool

    WalInspection

    pub(all) struct WalInspection {
    header : WalHeader?
    frames : Array[WalFrame]
    commits : Array[WalCommit]
    committed_frames : Int
    database_pages : UInt?
    stop_reason : WalStopReason
    stop_offset : Int
    trailing_bytes : Int
    } derive(
    Debug
    )

    WalReadEvent

    pub(all) enum WalReadEvent {
    NeedWalRange(Int64, Int)
    WalReady(RangeWalInspection)
    } derive(
    Debug
    )

    按顺序供给完整 WAL header 或帧;不执行宿主 I/O。

    WalSource

    pub struct WalSource {
    base : &PageSource
    wal : Bytes
    page_size : Int
    page_count : Int
    base_pages : Int
    overlay : Map[Int, Int]
    inspection : WalInspection
    }

    WalSource::byte_length

    fn WalSource::byte_length(self : WalSource) -> Int

    WalSource::inspection

    fn WalSource::inspection(self : WalSource) -> WalInspection

    WalSource::new

    fn WalSource::new(base : &PageSource, wal : Bytes, tail_policy? : WalTailPolicy, max_frames? : Int) -> WalSource raise SqliteError

    只读最新已提交快照;调用者负责提供同一数据库、同一时刻的不可变副本。

    WalSource::page_count

    fn WalSource::page_count(self : WalSource) -> Int

    WalSource::read_range

    fn WalSource::read_range(self : WalSource, offset : Int, count : Int) -> Bytes raise SqliteError

    WalStopReason

    pub(all) enum WalStopReason {
    WalEndOfFile
    WalTruncatedFrame
    WalSaltMismatch
    WalChecksumMismatch
    WalInvalidFrame
    WalFrameLimit
    } derive(Eq,
    Debug
    )

    WalStopReason::equal

    WalStopReason::not_equal

    fn WalStopReason::not_equal(x : WalStopReason, y : WalStopReason) -> Bool

    WalTailPolicy

    pub(all) enum WalTailPolicy {
    RejectInvalidTail
    UseValidPrefix
    } derive(Eq,
    Debug
    )

    WalTailPolicy::equal

    WalTailPolicy::not_equal

    fn WalTailPolicy::not_equal(x : WalTailPolicy, y : WalTailPolicy) -> Bool

    decode_record

    fn decode_record(payload : Bytes, encoding : Int) -> Array[Value] raise SqliteError

    解码完整的 SQLite record payload;编码编号与数据库文件头保持一致。

    decode_schema_entry

    fn decode_schema_entry(values : Array[Value], page_count : Int) -> SchemaEntry raise SqliteError

    异步适配层校验已解码的 sqlite_schema 记录,语义与同步 schema 一致。

    decode_varint

    fn decode_varint(data : Bytes, offset : Int) -> (UInt64, Int) raise SqliteError

    inspect_wal

    fn inspect_wal(data : Bytes, max_frames? : Int) -> WalInspection raise SqliteError

    只接受连续有效帧;遇到首个无效帧后不搜索更后面的提交标记。

    inspect_wal_source

    fn inspect_wal_source(source : &RangeSource, max_frames? : Int) -> RangeWalInspection raise SqliteError

    只接受连续有效帧;遇到首个无效帧后不搜索更后面的提交标记。

    open_database

    fn open_database(data : Bytes, limits? : Limits) -> Database raise SqliteError

    open_range_source

    fn open_range_source(source : &RangeSource, limits? : Limits, max_report_pages? : Int) -> Database raise SqliteError

    64 位寻址;页号保持 Int,超过 2147483647 页显式拒绝,避免静默截断。

    open_range_wal_source

    fn open_range_wal_source(source : RangeWalSource, limits? : Limits, max_report_pages? : Int) -> Database raise SqliteError

    open_source

    fn open_source(source : &PageSource, limits? : Limits) -> Database raise SqliteError

    open_wal_database

    fn open_wal_database(base : Bytes, wal : Bytes, limits? : Limits, tail_policy? : WalTailPolicy, max_frames? : Int) -> Database raise SqliteError

    open_wal_source

    fn open_wal_source(source : WalSource, limits? : Limits) -> Database raise SqliteError

    parse_header

    fn parse_header(data : Bytes) -> Header raise SqliteError

    parse_wal_header

    fn parse_wal_header(data : Bytes) -> WalHeader raise SqliteError

    验证 WAL header;头部不完整、格式或 checksum 错误直接抛出错误。