1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Replace OP_List with OP_Fifo. This is the first step toward allowing

recursive delete triggers and later foreign keys with cascading deletes. (CVS 2538)

FossilOrigin-Name: 94c120bb782fed53142317d1755e70c858930486
This commit is contained in:
drh
2005-07-08 13:07:59 +00:00
parent 9f18e8a0c4
commit a01f79df49
10 changed files with 192 additions and 129 deletions

View File

@@ -118,7 +118,8 @@ LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \
main.lo opcodes.lo os_unix.lo os_win.lo \
pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \
select.lo table.lo tokenize.lo trigger.lo update.lo \
util.lo vacuum.lo vdbe.lo vdbeapi.lo vdbeaux.lo vdbemem.lo \
util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \
where.lo utf.lo legacy.lo
# All of the source code files.
@@ -166,6 +167,7 @@ SRC = \
$(TOP)/src/vdbe.h \
$(TOP)/src/vdbeapi.c \
$(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/where.c
@@ -392,6 +394,9 @@ vdbeapi.lo: $(TOP)/src/vdbeapi.c $(VDBEHDR)
vdbeaux.lo: $(TOP)/src/vdbeaux.c $(VDBEHDR)
$(LTCOMPILE) -c $(TOP)/src/vdbeaux.c
vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR)
$(LTCOMPILE) -c $(TOP)/src/vdbefifo.c
vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR)
$(LTCOMPILE) -c $(TOP)/src/vdbemem.c

View File

