mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Modify the {quote: IdxDelete} opcode so that it takes an array of registers rather
than a record formed using {quote: MakeRecord.} This avoids a needless packing and unpacking of the record to be deleted. (CVS 4916) FossilOrigin-Name: ee381b43563e1b0637ee74389d076dff77deddf9
This commit is contained in:
36
manifest
36
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Test\sstring\svalues\spassed\sto\sbind_text()\sand\sresult_text()\sfor\sa\snul-terminator.\s(CVS\s4915)
|
C Modify\sthe\s{quote:\sIdxDelete}\sopcode\sso\sthat\sit\stakes\san\sarray\sof\sregisters\srather\r\nthan\sa\srecord\sformed\susing\s{quote:\sMakeRecord.}\s\sThis\savoids\sa\sneedless\spacking\r\nand\sunpacking\sof\sthe\srecord\sto\sbe\sdeleted.\s(CVS\s4916)
|
||||||
D 2008-03-25T16:16:29
|
D 2008-03-25T17:23:33
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
|
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -86,14 +86,14 @@ F src/attach.c bdc75e759ca25a16f4dc7fbdbc6d37ad2561bb24
|
|||||||
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
|
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
|
||||||
F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2
|
F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2
|
||||||
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
|
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
|
||||||
F src/btree.c 366f5f66ebb3dfdc8513242d4aecbfb402dcc0a9
|
F src/btree.c 6e60d634d236232efbb289b800dd76e72a5ecf9d
|
||||||
F src/btree.h e02869e1e7753ad5b3c7cb7852e952c95c2e609a
|
F src/btree.h c66cb17c6fffa84a88926dbef173bab4ae692fd4
|
||||||
F src/btreeInt.h d232be68a7ab2a24376dc6332a869e717551b0bd
|
F src/btreeInt.h d232be68a7ab2a24376dc6332a869e717551b0bd
|
||||||
F src/build.c d0715b3454b140cb405412e3029ec7c0fb434efd
|
F src/build.c 4e6321d112f0ed1070c579677573e4eb76cda1fd
|
||||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||||
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||||
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
|
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
|
||||||
F src/delete.c 526b783b71b9885b201d74720d44a386b971dc01
|
F src/delete.c 3dc7d7cc46c8675219a7776b7c67b626bba530df
|
||||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||||
F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88
|
F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88
|
||||||
F src/fault.c c28478c7190daef16be09d261c5461638b4d686c
|
F src/fault.c c28478c7190daef16be09d261c5461638b4d686c
|
||||||
@@ -131,22 +131,22 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
|||||||
F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4
|
F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4
|
||||||
F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
|
F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
|
||||||
F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
|
F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
|
||||||
F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2
|
F src/pragma.c 99cec6d99d0241436494aab15b05da97b0e70683
|
||||||
F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c
|
F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c
|
||||||
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
|
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
|
||||||
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
|
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
|
||||||
F src/select.c c06849a0d0ad408fbdd8180439176e94aae43e56
|
F src/select.c 831714d4f09f4b9f4be43d2399eff12dcf281c86
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
|
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
|
||||||
F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335
|
F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335
|
||||||
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
||||||
F src/sqliteInt.h 07b472437b2d7297c300f8b7cea5205984fa64d1
|
F src/sqliteInt.h 50a9313829041721d34f20c8be4562c3197dcff9
|
||||||
F src/sqliteLimit.h eecbc288b410ae5565e71aaa4a439aae57bb0707
|
F src/sqliteLimit.h eecbc288b410ae5565e71aaa4a439aae57bb0707
|
||||||
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
||||||
F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
|
F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
|
||||||
F src/test1.c 342a2628310fa709074d979e695a28a3bb570834
|
F src/test1.c 342a2628310fa709074d979e695a28a3bb570834
|
||||||
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
|
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
|
||||||
F src/test3.c 31027a4a190d2f3c1e479ea2d750e696160bbf04
|
F src/test3.c c715b5a8a6415d7b2c67f97c394eef488b6f7e63
|
||||||
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
||||||
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
||||||
F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05
|
F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05
|
||||||
@@ -174,11 +174,11 @@ F src/update.c 2aefd3c9277792e9fa2414dfe14202119fa49fe7
|
|||||||
F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
|
F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
|
||||||
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
|
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
|
||||||
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
||||||
F src/vdbe.c bdcbf54cf944a99b004e87a523736dd326fa34be
|
F src/vdbe.c 0068703495a197e7b77dbdff604b42896722a1cc
|
||||||
F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f
|
F src/vdbe.h ecca2e1c1ac1066f4e68ad38068a20ea32ea7063
|
||||||
F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919
|
F src/vdbeInt.h 4d767f189a1d13ff8d4881de60aacc470e54f5b8
|
||||||
F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817
|
F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817
|
||||||
F src/vdbeaux.c c071014d81c1d4b2c381247c16a3e86182951e51
|
F src/vdbeaux.c e45929a3b5e59e8f2d69b7d6164c9a636149e1df
|
||||||
F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
||||||
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
||||||
F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af
|
F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af
|
||||||
@@ -617,7 +617,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P fe1bc0f3b7cd87cd65f7d03b91095b59788a6f8d
|
P 24c3ebc0c5c53c234516d16dce761d713fb29578
|
||||||
R 033bb4545035899c2c5396ecb143bb5f
|
R 66dfc33f9c0d1eba54064363b17cc27e
|
||||||
U danielk1977
|
U drh
|
||||||
Z 09f5af34fae3a95557976f8d7d3936e3
|
Z 040d5190ae2e9926a42f3065a9864529
|
||||||
|
@@ -1 +1 @@
|
|||||||
24c3ebc0c5c53c234516d16dce761d713fb29578
|
ee381b43563e1b0637ee74389d076dff77deddf9
|
50
src/btree.c
50
src/btree.c
@@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.446 2008/03/25 14:24:57 danielk1977 Exp $
|
** $Id: btree.c,v 1.447 2008/03/25 17:23:33 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** See the header comment on "btreeInt.h" for additional information.
|
** See the header comment on "btreeInt.h" for additional information.
|
||||||
@@ -379,7 +379,7 @@ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pCur->eState = CURSOR_INVALID;
|
pCur->eState = CURSOR_INVALID;
|
||||||
rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
|
rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
sqlite3_free(pCur->pKey);
|
sqlite3_free(pCur->pKey);
|
||||||
pCur->pKey = 0;
|
pCur->pKey = 0;
|
||||||
@@ -3548,12 +3548,13 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move the cursor so that it points to an entry near pKey/nKey.
|
/* Move the cursor so that it points to an entry near the key
|
||||||
** Return a success code.
|
** specified by pKey/nKey/pUnKey. Return a success code.
|
||||||
**
|
**
|
||||||
** For INTKEY tables, only the nKey parameter is used. pKey is
|
** For INTKEY tables, only the nKey parameter is used. pKey
|
||||||
** ignored. For other tables, nKey is the number of bytes of data
|
** and pUnKey must be NULL. For index tables, either pUnKey
|
||||||
** in pKey.
|
** must point to a key that has already been unpacked, or else
|
||||||
|
** pKey/nKey describes a blob containing the key.
|
||||||
**
|
**
|
||||||
** If an exact match is not found, then the cursor is always
|
** If an exact match is not found, then the cursor is always
|
||||||
** left pointing at a leaf page which would hold the entry if it
|
** left pointing at a leaf page which would hold the entry if it
|
||||||
@@ -3578,12 +3579,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
|||||||
int sqlite3BtreeMoveto(
|
int sqlite3BtreeMoveto(
|
||||||
BtCursor *pCur, /* The cursor to be moved */
|
BtCursor *pCur, /* The cursor to be moved */
|
||||||
const void *pKey, /* The key content for indices. Not used by tables */
|
const void *pKey, /* The key content for indices. Not used by tables */
|
||||||
|
UnpackedRecord *pUnKey,/* Unpacked version of pKey */
|
||||||
i64 nKey, /* Size of pKey. Or the key for tables */
|
i64 nKey, /* Size of pKey. Or the key for tables */
|
||||||
int biasRight, /* If true, bias the search to the high end */
|
int biasRight, /* If true, bias the search to the high end */
|
||||||
int *pRes /* Search result flag */
|
int *pRes /* Search result flag */
|
||||||
){
|
){
|
||||||
int rc;
|
int rc;
|
||||||
VdbeParsedRecord *pPKey;
|
|
||||||
char aSpace[200];
|
char aSpace[200];
|
||||||
|
|
||||||
assert( cursorHoldsMutex(pCur) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
@@ -3600,11 +3601,22 @@ int sqlite3BtreeMoveto(
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
if( pCur->pPage->intKey ){
|
if( pCur->pPage->intKey ){
|
||||||
pPKey = 0;
|
/* We are given an SQL table to search. The key is the integer
|
||||||
}else{
|
** rowid contained in nKey. pKey and pUnKey should both be NULL */
|
||||||
pPKey = sqlite3VdbeRecordParse(pCur->pKeyInfo, nKey, pKey,
|
assert( pUnKey==0 );
|
||||||
|
assert( pKey==0 );
|
||||||
|
}else if( pUnKey==0 ){
|
||||||
|
/* We are to search an SQL index using a key encoded as a blob.
|
||||||
|
** The blob is found at pKey and is nKey bytes in length. Unpack
|
||||||
|
** this key so that we can use it. */
|
||||||
|
assert( pKey!=0 );
|
||||||
|
pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
|
||||||
aSpace, sizeof(aSpace));
|
aSpace, sizeof(aSpace));
|
||||||
if( pPKey==0 ) return SQLITE_NOMEM;
|
if( pUnKey==0 ) return SQLITE_NOMEM;
|
||||||
|
}else{
|
||||||
|
/* We are to search an SQL index using a key that is already unpacked
|
||||||
|
** and handed to us in pUnKey. */
|
||||||
|
assert( pKey==0 );
|
||||||
}
|
}
|
||||||
for(;;){
|
for(;;){
|
||||||
int lwr, upr;
|
int lwr, upr;
|
||||||
@@ -3613,7 +3625,7 @@ int sqlite3BtreeMoveto(
|
|||||||
int c = -1; /* pRes return if table is empty must be -1 */
|
int c = -1; /* pRes return if table is empty must be -1 */
|
||||||
lwr = 0;
|
lwr = 0;
|
||||||
upr = pPage->nCell-1;
|
upr = pPage->nCell-1;
|
||||||
if( !pPage->intKey && pKey==0 ){
|
if( !pPage->intKey && pUnKey==0 ){
|
||||||
rc = SQLITE_CORRUPT_BKPT;
|
rc = SQLITE_CORRUPT_BKPT;
|
||||||
goto moveto_finish;
|
goto moveto_finish;
|
||||||
}
|
}
|
||||||
@@ -3646,7 +3658,7 @@ int sqlite3BtreeMoveto(
|
|||||||
pCellKey = (void *)fetchPayload(pCur, &available, 0);
|
pCellKey = (void *)fetchPayload(pCur, &available, 0);
|
||||||
nCellKey = pCur->info.nKey;
|
nCellKey = pCur->info.nKey;
|
||||||
if( available>=nCellKey ){
|
if( available>=nCellKey ){
|
||||||
c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
|
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
|
||||||
}else{
|
}else{
|
||||||
pCellKey = sqlite3_malloc( nCellKey );
|
pCellKey = sqlite3_malloc( nCellKey );
|
||||||
if( pCellKey==0 ){
|
if( pCellKey==0 ){
|
||||||
@@ -3654,7 +3666,7 @@ int sqlite3BtreeMoveto(
|
|||||||
goto moveto_finish;
|
goto moveto_finish;
|
||||||
}
|
}
|
||||||
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
|
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
|
||||||
c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
|
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
|
||||||
sqlite3_free(pCellKey);
|
sqlite3_free(pCellKey);
|
||||||
if( rc ) goto moveto_finish;
|
if( rc ) goto moveto_finish;
|
||||||
}
|
}
|
||||||
@@ -3701,7 +3713,11 @@ int sqlite3BtreeMoveto(
|
|||||||
if( rc ) goto moveto_finish;
|
if( rc ) goto moveto_finish;
|
||||||
}
|
}
|
||||||
moveto_finish:
|
moveto_finish:
|
||||||
sqlite3VdbeRecordUnparse(pPKey);
|
if( pKey ){
|
||||||
|
/* If we created our own unpacked key at the top of this
|
||||||
|
** procedure, then destroy that key before returning. */
|
||||||
|
sqlite3VdbeDeleteUnpackedRecord(pUnKey);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5619,7 +5635,7 @@ int sqlite3BtreeInsert(
|
|||||||
clearCursorPosition(pCur);
|
clearCursorPosition(pCur);
|
||||||
if(
|
if(
|
||||||
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
|
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
|
||||||
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
|
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
|
||||||
){
|
){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
13
src/btree.h
13
src/btree.h
@@ -13,7 +13,7 @@
|
|||||||
** subsystem. See comments in the source code for a detailed description
|
** subsystem. See comments in the source code for a detailed description
|
||||||
** of what each interface routine does.
|
** of what each interface routine does.
|
||||||
**
|
**
|
||||||
** @(#) $Id: btree.h,v 1.96 2008/03/25 09:47:35 danielk1977 Exp $
|
** @(#) $Id: btree.h,v 1.97 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@@ -127,6 +127,8 @@ int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
|
|||||||
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||||
void sqlite3BtreeTripAllCursors(Btree*, int);
|
void sqlite3BtreeTripAllCursors(Btree*, int);
|
||||||
|
|
||||||
|
struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */
|
||||||
|
|
||||||
int sqlite3BtreeCursor(
|
int sqlite3BtreeCursor(
|
||||||
Btree*, /* BTree containing table to open */
|
Btree*, /* BTree containing table to open */
|
||||||
int iTable, /* Index of root page */
|
int iTable, /* Index of root page */
|
||||||
@@ -137,7 +139,14 @@ int sqlite3BtreeCursor(
|
|||||||
int sqlite3BtreeCursorSize();
|
int sqlite3BtreeCursorSize();
|
||||||
|
|
||||||
int sqlite3BtreeCloseCursor(BtCursor*);
|
int sqlite3BtreeCloseCursor(BtCursor*);
|
||||||
int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes);
|
int sqlite3BtreeMoveto(
|
||||||
|
BtCursor*,
|
||||||
|
const void *pKey,
|
||||||
|
struct UnpackedRecord *pUnKey,
|
||||||
|
i64 nKey,
|
||||||
|
int bias,
|
||||||
|
int *pRes
|
||||||
|
);
|
||||||
int sqlite3BtreeDelete(BtCursor*);
|
int sqlite3BtreeDelete(BtCursor*);
|
||||||
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
||||||
const void *pData, int nData,
|
const void *pData, int nData,
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.476 2008/03/25 09:47:35 danielk1977 Exp $
|
** $Id: build.c,v 1.477 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -2278,7 +2278,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
|||||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
||||||
regRecord = sqlite3GetTempReg(pParse);
|
regRecord = sqlite3GetTempReg(pParse);
|
||||||
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord);
|
regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
|
||||||
if( pIndex->onError!=OE_None ){
|
if( pIndex->onError!=OE_None ){
|
||||||
int j1, j2;
|
int j1, j2;
|
||||||
int regRowid;
|
int regRowid;
|
||||||
|
21
src/delete.c
21
src/delete.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** in order to generate code for DELETE FROM statements.
|
** in order to generate code for DELETE FROM statements.
|
||||||
**
|
**
|
||||||
** $Id: delete.c,v 1.163 2008/03/25 09:47:35 danielk1977 Exp $
|
** $Id: delete.c,v 1.164 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -488,18 +488,16 @@ void sqlite3GenerateRowIndexDelete(
|
|||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
int r1;
|
int r1;
|
||||||
|
|
||||||
r1 = sqlite3GetTempReg(pParse);
|
|
||||||
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||||
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
|
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
|
||||||
sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1);
|
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1, 0);
|
||||||
sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1);
|
sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
|
||||||
}
|
}
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code that will assemble an index key and put it on the top
|
** Generate code that will assemble an index key and put it in register
|
||||||
** of the tack. The key with be for index pIdx which is an index on pTab.
|
** regOut. The key with be for index pIdx which is an index on pTab.
|
||||||
** iCur is the index of a cursor open on the pTab table and pointing to
|
** iCur is the index of a cursor open on the pTab table and pointing to
|
||||||
** the entry that needs indexing.
|
** the entry that needs indexing.
|
||||||
**
|
**
|
||||||
@@ -512,7 +510,8 @@ int sqlite3GenerateIndexKey(
|
|||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
Index *pIdx, /* The index for which to generate a key */
|
Index *pIdx, /* The index for which to generate a key */
|
||||||
int iCur, /* Cursor number for the pIdx->pTable table */
|
int iCur, /* Cursor number for the pIdx->pTable table */
|
||||||
int regOut /* Write the new index key to this register */
|
int regOut, /* Write the new index key to this register */
|
||||||
|
int doMakeRec /* Run the OP_MakeRecord instruction if true */
|
||||||
){
|
){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int j;
|
int j;
|
||||||
@@ -532,8 +531,10 @@ int sqlite3GenerateIndexKey(
|
|||||||
sqlite3ColumnDefault(v, pTab, idx);
|
sqlite3ColumnDefault(v, pTab, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
if( doMakeRec ){
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
||||||
|
sqlite3IndexAffinityStr(v, pIdx);
|
||||||
|
}
|
||||||
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
||||||
return regBase;
|
return regBase;
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code used to implement the PRAGMA command.
|
** This file contains code used to implement the PRAGMA command.
|
||||||
**
|
**
|
||||||
** $Id: pragma.c,v 1.172 2008/03/20 11:04:21 danielk1977 Exp $
|
** $Id: pragma.c,v 1.173 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -941,7 +941,7 @@ void sqlite3Pragma(
|
|||||||
{ OP_IfPos, 1, 0, 0}, /* 9 */
|
{ OP_IfPos, 1, 0, 0}, /* 9 */
|
||||||
{ OP_Halt, 0, 0, 0},
|
{ OP_Halt, 0, 0, 0},
|
||||||
};
|
};
|
||||||
sqlite3GenerateIndexKey(pParse, pIdx, 1, 3);
|
sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1);
|
||||||
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
|
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
|
||||||
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
||||||
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
|
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.418 2008/03/25 09:47:35 danielk1977 Exp $
|
** $Id: select.c,v 1.419 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -598,12 +598,7 @@ static void selectInnerLoop(
|
|||||||
** the temporary table iParm.
|
** the temporary table iParm.
|
||||||
*/
|
*/
|
||||||
case SRT_Except: {
|
case SRT_Except: {
|
||||||
int r1;
|
sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
|
||||||
r1 = sqlite3GetTempReg(pParse);
|
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
|
||||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1);
|
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.679 2008/03/21 16:45:47 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.680 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1863,7 +1863,7 @@ int sqlite3ExprIsInteger(Expr*, int*);
|
|||||||
int sqlite3IsRowid(const char*);
|
int sqlite3IsRowid(const char*);
|
||||||
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
|
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
|
||||||
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
|
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
|
||||||
int sqlite3GenerateIndexKey(Parse*, Index*, int, int);
|
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
|
||||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
|
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
|
||||||
int*,int,int,int,int);
|
int*,int,int,int,int);
|
||||||
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int);
|
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int);
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test3.c,v 1.93 2008/03/25 09:47:35 danielk1977 Exp $
|
** $Id: test3.c,v 1.94 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "btreeInt.h"
|
#include "btreeInt.h"
|
||||||
@@ -788,9 +788,9 @@ static int btree_move_to(
|
|||||||
sqlite3BtreeLeave(pCur->pBtree);
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
|
rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res);
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
|
rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res);
|
||||||
}
|
}
|
||||||
sqlite3BtreeLeave(pCur->pBtree);
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
|
33
src/vdbe.c
33
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** commenting and indentation practices when changing or adding code.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.717 2008/03/25 09:47:35 danielk1977 Exp $
|
** $Id: vdbe.c,v 1.718 2008/03/25 17:23:33 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -2794,7 +2794,7 @@ case OP_MoveGt: { /* jump, in3 */
|
|||||||
pC->deferredMoveto = 1;
|
pC->deferredMoveto = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
|
rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto abort_due_to_error;
|
goto abort_due_to_error;
|
||||||
}
|
}
|
||||||
@@ -2803,7 +2803,7 @@ case OP_MoveGt: { /* jump, in3 */
|
|||||||
}else{
|
}else{
|
||||||
assert( pIn3->flags & MEM_Blob );
|
assert( pIn3->flags & MEM_Blob );
|
||||||
ExpandBlob(pIn3);
|
ExpandBlob(pIn3);
|
||||||
rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
|
rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto abort_due_to_error;
|
goto abort_due_to_error;
|
||||||
}
|
}
|
||||||
@@ -2888,7 +2888,7 @@ case OP_Found: { /* jump, in3 */
|
|||||||
if( pOp->opcode==OP_Found ){
|
if( pOp->opcode==OP_Found ){
|
||||||
pC->pKeyInfo->prefixIsEqual = 1;
|
pC->pKeyInfo->prefixIsEqual = 1;
|
||||||
}
|
}
|
||||||
rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
|
rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
|
||||||
pC->pKeyInfo->prefixIsEqual = 0;
|
pC->pKeyInfo->prefixIsEqual = 0;
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
break;
|
break;
|
||||||
@@ -2965,7 +2965,7 @@ case OP_IsUnique: { /* jump, in3 */
|
|||||||
*/
|
*/
|
||||||
assert( pCx->deferredMoveto==0 );
|
assert( pCx->deferredMoveto==0 );
|
||||||
pCx->cacheStatus = CACHE_STALE;
|
pCx->cacheStatus = CACHE_STALE;
|
||||||
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res);
|
rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto abort_due_to_error;
|
goto abort_due_to_error;
|
||||||
}
|
}
|
||||||
@@ -3033,7 +3033,7 @@ case OP_NotExists: { /* jump, in3 */
|
|||||||
assert( pIn3->flags & MEM_Int );
|
assert( pIn3->flags & MEM_Int );
|
||||||
assert( p->apCsr[i]->isTable );
|
assert( p->apCsr[i]->isTable );
|
||||||
iKey = intToKey(pIn3->u.i);
|
iKey = intToKey(pIn3->u.i);
|
||||||
rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
|
rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
|
||||||
pC->lastRowid = pIn3->u.i;
|
pC->lastRowid = pIn3->u.i;
|
||||||
pC->rowidIsValid = res==0;
|
pC->rowidIsValid = res==0;
|
||||||
pC->nullRow = 0;
|
pC->nullRow = 0;
|
||||||
@@ -3203,7 +3203,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
|||||||
}
|
}
|
||||||
if( v==0 ) continue;
|
if( v==0 ) continue;
|
||||||
x = intToKey(v);
|
x = intToKey(v);
|
||||||
rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res);
|
rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
|
||||||
cnt++;
|
cnt++;
|
||||||
}while( cnt<100 && rx==SQLITE_OK && res==0 );
|
}while( cnt<100 && rx==SQLITE_OK && res==0 );
|
||||||
db->priorNewRowid = v;
|
db->priorNewRowid = v;
|
||||||
@@ -3676,22 +3676,29 @@ case OP_IdxInsert: { /* in2 */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IdxDelete P1 P2 * * *
|
/* Opcode: IdxDeleteM P1 P2 P3 * *
|
||||||
**
|
**
|
||||||
** The content of register P2 is an index key built using the
|
** The content of P3 registers starting at register P2 form
|
||||||
** MakeIdxRec opcode. This opcode removes that entry from the
|
** an unpacked index key. This opcode removes that entry from the
|
||||||
** index opened by cursor P1.
|
** index opened by cursor P1.
|
||||||
*/
|
*/
|
||||||
case OP_IdxDelete: { /* in2 */
|
case OP_IdxDelete: {
|
||||||
int i = pOp->p1;
|
int i = pOp->p1;
|
||||||
Cursor *pC;
|
Cursor *pC;
|
||||||
BtCursor *pCrsr;
|
BtCursor *pCrsr;
|
||||||
assert( pIn2->flags & MEM_Blob );
|
assert( pOp->p3>0 );
|
||||||
|
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem );
|
||||||
assert( i>=0 && i<p->nCursor );
|
assert( i>=0 && i<p->nCursor );
|
||||||
assert( p->apCsr[i]!=0 );
|
assert( p->apCsr[i]!=0 );
|
||||||
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
|
||||||
int res;
|
int res;
|
||||||
rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
|
UnpackedRecord r;
|
||||||
|
r.pKeyInfo = pC->pKeyInfo;
|
||||||
|
r.nField = pOp->p3;
|
||||||
|
r.needFree = 0;
|
||||||
|
r.needDestroy = 0;
|
||||||
|
r.aMem = &p->aMem[pOp->p2];
|
||||||
|
rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
|
||||||
if( rc==SQLITE_OK && res==0 ){
|
if( rc==SQLITE_OK && res==0 ){
|
||||||
rc = sqlite3BtreeDelete(pCrsr);
|
rc = sqlite3BtreeDelete(pCrsr);
|
||||||
}
|
}
|
||||||
|
10
src/vdbe.h
10
src/vdbe.h
@@ -15,7 +15,7 @@
|
|||||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||||
** simple program to access and modify the underlying database.
|
** simple program to access and modify the underlying database.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.h,v 1.127 2008/03/25 00:22:21 drh Exp $
|
** $Id: vdbe.h,v 1.128 2008/03/25 17:23:34 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE_VDBE_H_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _SQLITE_VDBE_H_
|
#define _SQLITE_VDBE_H_
|
||||||
@@ -34,7 +34,7 @@ typedef struct Vdbe Vdbe;
|
|||||||
*/
|
*/
|
||||||
typedef struct VdbeFunc VdbeFunc;
|
typedef struct VdbeFunc VdbeFunc;
|
||||||
typedef struct Mem Mem;
|
typedef struct Mem Mem;
|
||||||
typedef struct VdbeParsedRecord VdbeParsedRecord;
|
typedef struct UnpackedRecord UnpackedRecord;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A single instruction of the virtual machine has an opcode
|
** A single instruction of the virtual machine has an opcode
|
||||||
@@ -182,9 +182,9 @@ sqlite3 *sqlite3VdbeDb(Vdbe*);
|
|||||||
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
|
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
|
||||||
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
|
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
|
||||||
|
|
||||||
VdbeParsedRecord *sqlite3VdbeRecordParse(KeyInfo*,int,const void*,void*,int);
|
UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
|
||||||
void sqlite3VdbeRecordUnparse(VdbeParsedRecord*);
|
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
|
||||||
int sqlite3VdbeRecordCompareParsed(int,const void*,VdbeParsedRecord*);
|
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@@ -335,6 +335,28 @@ struct Vdbe {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** An instance of the following structure holds information about a
|
||||||
|
** single index record that has already been parsed out into individual
|
||||||
|
** values.
|
||||||
|
**
|
||||||
|
** A record is an object that contains one or more fields of data.
|
||||||
|
** Records are used to store the content of a table row and to store
|
||||||
|
** the key of an index. A blob encoding of a record is created by
|
||||||
|
** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
|
||||||
|
** OP_Column opcode.
|
||||||
|
**
|
||||||
|
** This structure holds a record that has already been disassembled
|
||||||
|
** into its constitutent fields.
|
||||||
|
*/
|
||||||
|
struct UnpackedRecord {
|
||||||
|
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
||||||
|
u16 nField; /* Number of entries in apMem[] */
|
||||||
|
u8 needFree; /* True if memory obtained from sqlite3_malloc() */
|
||||||
|
u8 needDestroy; /* True if apMem[]s should be destroyed on close */
|
||||||
|
Mem *aMem; /* Values */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following are allowed values for Vdbe.magic
|
** The following are allowed values for Vdbe.magic
|
||||||
*/
|
*/
|
||||||
|
154
src/vdbeaux.c
154
src/vdbeaux.c
@@ -1803,7 +1803,7 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
|
|||||||
extern int sqlite3_search_count;
|
extern int sqlite3_search_count;
|
||||||
#endif
|
#endif
|
||||||
assert( p->isTable );
|
assert( p->isTable );
|
||||||
rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res);
|
rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
*p->pIncrKey = 0;
|
*p->pIncrKey = 0;
|
||||||
p->lastRowid = keyToInt(p->movetoTarget);
|
p->lastRowid = keyToInt(p->movetoTarget);
|
||||||
@@ -2143,120 +2143,9 @@ int sqlite3VdbeSerialGet(
|
|||||||
*/
|
*/
|
||||||
#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
|
#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
** This function compares the two table rows or index records specified by
|
|
||||||
** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero
|
|
||||||
** or positive integer if {nKey1, pKey1} is less than, equal to or
|
|
||||||
** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings
|
|
||||||
** composed by the OP_MakeRecord opcode of the VDBE.
|
|
||||||
**
|
|
||||||
** Key1 and Key2 do not have to contain the same number of fields.
|
|
||||||
** But if the lengths differ, Key2 must be the shorter of the two.
|
|
||||||
*/
|
|
||||||
int sqlite3VdbeRecordCompare(
|
|
||||||
void *userData,
|
|
||||||
int nKey1, const void *pKey1,
|
|
||||||
int nKey2, const void *pKey2
|
|
||||||
){
|
|
||||||
KeyInfo *pKeyInfo = (KeyInfo*)userData;
|
|
||||||
u32 d1, d2; /* Offset into aKey[] of next data element */
|
|
||||||
u32 idx1, idx2; /* Offset into aKey[] of next header element */
|
|
||||||
u32 szHdr1, szHdr2; /* Number of bytes in header */
|
|
||||||
int i = 0;
|
|
||||||
int nField;
|
|
||||||
int rc = 0;
|
|
||||||
const unsigned char *aKey1 = (const unsigned char *)pKey1;
|
|
||||||
const unsigned char *aKey2 = (const unsigned char *)pKey2;
|
|
||||||
|
|
||||||
Mem mem1;
|
|
||||||
Mem mem2;
|
|
||||||
mem1.enc = pKeyInfo->enc;
|
|
||||||
mem1.db = pKeyInfo->db;
|
|
||||||
mem1.flags = 0;
|
|
||||||
mem2.enc = pKeyInfo->enc;
|
|
||||||
mem2.db = pKeyInfo->db;
|
|
||||||
mem2.flags = 0;
|
|
||||||
|
|
||||||
idx1 = GetVarint(aKey1, szHdr1);
|
|
||||||
d1 = szHdr1;
|
|
||||||
idx2 = GetVarint(aKey2, szHdr2);
|
|
||||||
d2 = szHdr2;
|
|
||||||
nField = pKeyInfo->nField;
|
|
||||||
while( idx1<szHdr1 && idx2<szHdr2 ){
|
|
||||||
u32 serial_type1;
|
|
||||||
u32 serial_type2;
|
|
||||||
|
|
||||||
/* Read the serial types for the next element in each key. */
|
|
||||||
idx1 += GetVarint( aKey1+idx1, serial_type1 );
|
|
||||||
if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
|
|
||||||
idx2 += GetVarint( aKey2+idx2, serial_type2 );
|
|
||||||
if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break;
|
|
||||||
|
|
||||||
/* Extract the values to be compared.
|
|
||||||
*/
|
|
||||||
d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
|
|
||||||
d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2);
|
|
||||||
|
|
||||||
/* Do the comparison
|
|
||||||
*/
|
|
||||||
rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
|
|
||||||
if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
|
|
||||||
if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
|
|
||||||
if( rc!=0 ){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One of the keys ran out of fields, but all the fields up to that point
|
|
||||||
** were equal. If the incrKey flag is true, then the second key is
|
|
||||||
** treated as larger.
|
|
||||||
*/
|
|
||||||
if( rc==0 ){
|
|
||||||
if( pKeyInfo->incrKey ){
|
|
||||||
rc = -1;
|
|
||||||
}else if( !pKeyInfo->prefixIsEqual ){
|
|
||||||
if( d1<nKey1 ){
|
|
||||||
rc = 1;
|
|
||||||
}else if( d2<nKey2 ){
|
|
||||||
rc = -1; /* Only occurs on a corrupt database file */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
|
|
||||||
&& pKeyInfo->aSortOrder[i] ){
|
|
||||||
rc = -rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
** An instance of the following structure holds information about a
|
|
||||||
** single index record that has already been parsed out into individual
|
|
||||||
** values.
|
|
||||||
**
|
|
||||||
** A record is an object that contains one or more fields of data.
|
|
||||||
** Records are used to store the content of a table row and to store
|
|
||||||
** the key of an index. A blob encoding of a record is created by
|
|
||||||
** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
|
|
||||||
** OP_Column opcode.
|
|
||||||
**
|
|
||||||
** This structure holds a record that has already been disassembled
|
|
||||||
** into its constitutent fields.
|
|
||||||
*/
|
|
||||||
struct VdbeParsedRecord {
|
|
||||||
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
|
||||||
u16 nField; /* Number of entries in apMem[] */
|
|
||||||
u8 needFree; /* True if memory obtained from sqlite3_malloc() */
|
|
||||||
u8 needDestroy; /* True if apMem[]s should be destroyed on close */
|
|
||||||
Mem *apMem[1]; /* Values */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Given the nKey-byte encoding of a record in pKey[], parse the
|
** Given the nKey-byte encoding of a record in pKey[], parse the
|
||||||
** record into a VdbeParsedRecord structure. Return a pointer to
|
** record into a UnpackedRecord structure. Return a pointer to
|
||||||
** that structure.
|
** that structure.
|
||||||
**
|
**
|
||||||
** The calling function might provide szSpace bytes of memory
|
** The calling function might provide szSpace bytes of memory
|
||||||
@@ -2265,9 +2154,9 @@ struct VdbeParsedRecord {
|
|||||||
** not big enough, space is obtained from sqlite3_malloc().
|
** not big enough, space is obtained from sqlite3_malloc().
|
||||||
**
|
**
|
||||||
** The returned structure should be closed by a call to
|
** The returned structure should be closed by a call to
|
||||||
** sqlite3VdbeRecordUnparse().
|
** sqlite3VdbeDeleteUnpackedRecord().
|
||||||
*/
|
*/
|
||||||
VdbeParsedRecord *sqlite3VdbeRecordParse(
|
UnpackedRecord *sqlite3VdbeRecordUnpack(
|
||||||
KeyInfo *pKeyInfo, /* Information about the record format */
|
KeyInfo *pKeyInfo, /* Information about the record format */
|
||||||
int nKey, /* Size of the binary record */
|
int nKey, /* Size of the binary record */
|
||||||
const void *pKey, /* The binary record */
|
const void *pKey, /* The binary record */
|
||||||
@@ -2275,14 +2164,13 @@ VdbeParsedRecord *sqlite3VdbeRecordParse(
|
|||||||
int szSpace /* Size of pSpace[] in bytes */
|
int szSpace /* Size of pSpace[] in bytes */
|
||||||
){
|
){
|
||||||
const unsigned char *aKey = (const unsigned char *)pKey;
|
const unsigned char *aKey = (const unsigned char *)pKey;
|
||||||
VdbeParsedRecord *p;
|
UnpackedRecord *p;
|
||||||
int nByte;
|
int nByte;
|
||||||
int i, idx, d;
|
int i, idx, d;
|
||||||
u32 szHdr;
|
u32 szHdr;
|
||||||
Mem *pMem;
|
Mem *pMem;
|
||||||
|
|
||||||
nByte = sizeof(*p) + sizeof(Mem*)*pKeyInfo->nField
|
nByte = sizeof(*p) + sizeof(Mem)*(pKeyInfo->nField+1);
|
||||||
+ sizeof(Mem)*(pKeyInfo->nField+1);
|
|
||||||
if( nByte>szSpace ){
|
if( nByte>szSpace ){
|
||||||
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
|
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
|
||||||
if( p==0 ) return 0;
|
if( p==0 ) return 0;
|
||||||
@@ -2294,7 +2182,7 @@ VdbeParsedRecord *sqlite3VdbeRecordParse(
|
|||||||
p->pKeyInfo = pKeyInfo;
|
p->pKeyInfo = pKeyInfo;
|
||||||
p->nField = pKeyInfo->nField + 1;
|
p->nField = pKeyInfo->nField + 1;
|
||||||
p->needDestroy = 1;
|
p->needDestroy = 1;
|
||||||
pMem = (Mem*)&p->apMem[pKeyInfo->nField+1];
|
p->aMem = pMem = (Mem*)&p[1];
|
||||||
idx = GetVarint(aKey, szHdr);
|
idx = GetVarint(aKey, szHdr);
|
||||||
d = szHdr;
|
d = szHdr;
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -2307,22 +2195,24 @@ VdbeParsedRecord *sqlite3VdbeRecordParse(
|
|||||||
pMem->db = pKeyInfo->db;
|
pMem->db = pKeyInfo->db;
|
||||||
pMem->flags = 0;
|
pMem->flags = 0;
|
||||||
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
|
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
|
||||||
p->apMem[i++] = pMem++;
|
pMem++;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
p->nField = i;
|
p->nField = i;
|
||||||
return (void*)p;
|
return (void*)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine destroys a VdbeParsedRecord object
|
** This routine destroys a UnpackedRecord object
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){
|
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
|
||||||
if( p ){
|
if( p ){
|
||||||
if( p->needDestroy ){
|
if( p->needDestroy ){
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<p->nField; i++){
|
Mem *pMem;
|
||||||
if( p->apMem[i]->flags & MEM_Dyn ){
|
for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
|
||||||
sqlite3VdbeMemRelease(p->apMem[i]);
|
if( pMem->flags & MEM_Dyn ){
|
||||||
|
sqlite3VdbeMemRelease(pMem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2351,9 +2241,9 @@ void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){
|
|||||||
** separately and submit the parsed version. In this way, we avoid
|
** separately and submit the parsed version. In this way, we avoid
|
||||||
** parsing the same Key2 multiple times in a row.
|
** parsing the same Key2 multiple times in a row.
|
||||||
*/
|
*/
|
||||||
int sqlite3VdbeRecordCompareParsed(
|
int sqlite3VdbeRecordCompare(
|
||||||
int nKey1, const void *pKey1,
|
int nKey1, const void *pKey1,
|
||||||
VdbeParsedRecord *pPKey2
|
UnpackedRecord *pPKey2
|
||||||
){
|
){
|
||||||
u32 d1; /* Offset into aKey[] of next data element */
|
u32 d1; /* Offset into aKey[] of next data element */
|
||||||
u32 idx1; /* Offset into aKey[] of next header element */
|
u32 idx1; /* Offset into aKey[] of next header element */
|
||||||
@@ -2386,7 +2276,7 @@ int sqlite3VdbeRecordCompareParsed(
|
|||||||
|
|
||||||
/* Do the comparison
|
/* Do the comparison
|
||||||
*/
|
*/
|
||||||
rc = sqlite3MemCompare(&mem1, pPKey2->apMem[i],
|
rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
|
||||||
i<nField ? pKeyInfo->aColl[i] : 0);
|
i<nField ? pKeyInfo->aColl[i] : 0);
|
||||||
if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
|
if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
|
||||||
if( rc!=0 ){
|
if( rc!=0 ){
|
||||||
@@ -2483,7 +2373,7 @@ int sqlite3VdbeIdxKeyCompare(
|
|||||||
BtCursor *pCur = pC->pCursor;
|
BtCursor *pCur = pC->pCursor;
|
||||||
int lenRowid;
|
int lenRowid;
|
||||||
Mem m;
|
Mem m;
|
||||||
VdbeParsedRecord *pRec;
|
UnpackedRecord *pRec;
|
||||||
char zSpace[200];
|
char zSpace[200];
|
||||||
|
|
||||||
sqlite3BtreeKeySize(pCur, &nCellKey);
|
sqlite3BtreeKeySize(pCur, &nCellKey);
|
||||||
@@ -2498,13 +2388,13 @@ int sqlite3VdbeIdxKeyCompare(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
|
lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
|
||||||
pRec = sqlite3VdbeRecordParse(pC->pKeyInfo, nKey, pKey,
|
pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
|
||||||
zSpace, sizeof(zSpace));
|
zSpace, sizeof(zSpace));
|
||||||
if( pRec==0 ){
|
if( pRec==0 ){
|
||||||
return SQLITE_NOMEM;
|
return SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
*res = sqlite3VdbeRecordCompareParsed(m.n-lenRowid, m.z, pRec);
|
*res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
|
||||||
sqlite3VdbeRecordUnparse(pRec);
|
sqlite3VdbeDeleteUnpackedRecord(pRec);
|
||||||
sqlite3VdbeMemRelease(&m);
|
sqlite3VdbeMemRelease(&m);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user