第一范文网 - 专业文章范例文档资料分享平台

SQLite3源程序分析 - v100

来源:用户分享 时间:2025/5/29 6:55:51 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

if( pPage && (pPage->pLruNext || pPage==pcache1.pLruTail) ){ /* 从双向链表中删除 */ if( pPage->pLruPrev ){

pPage->pLruPrev->pLruNext = pPage->pLruNext; }

if( pPage->pLruNext ){

pPage->pLruNext->pLruPrev = pPage->pLruPrev; }

/* 如果是头结点,改头指针 */ if( pcache1.pLruHead==pPage ){

pcache1.pLruHead = pPage->pLruNext; }

/* 如果是尾结点,改尾指针 */ if( pcache1.pLruTail==pPage ){

pcache1.pLruTail = pPage->pLruPrev; }

pPage->pLruNext = 0; pPage->pLruPrev = 0;

pPage->pCache->nRecyclable--; /* 修改可重用页数 */ } }

使一个页不被钉住的程序如下,比典型的双向链表的插入算法多一点儿操作: /*

实现sqlite3_pcache.xUnpin方法。 使页不被钉住(使其可被回收) */

static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){ PCache1 *pCache = (PCache1 *)p;

PgHdr1 *pPage = PAGE_TO_PGHDR1(pCache, pPg);

if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){

/*如果该页看起来不会再被使用了,且LRU中页数已经太多,直接释放该页。*/ pcache1RemoveFromHash(pPage); /* 从该页所在的页缓冲区中删除 */ pcache1FreePage(pPage); /* 释放该页 */ /* 当然就不需要再向LRU链表中插入了 */ }else{

/* 将该页插入到LRU链表的头部。 */

if( pcache1.pLruHead ){ /* LRU链表不为空 */ pcache1.pLruHead->pLruPrev = pPage; pPage->pLruNext = pcache1.pLruHead; pcache1.pLruHead = pPage; }else{ /* LRU链表为空 */ pcache1.pLruTail = pPage;

pcache1.pLruHead = pPage; }

pCache->nRecyclable++; } }

写到这里还有两个问题我也没搞清楚: 一是“净化”机制没搞清楚;

二是我在跟踪SQLite运行时,静态缓冲区的大小总是为0,而不是传说中的“默认为2000页”。

没搞清楚就算了,我不怕丢人。

2.4. sqlite3_stmt主线

现在开始讨论SQLite内存数据结构的第2条主线。

2.4.1. Vdbe结构

记得网上有人问过,在SQLite源程序中为什么找不到sqlite3_stmt结构的定义。在SQLite对外的接口中都是使用sqlite3_stmt,而其实在SQLite的实现中,\是一个指向VDBE结构的不透明的指针。 /*

虚拟机的一个实例。

此结构包含了虚拟机的全部状态。 */

struct Vdbe {

Vdbe *pPrev,*pNext; /* 数据库连接中虚拟机链表的指针域 */ int nOp; /* 程序中的指令数 */

int nOpAlloc; /* 为aOp[]分配的槽位数 */ Op *aOp; /* 存放虚拟机程序的空间 */ Mem *aColName; /* 返回的各字段的名称 */ Mem *pResultSet; /* 指向一个结果数组的指针 */ u16 nResColumn; /* 结果集中每行的字段数 */ u16 nCursor; /* apCsr[]中的元素数 */

VdbeCursor **apCsr; /* 此数组中的每个元素为一个打开的游标 */ int pc; /* 程序计数器 */ };

每个数据库连接中可能有多个活动的虚拟机,这些虚拟机被组织成一个双向链表,pPrev和pNext域分别指向链表中的前趋和后继。

在sqlite3结构中有一个域pVdbe,为指向此双向链表的头指针。新创建的虚拟机插在该双向链表的头部,创建虚拟机的程序如下: /*

创建一个新的虚拟机。 */

Vdbe *sqlite3VdbeCreate(sqlite3 *db){ Vdbe *p;

p = sqlite3DbMallocZero(db, sizeof(Vdbe) ); if( p==0 ) return 0; p->db = db;

if( db->pVdbe ){

db->pVdbe->pPrev = p; }

p->pNext = db->pVdbe; p->pPrev = 0; db->pVdbe = p; return p; }

2.4.2. Mem结构

/*

Mem结构

在SQLite内部,vdbe用Mem结构来操作几乎所有的SQL值。 Mem结构会给出同一个值的多种表示法(string、integer等)。 一个值(也就是Mem结构)具有以下属性:

每个值具有一个弱类型。存储在Mem结构中的值的弱类型由MemType(Mem*)返回。

类型可以是SQLITE_NULL、SQLITE_INTEGER、SQLITE_REAL、SQLITE_TEXT或SQLITE_BLOB。 */

struct Mem { union {

i64 i; /* 整数值 */

int nZero; /* 当MEM_Zero位设置时有效 */

FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u;

double r; /* 实数值 */

sqlite3 *db; /* 相关的数据库连接 */ char *z; /* 字符串或BLOB值 */

int n; /* 字符串值中的字节数,不包括'\\0' */ u16 flags; /* 由MEM_Null, MEM_Str, MEM_Dyn等标志位组成,详见后面的注释 */ u8 type; /* SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER等值中的一个 */ u8 enc; /* 编码:SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ };

2.4.3. VdbeCursor结构

游标在虚拟机一层的表现形式。 /*

游标是数据库中特定的BTree指针。

游标可以用特定的键值在BTree中搜寻入口,或循环处理所有的入口。

你可以向BTree中插入新的入口或从游标当前指向的入口中取出键值或数据值。 虚拟机打开的每个游标为此结构的一个实例。 */

struct VdbeCursor {

BtCursor *pCursor; /* 后台游标结构 */

Btree *pBt; /* Separate file holding temporary table */ int nField; /* 字段数量 */ /* 游标当前指向的数据记录的信息。

仅在cacheStatus与Vdbe.cacheCtr匹配时有效。 */

u32 cacheStatus; /* 如果此值与Vdbe.cacheCtr匹配,说明缓冲区可用 */ int payloadSize; /* Payload大小,以字节为单位。 */ u32 *aType; /* 各字段的数据类型值 */ u32 *aOffset; /* 各字段数据的偏移量 */

u8 *aRow; /* 当前行的数据(如果它们都在同一个页中) */ };

注:各域的含义解释起来挺麻烦的,就不解释了。看看参考文献二,就全明白了。下面几个结构也存在此情况,不再说明。

2.4.4. BtCursor记录

/*

游标是指向一个特定入口的指针,这个入口在一个数据库文件的特定b-tree中。 入口由MemPage和MemPage.aCell[]的下标确定。

一个数据库文件可被多个数据库连接共享,但游标不能被共享。 */

struct BtCursor {

Pgno pgnoRoot; /* 此Btree的根页页号 */

CellInfo info; /* 当前指向的单元(cell)的解析结果 */ void *pKey; /* 游标最后已知的位置的键值 */ i64 nKey; /* pKey的大小或最后的整数键值 */

i16 iPage; /* 当前页在apPage中的索引 */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* 从根页到本页的所有页 */

u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* apPage[i]中的当前索引。空注:单元 指针数组中的当前下标。 */ };

搜索更多关于: SQLite3源程序分析 - v100 的文档
SQLite3源程序分析 - v100.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c6zlok0v0jd0weks4q39l_10.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top