mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Combine the rowid and WITHOUT ROWID paths for DELETE into a single path.
FossilOrigin-Name: c4734b881a64a9d21d03a14e901785797577fbd8
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C The\sone-pass\soptimization\sis\snow\sworking\sfor\sDELETE\son\sWITHOUT\sROWID\stables.
|
C Combine\sthe\srowid\sand\sWITHOUT\sROWID\spaths\sfor\sDELETE\sinto\sa\ssingle\spath.
|
||||||
D 2013-11-16T20:45:01.087
|
D 2013-11-16T22:48:52.173
|
||||||
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 35750d35fe9f174ccb98bae0d6627dcf83a7965a
|
F src/delete.c 1bcc9d7f2e48cf9043a44bdbd333c38c2ef6676a
|
||||||
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
|
||||||
@@ -1140,7 +1140,7 @@ 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 8f479a72758ab6fedb171ada612b1963143c32fa
|
P e4d220a381388f900a95d1b656a82f14c837f92e
|
||||||
R b6e41a6a6d551dfa6da0e7b0e42124eb
|
R d0df7aac2a46f76fbd08b30c4f269d2a
|
||||||
U drh
|
U drh
|
||||||
Z f0edfafd89abfe9d193a6a7758aa54ff
|
Z 2d947a1a8ff0ceb82e3a6fad03406bbd
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
e4d220a381388f900a95d1b656a82f14c837f92e
|
c4734b881a64a9d21d03a14e901785797577fbd8
|
||||||
214
src/delete.c
214
src/delete.c
@@ -227,7 +227,6 @@ void sqlite3DeleteFrom(
|
|||||||
Vdbe *v; /* The virtual database engine */
|
Vdbe *v; /* The virtual database engine */
|
||||||
Table *pTab; /* The table from which records will be deleted */
|
Table *pTab; /* The table from which records will be deleted */
|
||||||
const char *zDb; /* Name of database holding pTab */
|
const char *zDb; /* Name of database holding pTab */
|
||||||
int end, addr = 0; /* A couple addresses of generated code */
|
|
||||||
int i; /* Loop counter */
|
int i; /* Loop counter */
|
||||||
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
||||||
Index *pIdx; /* For looping over indices of the table */
|
Index *pIdx; /* For looping over indices of the table */
|
||||||
@@ -244,6 +243,17 @@ void sqlite3DeleteFrom(
|
|||||||
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
int okOnePass; /* True for one-pass algorithm without the FIFO */
|
||||||
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
|
int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
|
||||||
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
|
u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
|
||||||
|
Index *pPk; /* The PRIMARY KEY index on the table */
|
||||||
|
int iPk; /* First of nPk registerss holding PRIMARY KEY value */
|
||||||
|
i16 nPk = 1; /* Number of components of the PRIMARY KEY */
|
||||||
|
int iKey; /* Memory cell holding row key of to be deleted */
|
||||||
|
i16 nKey; /* Number of memory cells of row key */
|
||||||
|
int iEphCur = 0; /* Ephemeral table holding all primary key values */
|
||||||
|
int iRowSet = 0; /* Register for rowset of rows to delete */
|
||||||
|
int addrBypass = 0; /* Address of jump over the delete logic */
|
||||||
|
int addrLoop = 0; /* Top of the delete loop */
|
||||||
|
int addrDelete = 0; /* Jump directly to the delete logic */
|
||||||
|
int addrEphOpen = 0; /* Instruction to open the Ephermeral table */
|
||||||
|
|
||||||
#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 */
|
||||||
@@ -369,138 +379,113 @@ void sqlite3DeleteFrom(
|
|||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
||||||
if( !HasRowid(pTab) ){
|
{
|
||||||
/* There is a WHERE clause on a WITHOUT ROWID table.
|
if( HasRowid(pTab) ){
|
||||||
|
/* For a rowid table, initialize the RowSet to an empty set */
|
||||||
|
pPk = 0;
|
||||||
|
nPk = 1;
|
||||||
|
iRowSet = ++pParse->nMem;
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
||||||
|
}else{
|
||||||
|
/* For a WITHOUT ROWID table, create an ephermeral table used to
|
||||||
|
** hold all primary keys for rows to be deleted. */
|
||||||
|
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||||
|
assert( pPk!=0 );
|
||||||
|
nPk = pPk->nKeyCol;
|
||||||
|
iPk = pParse->nMem+1;
|
||||||
|
pParse->nMem += nPk;
|
||||||
|
iEphCur = pParse->nTab++;
|
||||||
|
addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
|
||||||
|
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct a query to find the rowid or primary key for every row
|
||||||
|
** to be deleted, based on the WHERE clause.
|
||||||
*/
|
*/
|
||||||
Index *pPk; /* The PRIMARY KEY index on the table */
|
|
||||||
int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
|
|
||||||
int iEph; /* Ephemeral table holding all primary key values */
|
|
||||||
int iKey; /* Key value inserting into iEph */
|
|
||||||
i16 nPk; /* Number of components of the PRIMARY KEY */
|
|
||||||
|
|
||||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
||||||
assert( pPk!=0 );
|
|
||||||
nPk = pPk->nKeyCol;
|
|
||||||
iPk = pParse->nMem+1;
|
|
||||||
pParse->nMem += nPk;
|
|
||||||
iKey = ++pParse->nMem;
|
|
||||||
iEph = pParse->nTab++;
|
|
||||||
|
|
||||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
|
|
||||||
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
|
||||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
|
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
|
||||||
WHERE_ONEPASS_DESIRED, iTabCur+1);
|
WHERE_ONEPASS_DESIRED, iTabCur+1);
|
||||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||||
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||||
for(i=0; i<nPk; i++){
|
|
||||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pPk->aiColumn[i],iPk+i);
|
/* Keep track of the number of rows to be deleted */
|
||||||
}
|
|
||||||
if( db->flags & SQLITE_CountRows ){
|
if( db->flags & SQLITE_CountRows ){
|
||||||
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extract the rowid or primary key for the current row */
|
||||||
|
if( pPk ){
|
||||||
|
for(i=0; i<nPk; i++){
|
||||||
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
|
||||||
|
pPk->aiColumn[i], iPk+i);
|
||||||
|
}
|
||||||
|
iKey = iPk;
|
||||||
|
nKey = nPk;
|
||||||
|
}else{
|
||||||
|
iKey = pParse->nMem + 1;
|
||||||
|
iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
|
||||||
|
if( iKey>pParse->nMem ) pParse->nMem = iKey;
|
||||||
|
}
|
||||||
|
|
||||||
if( okOnePass ){
|
if( okOnePass ){
|
||||||
|
/* For ONEPASS, no need to store the rowid/primary-key. There is only
|
||||||
|
** one, so just keep it in its register(s) and fall through to the
|
||||||
|
** delete code.
|
||||||
|
*/
|
||||||
|
nKey = nPk; /* OP_Found will use an unpacked key */
|
||||||
aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
|
aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
|
||||||
if( aToOpen==0 ) goto delete_from_cleanup;
|
if( aToOpen==0 ) goto delete_from_cleanup;
|
||||||
memset(aToOpen, 1, nIdx+1);
|
memset(aToOpen, 1, nIdx+1);
|
||||||
aToOpen[nIdx+1] = 0;
|
aToOpen[nIdx+1] = 0;
|
||||||
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
|
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
|
||||||
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
|
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
|
||||||
sqlite3VdbeChangeToNoop(v, addr);
|
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
|
||||||
addr = sqlite3VdbeAddOp0(v, OP_Goto);
|
addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */
|
||||||
}else{
|
}else if( pPk ){
|
||||||
|
/* Construct a composite key for the row to be deleted and remember it */
|
||||||
|
iKey = ++pParse->nMem;
|
||||||
|
nKey = 0; /* Zero tells OP_Found to use a composite key */
|
||||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
|
||||||
sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
|
sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, iKey);
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
|
||||||
}
|
|
||||||
sqlite3WhereEnd(pWInfo);
|
|
||||||
if( okOnePass ){
|
|
||||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open cursors for all indices of the table.
|
|
||||||
*/
|
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
|
||||||
&iDataCur, &iIdxCur);
|
|
||||||
|
|
||||||
/* Loop over the primary keys to be deleted. */
|
|
||||||
if( !okOnePass ){
|
|
||||||
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete the row */
|
|
||||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
|
||||||
iPk, nPk*okOnePass, 1, OE_Default, okOnePass);
|
|
||||||
|
|
||||||
/* End of the delete loop */
|
|
||||||
if( !okOnePass ){
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
|
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close the cursors open on the table and its indexes. */
|
|
||||||
assert( iDataCur>=iIdxCur );
|
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
|
||||||
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur+i);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
/* There is a WHERE clause on a rowid table. Run a loop that extracts
|
|
||||||
** all rowids to be deleted into a RowSet.
|
|
||||||
*/
|
|
||||||
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
|
|
||||||
int regRowid; /* Actual register containing rowids */
|
|
||||||
|
|
||||||
/* Collect rowids of every row to be deleted.
|
|
||||||
*/
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
|
|
||||||
pWInfo = sqlite3WhereBegin(
|
|
||||||
pParse, pTabList, pWhere, 0, 0,
|
|
||||||
WHERE_DUPLICATES_OK|WHERE_ONEPASS_DESIRED, iTabCur+1
|
|
||||||
);
|
|
||||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
|
||||||
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
|
||||||
if( db->flags & SQLITE_CountRows ){
|
|
||||||
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{
|
}else{
|
||||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
|
/* Get the rowid of the row to be deleted and remember it in the RowSet */
|
||||||
}
|
nKey = 1; /* OP_Seek always uses a single rowid */
|
||||||
sqlite3WhereEnd(pWInfo);
|
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
|
||||||
if( okOnePass ){
|
|
||||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete every item whose key was written to the list during the
|
/* End of the WHERE loop */
|
||||||
** database scan. We have to delete items after the scan is complete
|
sqlite3WhereEnd(pWInfo);
|
||||||
** because deleting an item can change the scan order. */
|
if( okOnePass ){
|
||||||
end = sqlite3VdbeMakeLabel(v);
|
/* Bypass the delete logic below if the WHERE loop found zero rows */
|
||||||
|
addrBypass = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||||
|
sqlite3VdbeJumpHere(v, addrDelete);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unless this is a view, open cursors for the table we are
|
/* Unless this is a view, open cursors for the table we are
|
||||||
** deleting from and all its indices. If this is a view, then the
|
** deleting from and all its indices. If this is a view, then the
|
||||||
** 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, aToOpen,
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
|
||||||
&iDataCur, &iIdxCur);
|
&iDataCur, &iIdxCur);
|
||||||
assert( iDataCur==iTabCur );
|
assert( pPk || iDataCur==iTabCur );
|
||||||
assert( iIdxCur==iDataCur+1 );
|
assert( pPk || iIdxCur==iDataCur+1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !okOnePass ){
|
/* Set up a loop over the rowids/primary-keys that were found in the
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, regRowid);
|
** where-clause loop above.
|
||||||
|
*/
|
||||||
|
if( okOnePass ){
|
||||||
|
/* Just one row. Hence the top-of-loop is a no-op */
|
||||||
|
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
|
||||||
|
}else if( pPk ){
|
||||||
|
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
|
||||||
|
assert( nKey==0 ); /* OP_Found will use a composite key */
|
||||||
|
}else{
|
||||||
|
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
|
||||||
|
assert( nKey==1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete the row */
|
/* Delete the row */
|
||||||
@@ -508,7 +493,7 @@ void sqlite3DeleteFrom(
|
|||||||
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, regRowid, pVTab, P4_VTAB);
|
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||||
sqlite3MayAbort(pParse);
|
sqlite3MayAbort(pParse);
|
||||||
}else
|
}else
|
||||||
@@ -516,23 +501,28 @@ 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,
|
||||||
regRowid, 1, count, OE_Default, okOnePass);
|
iKey, nKey, count, OE_Default, okOnePass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of the delete loop */
|
/* End of the loop over all rowids/primary-keys. */
|
||||||
if( !okOnePass ){
|
if( okOnePass ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
|
sqlite3VdbeJumpHere(v, addrBypass);
|
||||||
|
}else if( pPk ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1);
|
||||||
|
sqlite3VdbeJumpHere(v, addrLoop);
|
||||||
|
}else{
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop);
|
||||||
|
sqlite3VdbeJumpHere(v, addrLoop);
|
||||||
}
|
}
|
||||||
sqlite3VdbeResolveLabel(v, end);
|
|
||||||
|
|
||||||
/* Close the cursors open on the table and its indexes. */
|
/* Close the cursors open on the table and its indexes. */
|
||||||
if( !isView && !IsVirtual(pTab) ){
|
if( !isView && !IsVirtual(pTab) ){
|
||||||
sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
|
if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
|
||||||
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||||
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
|
sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} /* End non-truncate path */
|
||||||
|
|
||||||
/* Update the sqlite_sequence table by storing the content of the
|
/* Update the sqlite_sequence table by storing the content of the
|
||||||
** maximum rowid counter values recorded while inserting into
|
** maximum rowid counter values recorded while inserting into
|
||||||
|
|||||||
Reference in New Issue
Block a user