首页 > 数据库 > SQLite > 正文

Sqlite虚拟机VDBE原理

2020-02-10 17:55:24
字体:
来源:转载
供稿:网友

VDBE (virtual database engine)是一个运行他自己的虚拟机语言组成的程序的虚拟机。每条程序都是用来查询或者操作数据库的。出于这个目的,VDBE的机器语言被设计用来进行搜索,读和修改数据库。
每一条VDBE 说明包括一个OPCODE 和3个OPRANDS分别为P1,P2和P3。P1,P2 为整数,P3是一个指向数据结构或者字符串的指针,有可能为空。大多数说明只用到1-2个OPRANDS,只有少数 说明用到了全部3个OPRANDS。有很多非常重要的说明根本没有用到任何OPRANDS但是却能读取数据并且将结果写入运行时栈当中。
一段VDBE代码从说明0开始运行,直到
1。遇到致命错误;
2。执行了停止说明;
3。整段代码运行完毕,所有打开的数据库都已经关闭,所有内存都已经释放,栈为空。
example:
1.建立一个数据表,并且插入一个数据
CREATE TABLE examp(one text,two int);
INSERT INTO examp VALUES( 'Hello,World!'99);
VDBE将这样解释并执行这两条语句
addr opcode p1 p2 p3
---- ------------ ----- ----- -----------------------------------
0 Transaction 0 0
1 VerifyCookie 0 81
2 Transaction 1 0
3 Integer 0 0
4 OpenWrite 0 3 examp
5 NewRecno 0 0
6 String 0 0 Hello, World!
7 Integer 99 0 99
8 MakeRecord 2 0
9 PutIntKey 0 1
10 Close 0 0
11 Commit 0 0
12 Halt 0 0
整个操作被分解为12条VDBE说明,前3条和最后2条是系统的标准步骤,所以真正完成我们的工作的是中间7条说明。这段代码中没有跳转语句,所有整个代码段从上到下执行一遍。
0 Transaction 0 0
1 VerifyCookie 0 81
2 Transaction 1 0

Transaction 开始一项交互活动。直到 遇到Commit 或者Rollback 时停止。P1参数是交互开始的数据库文件的索引。0号索引是主文件,1代表这个文件存放的是临时表。如果P2参数不为0,则开始一个写交互。当交互开始之 后,对应的数据库文件获得"write lock"状态。在这项交互进行当中其他进程将无法读取这个文件。一项交互必须在任何对数据文件的修改动作之前进行。如果P2是0这文件将获得一个 "read lock"
VerifyCookie 检查数据库0号参数(计划版本)以确保它=P2,P1是数据库编号,0代表主数据库文件,1代表文件拥有临时表,其他更大的数字代表附加数据库。
在建立VerifyCookie之前,必须有一个Transaction已经开始,或者已经建立了一个read lock.
第2个Transaction语句开始一项交互,应用对象是数据库1 (一个临时数据表)。
3 Integer 0 0
4 OpenWrite 0 3 examp
Integer 将整数P1 (0)压入堆栈。0是下面 OpenWrite 所要用到的数据库的编号,如果P3不为0 ,那么它就是一个代表相同整数的字符串,执行这条语句后,堆栈看起来是这样
(integer) 0

OpenWrite 创建一个新的读/写指针,指向P1(0)也就是数据库中的主文件“examp”,他的根页(节点)是P2(3),因为数据库文件第一页是空的,第二页存放 的是数据表的索引。从第3页开始存放每个数据表当中的数据。P3("examp")是被打开的表的名字,这个参数是不被使用的,只是使代码更容易阅读而 已。这条语句将栈顶元素弹出(0) ,所以之后,堆栈为空。

5 NewRecno 0 0
NewRecno 为指针P1指向的数据表创建一个整型的新的纪录号。这个纪录好并不是一个用在表里的键值。新的纪录号被压入堆栈。这个动作之后,堆栈看起来是这样:
(integer) new record key

6 String 0 0 Hello, World!
String 将它的P3参数压入堆栈,之后,堆栈应该是这样:
(string) "Hello World!"
(integer) new record key

7 Integer 99 0 99
动作之后,堆栈应该是这样:
(integer) 99
(string) "Hello, World!"
(integer) new record key

8 MakeRecord 2 0
MakeRecord 将栈顶的P1个元素取出( 2个),并且将他们转换成二进制,然后再把新生成的结构压回堆栈。之后,堆栈应该是这样:
(record) "Hello, World!", 99
(integer) new record key
9 PutIntKey 0 1
PutIntKey 将栈顶的2个元素作为一个entry写入P1所指的表中,如果表中元素不存在,那么将被创建。如果已经存在,则会被覆盖。数据是栈顶元素,键是下面的元 素。这条语句当中,进行2次出栈操作。P2参数用来判定是否修改表中当前rowID,P2=1则rowID 1,并且由 last_insert_rowID()函数返回,如果rowID=0,则行号不变,仍未当前ID.(这就解释了"表中元素不存在,那么将被创建。如果已 经存在,则会被覆盖").这条语句是文件操作上的insert.

10 Close 0 0
Close 关闭之前打开的一个文件指针(0)(对应于前面的OpenWrite), 如果文件指针当前并没有打开,这条语句不被执行。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选