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:
drh 2013-10-24 14:16:10 +00:00
parent acbbc5ba36
commit 9eade087da
6 changed files with 46 additions and 29 deletions

View File

@ -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

View File

@ -1 +1 @@
53bb070c851db02c9d900cb041ab441895ddbfb7
0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04

View File

@ -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 ){

View File

@ -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)

View File

@ -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);

View File

@ -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);