3 个版本 (1 个稳定版)

1.0.0 2023 年 3 月 3 日
0.1.1 2023 年 2 月 26 日
0.1.0 2023 年 2 月 25 日

#1025 in 解析器实现

Apache-2.0

2MB
870

sqlite-parser-nom

SQLite 二进制数据库格式解析器。

同义词库

使用方法

在您的 Cargo.toml 中

[dependencies]
sqlite-parser-nom = "1.0.0"

懒惰地解析文件

在内存中加载和解析文件

use sqlite_parser_nom::Reader;
use sqlite_parser_nom::error;

fn main() -> Result<(), error::SQLiteError> {
    let reader = Reader::open_mmap("sample/sakila.db")?;
    println!("{}", reader.header.db_size);

    Ok(())
}

解析切片

您也可以直接使用解析器

use nom::Finish;
use sqlite_parser_nom::parser;
use sqlite_parser_nom::model;
use sqlite_parser_nom::error;

fn do_something_with_page(i: &[u8]) -> Result<model::Page, error::SQLiteError> {
    let (_, page) = parser::page(i)
        .finish()
        // the cast is necessary here, so the error could outlive the input 
        .map_err(|e| nom::error::Error {
            code: e.code,
            input: error::OwnedBytes(e.input.to_owned()),
        })?;

    Ok(page)
}

请查阅文档和 解析器,以选择适合您任务的正确解析器。

SQLite 格式规范

参考资料

物理结构

数据库文件

+---+-------+-----------+-----------+-----------+
| h |       |           |           |           |
| e |       |           |           |           |
| a | root  |   page 2  |    ...    |   page N  |
| d | page  |           |           |           |
| e |       |           |           |           |
| r |       |           |           |           |
+---+-------+-----------+-----------+-----------+
            ^           ^           ^
< page size | page size | page size | page size >
  • SQLite 数据库文件被分成大小相等的页面
    • 页面大小在头文件中定义
    • 根页面包括文件头,但总共仍然符合页面大小
    • 所有页面,包括根页面,都从页面本身的开始计数内部偏移量
    • 页面通过数字引用,因此可以计算它们在二进制文件中的位置

页面

+---------------------+
|     page header     |
+---------------------+
| cell pointer array  |
+---------------------+
|                     |
|  unallocated space  |
|                     |
+-------+-------------+
|cell N |free block   |
+-------+------+------+
|cell 5 |cell 4|cell 3|
+-------+----+-+------+
|   cell 2   | cell 1 |
+------------+--------+

页面类型

  • 索引和表页在其内部和叶类型中具有相同的结构,但在头部和一些额外字段上有所不同
    • 请参阅 模型 以获取确切定义,并在 BTree 部分中查看逻辑
  • 溢出页只在头部有 0x00,其余的是有效载荷
  • 锁定页是在数据库 > 1gb 时位于 1,073,741,824 偏移量的空页面
  • 指针页面存在于自动清理的数据库中,并包含指向已重组页面的指针
  • 空闲块存储在空闲列表中,且未被置零,它们可能包含应被删除的数据

页面结构

  • 单元格指针数组从页面顶部增长到页面底部
    • 指针是页面内的字节数偏移量
  • 单元格从页面底部增长到页面顶部

单元格

+-----------+--------+--------+--------+-----+--------+-----------+-----+-----------+
|Payload    |        | Header | Serial |     | Serial | Data Cell |     | Data Cell |
|(Cell Size)|  ...   |  Size  | Type 1 | ... | Type N | Column 1  | ... | Column N  |
+-----------+--------+--------+--------+-----+--------+-----------+-----+-----------+
                     |                                |
<    cell header     ^      record header             ^        table row data       >
                     <                            cell size                         >
  • 此结构经过一些修改后适用于表叶、索引叶和内部页面
  • 表内部页面包含指向其他页面和对应rowid的指针
  • 单元格内的头和辅助值大多为varint
  • 序列类型对应于数据有效负载,并在其中包含大小信息

依赖项