SQLite原始碼學習 38 對錶的一些處理

2021-10-09 04:54:10 字數 4164 閱讀 3345

在allocatecursor裡,中有openread或openwrite時才建立。

前者只是分配空間,後者是初始化的一些補充

ppage = pcur->ppage;

trace((

"insert: table=%d nkey=%lld ndata=%d page=%d %s\n"

, pcur->pgnoroot, px->nkey, px->ndata, ppage->pgno,

loc==0?

"overwrite"

:"new entry"))

;

pcur->pgnoroot是當前表根節點所在頁面,ppage->pgno是當前要插入的頁面序號,虛擬機器在執行newrowid命令時會呼叫

sqlite3btreelast()------->movetoroot()--------->getandinitpage()

來給pcur->ppage賦值,其中pppage就是pcur->ppage的位址

rc =

sqlite3pagerget

(pbt->ppager, pgno,

(dbpage**)

&pdbpage, breadonly);if

( rc )

*pppage =

(mempage*

)sqlite3pagergetextra

(pdbpage);if

((*pppage)

->isinit==0)

}

if

( pcur )

在newdatabase的zeropage,寫完資料庫的頭100個自己後,就會跟著建立一張sqlite_master表,這張表的資料更新也和普通表一樣,在insertcell函式裡

data = ppage->adata;

assert

(&data[ppage->celloffset]

==ppage->acellidx )

; rc =

allocatespace

(ppage, sz,

&idx);if

( rc )

/* the allocatespace() routine guarantees the following properties

** if it returns successfully */

assert

( idx >=0)

;assert

( idx >= ppage->celloffset+

2*ppage->ncell+

2|| corrupt_db )

;assert

( idx+sz <=

(int

)ppage->pbt->usablesize )

; ppage->nfree -

=(u16)(2

+ sz);if

( ichild )

else

pins = ppage->acellidx + i*2;

//更新cell索引陣列

memmove

(pins+

2, pins,2*

(ppage->ncell - i));

put2byte

(pins, idx)

; ppage->ncell++

;/* increment the cell count */

//更新這一頁的cell數量if(

(++data[ppage->hdroffset+4]

)==0) data[ppage->hdroffset+3]

++;

allocatespace裡更新第乙個cell的偏移位址

top -

= nbyte;

put2byte

(&data[hdr+5]

, top)

;assert

( top+nbyte <=

(int

)ppage->pbt->usablesize )

;*pidx = top;

那麼ppage->acellidx和ppage->celloffset是**來的呢,在zeropage函式裡,會被newdatabase()和btreecreatetable()函式呼叫

data[hdr]=(

char

)flags;

first = hdr +

((flags&ptf_leaf)==0

?12:8

);memset

(&data[hdr+1]

,0,4

);data[hdr+7]

=0;put2byte

(&data[hdr+5]

, pbt->usablesize)

; ppage->nfree =

(u16)

(pbt->usablesize - first)

;decodeflags

(ppage, flags)

; ppage->celloffset = first;

ppage->adataend =

&data[pbt->usablesize]

; ppage->acellidx =

&data[first]

;

相關測試**如下

do_execsql_test btree01-1.1 

看列印日誌,c(i) as (values(1) union all select i+1 from c where i<1)對應的應該是

insert: table=1 nkey=1 ndata=2 page=1 new entry
大概會在第1頁的1020位元組處寫入資料,之所以沒有寫入到資料庫的原因是,因為這個是臨時的,可以看位元組碼後面會執行到delete指令,還沒存到檔案之前就把這個cell給刪了,即把這些資料清0,呼叫關係

sqlite3btreedelete()----->dropcell()------>freespace()

但是我們知道第一頁在之前已經向檔案裡寫入了sqlite_master的資料了,而現在第一頁在記憶體裡的內容(pbt->ppage1)是清零的,為什麼最後在pager層寫檔案時

rc =

sqlite3oswrite

(ppager->fd, pdata, ppager->pagesize, offset)

;

這裡的pdata是原來檔案裡的資料,而不是清0後的資料

其實看上面這個就可以知道pbt->ppage1 被設為了0,而且p->pbt物件頁被釋放了

甚至在commit時,btree物件也被換掉了

我們再回過頭來看當時insert時的btree物件是哪來的

pcx->pbtx好像是乙個臨時物件

struct vdbecursor {

。。。。。。

btree *pbtx;

/* separate file holding temporary table */

所以這2個根本就不是同乙個btree物件

btree *pbt = db->adb[i]

.pbt;

//真實資料庫檔案對應的表

vdbecursor *pcx;

pcx->pbtx//臨時表,只在記憶體中存在

SQLite原始碼學習 36 Btree雜記

關鍵 如下 if pbt npage 0 只有在資料庫為空的時候才寫入,不為空的時候直接返回了,不會往下執行。30 tablelock 0 1 1 sqlite master 00 idb 0 root 1 write 1 首先定義字元陣列 161 tablelock ophelp idb p1 r...

redis原始碼學習之跳躍表

跳躍表對於我來說是乙個比較陌生的資料結構,因此花了一上午的時間先看了一蛤mit的公開課。網易雲課堂 mit跳躍表 什麼是跳躍表,有乙個很簡單的例子,有些地方的火車站跟高鐵站是同乙個站,有的地方只有火車站 假設現在的線路是a b c d e。其中a和c剛剛說的高鐵和火車站在一塊,其他的只有火車站,考慮...

Redis學習 鍊錶原始碼分析

0.前言 redis 中的鍊錶是以通用鍊錶的形式實現的,而對於鍊錶的用途來說,主要的功能就是增刪改查,所以對於查詢來說,redis其提供了乙個match函式指標,使用者負責實現其具體的匹配操作,從而實現通用化。涉及的檔案 adlist.h adlist.c 1.資料結構 typedef struct...