SQLite 架构

栏目: 数据库 · 发布时间: 7年前

介绍

本文描述了 SQLite 库的架构。本文信息对哪些想要理解或修改SQLite内部工作内容的人非常有用。

附图展示了SQLite的主要组件以及他们是如何相互操作的。其下的文字解释了各个组件的角色。

SQLite 架构

总览

SQLite 编译 SQL 文本为字节码 bytecode , 然后使用虚拟机运行字节码来工作。

sqlite3_prepare_v2() 以及相关接口扮演着编译器的角色,将SQL文本转换成字节码。  sqlite3_stmt 对象是一个容器。该容器用于包含一个实现某一SQL的字节码程序。  sqlite3_step() 接口向虚拟机传递字节码程序, 并执行字节码程序直到完成,或返回产生的一行结果,或碰到一个致命fatal错误, 或被打断。

接口

大部分的 C语言 的接口在 main.c ,  legacy.c 和 vdbeapi.c 这些源文件中,尽管一些程序被分散在其他文件中,他们可以通过文件域访问数据结构。 sqlite3_get_table() 程序在  table.c 中实现. sqlite3_mprintf() 程序在  printf.c 中实现。 sqlite3_complete() 接口在  tokenize.c 中.  TCL Interface 在  tclsqlite.c 中实现.

为了避免命名冲突,SQLite库的所有的外部符号都使用 sqlite3 前缀。那些用于外部使用的(换句话说,那些符号形成了SQLite的API)符号增加下划线,因此以  sqlite3_ 开头。 扩展API有时候在下划线前增加扩展名;例如:  sqlite3rbu_ 或  sqlite3session_ 。

分词器

当一个包含SQL句子的字符串被处理时,它首先会被发送到分词器。分词器将SQL文本拆分成词,然后将词一个接一个传递给解析器。分词器代码在 tokenize.c 文件中。 注意在这个设计中,分词器调用解析器。熟悉YACC和BISON的人可能习惯用相反的方式-让解析器调用分词器。让分词器调用解析器的方式更好一些,因为这样能够线程安全,并且执行的更快。

解析器

解析器根据上下文为词赋予意思。SQLite的解析器使用 Lemon parser generator 生成。Lemon和YACC/BISON做同样的事情,但是它使用另一种不容易出错的输入语法。Lemon生成一个可重入的,线程安全的parser。Lemon定义了一个非终端析构的概念,因此在遇到语法错误时它不会内存泄漏。在 parse.y 中可以找到驱动Lemon的语法文件和SQLite理解SQL语言的定义的文件。 因为Lemon这个程序一般不会在开发机器上找到,所以Lemon完整的源代码(就一个C文件)被包含在SQLite分发的“tool”子目录中。

代码生成器

在解析器将词装配成解析树后,代码生成器开始分析解析树,生成执行SQL语句工作的字节码。 prepared statement 对象是包含了这些字节码的容器。 代码生成器有很多文件,包含:  attach.c ,  auth.c ,  build.c , delete.c ,  expr.c ,  insert.c ,  pragma.c ,  select.c ,  trigger.c ,  update.c ,  vacuum.c ,  where.c ,  wherecode.c , 和  whereexpr.c . 大部分重要的魔法发生在这些文件中。  expr.c 操纵着代码生成器的表达。  where .c * 操纵代码生成器处理SELECT,UPDATE和DELETE的WHERE从句。 attach.c ,  delete.c ,  insert.c ,  select.c ,  trigger.c update.c , and  vacuum.c 这几个文件操纵代码生成器处理和文件名同名的SQL语句。(所有这些文件必要时在 expr.c 和  where.c 中调用)所有其他SQL语句被编写在  build.c .  auth.c 文件实现了  sqlite3_set_authorizer() 的功能。

代码生成器,尤其时在 where*.c 和  select.c 中的逻辑,有时候被称为查询计划  query planner 。对于任何具体的SQL语句,可能有成千上百个不同的算法来计算结果。查询计划query planner时一个力求从这么多算法中选择一个最好的算法的人工智能。

