Delete PRIMARY KEY index entries last. Only construct the unique prefix of
an index key when deleting entries from an index. FossilOrigin-Name: 0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04
This commit is contained in:
parent
acbbc5ba36
commit
9eade087da
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Remove\san\sobsolete\scomment\sfrom\sthe\sVDBE.\s\sNo\scode\schanges.
|
||||
D 2013-10-24T11:55:42.224
|
||||
C Delete\sPRIMARY\sKEY\sindex\sentries\slast.\s\sOnly\sconstruct\sthe\sunique\sprefix\sof\nan\sindex\skey\swhen\sdeleting\sentries\sfrom\san\sindex.
|
||||
D 2013-10-24T14:16:10.049
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -168,12 +168,12 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
|
||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 2dccf54c05a0102fce82a3147c39a4b582a7eb60
|
||||
F src/build.c f99c6980a258e32e0e0068b04dd8eed6a4af9445
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c 5dcd957b7af5b67b4cce125dd2b580248678db8a
|
||||
F src/delete.c 18bd99db316cf8f7ab2e779f9eea2fdc0d281960
|
||||
F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
|
||||
@ -212,7 +212,7 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||
F src/pragma.c 575a4462366b371076dd14bd93df21f325a10995
|
||||
F src/pragma.c d6eee7e1b6343996883e5c7e0f60bfad77be2180
|
||||
F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
@ -292,7 +292,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c b5f5244d53d965443661a324be270ac133cecd69
|
||||
F src/where.c 04217a957c1423dd5f177b21b4ced319bf24b77c
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
@ -1127,7 +1127,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P d8bc8595301789d0e9de24c391808121905ab559
|
||||
R 86e2d2460b05b7f34889d08f4aa01946
|
||||
P 53bb070c851db02c9d900cb041ab441895ddbfb7
|
||||
R 51fe8599e5a3fd933943a52c99bda7fd
|
||||
U drh
|
||||
Z 2b4e64eb89b8d486fb338d00ee41ab7d
|
||||
Z 341cc48c3c0ebe6f2ca7c21fb7db25ce
|
||||
|
@ -1 +1 @@
|
||||
53bb070c851db02c9d900cb041ab441895ddbfb7
|
||||
0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04
|
@ -1641,6 +1641,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
for(i=0; i<nPk; i++){
|
||||
pTab->aCol[pPk->aiColumn[i]].notNull = 1;
|
||||
}
|
||||
pPk->uniqNotNull = 1;
|
||||
|
||||
/* Update the in-memory representation of all UNIQUE indices by converting
|
||||
** the final rowid column into one or more columns of the PRIMARY KEY.
|
||||
@ -2635,7 +2636,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
|
||||
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1, &iPartIdxLabel);
|
||||
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 0, &iPartIdxLabel);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
|
||||
@ -2932,7 +2933,7 @@ Index *sqlite3CreateIndex(
|
||||
memcpy(pIndex->zName, zName, nName+1);
|
||||
pIndex->pTable = pTab;
|
||||
pIndex->onError = (u8)onError;
|
||||
pIndex->uniqNotNull = onError==OE_Abort;
|
||||
pIndex->uniqNotNull = onError!=OE_None;
|
||||
pIndex->autoIndex = (u8)(pName==0);
|
||||
pIndex->pSchema = db->aDb[iDb].pSchema;
|
||||
if( pPIWhere ){
|
||||
|
46
src/delete.c
46
src/delete.c
@ -134,7 +134,7 @@ Expr *sqlite3LimitWhere(
|
||||
ExprList *pOrderBy, /* The ORDER BY clause. May be null */
|
||||
Expr *pLimit, /* The LIMIT clause. May be null */
|
||||
Expr *pOffset, /* The OFFSET clause. May be null */
|
||||
char *zStmtType /* Either DELETE or UPDATE. For error messages. */
|
||||
char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
|
||||
){
|
||||
Expr *pWhereRowid = NULL; /* WHERE rowid .. */
|
||||
Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
|
||||
@ -209,7 +209,8 @@ limit_where_cleanup_2:
|
||||
sqlite3ExprDelete(pParse->db, pOffset);
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
|
||||
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
|
||||
/* && !defined(SQLITE_OMIT_SUBQUERY) */
|
||||
|
||||
/*
|
||||
** Generate code for a DELETE FROM statement.
|
||||
@ -408,7 +409,8 @@ void sqlite3DeleteFrom(
|
||||
#endif
|
||||
{
|
||||
int count = (pParse->nested==0); /* True to count changes */
|
||||
sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
|
||||
sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count,
|
||||
pTrigger, OE_Default);
|
||||
}
|
||||
|
||||
/* End of the delete loop */
|
||||
@ -466,10 +468,10 @@ delete_from_cleanup:
|
||||
** These are the requirements:
|
||||
**
|
||||
** 1. A read/write cursor pointing to pTab, the table containing the row
|
||||
** to be deleted, must be opened as cursor number $iCur.
|
||||
** to be deleted, must be opened as cursor number iCur.
|
||||
**
|
||||
** 2. Read/write cursors for all indices of pTab must be open as
|
||||
** cursor number base+i for the i-th index.
|
||||
** cursor number iCur+i for the i-th index.
|
||||
**
|
||||
** 3. The record number of the row to be deleted must be stored in
|
||||
** memory cell iRowid.
|
||||
@ -575,13 +577,17 @@ void sqlite3GenerateRowDelete(
|
||||
** These are the requirements:
|
||||
**
|
||||
** 1. A read/write cursor pointing to pTab, the table containing the row
|
||||
** to be deleted, must be opened as cursor number "iCur".
|
||||
** to be deleted, must be opened as cursor number "iCur". For
|
||||
** WITHOUT ROWID tables that do not have a main table, the iCur
|
||||
** cursor is unused.
|
||||
**
|
||||
** 2. Read/write cursors for all indices of pTab must be open as
|
||||
** cursor number iCur+i for the i-th index.
|
||||
**
|
||||
** 3. The "iCur" cursor must be pointing to the row that is to be
|
||||
** deleted.
|
||||
** deleted. Or, for WITHOUT ROWID tables, the iCur+i cursor for
|
||||
** the PRIMARY KEY index must be pointing to the row to that is
|
||||
** to be deleted.
|
||||
*/
|
||||
void sqlite3GenerateRowIndexDelete(
|
||||
Parse *pParse, /* Parsing and code generating context */
|
||||
@ -589,22 +595,32 @@ void sqlite3GenerateRowIndexDelete(
|
||||
int iCur, /* Cursor number for the table */
|
||||
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
|
||||
){
|
||||
int i;
|
||||
int i, iPk = 0;
|
||||
Index *pIdx;
|
||||
int r1;
|
||||
int iPartIdxLabel;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
Index *pPk;
|
||||
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0, &iPartIdxLabel);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1, pIdx->nKeyCol+1);
|
||||
if( pIdx==pPk ){ iPk = iCur+i; continue; }
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 1, &iPartIdxLabel);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1,
|
||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
}
|
||||
if( iPk ){
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pPk, iCur, 0, 1, &iPartIdxLabel);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iPk, r1,
|
||||
pPk->uniqNotNull ? pPk->nKeyCol : pPk->nColumn);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate code that will assemble an index key and put it in register
|
||||
** Generate code that will assemble an index key and stores it in register
|
||||
** 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
|
||||
** the entry that needs indexing.
|
||||
@ -625,8 +641,8 @@ int sqlite3GenerateIndexKey(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Index *pIdx, /* The index for which to generate a key */
|
||||
int iCur, /* Cursor number for the pIdx->pTable table */
|
||||
int regOut, /* Write the new index key to this register */
|
||||
int doMakeRec, /* Run the OP_MakeRecord instruction if true */
|
||||
int regOut, /* Put the new key into this register if not 0 */
|
||||
int prefixOnly, /* Compute only a unique prefix of the key */
|
||||
int *piPartIdxLabel /* OUT: Jump to this label to skip partial index */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
@ -646,7 +662,7 @@ int sqlite3GenerateIndexKey(
|
||||
*piPartIdxLabel = 0;
|
||||
}
|
||||
}
|
||||
nCol = pIdx->nColumn;
|
||||
nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
|
||||
regBase = sqlite3GetTempRange(pParse, nCol);
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
for(j=0; j<nCol; j++){
|
||||
@ -659,7 +675,7 @@ int sqlite3GenerateIndexKey(
|
||||
sqlite3ColumnDefault(v, pTab, idx, -1);
|
||||
}
|
||||
}
|
||||
if( doMakeRec ){
|
||||
if( regOut ){
|
||||
const char *zAff;
|
||||
if( pTab->pSelect
|
||||
|| OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
|
||||
|
@ -1869,7 +1869,7 @@ void sqlite3Pragma(
|
||||
{ OP_IfPos, 1, 0, 0}, /* 9 */
|
||||
{ OP_Halt, 0, 0, 0},
|
||||
};
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0, &jmp3);
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 0, 0, &jmp3);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 7+j, 1); /* increment entry count */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nKeyCol+1);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
|
||||
|
@ -2139,7 +2139,7 @@ static void constructAutomaticIndex(
|
||||
/* Fill the automatic index with content */
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1, 0);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user