2021SC@SDUSC SQLite源码分析(八)————SQLite虚拟机指令集
为了执行一个SQL语句,SQLite库首先解析SQL,分析该语句,然后生成简短的程序来执行该语句。产生的程序将由SQLite库实现的虚拟机来执行。虚拟机的源代码是vdbe.c文件。所有操作码的定义都包含在源文件注释中,下面是几个操作码指令实例分析
一、OP_Column
解析当前游标指定的记录的数据
p1为当前游标索引号,p2为列号
case OP_Column: {
u32 payloadSize;
int p1 = pOp->p1;
int p2 = pOp->p2;
Cursor *pC = 0;
char *zRec;
BtCursor *pCrsr;
u32 *aType;
u32 *aOffset;
u32 nField;
int len;
int i;
char *zData;
Mem sMem;
sMem.flags = 0;
assert( p1<p->nCursor );
pTos++;
pTos->flags = MEM_Null;
pC = p->apCsr[p1];
assert( pC!=0 );
if( pC->pCursor!=0 ){
rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
zRec = 0;
pCrsr = pC->pCursor;
if( pC->nullRow ){
payloadSize = 0;
}else if( pC->cacheStatus==p->cacheCtr ){
payloadSize = pC->payloadSize;
zRec = (char*)pC->aRow;
}else if( pC->isIndex ){
i64 payloadSize64;
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
payloadSize = payloadSize64;
}else{
sqlite3BtreeDataSize(pCrsr, &payloadSize);
}
nField = pC->nField;
}else if( pC->pseudoTable ){
payloadSize = pC->nData;
zRec = pC->pData;
pC->cacheStatus = CACHE_STALE;
assert( payloadSize==0 || zRec!=0 );
nField = pC->nField;
pCrsr = 0;
}else{
zRec = 0;
payloadSize = 0;
pCrsr = 0;
nField = 0;
}
if( payloadSize==0 ){
assert( pTos->flags==MEM_Null );
break;
}
assert( p2<nField );
if( pC && pC->cacheStatus==p->cacheCtr ){
aType = pC->aType;
aOffset = pC->aOffset;
}else{
u8 *zIdx;
u8 *zEndHdr;
u32 offset;
int szHdrSz;
int avail;
aType = pC->aType;
if( aType==0 ){
pC->aType = aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
}
if( aType==0 ){
goto no_mem;
}
pC->aOffset = aOffset = &aType[nField];
pC->payloadSize = payloadSize;
pC->cacheStatus = p->cacheCtr;
if( zRec ){
zData = zRec;
}else{
if( pC->isIndex ){
zData = (char*)sqlite3BtreeKeyFetch(pCrsr, &avail);
}else{
zData = (char*)sqlite3BtreeDataFetch(pCrsr, &avail);
}
if( avail>=payloadSize ){
zRec = zData;
pC->aRow = (u8*)zData;
}else{
pC->aRow = 0;
}
}
assert( zRec!=0 || avail>=payloadSize || avail>=9 );
szHdrSz = GetVarint((u8*)zData, offset);
if( !zRec && avail<offset ){
rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
zData = sMem.z;
}
zEndHdr = (u8 *)&zData[offset];
zIdx = (u8 *)&zData[szHdrSz];
for(i=0; i<nField; i++){
if( zIdx<zEndHdr ){
aOffset[i] = offset;
zIdx += GetVarint(zIdx, aType[i]);
offset += sqlite3VdbeSerialTypeLen(aType[i]);
}else{
aOffset[i] = 0;
}
}
Release(&sMem);
sMem.flags = MEM_Null;
if( zIdx>zEndHdr || offset>payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
}
if( aOffset[p2] ){
assert( rc==SQLITE_OK );
if( zRec ){
zData = &zRec[aOffset[p2]];
}else{
len = sqlite3VdbeSerialTypeLen(aType[p2]);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,&sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
zData = sMem.z;
}
sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos);
pTos->enc = encoding;
}else{
if( pOp->p3type==P3_MEM ){
sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
}else{
pTos->flags = MEM_Null;
}
}
if( (sMem.flags & MEM_Dyn)!=0 ){
assert( pTos->flags & MEM_Ephem );
assert( pTos->flags & (MEM_Str|MEM_Blob) );
assert( pTos->z==sMem.z );
assert( sMem.flags & MEM_Term );
pTos->flags &= ~MEM_Ephem;
pTos->flags |= MEM_Dyn|MEM_Term;
}
rc = sqlite3VdbeMemMakeWriteable(pTos);
op_column_out:
break;
}
二、OP_Next
移动游标使它指向表的下一个记录
case OP_Next: {
Cursor *pC;
BtCursor *pCrsr;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
if( (pCrsr = pC->pCursor)!=0 ){
int res;
if( pC->nullRow ){
res = 1;
}else{
assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
sqlite3BtreePrevious(pCrsr, &res);
pC->nullRow = res;
pC->cacheStatus = CACHE_STALE;
}
if( res==0 ){
pc = pOp->p2 - 1;
sqlite3_search_count++;
}
}else{
pC->nullRow = 1;
}
pC->rowidIsValid = 0;
break;
}
三、OP_Callback
该指令执行后,PC将指向下一条指令.
栈中栈顶的P1个值为查询的结果.该指令会导致sqlite3_step()函数将以SQLITE_ROW为返回码
而结束运行.此时用户程序就可以通过sqlite3_column_XXX读取位于栈中的数据了.
当sqlite3_step()再一次运行时,栈顶的P1个值会在执行Next指令前自动出栈.
case OP_Callback: {
Mem *pMem;
Mem *pFirstColumn;
assert( p->nResColumn==pOp->p1 );
pFirstColumn = &pTos[0-pOp->p1];
for(pMem = p->aStack; pMem<pFirstColumn; pMem++){
Deephemeralize(pMem);
}
p->cacheCtr = (p->cacheCtr + 2)|1;
for(; pMempTos; pMem++ ){
sqlite3VdbeMemNulTerminate(pMem);
storeTypeInfo(pMem, encoding);
}
p->resOnStack = 1;
p->nCallback++;
p->popStack = pOp->p1;
p->pc = pc + 1;
p->pTos = pTos;
return SQLITE_ROW;
}
Original: https://blog.csdn.net/qq_45936073/article/details/121543734
Author: 神明不自知
Title: 2021SC@SDUSC SQLite源码分析(八)————SQLite虚拟机指令集
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/817518/
转载文章受原作者版权保护。转载请注明原作者出处!