3 个版本 (1 个稳定版)
1.0.0 | 2023 年 3 月 3 日 |
---|---|
0.1.1 | 2023 年 2 月 26 日 |
0.1.0 | 2023 年 2 月 25 日 |
#1025 in 解析器实现
2MB
870 行
sqlite-parser-nom
SQLite 二进制数据库格式解析器。
同义词库
- sqlite_parser 是 rusqlite 的前端,实际上并不执行解析。
- sqlite3-parser 是 SQLite3 兼容 SQL 语法的解析器 + 词法分析器。
使用方法
在您的 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 格式规范
参考资料
- 数据库文件格式 - 官方文件格式指南
- SQLite 数据库文件格式要求 - 详细假设列表
- SQLite 完全指南 - 第 11 章,高级概述
- 移动取证 - 文件格式手册 - 直到单元格内容的高级描述
物理结构
数据库文件
+---+-------+-----------+-----------+-----------+
| 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
- 序列类型对应于数据有效负载,并在其中包含大小信息