为了执行SQL, SQLite首先解析分析SQL,生成一个由VM操作码组成的程序,类似汇编语言。SQLite虚拟机的实现代码在vdbe.c。 每个opcode的功能可以直接通过阅读源代码中的注释。
SQLite每条指令的格式是: Opcode p1 p2 p3 p4 p5
一个opcode以及最多5个 operands(P1, P2 P3, P4, and P5), 有些操作码使用所有的5个操作数,有的一个都不用,有的有1或2个。
P1, P2, and P3 类型为 32-bit signed integers, 通常这些操作数指向寄存器
P2 is always the jump destination in any operation that might cause a jump.
P4 可能的类型有
32-bit signed integer
64-bit signed integer,
64-bit floating point value
string literal
Blob literal
pointer to a collating sequence comparison function
pointer to the implementation of an application-defined SQL function
various other things.
P5 is an unsigned character normally used as a flag.
SQLite虚拟机从指令0开始执行,直到遇到halt指令,或者程序counter大于最后一条指令地址,或者出错了。如果虚拟机halt, 所有已分配内存将被释放,所有数据库游标将关闭。如果数据库执行出错,所有未完的数据库事务将关闭,已做的更新将回滚。虚拟机可以有一个或多个游标,每个 游标执行一个表或索引,多个游标可以指向同一个表或索引。所有游标独立执行,即使指向同一个表或索引。虚拟机操作数据库文件的唯一方法就是游标。数据操作 指令(OpenRead or OpenWrite)可以创建新的游标,读取,写入表或索引, 移动游标。指令执行结束所有游标会自动关闭SQLite虚拟机中包含固定数量的寄存器,用于存放字符串或保存计算中间结果。
启用打印VM指令的方法
(1) 加编译选项NDEBUG
(2) 在sqlite>下执行指令PRAGMA vdbe_trace=ON/OFF
(3) explain 命令
用explain命令可以看到虚拟机操作码的执行计划
$ sqlite3 ex1.db
sqlite> .explain
sqlite> explain delete from tbl1 where two<20;
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- --------- -- -------
0 Trace 0 0 0 explain.. 00
1 Goto 0 20 0 00
2 OpenRead 0 2 0 00 tbl
3 SetNumColumns 0 2 0 00
4 Rewind 0 11 0 00
5 Column 0 1 2 00 tbl.two
6 Integer 20 3 0 00
7 Ge 3 10 2 cs(BINARY) 6a
8 Rowid 0 1 0 00
9 FifoWrite 1 0 0 00
10 Next 0 5 0 00
11 Close 0 0 0 00
12 OpenWrite 0 2 0 00 tbl
13 SetNumColumns 0 2 0 00
14 FifoRead 1 18 0 00
15 NotExists 0 17 1 00
16 Delete 0 1 0 tbl 00
17 Goto 0 14 0 00
18 Close 0 0 0 00
19 Halt 0 0 0 00
20 Transaction 0 1 0 00
21 VerifyCookie 0 1 0 00
22 TableLock -1 2 0 tbl 00
23 Goto 0 2 0 00
sqlite>