Merge the BTREE_FORDELETE enhancement with this branch.
FossilOrigin-Name: 20da0849ce910ceb445954dfc5f985acf9a02695
This commit is contained in:
commit
c5dc3dcd6e
33
manifest
33
manifest
@ -1,5 +1,5 @@
|
||||
C Merge\sin\sall\strunk\schanges\sprior\sto\sthe\sBTREE_FORDELETE\senhancement.
|
||||
D 2015-10-26T18:51:09.614
|
||||
C Merge\sthe\sBTREE_FORDELETE\senhancement\swith\sthis\sbranch.
|
||||
D 2015-10-26T20:11:24.886
|
||||
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4
|
||||
@ -280,8 +280,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c
|
||||
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 6e7cafdb9f245e0670c3478136a3c0c39ff5cf7b
|
||||
F src/btree.h 9cc758f0f1e0002049d9eb0232f9783f21f25ac5
|
||||
F src/btree.c 8022201b3008c9ff151cf56cf2c36a0db93689fd
|
||||
F src/btree.h 1957827f808875473750026cf60ca0c2b3676c98
|
||||
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
|
||||
F src/build.c d6162335d690396dfc5c4bd59e8b2b0c14ba6285
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
@ -289,7 +289,7 @@ F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 509ef9c64d1321f42448f111da86400b1799218a
|
||||
F src/date.c fb1c99172017dcc8e237339132c91a21a0788584
|
||||
F src/dbstat.c e637e7a7ff40ef32132a418c6fdf1cfb63aa27c7
|
||||
F src/delete.c 35c939eb8bacc9dd8a6715964e5f69feb8c20e44
|
||||
F src/delete.c c4c6fb9da78b946fcba2a6aac5b24bc5c15e752a
|
||||
F src/expr.c ea3e0c2981ffc7bd358714fa6d5132cb2cd5fc3a
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 31900763094a3736a5fc887469202eb579fef2d0
|
||||
@ -298,7 +298,7 @@ F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 6dadbb671c2cc035ddbbf11a0b0209185d5bfe2c
|
||||
F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012
|
||||
@ -331,7 +331,7 @@ F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
|
||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035
|
||||
F src/pragma.c dcfe3a35d2de935feeaba1455528b4a5c4f1208c
|
||||
F src/pragma.c 8fd4c8a12e25f0d916426f160255ebe25415eba7
|
||||
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
|
||||
@ -343,14 +343,14 @@ F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
|
||||
F src/sqlite.h.in 839c818e16ea68703d90d17bd2bb3607191debce
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
|
||||
F src/sqliteInt.h af76837cad8fb696e6527ec2745f175de7cb9093
|
||||
F src/sqliteInt.h b1e72ffe282c91ae30a2bf403319126dbaebd556
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
F src/tclsqlite.c d9439b6a910985b7fff43ba6756bcef00de22649
|
||||
F src/test1.c 8fff9c5aa63d6490f516d018b70c12a9cb9a4d8a
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
F src/test3.c f7ae1d6a4aa07aac257de18a43800c1199b513fc
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
@ -397,11 +397,11 @@ F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0
|
||||
F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22
|
||||
F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c aa10336a2719bd1b9f89004f3d7ba6d566623a49
|
||||
F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 10d66354fec90acb5fc908ad36da404ef9796170
|
||||
F src/vdbe.c 1cdfa13e37dba217916112fffc639dee83406192
|
||||
F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637
|
||||
F src/vdbeInt.h 33403622c6a8feaaac5f0f3f17f5d1bf6df42286
|
||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||
@ -415,7 +415,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
|
||||
F src/where.c 51cca249502ee71fb77b425687dac611277925b2
|
||||
F src/where.c 6aceb72cc58dc06922a9e1604d559c8ca4c3e728
|
||||
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
|
||||
F src/wherecode.c 9aa2043685ec3eb73e87fa6f50aa4ec092f197dd
|
||||
F src/whereexpr.c e63244ca06c503e5f3c5b7f3c9aea0db826089ed
|
||||
@ -629,6 +629,7 @@ F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48
|
||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||
F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0
|
||||
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
|
||||
F test/fordelete.test ba12ec1d27cc34a4c23db4446029126d773f3849
|
||||
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
|
||||
F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c
|
||||
F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7
|
||||
@ -1392,7 +1393,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 26fa091d68e89a0b6af61ba706d23a9f37e8025a 138783b553602a055b3efdeac5947cf5ccd76b5d
|
||||
R 4b723e99df9abf57da690efface1cef0
|
||||
U drh
|
||||
Z 936e93924f01554045ee6552abb7ef82
|
||||
P 53d5a4add6b60722ad77daf98b6b8983b081e16a de6972515f65c5cf5da7cfdf876a05718299e9b8
|
||||
R eb548650b5c16f458e4886ea4649dc57
|
||||
U dan
|
||||
Z 682420f21bcc754cb8ec9b887c5ab3d8
|
||||
|
@ -1 +1 @@
|
||||
53d5a4add6b60722ad77daf98b6b8983b081e16a
|
||||
20da0849ce910ceb445954dfc5f985acf9a02695
|
10
src/btree.c
10
src/btree.c
@ -4076,13 +4076,16 @@ static int btreeCursor(
|
||||
BtCursor *pX; /* Looping over other all cursors */
|
||||
|
||||
assert( sqlite3BtreeHoldsMutex(p) );
|
||||
assert( wrFlag==0 || wrFlag==1 );
|
||||
assert( wrFlag==0
|
||||
|| wrFlag==BTREE_WRCSR
|
||||
|| wrFlag==(BTREE_WRCSR|BTREE_FORDELETE)
|
||||
);
|
||||
|
||||
/* The following assert statements verify that if this is a sharable
|
||||
** b-tree database, the connection is holding the required table locks,
|
||||
** and that no other connection has any open cursor that conflicts with
|
||||
** this lock. */
|
||||
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
|
||||
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
|
||||
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
|
||||
|
||||
/* Assert that the caller has opened the required transaction. */
|
||||
@ -4107,8 +4110,7 @@ static int btreeCursor(
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
pCur->pBtree = p;
|
||||
pCur->pBt = pBt;
|
||||
assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
|
||||
pCur->curFlags = wrFlag;
|
||||
pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
|
||||
pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
|
||||
/* If there are two or more cursors on the same btree, then all such
|
||||
** cursors *must* have the BTCF_Multiple flag set. */
|
||||
|
16
src/btree.h
16
src/btree.h
@ -201,6 +201,22 @@ int sqlite3BtreeNewDb(Btree *p);
|
||||
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
|
||||
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
|
||||
|
||||
/*
|
||||
** Flags passed as the third argument to sqlite3BtreeCursor().
|
||||
**
|
||||
** For read-only cursors the wrFlag argument is always zero. For read-write
|
||||
** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or
|
||||
** (BTREE_WRCSR). If the BTREE_FORDELETE flag is set, then the cursor will
|
||||
** only be used by SQLite for the following:
|
||||
**
|
||||
** * to seek to and delete specific entries, and/or
|
||||
**
|
||||
** * to read values that will be used to create keys that other
|
||||
** BTREE_FORDELETE cursors will seek to and delete.
|
||||
*/
|
||||
#define BTREE_WRCSR 0x00000004 /* read-write cursor */
|
||||
#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
|
||||
|
||||
int sqlite3BtreeCursor(
|
||||
Btree*, /* BTree containing table to open */
|
||||
int iTable, /* Index of root page */
|
||||
|
@ -478,12 +478,13 @@ void sqlite3DeleteFrom(
|
||||
*/
|
||||
if( !isView ){
|
||||
int iAddrOnce = 0;
|
||||
u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
}
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||
&iDataCur, &iIdxCur);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur,
|
||||
aToOpen, &iDataCur, &iIdxCur);
|
||||
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
||||
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
||||
if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
||||
|
@ -762,7 +762,7 @@ void sqlite3Insert(
|
||||
/* If this is not a view, open the table and and all indices */
|
||||
if( !isView ){
|
||||
int nIdx;
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
|
||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
|
||||
&iDataCur, &iIdxCur);
|
||||
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
|
||||
if( aRegIdx==0 ){
|
||||
@ -1650,6 +1650,7 @@ int sqlite3OpenTableAndIndices(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Table *pTab, /* Table to be opened */
|
||||
int op, /* OP_OpenRead or OP_OpenWrite */
|
||||
u8 p5, /* P5 value for OP_Open* instructions */
|
||||
int iBase, /* Use this for the table cursor, if there is one */
|
||||
u8 *aToOpen, /* If not NULL: boolean for each table and index */
|
||||
int *piDataCur, /* Write the database source cursor number here */
|
||||
@ -1662,6 +1663,7 @@ int sqlite3OpenTableAndIndices(
|
||||
Vdbe *v;
|
||||
|
||||
assert( op==OP_OpenRead || op==OP_OpenWrite );
|
||||
assert( op==OP_OpenWrite || p5==0 );
|
||||
if( IsVirtual(pTab) ){
|
||||
/* This routine is a no-op for virtual tables. Leave the output
|
||||
** variables *piDataCur and *piIdxCur uninitialized so that valgrind
|
||||
@ -1689,6 +1691,7 @@ int sqlite3OpenTableAndIndices(
|
||||
if( aToOpen==0 || aToOpen[i+1] ){
|
||||
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
sqlite3VdbeChangeP5(v, p5);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
}
|
||||
}
|
||||
|
@ -1465,7 +1465,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
|
@ -2795,7 +2795,8 @@ struct AuthContext {
|
||||
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
||||
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
|
||||
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
|
||||
#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
|
||||
#define OPFLAG_FORDELETE 0x08 /* OP_Open is opening for-delete csr */
|
||||
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
|
||||
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
|
||||
|
||||
/*
|
||||
@ -3466,7 +3467,7 @@ void sqlite3ResolvePartIdxLabel(Parse*,int);
|
||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||
u8,u8,int,int*);
|
||||
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
|
||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
|
||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||
void sqlite3MultiWrite(Parse*);
|
||||
void sqlite3MayAbort(Parse*);
|
||||
|
47
src/test3.c
47
src/test3.c
@ -214,11 +214,12 @@ static int btree_cursor(
|
||||
pBt = sqlite3TestTextToPtr(argv[1]);
|
||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
|
||||
if( wrFlag ) wrFlag = BTREE_WRCSR;
|
||||
pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
|
||||
memset(pCur, 0, sqlite3BtreeCursorSize());
|
||||
sqlite3BtreeEnter(pBt);
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
|
||||
rc = sqlite3BtreeLockTable(pBt, iTable, !!wrFlag);
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
|
||||
@ -598,6 +599,48 @@ static int btree_set_cache_size(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** usage: btree_insert CSR ?KEY? VALUE
|
||||
**
|
||||
** Set the size of the cache used by btree $ID.
|
||||
*/
|
||||
static int btree_insert(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const objv[]
|
||||
){
|
||||
BtCursor *pCur;
|
||||
int rc;
|
||||
void *pKey = 0;
|
||||
int nKey = 0;
|
||||
void *pData = 0;
|
||||
int nData = 0;
|
||||
|
||||
if( objc!=4 && objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-intkey? CSR KEY VALUE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if( objc==4 ){
|
||||
if( Tcl_GetIntFromObj(interp, objv[2], &nKey) ) return TCL_ERROR;
|
||||
pData = (void*)Tcl_GetByteArrayFromObj(objv[3], &nData);
|
||||
}else{
|
||||
pKey = (void*)Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
||||
}
|
||||
pCur = (BtCursor*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
||||
|
||||
sqlite3BtreeEnter(pCur->pBtree);
|
||||
rc = sqlite3BtreeInsert(pCur, pKey, nKey, pData, nData, 0, 0, 0);
|
||||
sqlite3BtreeLeave(pCur->pBtree);
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -629,5 +672,7 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
|
||||
Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
|
||||
}
|
||||
|
||||
Tcl_CreateObjCommand(interp, "btree_insert", btree_insert, 0, 0);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ void sqlite3Update(
|
||||
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
|
||||
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
|
||||
}
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
|
@ -3324,7 +3324,6 @@ case OP_ReopenIdx: {
|
||||
case OP_OpenRead:
|
||||
case OP_OpenWrite:
|
||||
|
||||
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
|
||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
|
||||
assert( p->bIsReader );
|
||||
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|
||||
@ -3345,7 +3344,8 @@ case OP_OpenWrite:
|
||||
pX = pDb->pBt;
|
||||
assert( pX!=0 );
|
||||
if( pOp->opcode==OP_OpenWrite ){
|
||||
wrFlag = 1;
|
||||
assert( OPFLAG_FORDELETE==BTREE_FORDELETE );
|
||||
wrFlag = BTREE_WRCSR | (pOp->p5 & OPFLAG_FORDELETE);
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
|
||||
p->minWriteFileFormat = pDb->pSchema->file_format;
|
||||
@ -3469,11 +3469,11 @@ case OP_OpenEphemeral: {
|
||||
assert( pKeyInfo->db==db );
|
||||
assert( pKeyInfo->enc==ENC(db) );
|
||||
pCx->pKeyInfo = pKeyInfo;
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR, pKeyInfo, pCx->pCursor);
|
||||
}
|
||||
pCx->isTable = 0;
|
||||
}else{
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR, 0, pCx->pCursor);
|
||||
pCx->isTable = 1;
|
||||
}
|
||||
}
|
||||
|
15
src/where.c
15
src/where.c
@ -4010,6 +4010,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
int ii; /* Loop counter */
|
||||
sqlite3 *db; /* Database connection */
|
||||
int rc; /* Return code */
|
||||
u8 bFordelete = 0;
|
||||
|
||||
assert( (wctrlFlags & WHERE_ONEPASS_MULTIROW)==0 || (
|
||||
(wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
|
||||
@ -4265,8 +4266,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
&& 0==(wsFlags & WHERE_VIRTUALTABLE)
|
||||
)){
|
||||
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
|
||||
if( HasRowid(pTabList->a[0].pTab) ){
|
||||
pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
|
||||
if( HasRowid(pTabList->a[0].pTab) && (wsFlags & WHERE_IDX_ONLY) ){
|
||||
if( wctrlFlags & WHERE_ONEPASS_MULTIROW ){
|
||||
bFordelete = OPFLAG_FORDELETE;
|
||||
}
|
||||
pWInfo->a[0].pWLoop->wsFlags = (wsFlags & ~WHERE_IDX_ONLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4315,8 +4319,13 @@ WhereInfo *sqlite3WhereBegin(
|
||||
assert( n<=pTab->nCol );
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
if( pLoop->u.btree.pIndex!=0 ) sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ);
|
||||
if( pLoop->u.btree.pIndex!=0 ){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3VdbeChangeP5(v, bFordelete);
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
|
||||
(const u8*)&pTabItem->colUsed, P4_INT64);
|
||||
|
130
test/fordelete.test
Normal file
130
test/fordelete.test
Normal file
@ -0,0 +1,130 @@
|
||||
# 2001 September 15
|
||||
#
|
||||
# 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 regression tests for SQLite library. The
|
||||
# focus of this file is testing the SELECT statement.
|
||||
#
|
||||
# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix fordelete
|
||||
|
||||
# This function returns a list of the tables or indexes opened with
|
||||
# OP_OpenWrite instructions when the SQL statement passed as the only
|
||||
# argument is executed. If the OPFLAG_FORDELETE flag is specified on
|
||||
# the OP_OpenWrite, an asterix is appended to the object name. The list
|
||||
# is sorted in [lsort] order before it is returned.
|
||||
#
|
||||
proc analyze_delete_program {sql} {
|
||||
# Build a map from root page to table/index name.
|
||||
db eval {
|
||||
SELECT name, rootpage FROM sqlite_master
|
||||
} {
|
||||
set T($rootpage) $name
|
||||
}
|
||||
|
||||
# Calculate the results.
|
||||
set res [list]
|
||||
db eval "EXPLAIN $sql" R {
|
||||
if {$R(opcode) == "OpenWrite"} {
|
||||
set obj $T($R(p2))
|
||||
if {"0x$R(p5)" & 0x08} { append obj *}
|
||||
lappend res $obj
|
||||
}
|
||||
}
|
||||
|
||||
lsort $res
|
||||
}
|
||||
|
||||
proc do_adp_test {tn sql res} {
|
||||
uplevel [list do_test $tn [list analyze_delete_program $sql] [list {*}$res]]
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
}
|
||||
|
||||
foreach {tn sql res} {
|
||||
1 { DELETE FROM t1 WHERE a=?} { sqlite_autoindex_t1_1 t1* }
|
||||
2 { DELETE FROM t1 WHERE a=? AND b=? } { sqlite_autoindex_t1_1 t1 }
|
||||
3 { DELETE FROM t1 WHERE a>? } { sqlite_autoindex_t1_1 t1* }
|
||||
4 { DELETE FROM t1 WHERE rowid=? } { sqlite_autoindex_t1_1* t1 }
|
||||
} {
|
||||
do_adp_test 1.$tn $sql $res
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t2(a, b, c);
|
||||
CREATE INDEX t2a ON t2(a);
|
||||
CREATE INDEX t2b ON t2(b);
|
||||
CREATE INDEX t2c ON t2(c);
|
||||
}
|
||||
foreach {tn sql res} {
|
||||
1 { DELETE FROM t2 WHERE a=?} { t2* t2a t2b* t2c* }
|
||||
2 { DELETE FROM t2 WHERE a=? AND +b=?} { t2 t2a t2b* t2c* }
|
||||
3 { DELETE FROM t2 WHERE a=? OR b=?} { t2 t2a* t2b* t2c* }
|
||||
4 { DELETE FROM t2 WHERE +a=? } { t2 t2a* t2b* t2c* }
|
||||
5 { DELETE FROM t2 WHERE rowid=? } { t2 t2a* t2b* t2c* }
|
||||
} {
|
||||
do_adp_test 2.$tn $sql $res
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a record that consists of the bytes:
|
||||
#
|
||||
# 0x01 0x00
|
||||
#
|
||||
# is interpreted by OP_Column as a vector of NULL values (assuming the
|
||||
# default column values are NULL). Also test that:
|
||||
#
|
||||
# 0x00
|
||||
#
|
||||
# is handled in the same way.
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c, d);
|
||||
CREATE TABLE x2(a INTEGER PRIMARY KEY, b, c, d);
|
||||
}
|
||||
|
||||
do_test 3.1 {
|
||||
set root [db one { SELECT rootpage FROM sqlite_master WHERE name = 'x1' }]
|
||||
db eval {
|
||||
BEGIN IMMEDIATE;
|
||||
}
|
||||
set bt [btree_from_db db]
|
||||
set csr [btree_cursor $bt $root 1]
|
||||
btree_insert $csr 5 "\000"
|
||||
btree_close_cursor $csr
|
||||
db eval { COMMIT }
|
||||
|
||||
db eval {
|
||||
SELECT * FROM x1;
|
||||
}
|
||||
} {5 {} {} {}}
|
||||
|
||||
do_test 3.2 {
|
||||
set root [db one { SELECT rootpage FROM sqlite_master WHERE name = 'x2' }]
|
||||
db eval {
|
||||
BEGIN IMMEDIATE;
|
||||
}
|
||||
set bt [btree_from_db db]
|
||||
set csr [btree_cursor $bt $root 1]
|
||||
btree_insert $csr 6 "\000"
|
||||
btree_close_cursor $csr
|
||||
db eval { COMMIT }
|
||||
|
||||
db eval {
|
||||
SELECT * FROM x2;
|
||||
}
|
||||
} {6 {} {} {}}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user