为了执行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>