mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Enhance the DELETE logic so that it can make use of WHERE_ONEPASS_DESIRED
for rowid tables. FossilOrigin-Name: 8f479a72758ab6fedb171ada612b1963143c32fa
This commit is contained in:
23
manifest
23
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fully\sconstraint\sthe\sORDER\sBY\son\sthe\stop-10\sline\sof\sthe\s--summary\soutput\nfrom\sthe\swordcount\stest\sprogram.\s\sAdd\sthe\srun-wordcount.bash\sscript\sfor\nrunning\swordcount\sin\svarious\sconfigurations.
|
C Enhance\sthe\sDELETE\slogic\sso\sthat\sit\scan\smake\suse\sof\sWHERE_ONEPASS_DESIRED\nfor\srowid\stables.
|
||||||
D 2013-11-16T15:35:18.956
|
D 2013-11-16T20:13:39.579
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
|
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -174,7 +174,7 @@ F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
|||||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||||
F src/delete.c ddb92f44595366c4817e576b5f11cad5a915c3ef
|
F src/delete.c 765215277172cd66123516b92c99804bfab490f1
|
||||||
F src/expr.c 1a295d8b0a2ba08919ad9300ebf7b67988ff4030
|
F src/expr.c 1a295d8b0a2ba08919ad9300ebf7b67988ff4030
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6
|
F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6
|
||||||
@@ -183,7 +183,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
|||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c 63003c569c55793c3278ad7634bdd0c49d755a47
|
F src/insert.c 3cf8012325857d162f74389420b14be7976a538d
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||||
@@ -213,7 +213,7 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
|
|||||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||||
F src/pragma.c c8d70c47ec8d8ba93575d92e34d30ddff8e9b517
|
F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7
|
||||||
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
|
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
|
||||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||||
@@ -224,7 +224,7 @@ F src/shell.c b98e74123d6c2e20369607c1da2d23c71db633d9
|
|||||||
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
|
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h e16eb6e62146234c05f34a4403a75cf242777ad7
|
F src/sqliteInt.h 03b91c6bceccd7718473f3d790abcb8d5c2b1bf1
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -276,7 +276,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
|
|||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
|
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
|
||||||
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
|
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
|
||||||
F src/update.c 3de7e657b98ac67338d775c114a4068faf732402
|
F src/update.c 6a45368f8c7b400ffdac9a4c6cd19a5bbf3385e2
|
||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
@@ -1140,7 +1140,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P de08a7e7abbad9b94d0268d096ef4555d31c8b0c
|
P 7edf39eb93a8f9059a788f5fccf41c2be40afd4d
|
||||||
R 172f7957a55e2959255a9b6c3406c731
|
R a6d07ee396f35147cc60e236a37bb900
|
||||||
|
T *branch * optimize-delete
|
||||||
|
T *sym-optimize-delete *
|
||||||
|
T -sym-trunk *
|
||||||
U drh
|
U drh
|
||||||
Z e8555787a9b5df5e1de6c7d36654ffb3
|
Z fab6ca68390544d72160beaeac98129b
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
7edf39eb93a8f9059a788f5fccf41c2be40afd4d
|
8f479a72758ab6fedb171ada612b1963143c32fa
|
||||||
52
src/delete.c
52
src/delete.c
@@ -234,12 +234,16 @@ void sqlite3DeleteFrom(
|
|||||||
int iTabCur; /* Cursor number for the table */
|
int iTabCur; /* Cursor number for the table */
|
||||||
int iDataCur; /* VDBE cursor for the canonical data source */
|
int iDataCur; /* VDBE cursor for the canonical data source */
|
||||||
int iIdxCur; /* Cursor number of the first index */
|
int iIdxCur; /* Cursor number of the first index */
|
||||||
|
int nIdx; /* Number of indices */
|
||||||
sqlite3 *db; /* Main database structure */
|
sqlite3 *db; /* Main database structure */
|
||||||
AuthContext sContext; /* Authorization context */
|
AuthContext sContext; /* Authorization context */
|
||||||
NameContext sNC; /* Name context to resolve expressions in */
|
NameContext sNC; /* Name context to resolve expressions in */
|
||||||
int iDb; /* Database number */
|
int iDb; /* Database number */
|
||||||
int memCnt = -1; /* Memory cell used for change counting */
|
int memCnt = -1; /* Memory cell used for change counting */
|
||||||
int rcauth; /* Value returned by authorization callback */
|
int rcauth; /* Value returned by authorization callback */
|
||||||
|
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
||||||
|
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
|
||||||
|
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
int isView; /* True if attempting to delete from a view */
|
int isView; /* True if attempting to delete from a view */
|
||||||
@@ -295,11 +299,11 @@ void sqlite3DeleteFrom(
|
|||||||
}
|
}
|
||||||
assert(!isView || pTrigger);
|
assert(!isView || pTrigger);
|
||||||
|
|
||||||
/* Assign cursor number to the table and all its indices.
|
/* Assign cursor numbers to the table and all its indices.
|
||||||
*/
|
*/
|
||||||
assert( pTabList->nSrc==1 );
|
assert( pTabList->nSrc==1 );
|
||||||
iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
|
iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
|
||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
|
||||||
pParse->nTab++;
|
pParse->nTab++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +403,8 @@ void sqlite3DeleteFrom(
|
|||||||
|
|
||||||
/* Open cursors for all indices of the table.
|
/* Open cursors for all indices of the table.
|
||||||
*/
|
*/
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite,
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||||
iTabCur, &iDataCur, &iIdxCur);
|
&iDataCur, &iIdxCur);
|
||||||
|
|
||||||
/* Loop over the primary keys to be deleted. */
|
/* Loop over the primary keys to be deleted. */
|
||||||
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
|
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
|
||||||
@@ -424,22 +428,39 @@ void sqlite3DeleteFrom(
|
|||||||
** all rowids to be deleted into a RowSet.
|
** all rowids to be deleted into a RowSet.
|
||||||
*/
|
*/
|
||||||
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
|
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
|
||||||
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
|
|
||||||
int regRowid; /* Actual register containing rowids */
|
int regRowid; /* Actual register containing rowids */
|
||||||
|
|
||||||
/* Collect rowids of every row to be deleted.
|
/* Collect rowids of every row to be deleted.
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||||
pWInfo = sqlite3WhereBegin(
|
pWInfo = sqlite3WhereBegin(
|
||||||
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
|
pParse, pTabList, pWhere, 0, 0,
|
||||||
|
WHERE_DUPLICATES_OK|WHERE_ONEPASS_DESIRED, iTabCur+1
|
||||||
);
|
);
|
||||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||||
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iRowid, 0);
|
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
|
||||||
if( db->flags & SQLITE_CountRows ){
|
if( db->flags & SQLITE_CountRows ){
|
||||||
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
||||||
}
|
}
|
||||||
|
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur,
|
||||||
|
pParse->nMem+1, 0);
|
||||||
|
if( regRowid>pParse->nMem ) pParse->nMem = regRowid;
|
||||||
|
if( okOnePass ){
|
||||||
|
aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
|
||||||
|
if( aToOpen==0 ) goto delete_from_cleanup;
|
||||||
|
memset(aToOpen, 1, nIdx+1);
|
||||||
|
aToOpen[nIdx+1] = 0;
|
||||||
|
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
|
||||||
|
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
|
||||||
|
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
|
}else{
|
||||||
|
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
||||||
|
}
|
||||||
sqlite3WhereEnd(pWInfo);
|
sqlite3WhereEnd(pWInfo);
|
||||||
|
if( okOnePass ){
|
||||||
|
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||||
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete every item whose key was written to the list during the
|
/* Delete every item whose key was written to the list during the
|
||||||
** database scan. We have to delete items after the scan is complete
|
** database scan. We have to delete items after the scan is complete
|
||||||
@@ -451,20 +472,22 @@ void sqlite3DeleteFrom(
|
|||||||
** only effect this statement has is to fire the INSTEAD OF
|
** only effect this statement has is to fire the INSTEAD OF
|
||||||
** triggers. */
|
** triggers. */
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur,
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||||
&iDataCur, &iIdxCur);
|
&iDataCur, &iIdxCur);
|
||||||
assert( iDataCur==iTabCur );
|
assert( iDataCur==iTabCur );
|
||||||
assert( iIdxCur==iDataCur+1 );
|
assert( iIdxCur==iDataCur+1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
|
if( !okOnePass ){
|
||||||
|
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, regRowid);
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete the row */
|
/* Delete the row */
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
if( IsVirtual(pTab) ){
|
if( IsVirtual(pTab) ){
|
||||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||||
sqlite3VtabMakeWritable(pParse, pTab);
|
sqlite3VtabMakeWritable(pParse, pTab);
|
||||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
|
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, regRowid, pVTab, P4_VTAB);
|
||||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||||
sqlite3MayAbort(pParse);
|
sqlite3MayAbort(pParse);
|
||||||
}else
|
}else
|
||||||
@@ -472,11 +495,13 @@ void sqlite3DeleteFrom(
|
|||||||
{
|
{
|
||||||
int count = (pParse->nested==0); /* True to count changes */
|
int count = (pParse->nested==0); /* True to count changes */
|
||||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||||
iRowid, 1, count, OE_Default, 0);
|
regRowid, 1, count, OE_Default, okOnePass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of the delete loop */
|
/* End of the delete loop */
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
if( !okOnePass ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
||||||
|
}
|
||||||
sqlite3VdbeResolveLabel(v, end);
|
sqlite3VdbeResolveLabel(v, end);
|
||||||
|
|
||||||
/* Close the cursors open on the table and its indexes. */
|
/* Close the cursors open on the table and its indexes. */
|
||||||
@@ -510,6 +535,7 @@ delete_from_cleanup:
|
|||||||
sqlite3AuthContextPop(&sContext);
|
sqlite3AuthContextPop(&sContext);
|
||||||
sqlite3SrcListDelete(db, pTabList);
|
sqlite3SrcListDelete(db, pTabList);
|
||||||
sqlite3ExprDelete(db, pWhere);
|
sqlite3ExprDelete(db, pWhere);
|
||||||
|
sqlite3DbFree(db, aToOpen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
/* Make sure "isView" and other macros defined above are undefined. Otherwise
|
||||||
|
|||||||
26
src/insert.c
26
src/insert.c
@@ -820,7 +820,7 @@ void sqlite3Insert(
|
|||||||
/* If this is not a view, open the table and and all indices */
|
/* If this is not a view, open the table and and all indices */
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
int nIdx;
|
int nIdx;
|
||||||
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1,
|
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
|
||||||
&iDataCur, &iIdxCur);
|
&iDataCur, &iIdxCur);
|
||||||
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
|
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
|
||||||
if( aRegIdx==0 ){
|
if( aRegIdx==0 ){
|
||||||
@@ -1680,16 +1680,19 @@ int sqlite3OpenTableAndIndices(
|
|||||||
Table *pTab, /* Table to be opened */
|
Table *pTab, /* Table to be opened */
|
||||||
int op, /* OP_OpenRead or OP_OpenWrite */
|
int op, /* OP_OpenRead or OP_OpenWrite */
|
||||||
int iBase, /* Use this for the table cursor, if there is one */
|
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 */
|
int *piDataCur, /* Write the database source cursor number here */
|
||||||
int *piIdxCur /* Write the first index cursor number here */
|
int *piIdxCur /* Write the first index cursor number here */
|
||||||
){
|
){
|
||||||
int i;
|
int i;
|
||||||
int iDb;
|
int iDb;
|
||||||
|
int iDataCur;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
Vdbe *v;
|
Vdbe *v;
|
||||||
|
|
||||||
assert( op==OP_OpenRead || op==OP_OpenWrite );
|
assert( op==OP_OpenRead || op==OP_OpenWrite );
|
||||||
if( IsVirtual(pTab) ){
|
if( IsVirtual(pTab) ){
|
||||||
|
assert( aToOpen==0 );
|
||||||
*piDataCur = 0;
|
*piDataCur = 0;
|
||||||
*piIdxCur = 1;
|
*piIdxCur = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1698,20 +1701,25 @@ int sqlite3OpenTableAndIndices(
|
|||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
if( iBase<0 ) iBase = pParse->nTab;
|
if( iBase<0 ) iBase = pParse->nTab;
|
||||||
if( HasRowid(pTab) ){
|
iDataCur = iBase++;
|
||||||
*piDataCur = iBase++;
|
if( piDataCur ) *piDataCur = iDataCur;
|
||||||
sqlite3OpenTable(pParse, *piDataCur, iDb, pTab, op);
|
if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
|
||||||
|
sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
|
||||||
}else{
|
}else{
|
||||||
sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
|
sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
|
||||||
}
|
}
|
||||||
*piIdxCur = iBase;
|
if( piIdxCur ) *piIdxCur = iBase;
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||||
int iIdxCur = iBase++;
|
int iIdxCur = iBase++;
|
||||||
assert( pIdx->pSchema==pTab->pSchema );
|
assert( pIdx->pSchema==pTab->pSchema );
|
||||||
if( pIdx->autoIndex==2 && !HasRowid(pTab) ) *piDataCur = iIdxCur;
|
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
|
||||||
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
|
*piDataCur = iIdxCur;
|
||||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
}
|
||||||
VdbeComment((v, "%s", pIdx->zName));
|
if( aToOpen==0 || aToOpen[i+1] ){
|
||||||
|
sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
|
||||||
|
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||||
|
VdbeComment((v, "%s", pIdx->zName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( iBase>pParse->nTab ) pParse->nTab = iBase;
|
if( iBase>pParse->nTab ) pParse->nTab = iBase;
|
||||||
return i;
|
return i;
|
||||||
|
|||||||
@@ -1891,7 +1891,7 @@ void sqlite3Pragma(
|
|||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
sqlite3ExprCacheClear(pParse);
|
sqlite3ExprCacheClear(pParse);
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
|
||||||
1, &iDataCur, &iIdxCur);
|
1, 0, &iDataCur, &iIdxCur);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
||||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
|
||||||
|
|||||||
@@ -2942,7 +2942,7 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
|
|||||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||||
u8,u8,int,int*);
|
u8,u8,int,int*);
|
||||||
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
||||||
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, int*, int*);
|
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
|
||||||
void sqlite3BeginWriteOperation(Parse*, int, int);
|
void sqlite3BeginWriteOperation(Parse*, int, int);
|
||||||
void sqlite3MultiWrite(Parse*);
|
void sqlite3MultiWrite(Parse*);
|
||||||
void sqlite3MayAbort(Parse*);
|
void sqlite3MayAbort(Parse*);
|
||||||
|
|||||||
66
src/update.c
66
src/update.c
@@ -101,6 +101,7 @@ void sqlite3Update(
|
|||||||
Index *pIdx; /* For looping over indices */
|
Index *pIdx; /* For looping over indices */
|
||||||
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
|
Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
|
||||||
int nIdx; /* Number of indices that need updating */
|
int nIdx; /* Number of indices that need updating */
|
||||||
|
int iBaseCur; /* Base cursor number */
|
||||||
int iDataCur; /* Cursor for the canonical data btree */
|
int iDataCur; /* Cursor for the canonical data btree */
|
||||||
int iIdxCur; /* Cursor for the first index */
|
int iIdxCur; /* Cursor for the first index */
|
||||||
sqlite3 *db; /* The database structure */
|
sqlite3 *db; /* The database structure */
|
||||||
@@ -108,6 +109,7 @@ void sqlite3Update(
|
|||||||
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
|
||||||
** an expression for the i-th column of the table.
|
** an expression for the i-th column of the table.
|
||||||
** aXRef[i]==-1 if the i-th column is not changed. */
|
** aXRef[i]==-1 if the i-th column is not changed. */
|
||||||
|
u8 *aToOpen; /* 1 for tables and indices to be opened */
|
||||||
u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
|
u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
|
||||||
u8 chngRowid; /* Rowid changed in a normal table */
|
u8 chngRowid; /* Rowid changed in a normal table */
|
||||||
u8 chngKey; /* Either chngPk or chngRowid */
|
u8 chngKey; /* Either chngPk or chngRowid */
|
||||||
@@ -176,16 +178,13 @@ void sqlite3Update(
|
|||||||
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
|
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
|
||||||
goto update_cleanup;
|
goto update_cleanup;
|
||||||
}
|
}
|
||||||
aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
|
|
||||||
if( aXRef==0 ) goto update_cleanup;
|
|
||||||
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
|
|
||||||
|
|
||||||
/* Allocate a cursors for the main database table and for all indices.
|
/* Allocate a cursors for the main database table and for all indices.
|
||||||
** The index cursors might not be used, but if they are used they
|
** The index cursors might not be used, but if they are used they
|
||||||
** need to occur right after the database cursor. So go ahead and
|
** need to occur right after the database cursor. So go ahead and
|
||||||
** allocate enough space, just in case.
|
** allocate enough space, just in case.
|
||||||
*/
|
*/
|
||||||
pTabList->a[0].iCursor = iDataCur = pParse->nTab++;
|
pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++;
|
||||||
iIdxCur = iDataCur+1;
|
iIdxCur = iDataCur+1;
|
||||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
|
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
|
||||||
@@ -196,6 +195,17 @@ void sqlite3Update(
|
|||||||
pParse->nTab++;
|
pParse->nTab++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
|
||||||
|
** Initialize aXRef[] and aToOpen[] to their default values.
|
||||||
|
*/
|
||||||
|
aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
|
||||||
|
if( aXRef==0 ) goto update_cleanup;
|
||||||
|
aRegIdx = aXRef+pTab->nCol;
|
||||||
|
aToOpen = (u8*)(aRegIdx+nIdx);
|
||||||
|
memset(aToOpen, 1, nIdx+1);
|
||||||
|
aToOpen[nIdx+1] = 0;
|
||||||
|
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
|
||||||
|
|
||||||
/* Initialize the name-context */
|
/* Initialize the name-context */
|
||||||
memset(&sNC, 0, sizeof(sNC));
|
memset(&sNC, 0, sizeof(sNC));
|
||||||
sNC.pParse = pParse;
|
sNC.pParse = pParse;
|
||||||
@@ -256,15 +266,10 @@ void sqlite3Update(
|
|||||||
|
|
||||||
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
|
hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
|
||||||
|
|
||||||
/* Allocate memory for the array aRegIdx[]. There is one entry in the
|
/* There is one entry in the aRegIdx[] array for each index on the table
|
||||||
** array for each index associated with table being updated. Fill in
|
** being updated. Fill in aRegIdx[] with a register number that will hold
|
||||||
** the value with a register number for indices that are to be used
|
** the key for accessing each index.
|
||||||
** and with zero for unused indices.
|
|
||||||
*/
|
*/
|
||||||
if( nIdx>0 ){
|
|
||||||
aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
|
|
||||||
if( aRegIdx==0 ) goto update_cleanup;
|
|
||||||
}
|
|
||||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||||
int reg;
|
int reg;
|
||||||
if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
|
if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
|
||||||
@@ -278,6 +283,7 @@ void sqlite3Update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( reg==0 ) aToOpen[j+1] = 0;
|
||||||
aRegIdx[j] = reg;
|
aRegIdx[j] = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,42 +407,29 @@ void sqlite3Update(
|
|||||||
** action, then we need to open all indices because we might need
|
** action, then we need to open all indices because we might need
|
||||||
** to be deleting some records.
|
** to be deleting some records.
|
||||||
*/
|
*/
|
||||||
if( !okOnePass && HasRowid(pTab) ){
|
|
||||||
sqlite3OpenTable(pParse, iDataCur, iDb, pTab, OP_OpenWrite);
|
|
||||||
}
|
|
||||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
|
|
||||||
if( onError==OE_Replace ){
|
if( onError==OE_Replace ){
|
||||||
openAll = 1;
|
memset(aToOpen, 1, nIdx+1);
|
||||||
}else{
|
}else{
|
||||||
openAll = 0;
|
|
||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
if( pIdx->onError==OE_Replace ){
|
if( pIdx->onError==OE_Replace ){
|
||||||
openAll = 1;
|
memset(aToOpen, 1, nIdx+1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
if( okOnePass ){
|
||||||
int iThisCur = iIdxCur+i;
|
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
|
||||||
assert( aRegIdx );
|
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
|
||||||
if( (openAll || aRegIdx[i]>0)
|
|
||||||
&& iThisCur!=aiCurOnePass[1]
|
|
||||||
){
|
|
||||||
assert( iThisCur!=aiCurOnePass[0] );
|
|
||||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iThisCur, pIdx->tnum, iDb);
|
|
||||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
|
||||||
assert( pParse->nTab>iThisCur );
|
|
||||||
VdbeComment((v, "%s", pIdx->zName));
|
|
||||||
if( okOnePass && pPk && iThisCur==iDataCur ){
|
|
||||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak,
|
|
||||||
regKey, nKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
|
||||||
|
0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Top of the update loop */
|
/* Top of the update loop */
|
||||||
if( okOnePass ){
|
if( okOnePass ){
|
||||||
|
if( pPk ){
|
||||||
|
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
|
||||||
|
}
|
||||||
labelContinue = labelBreak;
|
labelContinue = labelBreak;
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
|
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
|
||||||
}else if( pPk ){
|
}else if( pPk ){
|
||||||
@@ -656,8 +649,7 @@ void sqlite3Update(
|
|||||||
|
|
||||||
update_cleanup:
|
update_cleanup:
|
||||||
sqlite3AuthContextPop(&sContext);
|
sqlite3AuthContextPop(&sContext);
|
||||||
sqlite3DbFree(db, aRegIdx);
|
sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
|
||||||
sqlite3DbFree(db, aXRef);
|
|
||||||
sqlite3SrcListDelete(db, pTabList);
|
sqlite3SrcListDelete(db, pTabList);
|
||||||
sqlite3ExprListDelete(db, pChanges);
|
sqlite3ExprListDelete(db, pChanges);
|
||||||
sqlite3ExprDelete(db, pWhere);
|
sqlite3ExprDelete(db, pWhere);
|
||||||
|
|||||||
Reference in New Issue
Block a user