sqlite阅读笔记(一)安装和源码概述

前言

总归要阅读代码,学习前人的智慧才能真的掌握知识,才能真的学会知识。

下载源码

sqlite使用fossil管理源码,我们首先要安装fossil。

brew install fossil

然后创建sqlite目录,用fossil下载源码

mkdir ~/sqlite
cd ~/sqlite
fossil clone https://www.sqlite.org/src sqlite.fossil
fossil open sqlite.fossil --force  不知道为什么提示我目录存在,无法创建。
fossil update trunk   ;# latest trunk check-in 更新到主干代码
fossil update release ;# latest official release  更新到最新release版本

fossil ui # 通过浏览器查看代码

编译

mkdir bld                ;#  Build will occur in a sibling directory 在同级目录创建一个build目录
cd bld                   ;#  Change to the build directory
../sqlite/configure      ;#  Run the configure script
make                     ;#  Run the makefile.
make sqlite3.c           ;#  Build the "amalgamation" source file
make test                ;#  Run some tests (requires Tcl)

最后一步,运行测试用例失败了(感觉和我的tcl版本有关系),剩下都成功了。总之开始看代码吧。

源文件概览

大部分源码都在src目录下面。
shell.c是sqlite3命令行程序的实现。
ext/ 目录下面包含了扩展的代码,例如全文搜索引擎ext/fts3。R-Tree引擎ext/rtree。
ext/misc 下面包含了单个文件的扩展程序,例如REGEXP正则匹配操作。
tool/ 目录包含了各种脚本程序,用来生成源码文件或者生成测试程序。

parse.c

sql语言的parser由parse.c实现。它是由src/parse.y(用lemon的LALR(1)文法书写)文件生成的。lemon文法的源码在tool/lemon.c中。lemon使用tool/lempar.c文件作为模版来生成parser。lemon也生成了parse.h头文件。

opcodes.h

opcodes.h头文件包含了VDBE虚拟机的opcode的宏定义。opcodes.h是通过扫描src/vdbe.c文件,通过./mkopcodeh.tcl脚本生成的。另一个脚本./mkopcodec.tcl通过opcodes.h生成opcodes.c文件。opcodes.c文件包含了opcode-number和opcode-name的映射关系,用于explan命令。

keywordhash.h

keywordhash.h头文件包含了sql语言关键字(create,select,index等等)的hash映射。keywordhash.h文件是由mkkeywordhash.c工具生成的。

pragma.h

pragma预编译指令。pragma.h文件包含了PRAGMA指令声明的定义和实现。这个文件是tool/mkpragmatab.tcl脚本生成的。

sqlite3.c

所有c文件和头文件可以聚合成一个大的源文件sqlite3.c。这个大文件是通过tool/mksqlite3c.tcl脚本生成的。生成的前提是tsrc子目录下面的文件都编译存在。这个大文件有20万行,通过大文件编译出来的程序要比单个文件快5%左右。

sqlite3.h

sqlite3.h头文件包含了所有sqlite定义的接口和对象。这个文件是src/sqlite.h.in,./manifest.uuid和./VERSION三个文件生成的。生成的脚本是tool/mksqlite3h.tcl。


其他核心文件

sqlite.h.in

sqlite对外api,是sqlite3.h的源文件。

sqliteInt.h

sqlite内部使用的数据结构定义头文件。

vdbe.c

这个文件实现了虚拟机功能。

where.c

这个文件(以及其他以where*.c)用于分析where语句,生成虚拟机器码

btree.c

这个文件包含了存储引擎的b树实现。对外接口是btree.h。另外btreeInt.h定义了btree.c内部使用的对象。

pager.c

和pager.h功能使用。实现了事务。

os_unix.c和os_win.c

这两个文件实现了不同操作系统平台的VFS(虚拟文件系统)接口。

ext/misc/json1.c

这个文件实现了sqlite的json函数。

后续todo

从sqlite的功能看,有四个方面是需要额外学习才能了解核心功能。

  1. tcl脚本
  2. lemon和编译原理
  3. vdbe和虚拟机
  4. sqlite3的使用

总结

  1. 虽然sqlite3代码并不多,但是里面五脏俱全(parser,虚拟机,存储引擎,事务引擎,代码生成,模块化的设计思想,用c实现的面向对象等),应有尽有。
  2. 官网说到manifest文件应该是自解释的,深表认同。
    [me]:很多时候我们的代码也应该是自解释的,但是不知道为什么我总看莫名其妙的操作,意义不明的变量和业务无法直接关联的代码。

ref

  1. github仓库readme
  2. 源码下载文档
  3. 官网文档目录