Code simplifications, especially to the pseudo-table logic, and comment
improvements. FossilOrigin-Name: 52449a9569b7142095cc88ee208b31cc59a3cab4
This commit is contained in:
parent
417168ade2
commit
3e9ca09453
30
manifest
30
manifest
@ -1,8 +1,8 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Add\sthe\sSQLITE_LIMIT_TRIGGER_DEPTH\soption\sto\ssqlite3_limit().
|
||||
D 2009-09-07T18:14:02
|
||||
C Code\ssimplifications,\sespecially\sto\sthe\spseudo-table\slogic,\sand\scomment\nimprovements.
|
||||
D 2009-09-08T01:14:49
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -105,11 +105,11 @@ F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 55b601857d924e07c91cfa69e9b2cb5093498c93
|
||||
F src/analyze.c 5a8b8aa3d170eac5e71af45458cec61f83c623ee
|
||||
F src/attach.c 13995348fc5a26cdd136a50806faf292aabc173f
|
||||
F src/auth.c 4cfb8fae12656cca2739176abebab84ed79dd8f6
|
||||
F src/auth.c d6a88bf8e81e6a079ccb8881002b327e42ec46b9
|
||||
F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
|
||||
F src/bitvec.c e08f6c1a9551b88081fc737916c6c3fd5029a6cf
|
||||
F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
|
||||
F src/btree.c 6b60ece56141bbe23aa6efca10f1612d34271c2f
|
||||
F src/btree.c 873a82706e07604a638e02e12617983df8e8070a
|
||||
F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
|
||||
F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
|
||||
F src/build.c df8dfff696329c192240e3d532f9dad0ef5abace
|
||||
@ -162,11 +162,11 @@ F src/printf.c 508a1c59433353552b6553cba175eaa7331f8fc1
|
||||
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
|
||||
F src/resolve.c 941843301f6fda6c6350839c6955a172441a0782
|
||||
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
|
||||
F src/select.c 95809555bf3614d0043d635c85948520fe21e741
|
||||
F src/select.c a7a075456d4e640ffd7d0a33202d306c69c88f72
|
||||
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
|
||||
F src/sqlite.h.in e5949b46f9a05aadde22848f92fae5c9ba87ee0e
|
||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||
F src/sqliteInt.h 13bb8c9abbdfe33c1fe685921b4a36e484a3d108
|
||||
F src/sqliteInt.h 6c03c685f37c2403ae78c4eb34f9ee9082748270
|
||||
F src/sqliteLimit.h be44f7f46c14bb4c21870074b1e6f1ac0abd6701
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||
@ -208,11 +208,11 @@ F src/update.c 3e97974baa914f32d4ae690fa0cb7281aff8cd39
|
||||
F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30
|
||||
F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
|
||||
F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0
|
||||
F src/vdbe.c 4e3c6895475cf8a9930cb39f7e9855acb7019349
|
||||
F src/vdbe.c 3ead9f634776836a42dd3b959557faff96911194
|
||||
F src/vdbe.h 080fe6bc1264438becb8bf9b9f3c84074c336b78
|
||||
F src/vdbeInt.h 6094e60f64d7a9d4352d4e6b90d1219dce947ad9
|
||||
F src/vdbeInt.h 004dbb28a9195b6c85fe3255c7cc300ffd8b9453
|
||||
F src/vdbeapi.c 8d5013ab6104be757c208a70ffb191cc27d2b688
|
||||
F src/vdbeaux.c ea6d2f215a6a77a77882719ff23a757437e2cbcd
|
||||
F src/vdbeaux.c ec1545ece73dd739c9043f14963fb3f20d3880d6
|
||||
F src/vdbeblob.c f93cb60ac388633ed3bde8a94ef161ad2dbfb689
|
||||
F src/vdbemem.c dc551981833756ea34a3e0b238f759479e7cf526
|
||||
F src/vtab.c 3e54fe39374e5feb8b174de32a90e7a21966025d
|
||||
@ -753,14 +753,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P ecbe0832be77599c7cc66fb9968d0f419000d231
|
||||
R d34c486626a8ce5a53145ee9d825c061
|
||||
P d7dc8b433691745b3842282569f1573d1e057963
|
||||
R 9e0da6af96f3821c9fbb99c40116f7d0
|
||||
U drh
|
||||
Z c32d324c29421eb9787794c39572ee17
|
||||
Z 49ac72c18b4c2aedd979564a1a2e66cc
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFKpU1toxKgR168RlERAiq6AJ9XuXc0u1hWnpGpmA/epzDAzopjbQCeJgNH
|
||||
Khw73UH7YVrOiFFOVF+gTAk=
|
||||
=8PSG
|
||||
iD8DBQFKpbAMoxKgR168RlERAh/DAJ4q07I078rtqsLLizRq8qQzLiSLlQCfUo1D
|
||||
jfuHFqkXs2sHSUl8rZ5owsY=
|
||||
=1zOu
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -1 +1 @@
|
||||
d7dc8b433691745b3842282569f1573d1e057963
|
||||
52449a9569b7142095cc88ee208b31cc59a3cab4
|
@ -128,7 +128,7 @@ void sqlite3AuthRead(
|
||||
pTab = pParse->pTriggerTab;
|
||||
}else{
|
||||
assert( pTabList );
|
||||
for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
|
||||
for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
|
||||
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
|
||||
pTab = pTabList->a[iSrc].pTab;
|
||||
break;
|
||||
|
@ -6420,8 +6420,10 @@ static int balance(BtCursor *pCur){
|
||||
** a positive value if pCur points at an etry that is larger than
|
||||
** (pKey, nKey)).
|
||||
**
|
||||
** If the seekResult parameter is 0, then cursor pCur may point to any
|
||||
** entry or to no entry at all. In this case this function has to seek
|
||||
** If the seekResult parameter is non-zero, then the caller guarantees that
|
||||
** cursor pCur is pointing at the existing copy of a row that is to be
|
||||
** overwritten. If the seekResult parameter is 0, then cursor pCur may
|
||||
** point to any entry or to no entry at all and so this function has to seek
|
||||
** the cursor before the new key can be inserted.
|
||||
*/
|
||||
int sqlite3BtreeInsert(
|
||||
@ -6433,7 +6435,7 @@ int sqlite3BtreeInsert(
|
||||
int seekResult /* Result of prior MovetoUnpacked() call */
|
||||
){
|
||||
int rc;
|
||||
int loc = seekResult;
|
||||
int loc = seekResult; /* -1: before desired location +1: after */
|
||||
int szNew;
|
||||
int idx;
|
||||
MemPage *pPage;
|
||||
|
13
src/select.c
13
src/select.c
@ -766,14 +766,16 @@ static void generateSortTail(
|
||||
int regRowid;
|
||||
|
||||
iTab = pOrderBy->iECursor;
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
|
||||
pseudoTab = pParse->nTab++;
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output, nColumn);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
|
||||
regRowid = 0;
|
||||
}else{
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
}
|
||||
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
|
||||
codeOffset(v, p, addrContinue);
|
||||
regRow = sqlite3GetTempReg(pParse);
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
|
||||
switch( eDest ){
|
||||
case SRT_Table:
|
||||
@ -805,11 +807,12 @@ static void generateSortTail(
|
||||
assert( eDest==SRT_Output || eDest==SRT_Coroutine );
|
||||
testcase( eDest==SRT_Output );
|
||||
testcase( eDest==SRT_Coroutine );
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid);
|
||||
for(i=0; i<nColumn; i++){
|
||||
assert( regRow!=pDest->iMem+i );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
|
||||
if( i==0 ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
|
||||
}
|
||||
}
|
||||
if( eDest==SRT_Output ){
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
|
||||
|
@ -2161,11 +2161,12 @@ struct AuthContext {
|
||||
/*
|
||||
** Bitfield flags for P5 value in OP_Insert and OP_Delete
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 1 /* Set to update db->nChange */
|
||||
#define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */
|
||||
#define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */
|
||||
#define OPFLAG_APPEND 8 /* This is likely to be an append */
|
||||
#define OPFLAG_USESEEKRESULT 16 /* Try to avoid a seek in BtreeInsert() */
|
||||
#define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */
|
||||
#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
|
||||
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
|
||||
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
|
||||
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
|
||||
#define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */
|
||||
|
||||
/*
|
||||
* Each trigger present in the database schema is stored as an instance of
|
||||
|
156
src/vdbe.c
156
src/vdbe.c
@ -189,7 +189,7 @@ static VdbeCursor *allocateCursor(
|
||||
int iCur, /* Index of the new VdbeCursor */
|
||||
int nField, /* Number of fields in the table or index */
|
||||
int iDb, /* When database the cursor belongs to, or -1 */
|
||||
int isBtreeCursor /* True for B-Tree vs. pseudo-table or vtab */
|
||||
int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */
|
||||
){
|
||||
/* Find the memory cell that will be used to store the blob of memory
|
||||
** required for this VdbeCursor structure. It is convenient to use a
|
||||
@ -1975,29 +1975,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SetNumColumns * P2 * * *
|
||||
**
|
||||
** This opcode sets the number of columns for the cursor opened by the
|
||||
** following instruction to P2.
|
||||
**
|
||||
** An OP_SetNumColumns is only useful if it occurs immediately before
|
||||
** one of the following opcodes:
|
||||
**
|
||||
** OpenRead
|
||||
** OpenWrite
|
||||
** OpenPseudo
|
||||
**
|
||||
** If the OP_Column opcode is to be executed on a cursor, then
|
||||
** this opcode must be present immediately before the opcode that
|
||||
** opens the cursor.
|
||||
*/
|
||||
#if 0
|
||||
case OP_SetNumColumns: {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: Column P1 P2 P3 P4 *
|
||||
/* Opcode: Column P1 P2 P3 P4 P5
|
||||
**
|
||||
** Interpret the data that cursor P1 points to as a structure built using
|
||||
** the MakeRecord instruction. (See the MakeRecord opcode for additional
|
||||
@ -2010,6 +1988,11 @@ case OP_SetNumColumns: {
|
||||
** If the column contains fewer than P2 fields, then extract a NULL. Or,
|
||||
** if the P4 argument is a P4_MEM use the value of the P4 argument as
|
||||
** the result.
|
||||
**
|
||||
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
|
||||
** then the cache of the cursor is reset prior to extracting the column.
|
||||
** The first OP_Column against a pseudo-table after the value of the content
|
||||
** register has changed should have this bit set.
|
||||
*/
|
||||
case OP_Column: {
|
||||
u32 payloadSize; /* Number of bytes in the record */
|
||||
@ -2033,6 +2016,7 @@ case OP_Column: {
|
||||
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
|
||||
int szHdr; /* Size of the header size field at start of record */
|
||||
int avail; /* Number of bytes of available data */
|
||||
Mem *pReg; /* PseudoTable input register */
|
||||
|
||||
|
||||
p1 = pOp->p1;
|
||||
@ -2086,11 +2070,12 @@ case OP_Column: {
|
||||
rc = sqlite3BtreeDataSize(pCrsr, &payloadSize);
|
||||
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
|
||||
}
|
||||
}else if( pC->pseudoTable ){
|
||||
/* The record is the sole entry of a pseudo-table */
|
||||
payloadSize = pC->nData;
|
||||
zRec = pC->pData;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}else if( pC->pseudoTableReg>0 ){
|
||||
pReg = &p->aMem[pC->pseudoTableReg];
|
||||
assert( pReg->flags & MEM_Blob );
|
||||
payloadSize = pReg->n;
|
||||
zRec = pReg->z;
|
||||
pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
|
||||
assert( payloadSize==0 || zRec!=0 );
|
||||
}else{
|
||||
/* Consider the row to be NULL */
|
||||
@ -3067,22 +3052,14 @@ case OP_OpenEphemeral: {
|
||||
/* Opcode: OpenPseudo P1 P2 P3 * *
|
||||
**
|
||||
** Open a new cursor that points to a fake table that contains a single
|
||||
** row of data. Any attempt to write a second row of data causes the
|
||||
** first row to be deleted. All data is deleted when the cursor is
|
||||
** closed.
|
||||
** row of data. The content of that one row in the content of memory
|
||||
** register P2. In other words, cursor P1 becomes an alias for the
|
||||
** MEM_Blob content contained in register P2.
|
||||
**
|
||||
** A pseudo-table created by this opcode is useful for holding the
|
||||
** NEW or OLD tables in a trigger. Also used to hold the a single
|
||||
** A pseudo-table created by this opcode is used to hold the a single
|
||||
** row output from the sorter so that the row can be decomposed into
|
||||
** individual columns using the OP_Column opcode.
|
||||
**
|
||||
** When OP_Insert is executed to insert a row in to the pseudo table,
|
||||
** the pseudo-table cursor may or may not make it's own copy of the
|
||||
** original row data. If P2 is 0, then the pseudo-table will copy the
|
||||
** original row data. Otherwise, a pointer to the original memory cell
|
||||
** is stored. In this case, the vdbe program must ensure that the
|
||||
** memory cell containing the row data is not overwritten until the
|
||||
** pseudo table is closed (or a new row is inserted into it).
|
||||
** individual columns using the OP_Column opcode. The OP_Column opcode
|
||||
** is the only cursor opcode that works with a pseudo-table.
|
||||
**
|
||||
** P3 is the number of fields in the records that will be stored by
|
||||
** the pseudo-table.
|
||||
@ -3094,8 +3071,7 @@ case OP_OpenPseudo: {
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->nullRow = 1;
|
||||
pCx->pseudoTable = 1;
|
||||
pCx->ephemPseudoTable = (u8)pOp->p2;
|
||||
pCx->pseudoTableReg = pOp->p2;
|
||||
pCx->isTable = 1;
|
||||
pCx->isIndex = 0;
|
||||
break;
|
||||
@ -3180,6 +3156,7 @@ case OP_SeekGt: { /* jump, in3 */
|
||||
assert( pOp->p2!=0 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
if( pC->pCursor!=0 ){
|
||||
oc = pOp->opcode;
|
||||
pC->nullRow = 0;
|
||||
@ -3293,7 +3270,6 @@ case OP_SeekGt: { /* jump, in3 */
|
||||
** for read access returns SQLITE_EMPTY. In this case always
|
||||
** take the jump (since there are no records in the table).
|
||||
*/
|
||||
assert( pC->pseudoTable==0 );
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
break;
|
||||
@ -3504,6 +3480,7 @@ case OP_NotExists: { /* jump, in3 */
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->isTable );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
pCrsr = pC->pCursor;
|
||||
if( pCrsr!=0 ){
|
||||
res = 0;
|
||||
@ -3523,8 +3500,6 @@ case OP_NotExists: { /* jump, in3 */
|
||||
/* This happens when an attempt to open a read cursor on the
|
||||
** sqlite_master table returns SQLITE_EMPTY.
|
||||
*/
|
||||
assert( !pC->pseudoTable );
|
||||
assert( pC->isTable );
|
||||
pc = pOp->p2 - 1;
|
||||
assert( pC->rowidIsValid==0 );
|
||||
pC->seekResult = 0;
|
||||
@ -3685,15 +3660,28 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
**
|
||||
** Write an entry into the table of cursor P1. A new entry is
|
||||
** created if it doesn't already exist or the data for an existing
|
||||
** entry is overwritten. The data is the value stored register
|
||||
** entry is overwritten. The data is the value MEM_Blob stored in register
|
||||
** number P2. The key is stored in register P3. The key must
|
||||
** be an integer.
|
||||
** be a MEM_Int.
|
||||
**
|
||||
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
|
||||
** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P5 is set,
|
||||
** then rowid is stored for subsequent return by the
|
||||
** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
|
||||
**
|
||||
** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
|
||||
** the last seek operation (OP_NotExists) was a success, then this
|
||||
** operation will not attempt to find the appropriate row before doing
|
||||
** the insert but will instead overwrite the row that the cursor is
|
||||
** currently pointing to. Presumably, the prior OP_NotExists opcode
|
||||
** has already positioned the cursor correctly. This is an optimization
|
||||
** that boosts performance by avoiding redundant seeks.
|
||||
**
|
||||
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
|
||||
** UPDATE operation. Otherwise (if the flag is clear) then this opcode
|
||||
** is part of an INSERT operation. The difference is only important to
|
||||
** the update hook.
|
||||
**
|
||||
** Parameter P4 may point to a string containing the table-name, or
|
||||
** may be NULL. If it is not NULL, then the update-hook
|
||||
** (sqlite3.xUpdateCallback) is invoked following a successful insert.
|
||||
@ -3708,22 +3696,23 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
** for indices is OP_IdxInsert.
|
||||
*/
|
||||
case OP_Insert: {
|
||||
Mem *pData;
|
||||
Mem *pKey;
|
||||
i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
||||
VdbeCursor *pC;
|
||||
int nZero;
|
||||
int seekResult;
|
||||
const char *zDb;
|
||||
const char *zTbl;
|
||||
int op;
|
||||
Mem *pData; /* MEM cell holding data for the record to be inserted */
|
||||
Mem *pKey; /* MEM cell holding key for the record */
|
||||
i64 iKey; /* The integer ROWID or key for the record to be inserted */
|
||||
VdbeCursor *pC; /* Cursor to table into which insert is written */
|
||||
int nZero; /* Number of zero-bytes to append */
|
||||
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
|
||||
const char *zDb; /* database name - used by the update hook */
|
||||
const char *zTbl; /* Table name - used by the opdate hook */
|
||||
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
|
||||
|
||||
pData = &p->aMem[pOp->p2];
|
||||
pKey = &p->aMem[pOp->p3];
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->pCursor!=0 || pC->pseudoTable );
|
||||
assert( pC->pCursor!=0 );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
assert( pKey->flags & MEM_Int );
|
||||
assert( pC->isTable );
|
||||
REGISTER_TRACE(pOp->p2, pData);
|
||||
@ -3738,41 +3727,17 @@ case OP_Insert: {
|
||||
}else{
|
||||
assert( pData->flags & (MEM_Blob|MEM_Str) );
|
||||
}
|
||||
if( pC->pseudoTable ){
|
||||
if( !pC->ephemPseudoTable ){
|
||||
sqlite3DbFree(db, pC->pData);
|
||||
}
|
||||
pC->iKey = iKey;
|
||||
pC->nData = pData->n;
|
||||
if( pC->ephemPseudoTable || pData->z==pData->zMalloc ){
|
||||
pC->pData = pData->z;
|
||||
if( !pC->ephemPseudoTable ){
|
||||
pData->flags &= ~MEM_Dyn;
|
||||
pData->flags |= MEM_Ephem;
|
||||
pData->zMalloc = 0;
|
||||
}
|
||||
}else{
|
||||
pC->pData = sqlite3Malloc( pC->nData+2 );
|
||||
if( !pC->pData ) goto no_mem;
|
||||
memcpy(pC->pData, pData->z, pC->nData);
|
||||
pC->pData[pC->nData] = 0;
|
||||
pC->pData[pC->nData+1] = 0;
|
||||
}
|
||||
pC->nullRow = 0;
|
||||
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
|
||||
if( pData->flags & MEM_Zero ){
|
||||
nZero = pData->u.nZero;
|
||||
}else{
|
||||
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
|
||||
if( pData->flags & MEM_Zero ){
|
||||
nZero = pData->u.nZero;
|
||||
}else{
|
||||
nZero = 0;
|
||||
}
|
||||
sqlite3BtreeSetCachedRowid(pC->pCursor, 0);
|
||||
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
|
||||
pData->z, pData->n, nZero,
|
||||
pOp->p5 & OPFLAG_APPEND, seekResult
|
||||
);
|
||||
nZero = 0;
|
||||
}
|
||||
|
||||
sqlite3BtreeSetCachedRowid(pC->pCursor, 0);
|
||||
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
|
||||
pData->z, pData->n, nZero,
|
||||
pOp->p5 & OPFLAG_APPEND, seekResult
|
||||
);
|
||||
pC->rowidIsValid = 0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
@ -3905,7 +3870,7 @@ case OP_RowData: {
|
||||
assert( pC->isIndex || pOp->opcode==OP_RowData );
|
||||
assert( pC!=0 );
|
||||
assert( pC->nullRow==0 );
|
||||
assert( pC->pseudoTable==0 );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
assert( pC->pCursor!=0 );
|
||||
pCrsr = pC->pCursor;
|
||||
assert( sqlite3BtreeCursorIsValid(pCrsr) );
|
||||
@ -3967,13 +3932,12 @@ case OP_Rowid: { /* out2-prerelease */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
if( pC->nullRow ){
|
||||
/* Do nothing so that reg[P2] remains NULL */
|
||||
break;
|
||||
}else if( pC->deferredMoveto ){
|
||||
v = pC->movetoTarget;
|
||||
}else if( pC->pseudoTable ){
|
||||
v = pC->iKey;
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
}else if( pC->pVtabCursor ){
|
||||
pVtab = pC->pVtabCursor->pVtab;
|
||||
|
@ -56,16 +56,12 @@ struct VdbeCursor {
|
||||
Bool atFirst; /* True if pointing to first entry */
|
||||
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
|
||||
Bool nullRow; /* True if pointing to a row with no data */
|
||||
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
|
||||
Bool ephemPseudoTable;
|
||||
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
|
||||
Bool isTable; /* True if a table requiring integer keys */
|
||||
Bool isIndex; /* True if an index containing keys only - no data */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
Btree *pBt; /* Separate file holding temporary table */
|
||||
int nData; /* Number of bytes in pData */
|
||||
char *pData; /* Data for a NEW or OLD pseudo-table */
|
||||
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
|
||||
int pseudoTableReg; /* Register holding pseudotable content. */
|
||||
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
|
||||
int nField; /* Number of fields in the header */
|
||||
i64 seqCount; /* Sequence counter */
|
||||
@ -77,11 +73,15 @@ struct VdbeCursor {
|
||||
int seekResult;
|
||||
|
||||
/* Cached information about the header for the data record that the
|
||||
** cursor is currently pointing to. Only valid if cacheValid is true.
|
||||
** cursor is currently pointing to. Only valid if cacheStatus matches
|
||||
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
|
||||
** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
|
||||
** the cache is out of date.
|
||||
**
|
||||
** aRow might point to (ephemeral) data for the current row, or it might
|
||||
** be NULL.
|
||||
*/
|
||||
int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
|
||||
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
|
||||
int payloadSize; /* Total number of bytes in the record */
|
||||
u32 *aType; /* Type values for all entries in the record */
|
||||
u32 *aOffset; /* Cached offsets to the start of each columns data */
|
||||
@ -296,7 +296,7 @@ struct Vdbe {
|
||||
u32 magic; /* Magic number for sanity checking */
|
||||
int nMem; /* Number of memory locations currently allocated */
|
||||
Mem *aMem; /* The memory locations */
|
||||
int cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
char *zErrMsg; /* Error message written here */
|
||||
|
@ -1365,9 +1365,6 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
||||
p->inVtabMethod = 0;
|
||||
}
|
||||
#endif
|
||||
if( !pCx->ephemPseudoTable ){
|
||||
sqlite3DbFree(p->db, pCx->pData);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user