May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.
体系结构
关于SQLite的体系结构,官网有详细介绍,作为源码剖析系列文章,本不应该有如此多的废话,而应该直奔主题上代码。但基于本人的经验,源码阅读前最好能够先简单实用过该软件,清楚该软件的体系结构,清晰的了解源代码的分布,在开始阅读源码时才能更加顺畅,So,推荐一读SQLite体系结构。
SQLite体系结构
就这张完美的图片,简单一讲:SQLite数据库将数据按照作者设计好的存储结构以文件方式存储到文件系统上,用户通过SQL语句实现数据的CURD,必要的步骤为:
- Interface接口接受用于输入的CURD请求,请求严格遵守SQL标准;
- 拿到SQL语句后,需要由分词器Tokenizer把原有字符串分割成一个个标识符(token),并把这些标识符传递给解析器,Tokenizer是用手工编写的;
- 解析器(Parser)拿到一个个Token后,进行语法分析。SQLite的语法分析器使用Lemon LALR(1)分析程序生成器来产生,代码非常精简,后续我们将认真分析;
- 语法分析一旦产生了规约(专业术语,后续文章详细讨论),就要调用代码生成器(Code Generator),生成虚拟机代码,以执行SQL语句请求的工作。代码生成器包含许多文件:attach.c, auth.c, build.c, delete.c, expr.c, insert.c,pragma.c, select.c, trigger.c, update.c, vacuum.c和where.c。这些文件涵盖了大部分最重要、最有意义的事情。
- 代码生成器生成的代码由虚拟机(VDBE)来执行,参考阅读:SQLite虚拟机原理。虚拟机实现一个专为操作数据库文件而设计的抽象计算引擎。它有一个存储中间数据的存储栈,每条指令包含一个操作码和不超过三个额外的操作数,它就像一个发动机,驱动着将用户的意图转换成实际的动作,向数据库文件拿或存用户想要的数据。
- 虚拟机指令的动作,驱动了Page模块向数据库文件增删改查数据,而数据库文件核心存储结构是B-树,因此,其动作需要遵守B-树结构的指导进行。
- 数据库文件被抽象出了一个个页面(Page)存在硬盘中,每一页都是B-树(及其变种)的一个Node,操作系统提供标准文件操作接口供用户访问,SQLite通过内部计算后有目的的向文件的特定位置进行读取和写入。
- 由此,完成了整个数据操作过程。
代码结构
不多说,直接上表格:
所属模块 | 文件名称 | 备注 |
---|---|---|
API | main.c | SQLite Library的大部分接口 |
legacy.c | sqlite3_exec的实现 | |
table.c | the sqlite3_get_table() and sqlite3_free_table()的实现,它们是sqlite3_exec的包装 | |
preprare.c | 主要实现sqlite3_prepare() | |
分词器部分(Tokenizer) | tokenize.c | 分词器的实现 |
语法分析器部分(Parser) | parser.c | 分析器的实现,由Lemon自动生成 |
parser.h | 分析器内部定义的关键字 | |
代码生成器(Code Generator) | update.c | 处理UPDATTE语句 |
delete.c | 处理DELETE语句 | |
insert.c | 处理INSERT语句 | |
trigger.c | 处理TRIGGER语句 | |
attach.c | 处理ATTACHT 和DEATTACH语句 | |
select.c | 处理SELECT语句 | |
where.c | 处理WHERE语句 | |
vacuum.c | 处理VACUUM语句 | |
pragma.c | 处理PRAGMA命令 | |
expr.c | 处理SQL语句中的表达式 | |
auth.c | 主要实现sqlite3_set_authorizer() | |
analyze.c | 实现ANALYZE命令 | |
alter.c | 实现ALTER TABLE功能 | |
build.c | 处理以下语法:CREATE TABLE, DROP TABLE, CREATE INDEX,DROP INDEX,creating ID lists,BEGIN TRANSACTION,COMMIT,ROLLBACK | |
func.c | 实现SQL语句的函数语句 | |
date.c | 与日期和时间转换有关的函数 | |
虚拟机(Virtual Machine) | vdbeapi.c | 虚拟机提供上层模块调用的API实现部分 |
vdbe.c | 虚拟机的主要实现部分 | |
vdbe.h | 定义了VDBE的接口,VdbeOp结构体(代表一条指令) | |
vdbeaux.c | Vdbe.h的接口的实现 | |
vdbeInt.h | Vdbe.c的私有头文件,定义了VDBE常用的数据结构:Cursor——虚拟机中使用的游标, Mem——vdbe在内部把所有的SQL值当作一个Mem数据结构来处理,Vdbe——虚拟机数据结构 | |
vdbemem.c | 操作”Mem”数据结构的函数 | |
vdbefifo.c | ||
B-Tree部分 | btree.h | 头文件,定义了B-tree提供的操作接口 |
btree.c | B-Tree部分的主要实现,并定义了以下数据结构:Btree——Btree handler,BtCursor——使用的游标, BtLock——锁, BtShared——包含了一个打开的数据库的所有信息,MemPage——文件在内存存放在该数据结构中,aCellInfo | |
OS Interface部分 | os.h | 定义了为上层模块提供的操作函数,并定义了以下数据结构:OsFile——描述一个文件;ioMethod——OsFile所支持的操作函数(对所有架构都适用的OS Interface) |
os.c | 对IoMethod中的函数的包装 | |
os_win.c | Windows平台下的OS Interface | |
os_unix.c | Unix平台下的OS Interface | |
os_os2.c | OS2平台下的OS Interface | |
其它部分 | utf.c | 与UTF编码有关的函数 |
util.c | 一些实用函数,比如:sqlite3Malloc(),sqlite3FreeX() | |
sqlite3.h | SQLite的头文件,定义了提供给应用使用的API和数据结构。 | |
sqliteInt.h | 定义了SQLite内部使用的接口和数据结构 | |
printf.c | 主要实现与printf有关的函数 | |
random.c | 随机数生成 | |
hash.c | SQLite使用的hash表 | |
hash.h | Hash 表头文件 |
有了对SQLite源码从整体角度上的理解,我们源码分析算是已经开了一个头了,后面的文章我们就将直接就某一块代码展开分析,感兴趣的同学请持续关注!