本文介绍SQLite虚拟机指令的版本是2.8.0. SQLite3以及以后版本的虚拟机概念上是一样的。但是一些操作码,操作数用法,个数有所改变,算法也有所不同。VDBE虚拟机语言,类似汇编语言,VDBE的每天指令由一个opcode和3个operand组成(SQLite3以后有5个)。下面看个例子来学习。 1 INSERT SQL CREATE TABLE examp(one text,two int); INSERT INTO examp VALUES('Hello,World!',99); 通过explain指令,我们可以得到这条INSERT SQL的VDBE指令
$sqlitetest_database_1 sqlite>CREATETABLEexamp(onetext,twoint); sqlite>.explain sqlite>EXPLAININSERTINTOexampVALUES('Hello,99); addropcodep1p2p3 ------------------------------------------------------------- 0Transaction00 1VerifyCookie081 2Transaction10 3Integer00 4OpenWrite03examp 5NewRecno00 6String00Hello,World! 7Integer99099 8MakeRecord20 9PutIntKey01 10Close00 11Commit00 12Halt00
这个INSERT由12条指令完成,头3条指令和最后2条指令时标准指令,每个SQL都会有这几个指令。实际完成INSERT操作的是中间的7条指令。下面我们来逐条分析。
(1)开始执行 0Transaction00 1VerifyCookie081 2Transaction10 Transaction开始一个事务。P1数作用的数据库的id,0表述main database。用.databases指令可以查看数据库的情况。第二个Transaction指令在rollback journal上创建一个事务。
sqlite> .databases seqnamefile ---------------------------------------------------------------------------- 0main VerifyCookie指令验证下P1数据的cookie值与P2值相同,保证修改之前这个数据库没有被其他线程修改过。以免读脏数据或覆盖已更新数据。
(2)打开游标 3Integer00 4OpenWrite03examp
Integer指令将P1=database id push到VDB Stack中。如果P3不为NULL,它的值就是database名字的string OpenWrite指令打开一个read/write的游标。P1=0 table id,P2=3 table所在页page id
(3)写入db文件 5NewRecno00//创建一个新的record id,并压入栈 6String00Hello,World!//将P3值压入栈 7Integer99099//将值99压入栈 8MakeRecord20//将栈中的top P1=2个元素弹出,转换成二进制(用于写入db文件),压入栈。 9PutIntKey01//pop栈中的2个元素,写入db文件,P2=1表示改变的元素个数。 (4)结束 10Close00//关闭游标 11Commit00//提交所有update,deletes the journal file and releases the write lock on the database. A read lock continues to be held if there are still cursors open. 12Halt00//VDB engine exit
2SELECT查询
sqlite>EXPLAINSELECT*FROMexamp; addropcodep1p2p3 ------------------------------------------------------------- 0ColumnName00one 1ColumnName10two 2Integer00 3OpenRead03examp 4VerifyCookie081 5Rewind010 6Column00 7Column01 8Callback20 9Next06 10Close00 11Halt00
如果熟悉SQLite API就知道有一个callback函数 int Callback(void *pUserData,int nColumn,char *azData[],char *azColumnName[]);
VDBE的任务就是传入后三个参数 int nColumn返回的column个数 char *azData[]返回data char*azColumnName[] column名数组 (1)开始执行准备要返回的column名 0ColumnName00one 1ColumnName10two ColumnName指令将column名字传入azColumnName字符串数组,然后后面会有相应的column指令将值传入 (2) 打开游标 2Integer00 3OpenRead03examp//打开一个只读的游标 4VerifyCookie081 (3)循环
5Rewind010初始化一个循环,将游标移到P1指向的数据库的第一个entery,然后Column and Next指令会用这个游标来轮询整个table。如果是空表,就直接跳转到P2=10指向的地址。
6Column00将P2=0th column压入栈 7Column01 将P2=1th column压入栈 8Callback20//从栈中弹出P1=2个元素,传入azData 9Next06//循环跳转到第p2=6条指令,继续执行
3. SQLite3版本的生成的指令 指令稍有改动,基于上面的分析还是可以看懂的,具体每个指令用法可以看指令参考http://www.sqlite.org/opcode.html
sqlite> EXPLAIN INSERT INTO examp VALUES('Hello,99);
addropcodep1p2p3p4p5comment --------------------------------------------------------- 0Trace00000 1Goto010000 2OpenWrite020200 3NewRowid01000 4String8020Hello,World!00 5Integer993000 6MakeRecord224ad00 7Insert041examp1b 8Close00000 9Halt00000 10Transaction01000 11VerifyCookie01000 12TableLock021examp00 13Goto02000
sqlite> EXPLAIN SELECT * FROM examp; addropcodep1p2p3p4p5comment --------------------------------------------------------- 0Trace00000 1Goto010000 2OpenRead020200 3Rewind08000 4Column00100 5Column01200 6ResultRow12000 7Next04001 8Close00000 9Halt00000 10Transaction00000 11VerifyCookie01000 12TableLock020examp00 13Goto02000 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|