]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Delete PRIMARY KEY index entries last. Only construct the unique prefix of
authordrh <drh@noemail.net>
Thu, 24 Oct 2013 14:16:10 +0000 (14:16 +0000)
committerdrh <drh@noemail.net>
Thu, 24 Oct 2013 14:16:10 +0000 (14:16 +0000)
an index key when deleting entries from an index.

FossilOrigin-Name: 0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04

manifest
manifest.uuid
src/build.c
src/delete.c
src/pragma.c
src/where.c

index 14497e8f1d689a380949a91c7cc29b9af6150801..41b9154edf1ed14cf4ec5a9f6c1064ef91453cb9 100644 (file)
--- a/manifest
+++ b/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
index d0a19d73136b17c0b9f921a8a13ce5f12dd32642..1e374fcb35d3b427b12b74d697ea7c6de8758f15 100644 (file)
@@ -1 +1 @@
-53bb070c851db02c9d900cb041ab441895ddbfb7
\ No newline at end of file
+0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04
\ No newline at end of file
index 1612a4fb606693f352c54c72168cfe99556f8d9f..5fd6272daba8ad540473b729808f4f28965e7f76 100644 (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 ){
index 1a38f79e70c8df414a0e0b97bfcfd5aff0cb3b93..b16cdab567eccd9adc1fd95f35a93808b5580bfc 100644 (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)
index 21f1e1a720a2e3048ef7b3f9efb47edca4ee5f31..ee85445654fd97e01c2cf321b0deb0754f4f1b0b 100644 (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);
index a43c5a39c0dd58e4e80d4f43cb7f82e6c6512259..af654e984b34ecbf745ff6dbb75f3d9b80b5448b 100644 (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);