Replace the VDBE Fifo object with the new RowSet object. (CVS 5977)

FossilOrigin-Name: 39a0750b49cf55e9c0927169ca47db909f5c16ea
This commit is contained in:
drh 2008-12-04 20:40:10 +00:00
parent 947bd8091b
commit 3d4501e573
15 changed files with 407 additions and 258 deletions

View File

@ -168,10 +168,10 @@ OBJS0 = alter.lo analyze.lo attach.lo auth.lo bitvec.lo btmutex.lo \
mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo select.lo status.lo \
random.lo resolve.lo rowset.lo select.lo status.lo \
table.lo tokenize.lo trigger.lo update.lo \
util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo \
walker.lo where.lo utf.lo vtab.lo
# Object files for the amalgamation.
@ -243,6 +243,7 @@ SRC = \
$(TOP)/src/printf.c \
$(TOP)/src/random.c \
$(TOP)/src/resolve.c \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
$(TOP)/src/shell.c \
@ -263,7 +264,6 @@ SRC = \
$(TOP)/src/vdbeapi.c \
$(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbeblob.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/vtab.c \
@ -649,6 +649,9 @@ random.lo: $(TOP)/src/random.c $(HDR)
resolve.lo: $(TOP)/src/resolve.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/resolve.c
rowset.lo: $(TOP)/src/rowset.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/rowset.c
select.lo: $(TOP)/src/select.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/select.c
@ -699,9 +702,6 @@ vdbeaux.lo: $(TOP)/src/vdbeaux.c $(HDR)
vdbeblob.lo: $(TOP)/src/vdbeblob.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/vdbeblob.c
vdbefifo.lo: $(TOP)/src/vdbefifo.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/vdbefifo.c
vdbemem.lo: $(TOP)/src/vdbemem.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/vdbemem.c

View File

@ -61,10 +61,10 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
opcodes.o os.o os_os2.o os_unix.o os_win.o \
pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rtree.o select.o status.o \
random.o resolve.o rowset.o rtree.o select.o status.o \
table.o tokenize.o trigger.o \
update.o util.o vacuum.o \
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \
walker.o where.o utf.o vtab.o
@ -128,6 +128,7 @@ SRC = \
$(TOP)/src/printf.c \
$(TOP)/src/random.c \
$(TOP)/src/resolve.c \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
$(TOP)/src/shell.c \
@ -148,7 +149,6 @@ SRC = \
$(TOP)/src/vdbeapi.c \
$(TOP)/src/vdbeaux.c \
$(TOP)/src/vdbeblob.c \
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
$(TOP)/src/vtab.c \

View File

@ -1,7 +1,7 @@
C Make\ssure\sdot-lock\sis\sfully\senabled\swhen\sSQLITE_ENABLE_LOCKING_STYLE\sis\ndisabled.\s\sFix\scompiler\swarnings\swhen\sSQLITE_ENABLE_LOCKING_STYLE\sis\ndisabled.\s(CVS\s5976)
D 2008-12-04T12:34:16
C Replace\sthe\sVDBE\sFifo\sobject\swith\sthe\snew\sRowSet\sobject.\s(CVS\s5977)
D 2008-12-04T20:40:10
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 0aa7bbe3be6acc4045706e3bb3fd0b8f38f4a3b5
F Makefile.in f7e4c81c347b04f7b0f1c1b081a168645d7b8af7
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F Makefile.vxwSH4 d53b4be86491060d498b22148951b6d765884cab
F README b974cdc3f9f12b87e851b04e75996d720ebf81ac
@ -80,7 +80,7 @@ F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc
F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh 09fe5815427dc7d0abb188bbcdf0e34896577210
F main.mk 87a73e91a3d0827dc796a249260866335e38a36e
F main.mk 5923e75b5ac4b265f322597c3953dda7175f4405
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
@ -107,7 +107,7 @@ F src/build.c a89e901ea24d8ec845286f9a1fbfd14572a7777e
F src/callback.c e970e5beddbdb23f89a6d05cb1a6419d9f755624
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
F src/date.c 88898ae96a0d7f66711caffa40b2cf30e623a387
F src/delete.c 2f85d6d00333343a76824a899e15f241ca383c7c
F src/delete.c d60885716666e5ea0f177b8db73c22c67ccba2cb
F src/expr.c 01b1cf0783a6d0093d72b799fcb22c86146362ef
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/func.c b4570eb73d873041b8e68f5cdbb4556ff13a94c3
@ -142,7 +142,7 @@ F src/os_win.c 3dff41670fb9798a869c636626bb7d6d8b6a45bb
F src/pager.c a193da9e271898077de815819e4c29fc2b6ece2a
F src/pager.h a02ef8e6cc7e78b54874166e5ce786c9d4c489bf
F src/parse.y 72397fe334b25b4f3411edbf49b5b706f2d7bdae
F src/pcache.c f3121a531745b20f5b824201eb63949a7e2959ac
F src/pcache.c 16dc8da6e6ba6250f8dfd9ee46036db1cbceedc6
F src/pcache.h f20c3e82dd6da622c3fe296170cb1801f9a2d75a
F src/pcache1.c d8d412326cc5123ba3bfaa66e36205ca8c5dbc5e
F src/pragma.c 539e28c90e782fa909a3b3a6849d18a9eb11a548
@ -150,11 +150,12 @@ F src/prepare.c fcadb25d2ad722d87103517333c825b56b79a770
F src/printf.c e29d9475c63e1dbfae005b98da3a60e07b5c1ca5
F src/random.c a87afbd598aa877e23ac676ee92fd8ee5c786a51
F src/resolve.c 4af5391d2b4c1d6c583a6805ac6660181de4545b
F src/rowset.c 2256fa4a928f750e2f3d6fc733523034beceb1d6
F src/select.c b296a7b53dd0b2c42ab8b67d969e2c924529008c
F src/shell.c 838c745e7ac5c9fe17bc996224ed2f928d178bb2
F src/sqlite.h.in b5d50f12fb9c7460a4ddfef8c1e799afaabefebf
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 54d956e75ec8b8d174eb3d98de6f54db8507da5d
F src/sqliteInt.h 1ed98f6df8475b82fed5bc174ebe1637dd9fc7d1
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
@ -189,18 +190,17 @@ F src/test_thread.c d74fc445e0dba0e00806117eb449b307c0b146bf
F src/test_wsd.c c297d7d6b8a990239e1bd25935e81d612d8ae31d
F src/tokenize.c aaa5fa6a4536a9dd7c855a3f66f32508f1612138
F src/trigger.c b86eb6d216c0014138f858a04185113cb54518e4
F src/update.c 37d03659f4d2186ffb8d0ab1df9c3038273fb488
F src/update.c 7143ac31d26dee156277126e9a7c5be953b18347
F src/utf.c 86dc0f8076f606432a01f1498ae054c32de1f9d2
F src/util.c b9a5d1c4c1a433e17d5828f9717fac763016a2cb
F src/vacuum.c 383d6297bddc011ab04a9eed110db6eaf523e8e9
F src/vdbe.c 3291fb0fe366634da2b92db4ca962b8d21427324
F src/vdbe.c 5c46d3742f36599e615ce57164e44c64df5d0470
F src/vdbe.h 03516f28bf5aca00a53c4dccd6c313f96adb94f6
F src/vdbeInt.h 6b1082480832d406c57a7f469a1c61f1a8759aca
F src/vdbeInt.h 1df957ab0f6a129735513d528c930dddfb4b23ef
F src/vdbeapi.c 20722164e7701a0747eaea03cddbbe0de5cb37bf
F src/vdbeaux.c 250296ad13b368b9e1076c7b002b3435154ed31f
F src/vdbeaux.c 33ba6b66bc595f5522e6a6995a86799bacd8961b
F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935
F src/vdbefifo.c e6326ad6d16ccd8c2ef659046e3a509c0ae4990a
F src/vdbemem.c 223e03281855515e9474dbf66f157452093a77c2
F src/vdbemem.c 2f386accfa1f4f11f0f12c2b6dcd4948e6df9c1f
F src/vtab.c 02c51eac45dbff1a1d6e73f58febf92ecb563f7f
F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
F src/where.c 96f7c2bd9e83c252d90ee2794f7a902fc5ba505b
@ -647,7 +647,7 @@ F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
F tool/mkkeywordhash.c c219ee2b8b5b8e7011cccfa1caec62d9812e82e7
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c.tcl 619c0629ac51f670f1f522cd0ab1fbb62ca97d45
F tool/mksqlite3c.tcl 75cb8cdbea59c0db53a2393df15229376c211ca1
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@ -662,7 +662,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P cb9c15431c53b13b70d006d8c47741ebc1caaca3
R 39955cff0967682033948df06f70c97f
P 4697249fcc6041ba7d2fb89589c855a8bec71eb2
R 854bd2622f9c32e838b36a1ab2f599ef
U drh
Z 033061a221ce993448c8fae205600a11
Z 79aa37bffdc9ab8f785db1e32012837b

View File

@ -1 +1 @@
4697249fcc6041ba7d2fb89589c855a8bec71eb2
39a0750b49cf55e9c0927169ca47db909f5c16ea

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.187 2008/11/19 09:05:27 danielk1977 Exp $
** $Id: delete.c,v 1.188 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
@ -390,6 +390,7 @@ void sqlite3DeleteFrom(
*/
{
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
/* Begin the database scan
*/
@ -399,7 +400,7 @@ void sqlite3DeleteFrom(
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid);
sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid);
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iRowid);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
@ -434,7 +435,7 @@ void sqlite3DeleteFrom(
if( triggers_exist ){
sqlite3VdbeResolveLabel(v, addr);
}
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
if( triggers_exist ){
int iData = ++pParse->nMem; /* For storing row data of OLD table */

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file implements that page cache.
**
** @(#) $Id: pcache.c,v 1.38 2008/11/19 16:52:44 danielk1977 Exp $
** @(#) $Id: pcache.c,v 1.39 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
@ -578,4 +578,3 @@ void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
}
}
#endif

238
src/rowset.c Normal file
View File

@ -0,0 +1,238 @@
/*
** 2008 December 3
**
** 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 module implements an object we call a "Row Set".
**
** The RowSet object is a bag of rowids. Rowids
** are inserted into the bag in an arbitrary order. Then they are
** pulled from the bag in sorted order. Rowids only appear in the
** bag once. If the same rowid is inserted multiple times, the
** second and subsequent inserts make no difference on the output.
**
** This implementation accumulates rowids in a linked list. For
** output, it first sorts the linked list (removing duplicates during
** the sort) then returns elements one by one by walking the list.
**
** Big chunks of rowid/next-ptr pairs are allocated at a time, to
** reduce the malloc overhead.
*/
#include "sqliteInt.h"
/*
** The number of rowset entries per allocation chunk.
*/
#define ROWSET_ENTRY_PER_CHUNK 63
/*
** Each entry in a RowSet is an instance of the following
** structure:
*/
struct RowSetEntry {
i64 v; /* ROWID value for this entry */
struct RowSetEntry *pNext; /* Next entry on a list of all entries */
};
/*
** Index entries are allocated in large chunks (instances of the
** following structure) to reduce memory allocation overhead. The
** chunks are kept on a linked list so that they can be deallocated
** when the RowSet is destroyed.
*/
struct RowSetChunk {
struct RowSetChunk *pNext; /* Next chunk on list of them all */
struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
};
/*
** A RowSet in an instance of the following structure.
**
** A typedef of this structure if found in sqliteInt.h.
*/
struct RowSet {
struct RowSetChunk *pChunk; /* List of all chunk allocations */
sqlite3 *db; /* The database connection */
struct RowSetEntry *pEntry; /* List of entries in the rowset */
struct RowSetEntry *pLast; /* Last entry on the pEntry list */
struct RowSetEntry *pFresh; /* Source of new entry objects */
u16 nFresh; /* Number of objects on pFresh */
u8 isSorted; /* True if content is sorted */
};
/*
** Turn bulk memory into a RowSet object. N bytes of memory
** are available at pSpace. The db pointer is used as a memory context
** for any subsequent allocations that need to occur.
** Return a pointer to the new RowSet object.
**
** If N is not sufficient memory to make even a minimum RowSet,
** then return NULL. If N is larger than the minimum, use
** the surplus as an initial allocation of entries available to
** be filled.
*/
RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
RowSet *p;
if( N<sizeof(*p) ){
p = 0;
}else{
p = pSpace;
p->pChunk = 0;
p->db = db;
p->pEntry = 0;
p->pLast = 0;
p->pFresh = (struct RowSetEntry*)&p[1];
p->nFresh = (u16)((N - sizeof(*p))/sizeof(struct RowSetEntry));
p->isSorted = 1;
}
return p;
}
/*
** Deallocate all chunks from a RowSet.
*/
void sqlite3RowSetClear(RowSet *p){
struct RowSetChunk *pChunk, *pNextChunk;
for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
pNextChunk = pChunk->pNext;
sqlite3DbFree(p->db, pChunk);
}
p->pChunk = 0;
p->nFresh = 0;
p->pEntry = 0;
p->pLast = 0;
p->isSorted = 1;
}
/*
** Insert a new value into a RowSet.
**
** The mallocFailed flag of the database connection is set if a
** memory allocation fails.
*/
void sqlite3RowSetInsert(RowSet *p, i64 rowid){
struct RowSetEntry *pEntry;
struct RowSetEntry *pLast;
if( p==0 ) return; /* Must have been a malloc failure */
if( p->nFresh==0 ){
struct RowSetChunk *pNew;
pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
if( pNew==0 ){
return;
}
pNew->pNext = p->pChunk;
p->pChunk = pNew;
p->pFresh = pNew->aEntry;
p->nFresh = ROWSET_ENTRY_PER_CHUNK;
}
pEntry = p->pFresh++;
p->nFresh--;
pEntry->v = rowid;
pEntry->pNext = 0;
pLast = p->pLast;
if( pLast ){
if( p->isSorted && rowid<=pLast->v ){
p->isSorted = 0;
}
pLast->pNext = pEntry;
}else{
assert( p->pEntry==0 );
p->pEntry = pEntry;
}
p->pLast = pEntry;
}
/*
** Merge two lists of RowSet entries. Remove duplicates.
**
** The input lists are assumed to be in sorted order.
*/
static struct RowSetEntry *boolidxMerge(
struct RowSetEntry *pA, /* First sorted list to be merged */
struct RowSetEntry *pB /* Second sorted list to be merged */
){
struct RowSetEntry head;
struct RowSetEntry *pTail;
pTail = &head;
while( pA && pB ){
assert( pA->pNext==0 || pA->v<=pA->pNext->v );
assert( pB->pNext==0 || pB->v<=pB->pNext->v );
if( pA->v<pB->v ){
pTail->pNext = pA;
pA = pA->pNext;
pTail = pTail->pNext;
}else if( pB->v<pA->v ){
pTail->pNext = pB;
pB = pB->pNext;
pTail = pTail->pNext;
}else{
pA = pA->pNext;
}
}
if( pA ){
assert( pA->pNext==0 || pA->v<=pA->pNext->v );
pTail->pNext = pA;
}else{
assert( pB==0 || pB->pNext==0 || pB->v<=pB->pNext->v );
pTail->pNext = pB;
}
return head.pNext;
}
/*
** Sort all elements of the RowSet into ascending order.
*/
static void sqlite3RowSetSort(RowSet *p){
unsigned int i;
struct RowSetEntry *pEntry;
struct RowSetEntry *aBucket[40];
assert( p->isSorted==0 );
memset(aBucket, 0, sizeof(aBucket));
while( p->pEntry ){
pEntry = p->pEntry;
p->pEntry = pEntry->pNext;
pEntry->pNext = 0;
for(i=0; aBucket[i]; i++){
pEntry = boolidxMerge(aBucket[i],pEntry);
aBucket[i] = 0;
}
aBucket[i] = pEntry;
}
pEntry = 0;
for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
pEntry = boolidxMerge(pEntry,aBucket[i]);
}
p->pEntry = pEntry;
p->pLast = 0;
p->isSorted = 1;
}
/*
** Extract the next (smallest) element from the RowSet.
** Write the element into *pRowid. Return 1 on success. Return
** 0 if the RowSet is already empty.
*/
int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
if( !p->isSorted ){
sqlite3RowSetSort(p);
}
if( p->pEntry ){
*pRowid = p->pEntry->v;
p->pEntry = p->pEntry->pNext;
if( p->pEntry==0 ){
sqlite3RowSetClear(p);
}
return 1;
}else{
return 0;
}
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.799 2008/11/24 20:01:33 shane Exp $
** @(#) $Id: sqliteInt.h,v 1.800 2008/12/04 20:40:10 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -503,6 +503,7 @@ struct BusyHandler {
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct Bitvec Bitvec;
typedef struct RowSet RowSet;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
@ -2161,6 +2162,11 @@ void sqlite3BitvecClear(Bitvec*, u32);
void sqlite3BitvecDestroy(Bitvec*);
int sqlite3BitvecBuiltinTest(int,int*);
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
void sqlite3RowSetClear(RowSet*);
void sqlite3RowSetInsert(RowSet*, i64);
int sqlite3RowSetNext(RowSet*, i64*);
void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)

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.187 2008/11/19 09:05:27 danielk1977 Exp $
** $Id: update.c,v 1.188 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
@ -124,6 +124,7 @@ void sqlite3Update(
int regOldRowid; /* The old rowid */
int regNewRowid; /* The new rowid */
int regData; /* New data for the row */
int regRowSet; /* Rowset of rows to be updated */
sContext.pParse = 0;
db = pParse->db;
@ -352,7 +353,10 @@ void sqlite3Update(
/* Remember the rowid of every item to be updated.
*/
sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
if( !okOnePass ){
regRowSet = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
}
/* End the database scan loop.
*/
@ -405,7 +409,7 @@ void sqlite3Update(
addr = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, a1);
}else{
addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
}
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.789 2008/12/04 12:17:30 drh Exp $
** $Id: vdbe.c,v 1.790 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -189,7 +189,7 @@ static VdbeCursor *allocateCursor(
Vdbe *p, /* The virtual machine */
int iCur, /* Index of the new VdbeCursor */
Op *pOp, /* */
int iDb, /* */
int iDb, /* When database the cursor belongs to, or -1 */
int isBtreeCursor /* */
){
/* Find the memory cell that will be used to store the blob of memory
@ -804,7 +804,7 @@ case OP_Yield: {
/* Opcode: Halt P1 P2 * P4 *
**
** Exit immediately. All open cursors, Fifos, etc are closed
** Exit immediately. All open cursors, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
@ -4285,35 +4285,55 @@ case OP_IntegrityCk: {
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/* Opcode: FifoWrite P1 * * * *
/* Opcode: RowSetAdd P1 P2 * * *
**
** Write the integer from register P1 into the Fifo.
** Insert the integer value held by register P2 into a boolean index
** held in register P1.
**
** An assertion fails if P2 is not an integer.
*/
case OP_FifoWrite: { /* in1 */
p->sFifo.db = db;
if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
goto no_mem;
case OP_RowSetAdd: { /* in2 */
Mem *pIdx;
Mem *pVal;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
pIdx = &p->aMem[pOp->p1];
assert( pOp->p2>0 && pOp->p2<=p->nMem );
pVal = &p->aMem[pOp->p2];
assert( (pVal->flags & MEM_Int)!=0 );
if( (pIdx->flags & MEM_RowSet)==0 ){
sqlite3VdbeMemSetRowSet(pIdx);
}
sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i);
break;
}
/* Opcode: RowSetRead P1 P2 P3 * *
**
** Extract the smallest value from boolean index P1 and put that value into
** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, out3 */
Mem *pIdx;
i64 val;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
CHECK_FOR_INTERRUPT;
pIdx = &p->aMem[pOp->p1];
if( (pIdx->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIdx);
pc = pOp->p2 - 1;
}else{
/* A value was pulled from the index */
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &p->aMem[pOp->p3];
sqlite3VdbeMemSetInt64(pOut, val);
}
break;
}
/* Opcode: FifoRead P1 P2 * * *
**
** Attempt to read a single integer from the Fifo. Store that
** integer in register P1.
**
** If the Fifo is empty jump to P2.
*/
case OP_FifoRead: { /* jump */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
pOut = &p->aMem[pOp->p1];
MemSetTypeFlag(pOut, MEM_Int);
if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
pc = pOp->p2 - 1;
}
break;
}
#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * *
@ -4337,8 +4357,6 @@ case OP_ContextPush: {
pContext = &p->contextStack[i];
pContext->lastRowid = db->lastRowid;
pContext->nChange = p->nChange;
pContext->sFifo = p->sFifo;
sqlite3VdbeFifoInit(&p->sFifo, db);
break;
}
@ -4353,8 +4371,6 @@ case OP_ContextPop: {
assert( p->contextStackTop>=0 );
db->lastRowid = pContext->lastRowid;
p->nChange = pContext->nChange;
sqlite3VdbeFifoClear(&p->sFifo);
p->sFifo = pContext->sFifo;
break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */

View File

@ -15,7 +15,7 @@
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
** $Id: vdbeInt.h,v 1.158 2008/11/17 15:31:48 danielk1977 Exp $
** $Id: vdbeInt.h,v 1.159 2008/12/04 20:40:10 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@ -113,8 +113,9 @@ typedef struct VdbeCursor VdbeCursor;
*/
struct Mem {
union {
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
i64 i; /* Integer value. */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
} u;
double r; /* Real value */
sqlite3 *db; /* The associated database connection */
@ -147,21 +148,20 @@ struct Mem {
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MemSetTypeFlag(p, f) \
((p)->flags = ((p)->flags&~(MEM_Int|MEM_Real|MEM_Null|MEM_Blob|MEM_Str))|f)
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
#define MEM_TypeMask 0x00ff /* Mask of type bits */
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
#define MEM_Term 0x0020 /* String rep is nul terminated */
#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
#define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */
#define MEM_Term 0x0200 /* String rep is nul terminated */
#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0800 /* Mem.z points to a static string */
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
#ifdef SQLITE_OMIT_INCRBLOB
#undef MEM_Zero
@ -169,6 +169,12 @@ struct Mem {
#endif
/*
** Clear any existing type flags from a Mem and replace them with f
*/
#define MemSetTypeFlag(p, f) ((p)->flags = ((p)->flags&~(MEM_TypeMask))|f)
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function. This is used to implement the sqlite3_get_auxdata()
@ -221,33 +227,6 @@ struct Set {
HashElem *prev; /* Previously accessed hash elemen */
};
/*
** A FifoPage structure holds a single page of valves. Pages are arranged
** in a list.
*/
typedef struct FifoPage FifoPage;
struct FifoPage {
int nSlot; /* Number of entries aSlot[] */
int iWrite; /* Push the next value into this entry in aSlot[] */
int 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 */
sqlite3 *db; /* The associated database connection */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
/*
** A Context stores the last insert rowid, the last statement change count,
** and the current statement change count (i.e. changes since last statement).
@ -261,7 +240,6 @@ typedef struct Context Context;
struct Context {
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
@ -301,7 +279,6 @@ struct Vdbe {
Mem *aMem; /* The memory locations */
int nCallback; /* Number of callbacks invoked so far */
int cacheCtr; /* VdbeCursor row cache generation counter */
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*/
@ -383,6 +360,7 @@ void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
void sqlite3VdbeMemSetZeroBlob(Mem*,int);
void sqlite3VdbeMemSetRowSet(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
@ -411,10 +389,6 @@ int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*, sqlite3*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);
#ifndef SQLITE_OMIT_INCRBLOB
int sqlite3VdbeMemExpandBlob(Mem *);

View File

@ -14,7 +14,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.421 2008/11/21 16:58:03 danielk1977 Exp $
** $Id: vdbeaux.c,v 1.422 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -802,6 +802,9 @@ int sqlite3VdbeReleaseBuffers(Vdbe *p){
assert( sqlite3_mutex_held(p->db->mutex) );
for(ii=1; ii<=p->nMem; ii++){
Mem *pMem = &p->aMem[ii];
if( pMem->flags & MEM_RowSet ){
sqlite3RowSetClear(pMem->u.pRowSet);
}
if( pMem->z && pMem->flags&MEM_Dyn ){
assert( !pMem->xDel );
nFree += sqlite3DbMallocSize(pMem->db, pMem->z);
@ -1156,16 +1159,16 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
static void Cleanup(Vdbe *p){
int i;
sqlite3 *db = p->db;
Mem *pMem;
closeAllCursorsExceptActiveVtabs(p);
for(i=1; i<=p->nMem; i++){
MemSetTypeFlag(&p->aMem[i], MEM_Null);
for(pMem=&p->aMem[1], i=1; i<=p->nMem; i++, pMem++){
if( pMem->flags & MEM_RowSet ){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
}
releaseMemArray(&p->aMem[1], p->nMem);
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
sqlite3DbFree(db, p->contextStack);
}
p->contextStack = 0;

View File

@ -1,130 +0,0 @@
/*
** 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.
**
** $Id: vdbefifo.c,v 1.9 2008/11/17 19:18:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial
** number of entries in a fifo page and the maximum number of
** entries in a fifo page.
*/
#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1)
#ifdef SQLITE_MALLOC_SOFT_LIMIT
# define FIFOSIZE_MAX (int)(((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
#else
# define FIFOSIZE_MAX (int)(((262144-sizeof(FifoPage))/8)+1)
#endif
/*
** 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 *allocateFifoPage(sqlite3 *db, int nEntry){
FifoPage *pPage;
if( nEntry>FIFOSIZE_MAX ){
nEntry = FIFOSIZE_MAX;
}
pPage = sqlite3DbMallocRaw(db, 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, sqlite3 *db){
memset(pFifo, 0, sizeof(*pFifo));
pFifo->db = db;
}
/*
** 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 =
allocateFifoPage(pFifo->db, FIFOSIZE_FIRST);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
pPage->pNext = allocateFifoPage(pFifo->db, 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->iWrite<=pPage->nSlot );
assert( pPage->iRead<pPage->nSlot );
assert( pPage->iRead>=0 );
*pVal = pPage->aSlot[pPage->iRead++];
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
sqlite3DbFree(pFifo->db, 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;
sqlite3DbFree(pFifo->db, pPage);
}
sqlite3VdbeFifoInit(pFifo, pFifo->db);
}

View File

@ -15,7 +15,7 @@
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
** $Id: vdbemem.c,v 1.126 2008/11/11 00:21:30 drh Exp $
** $Id: vdbemem.c,v 1.127 2008/12/04 20:40:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -42,6 +42,7 @@
*/
int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
int rc;
assert( (pMem->flags&MEM_RowSet)==0 );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
@ -81,6 +82,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
((pMem->flags&MEM_Ephem) ? 1 : 0) +
((pMem->flags&MEM_Static) ? 1 : 0)
);
assert( (pMem->flags&MEM_RowSet)==0 );
if( n<32 ) n = 32;
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
@ -121,6 +123,7 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int f;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( (pMem->flags&MEM_RowSet)==0 );
expandBlob(pMem);
f = pMem->flags;
if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
@ -144,6 +147,7 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
if( pMem->flags & MEM_Zero ){
int nByte;
assert( pMem->flags&MEM_Blob );
assert( (pMem->flags&MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
@ -203,6 +207,8 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
assert( (pMem->flags&MEM_RowSet)==0 );
if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
return SQLITE_NOMEM;
@ -267,8 +273,11 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else if( p->flags&MEM_Dyn && p->xDel ){
assert( (p->flags&MEM_RowSet)==0 );
p->xDel((void *)p->z);
p->xDel = 0;
}else if( p->flags&MEM_RowSet ){
sqlite3RowSetClear(p->u.pRowSet);
}
}
@ -383,6 +392,7 @@ double sqlite3VdbeRealValue(Mem *pMem){
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
assert( (pMem->flags & MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = doubleToInt64(pMem->r);
@ -391,17 +401,14 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
}
}
static void setTypeFlag(Mem *pMem, int f){
MemSetTypeFlag(pMem, f);
}
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( (pMem->flags & MEM_RowSet)==0 );
pMem->u.i = sqlite3VdbeIntValue(pMem);
setTypeFlag(pMem, MEM_Int);
MemSetTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
}
@ -412,7 +419,7 @@ int sqlite3VdbeMemIntegerify(Mem *pMem){
int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->r = sqlite3VdbeRealValue(pMem);
setTypeFlag(pMem, MEM_Real);
MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
@ -433,7 +440,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3VdbeMemIntegerify(pMem);
}else{
pMem->r = r1;
setTypeFlag(pMem, MEM_Real);
MemSetTypeFlag(pMem, MEM_Real);
}
return SQLITE_OK;
}
@ -442,7 +449,10 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
** Delete any previous value and set the value stored in *pMem to NULL.
*/
void sqlite3VdbeMemSetNull(Mem *pMem){
setTypeFlag(pMem, MEM_Null);
if( pMem->flags & MEM_RowSet ){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
pMem->type = SQLITE_NULL;
}
@ -452,7 +462,7 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
*/
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
setTypeFlag(pMem, MEM_Blob);
MemSetTypeFlag(pMem, MEM_Blob);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->type = SQLITE_BLOB;
pMem->n = 0;
@ -487,6 +497,28 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
}
}
/*
** Delete any previous value and set the value of pMem to be an
** empty boolean index.
*/
void sqlite3VdbeMemSetRowSet(Mem *pMem){
sqlite3 *db = pMem->db;
assert( db!=0 );
if( pMem->flags & MEM_RowSet ){
sqlite3RowSetClear(pMem->u.pRowSet);
}else{
sqlite3VdbeMemRelease(pMem);
pMem->zMalloc = sqlite3DbMallocRaw(db, 32);
}
if( !db->mallocFailed ){
assert( pMem->zMalloc );
pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
sqlite3DbMallocSize(db, pMem->zMalloc));
assert( pMem->u.pRowSet!=0 );
pMem->flags = MEM_RowSet|MEM_Dyn;
}
}
/*
** Return true if the Mem object contains a TEXT or BLOB that is
** too large - whose size exceeds SQLITE_MAX_LENGTH.
@ -515,6 +547,7 @@ int sqlite3VdbeMemTooBig(Mem *p){
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
assert( (pFrom->flags & MEM_RowSet)==0 );
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
@ -532,6 +565,7 @@ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
assert( (pFrom->flags & MEM_RowSet)==0 );
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
@ -585,6 +619,7 @@ int sqlite3VdbeMemSetStr(
int flags = 0; /* New value for pMem->flags */
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( (pMem->flags & MEM_RowSet)==0 );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
@ -672,6 +707,7 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
f1 = pMem1->flags;
f2 = pMem2->flags;
combined_flags = f1|f2;
assert( (combined_flags & MEM_RowSet)==0 );
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
@ -799,6 +835,7 @@ int sqlite3VdbeMemFromBtree(
db = sqlite3BtreeCursorDb(pCur);
assert( sqlite3_mutex_held(db->mutex) );
assert( (pMem->flags & MEM_RowSet)==0 );
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
}else{
@ -894,6 +931,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
assert( (pVal->flags & MEM_RowSet)==0 );
if( pVal->flags&MEM_Null ){
return 0;

View File

@ -236,12 +236,12 @@ foreach file {
bitvec.c
pcache.c
pcache1.c
rowset.c
pager.c
btmutex.c
btree.c
vdbefifo.c
vdbemem.c
vdbeaux.c
vdbeapi.c