@@ -61,7 +61,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \
pager.o parse.o pragma.o prepare.o printf.o random.o \
select.o table.o tclsqlite.o tokenize.o trigger.o \
update.o util.o vacuum.o \
vdbe.o vdbeapi.o vdbeaux.o vdbemem.o \
vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \
where.o utf.o legacy.o
# All of the source code files.
@@ -109,6 +109,7 @@ SRC = \
$(TOP)/src/vdbe.h \
$(TOP)/src/vdbeapi.c \
$(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/where.c
@@ -328,6 +329,9 @@ vdbeapi.o: $(TOP)/src/vdbeapi.c $(VDBEHDR)
vdbeaux.o: $(TOP)/src/vdbeaux.c $(VDBEHDR)
$(TCCX) -c $(TOP)/src/vdbeaux.c
vdbefifo.o: $(TOP)/src/vdbefifo.c $(VDBEHDR)
$(TCCX) -c $(TOP)/src/vdbefifo.c
vdbemem.o: $(TOP)/src/vdbemem.c $(VDBEHDR)
$(TCCX) -c $(TOP)/src/vdbemem.c

View File

@@ -1,6 +1,6 @@
C Add\sinfrastructure\sfor\sthe\sANALYZE\scommand.\s\sDoes\snot\syet\sactually\ndo\sanything.\s(CVS\s2537)
D 2005-07-08T12:13:04
F Makefile.in bc7bffc4ca6f09f2ffa9c9f5c43fc624fb566970
C Replace\sOP_List\swith\sOP_Fifo.\s\sThis\sis\sthe\sfirst\sstep\stoward\sallowing\nrecursive\sdelete\striggers\sand\slater\sforeign\skeys\swith\scascading\sdeletes.\s(CVS\s2538)
D 2005-07-08T13:08:00
F Makefile.in 3c10cd7bc3ecbd60fe4d5a5c0f59bfa7fb217a66
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F VERSION 44fad0bf0996660a11bf8187361de03941d9b7b0
@@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
F main.mk 675e435ca670e30513907265cc9cc0c011b40c17
F main.mk b2d38013a10e1c6a821e3d117294bf785deecf97
F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
F mkopcodeh.awk 7563ad235670e864ead95cf672be3fe081450ae0
@@ -36,7 +36,7 @@ F src/btree.h 41a71ce027db9ddee72cb43df2316bbe3a1d92af
F src/build.c 1f40c07a11e0a4eed1cef1ad4e52cf3f9770f220
F src/callback.c 0910b611e0c158f107ee3ff86f8a371654971e2b
F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
F src/delete.c 9bb19ede439cf325bc6d6f5995b6393fb85b5162
F src/delete.c 250d436a68fe371b4ab403d1c0f6fdc9a6860c39
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
F src/expr.c fdc8b82babbb266eeded4a314fd2f1d315133797
F src/func.c cbdf7256400ac7d5f020d131261bb2bd41bb631f
@@ -74,15 +74,16 @@ F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
F src/tokenize.c 57ec9926612fb9e325b57a141303573bc20c79bf
F src/trigger.c f51dec15921629591cb98bf2e350018e268b109a
F src/update.c e96c7b342cd8903c672162f4cf84d2c737943347
F src/update.c 49a9c618c3ba1ca57038d9ce41f14e958442fe58
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
F src/util.c 1acbe299cbe51f45176ac1e48ded9bea206c3c23
F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
F src/vdbe.c 56e892e351eb3ed634c3c239e4ad5c03aecfc2bf
F src/vdbe.c 87dda3fc214e4828641dd53527777f1b7d37b85f
F src/vdbe.h 75e466d84d362b0c4498978a9d6b1e6bd32ecf3b
F src/vdbeInt.h 4312faf41630a6c215924b6c7c2f39ebb1af8ffb
F src/vdbeInt.h 9be9a6c43d38124bd03cc5cf05715605b1789fd9
F src/vdbeapi.c 7f392f0792d1258c958083d7de9eae7c3530c9a6
F src/vdbeaux.c 38332d91887817a2146f46b58fff2a8a88ed0278
F src/vdbeaux.c 3732a86566a6be4da4c606e9334baf3fd98667af
F src/vdbefifo.c b8805850afe13b43f1de78d58088cb5d66f88e1e
F src/vdbemem.c da8e8d6f29dd1323f782f000d7cd120027c9ff03
F src/where.c 97f356317024597e684b750658f2e8822cb15f10
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
@@ -284,7 +285,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
P b34647a2ebec6f915f9914034e9370459873215e
R e47c1bc2e59627b5b8cf84918bbd5426
P 05b6ac9a76fd5765c50e81588f8e71c59fe35ce4
R ad75c3dbc9b87159735faff9e7381646
U drh
Z 50fe8e6711c2298fa85b1472b5a9b5e5
Z 29241e9900ff613d77be112c57ad8310

View File

@@ -1 +1 @@
05b6ac9a76fd5765c50e81588f8e71c59fe35ce4
94c120bb782fed53142317d1755e70c858930486

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.107 2005/06/24 03:53:06 drh Exp $
** $Id: delete.c,v 1.108 2005/07/08 13:08:00 drh Exp $
*/
#include "sqliteInt.h"
@@ -240,7 +240,7 @@ void sqlite3DeleteFrom(
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
}
@@ -260,14 +260,13 @@ void sqlite3DeleteFrom(
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
end = sqlite3VdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTableForReading(v, iCur, pTab);
@@ -288,7 +287,7 @@ void sqlite3DeleteFrom(
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** OP_FifoRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
@@ -297,7 +296,7 @@ void sqlite3DeleteFrom(
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
}
/* Delete the row */
@@ -322,7 +321,6 @@ void sqlite3DeleteFrom(
/* End of the delete loop */
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeResolveLabel(v, end);
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
if( !triggers_exist ){

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.108 2005/06/12 21:35:53 drh Exp $
** $Id: update.c,v 1.109 2005/07/08 13:08:00 drh Exp $
*/
#include "sqliteInt.h"
@@ -273,7 +273,7 @@ void sqlite3Update(
/* Remember the index of every item to be updated.
*/
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
/* End the database scan loop.
*/
@@ -295,8 +295,7 @@ void sqlite3Update(
/* The top of the update loop for when there are triggers.
*/
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
@@ -389,8 +388,7 @@ void sqlite3Update(
** So make the cursor point at the old record.
*/
if( !triggers_exist ){
sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
@@ -468,7 +466,6 @@ void sqlite3Update(
*/
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp(v, OP_ListReset, 0, 0);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !triggers_exist ){

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.472 2005/06/25 18:42:15 drh Exp $
** $Id: vdbe.c,v 1.473 2005/07/08 13:08:00 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -3975,86 +3975,35 @@ case OP_IntegrityCk: {
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/* Opcode: ListWrite * * *
/* Opcode: FifoWrite * * *
**
** Write the integer on the top of the stack
** into the temporary storage list.
** into the Fifo.
*/
case OP_ListWrite: { /* no-push */
Keylist *pKeylist;
case OP_FifoWrite: { /* no-push */
assert( pTos>=p->aStack );
pKeylist = p->pList;
if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
if( pKeylist==0 ) goto no_mem;
pKeylist->nKey = 1000;
pKeylist->nRead = 0;
pKeylist->nUsed = 0;
pKeylist->pNext = p->pList;
p->pList = pKeylist;
}
Integerify(pTos);
pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
sqlite3VdbeFifoPush(&p->sFifo, pTos->i);
assert( (pTos->flags & MEM_Dyn)==0 );
pTos--;
break;
}
/* Opcode: ListRewind * * *
/* Opcode: FifoRead * P2 *
**
** Rewind the temporary buffer back to the beginning.
*/
case OP_ListRewind: { /* no-push */
/* What this opcode codes, really, is reverse the order of the
** linked list of Keylist structures so that they are read out
** in the same order that they were read in. */
Keylist *pRev, *pTop;
pRev = 0;
while( p->pList ){
pTop = p->pList;
p->pList = pTop->pNext;
pTop->pNext = pRev;
pRev = pTop;
}
p->pList = pRev;
break;
}
/* Opcode: ListRead * P2 *
**
** Attempt to read an integer from the temporary storage buffer
** and push it onto the stack. If the storage buffer is empty,
** Attempt to read a single integer from the Fifo
** and push it onto the stack. If the Fifo is empty
** push nothing but instead jump to P2.
*/
case OP_ListRead: {
Keylist *pKeylist;
case OP_FifoRead: {
i64 v;
CHECK_FOR_INTERRUPT;
pKeylist = p->pList;
if( pKeylist!=0 ){
assert( pKeylist->nRead>=0 );
assert( pKeylist->nRead<pKeylist->nUsed );
assert( pKeylist->nRead<pKeylist->nKey );
pTos++;
pTos->i = pKeylist->aKey[pKeylist->nRead++];
pTos->flags = MEM_Int;
if( pKeylist->nRead>=pKeylist->nUsed ){
p->pList = pKeylist->pNext;
sqliteFree(pKeylist);
}
}else{
if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: ListReset * * *
**
** Reset the temporary storage buffer so that it holds nothing.
*/
case OP_ListReset: { /* no-push */
if( p->pList ){
sqlite3VdbeKeylistFree(p->pList);
p->pList = 0;
}else{
pTos++;
pTos->i = v;
pTos->flags = MEM_Int;
}
break;
}
@@ -4105,8 +4054,8 @@ case OP_ContextPush: { /* no-push */
pContext = &p->contextStack[i];
pContext->lastRowid = db->lastRowid;
pContext->nChange = p->nChange;
pContext->pList = p->pList;
p->pList = 0;
pContext->sFifo = p->sFifo;
sqlite3VdbeFifoInit(&p->sFifo);
break;
}
@@ -4121,8 +4070,8 @@ case OP_ContextPop: { /* no-push */
assert( p->contextStackTop>=0 );
db->lastRowid = pContext->lastRowid;
p->nChange = pContext->nChange;
sqlite3VdbeKeylistFree(p->pList);
p->pList = pContext->pList;
sqlite3VdbeFifoClear(&p->sFifo);
p->sFifo = pContext->sFifo;
break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */

View File

@@ -260,17 +260,29 @@ struct Set {
};
/*
** A Keylist is a bunch of keys into a table. The keylist can
** grow without bound. The keylist stores the ROWIDs of database
** records that need to be deleted or updated.
** A FifoPage structure holds a single page of valves. Pages are arranged
** in a list.
*/
typedef struct Keylist Keylist;
struct Keylist {
int nKey; /* Number of slots in aKey[] */
int nUsed; /* Next unwritten slot in aKey[] */
int nRead; /* Next unread slot in aKey[] */
Keylist *pNext; /* Next block of keys */
i64 aKey[1]; /* One or more keys. Extra space allocated as needed */
typedef struct FifoPage FifoPage;
struct FifoPage {
u16 nSlot; /* Number of entries aSlot[] */
u16 iWrite; /* Push the next value into this entry in aSlot[] */
i16 iRead; /* Read the next value from this entry in aSlot[] */
FifoPage *pNext; /* Next page in the fifo */
i64 aSlot[1]; /* One or more slots for rowid values */
};
/*
** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation
** of that structure is private to this file.
**
** The Fifo structure describes the entire fifo.
*/
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
/*
@@ -286,7 +298,7 @@ typedef struct Context Context;
struct Context {
int lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
Keylist *pList; /* Records that will participate in a DELETE or UPDATE */
Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
@@ -325,7 +337,7 @@ struct Vdbe {
Agg *apAgg; /* Array of aggregate contexts */
Agg *pAgg; /* Current aggregate context */
int nCallback; /* Number of callbacks invoked so far */
Keylist *pList; /* A list of ROWIDs */
Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
@@ -362,7 +374,6 @@ struct Vdbe {
void sqlite3VdbeFreeCursor(Cursor*);
void sqlite3VdbeSorterReset(Vdbe*);
int sqlite3VdbeAggReset(sqlite3*, Agg *, KeyInfo *);
void sqlite3VdbeKeylistFree(Keylist*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@@ -411,3 +422,7 @@ int sqlite3VdbeOpcodeNoPush(u8);
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);

View File

@@ -952,18 +952,6 @@ int sqlite3VdbeAggReset(sqlite3 *db, Agg *pAgg, KeyInfo *pKeyInfo){
return SQLITE_OK;
}
/*
** Delete a keylist
*/
void sqlite3VdbeKeylistFree(Keylist *p){
while( p ){
Keylist *pNext = p->pNext;
sqliteFree(p);
p = pNext;
}
}
/*
** Close a cursor and release all the resources that cursor happens
** to hold.
@@ -1010,13 +998,10 @@ static void Cleanup(Vdbe *p){
}
closeAllCursors(p);
releaseMemArray(p->aMem, p->nMem);
if( p->pList ){
sqlite3VdbeKeylistFree(p->pList);
p->pList = 0;
}
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeKeylistFree(p->contextStack[i].pList);
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
sqliteFree(p->contextStack);
}

109
src/vdbefifo.c Normal file
View File

@@ -0,0 +1,109 @@
/*
** 2005 June 16
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a FIFO queue of rowids used for processing
** UPDATE and DELETE statements.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
static FifoPage *allocatePage(int nEntry){
FifoPage *pPage;
pPage = sqliteMallocRaw( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
pPage->iWrite = 0;
pPage->iRead = 0;
pPage->pNext = 0;
}
return pPage;
}
/*
** Initialize a Fifo structure.
*/
void sqlite3VdbeFifoInit(Fifo *pFifo){
memset(pFifo, 0, sizeof(*pFifo));
}
/*
** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK
** normally. SQLITE_NOMEM is returned if we are unable to allocate
** memory.
*/
int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
pPage = pFifo->pLast = pFifo->pFirst = allocatePage(20);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
pPage->pNext = allocatePage(pFifo->nEntry);
if( pPage->pNext==0 ){
return SQLITE_NOMEM;
}
pPage = pFifo->pLast = pPage->pNext;
}
pPage->aSlot[pPage->iWrite++] = val;
pFifo->nEntry++;
return SQLITE_OK;
}
/*
** Extract a single 64-bit integer value from the Fifo. The integer
** extracted is the one least recently inserted. If the Fifo is empty
** return SQLITE_DONE.
*/
int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
FifoPage *pPage;
if( pFifo->nEntry==0 ){
return SQLITE_DONE;
}
assert( pFifo->nEntry>0 );
pPage = pFifo->pFirst;
assert( pPage!=0 );
assert( pPage->iWrite>pPage->iRead );
assert( pPage->iRead<pPage->nSlot );
*pVal = pPage->aSlot[pPage->iRead++];
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
sqliteFree(pPage);
if( pFifo->nEntry==0 ){
assert( pFifo->pLast==pPage );
pFifo->pLast = 0;
}else{
assert( pFifo->pFirst!=0 );
}
}else{
assert( pFifo->nEntry>0 );
}
return SQLITE_OK;
}
/*
** Delete all information from a Fifo object. Free all memory held
** by the Fifo.
*/
void sqlite3VdbeFifoClear(Fifo *pFifo){
FifoPage *pPage, *pNextPage;
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
pNextPage = pPage->pNext;
sqliteFree(pPage);
}
sqlite3VdbeFifoInit(pFifo);
}