字节码引擎

字节码程序被代码生成器生成,运行在虚拟机上。 虚拟机自身完整地包含在单独的 vdbe.c 源文件中。 vdbe.h 头文件在虚拟机和剩余的SQLite库之间定义了接口,  vdbeInt.h 定义的结构和接口是虚拟机自己私有的。其他几个 vdbe*.c 文件是虚拟机的助手。 vdbeaux.c 文件包含虚拟机使用的有效 工具 和剩余SQLite库用于构建VM程序的接口模块。 vdbeapi.c 文件包含虚拟机的扩展接口,如  sqlite3_bind_int() 和  sqlite3_step() 。独立的值 (strings, integer, floating point numbers, and BLOBs) 被存储在由 vdbemem.c 实现,命名为“Mem”的内部对象中。

SQLite使用C语言程序的callbacks来实现SQL函数。即使内置的SQL函数也是这个方式实现。大部分内置SQL函数(如: abs() ,  count() ,  substr() , 等等) 能够在  func.c 源文件中找到。日期和时间转换函数在  date.c 中找到。 一些函数如 coalesce() 和  typeof() 由代码生成器直接生成字节码实现。

B-Tree

SQLite数据库使用B-tree来保存数据到磁盘,B-tree在源文件 btree.c 中实现。在数据库中的每个表和索引使用单独的B-tree。所有的B-tree存储在同一个磁盘文件中。文件格式 file format 细节是稳定的、明确的、在更新中保证兼容性的。

B-tree子系统和其他SQLite库的交互接口在头文件 btree.h 中定义。

页缓存

B-tree模块以固定大小的页向磁盘请求信息。默认的页大小是4096字节,也可以是512字节和65525字节之间任意的2的n次幂。页缓存负责读、写、缓存这些页。页缓存同时提供回滚和原子提交的抽象,同时负责锁定数据库文件。B-tree驱动从页缓存请求指定的页,当它想修改页、或提交、或回滚修改时,通知页缓存。页缓存确保快速、安全、高效地处理请求的所有混杂细节。 基本的页缓存在 pager.c 文件中实现。 WAL mode 逻辑在单独的 wal.c 中。内存缓存在  pcache.c 和  pcache1.c 文件中实现。在 pager.h 头文件中,实现了页缓存子系统和SQLite库的其他系统交互的接口。

操作系统接口

SQLite使用抽象的 VFS 对象,提供在不同操作系统间的移植能力。每个VFS提供了打开(opening)、读(read)、写(writing)和关闭(closing)磁盘上的文件的方法; 提供具体的操作系统任务,比如查找当前时间,获取随机数用来初始化内置的伪随机数生成器。SQLite当前版本为unix在 os_unix.c 文件提供VFS,为windows在 os_win.c 文件提供VFS。

工具

内存分配程序,不区分大小写的字符串比较程序,可移植的文本转数字程序,以及其他工具在 util.c 文件中。在解析器使用的符号表使用 hash.c 中的hash表来存储。 utf.c 源文件包含了Unicode转换子程序。SQLite在 printf.c 有自己私有的 printf() 实现,包含了一些扩展。SQLite在 random.c 中有自己的伪随机数生成器(PRNG)

测试代码

在"src/"文件夹中,那些以 test 开头的源文件是用来做测试的,不会被包含在构建的库中。


以上所述就是小编给大家介绍的《SQLite 架构》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

编程珠玑

编程珠玑

Jon Bentley / 黄倩、钱丽艳 / 人民邮电出版社 / 2008-10 / 39.00元

本书是计算机科学方面的经典名著。书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中至关重要的。本书的特色是通过一些精心设计的有趣而又颇具指导意义的程序,对实用程序设计技巧及基本设计原则进行了透彻而睿智的描述,为复杂的编程问题提供了清晰而完备的解决思路。本书对各个层次的程序员都具有......一起来看看 《编程珠玑》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具