本文介绍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个元素d出,转换成二进制(用于写入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//从栈中d出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
总结以上是内存溢出为你收集整理的SQLite学习(九) - 虚拟机指令2全部内容,希望文章能够帮你解决SQLite学习(九) - 虚拟机指令2所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)