在线文档教程
Sqlite
其他 | Miscellaneous

Architecture of SQLite

Architecture of SQLite

介绍

本文档描述了SQLite库的体系结构。这里的信息对那些想要理解或修改SQLite内部工作的人很有用。

附近的图表显示了SQLite的主要组件以及它们如何互操作。以下文本解释了各个组件的作用。

概观

SQLite的工作原理是将SQL文本编译为字节码,然后使用虚拟机运行该字节码。

sqlite3_prepare_v2()和相关接口充当用于将SQL文本转换为字节码的编译器。sqlite3_stmt对象是用于实现单个SQL语句的单个字节码程序的容器。sqlite3_step()接口将一个字节码程序传递给虚拟机,并运行该程序直到它完成,或者形成一行结果返回,或者发生致命错误或中断。

接口

许多C语言接口可以在源文件main.clegacy.cvdbeapi.c中找到,尽管一些例程分散在其他文件中,在这些文件中它们可以访问具有文件范围的数据结构。sqlite3_get_table()例程在table.c中实现。sqlite3_mprintf()例程在printf.c中找到。sqlite3_complete()接口位于tokenize.c中。TCL接口由tclsqlite.c实现。

为避免名称冲突,SQLite库中的所有外部符号都以前缀sqlite3开头。那些用于外部使用的符号(换句话说,那些构成SQLite API的符号)会添加一个下划线,因此以sqlite3_开头。扩展API有时会在下划线之前添加扩展名; 例如:sqlite3rbu_sqlite3session_

标记生成器

当包含SQL语句的字符串要被评估时,它首先被发送到标记器。标记器将SQL文本分解为标记并将这些标记逐个传递给解析器。标记器是在文件tokenize.c中手动编码的。

请注意,在此设计中,标记器调用解析器。熟悉YACC和BISON的人可能习惯于以相反的方式做事 - 让解析器调用标记器。不过,令牌分析器调用分析器会更好,因为它可以做成线程安全的并且运行速度更快。

分析器

解析器根据其上下文为令牌分配含义。SQLite的解析器是使用Lemon LALR(1)解析器生成器生成的。柠檬和YACC / BISON一样工作,但它使用了不太容易出错的输入语法。柠檬还生成一个可重入且线程安全的解析器。柠檬定义了非终端析构函数的概念,以便在遇到语法错误时不会泄漏内存。驱动Lemon并定义SQLite可理解的SQL语言的语法文件可在parse.y中找到。

因为Lemon是一个通常在开发机器上找不到的程序,Lemon的完整源代码(只有一个C文件)包含在SQLite分发的“tool”子目录中。

代码生成器

解析器将令牌组装成解析树之后,代码生成器运行以分析解析器树并生成执行SQL语句工作的字节码。准备好的语句对象是这个字节码的容器。有许多文件中的代码生成器,包括:attach.cauth.cbuild.cdelete.cexpr.cinsert.cpragma.cselect.ctrigger.cupdate.cvacuum.cwhere.cwherecode.cwhereexpr.c。在这些文件中,大部分严重的魔法都是在这里发生的。expr.c处理表达式的代码生成。其中* .c处理SELECT,UPDATE和DELETE语句中WHERE子句的代码生成。该文件attach.cdelete.cinsert.cselect.ctrigger.c update.cvacuum.c处理代码生成具有相同名称的SQL语句。(这些文件中的每一个都根据需要调用expr.cwhere.c中的例程。)所有其他SQL语句都由build.c编码。该auth.c 文件实现了sqlite3_set_authorizer()的功能。

代码生成器,特别是* .cselect.c中的逻辑有时称为查询规划器。对于任何特定的SQL语句,可能有数百,数千或数百万种不同的算法来计算答案。查询计划员是一个AI,致力于从数百万个选择中选择最佳算法。

字节码引擎

由代码生成器创建的字节码程序由虚拟机运行。

虚拟机本身完全包含在单个源文件vdbe.c中。所述vdbe.h头文件定义了虚拟机和SQLite库的其余部分之间的界面vdbeInt.h其定义了私人虚拟机本身的结构和接口。其他各种vdbe * .c文件都是虚拟机的助手。所述vdbeaux.c文件包含由所用的库的其余部分来构造VM程序在虚拟机和接口模块中使用的工具。该vdbeapi.c文件包含虚拟机的外部接口,如sqlite3_bind_int()和sqlite3_step()。各个值(字符串,整数,浮点数和BLOB)存储在由vdbemem.c实现的名为“Mem”的内部对象中。

SQLite使用C语言例程的回调来实现SQL函数。即使内置的SQL函数也是这样实现的。大多数内置的SQL函数(例如:abs(),count(),substr()等)都可以在func.c源文件中找到。日期和时间转换函数可在date.c中找到。一些函数如coalesce()和typeof()直接由代码生成器实现为字节码。

B树

SQLite数据库使用btree.c源文件中的B-tree实现在磁盘上进行维护。数据库中的每个表和索引都使用单独的B树。所有B树都存储在同一个磁盘文件中。文件格式细节稳定且定义明确,并保证向前兼容。

B树子系统和SQLite库的其余部分的接口由头文件btree.h定义。

页面缓存

B树模块以固定大小的页面从磁盘请求信息。默认的page_size是4096字节,但可以是512到65536字节之间的任意两个幂。页面缓存负责读取,写入和缓存这些页面。页面缓存还提供了回滚和原子提交抽象,并负责锁定数据库文件。B树驱动程序请求页面缓存中的特定页面,并在需要修改页面或提交或回滚更改时通知页面缓存。页面缓存处理了确保请求被快速,安全和有效地处理的所有细节。

主页面缓存实现在pager.c文件中。WAL模式逻辑位于单独的wal.c中。内存中缓存由pcache.cpcache1.c文件实现。页面缓存子系统和SQLite其余部分之间的接口由头文件pager.h定义。

OS界面

为了提供跨操作系统的可移植性,SQLite使用称为VFS的抽象对象。每个VFS都提供了打开,读取,写入和关闭磁盘上的文件以及执行其他特定于操作系统的任务(如查找当前时间或获取随机性以初始化内置伪随机数生成器的方法)。SQLite当前为unix(在os_unix.c文件中)和Windows(在os_win.c文件中)提供了VFSes

公用事业

内存分配,无格式字符串比较例程,可移植的文本到数字转换例程以及其他实用程序位于util.c中。解析器使用的符号表由hash.c中的哈希表维护。该utf.c源文件包含Unicode转换子程序。SQLite的有()自己的私人执行的printf(有一些扩展)在printf.c并在其自己的伪随机数生成器(PRNG)random.c

测试代码

源代码树的“src /”文件夹中名称以test开头的文件仅用于测试,不包含在库的标准版本中。

SQLite在公共领域。