]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Attempt to fix multi-object DROP. Working better, but still not perfect.
authordrh <>
Thu, 29 Feb 2024 19:40:38 +0000 (19:40 +0000)
committerdrh <>
Thu, 29 Feb 2024 19:40:38 +0000 (19:40 +0000)
FossilOrigin-Name: 02f9fc73eef80f528097581580977aae46942baac2d7fb205c52f7f25472f2a8

manifest
manifest.uuid
src/build.c
src/fkey.c
src/sqliteInt.h
src/trigger.c

index 8e933bf204c606a6a9ad3ea80553b7acf486a958..84a66be780b98aeb4a55ce39f1c6c2546c4479e4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\sability\sto\sDROP\sone\sor\smore\sobjects\sof\sthe\ssame\sclass\nin\sa\ssingle\sstatement\sby\slisting\sthe\sobjects\sas\smultiple\sarguments\sto\sthe\nDROP\scommand.
-D 2024-02-29T13:44:15.183
+C Attempt\sto\sfix\smulti-object\sDROP.\s\sWorking\sbetter,\sbut\sstill\snot\sperfect.
+D 2024-02-29T19:40:38.822
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -692,7 +692,7 @@ F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
 F src/btree.c 285b493d843e7ba8ef78b6ae7d31238e904901dbc0c484f7904de4cf18fd8802
 F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
 F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
-F src/build.c 786e47a8ccefa14fbdca52e22bc51dbe24074a9c7dbe4f2afd2050736a7352c5
+F src/build.c 25384963d1b9d6ebc73777bc7c1112973ba36ea8a8ca9f0a39bd94c047ba24eb
 F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
@@ -702,7 +702,7 @@ F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
 F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
 F src/expr.c 2803f5e7e3458ced24c0de48ec3640cd7a68ec61350d99c9f30b1bcd6640bd61
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
+F src/fkey.c b7ecbc98b4da91d03e3435ca6abc167efa30f6691b090820969c4be625739e45
 F src/func.c 4204c56196847faefef57fa14e43b8e4d65eb8d7e65318abe463472e3fd148cb
 F src/global.c 765a0656d6cbf043cb272ff0ae38f39cc46713539ffe6793258ed3eb4b188b52
 F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
@@ -755,7 +755,7 @@ F src/shell.c.in 2ec564ed3ff0147036be313efeb47b3dbfb8753d5eb5ea0e90636427c6b3a36
 F src/sqlite.h.in 19a2db3995a699bd7f6dfb423856242bfceb7ec849a93c91d241d19fc28d9f0f
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h 58b7295a748ca5ed9e211510205b4a66a24c68f864225b81e19d4cf6038b40a1
+F src/sqliteInt.h bdb0bba047cd39c8733c14131c379a91f3d1f437c57f11270db14860ab09dffd
 F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
 F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -814,7 +814,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c 3f703cacdab728d7741e5a6ac242006d74fe1c2754d4f03ed889d7253259bd68
 F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
-F src/trigger.c a23049b9771927763ade8389fb6a0494324bad15394893895f6aa4e346e6b295
+F src/trigger.c a6fd09ef8b4613db9b9db046ff5abacda4bf517a09da889031d22c7c18ac6c49
 F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
 F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
 F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
@@ -1069,7 +1069,7 @@ F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
 F test/distinct.test 691c9e850b0d0b56b66e7e235453198cb4cf0760e324b7403d3c5abbeab0a014
 F test/distinct2.test bb71cc7b5e58e895787f9910a788c254f679928d324732d063fe9bc202ecbe71
 F test/distinctagg.test 40d7169ae5846caaf62c6e307d2ca3c333daf9b6f7cde888956a339a97afe85f
-F test/drop-many.test 30dd091a4fd0a04b1a38e70c93f69c55749e62a3d895ac5e09277cd97caa5bbf w test/drop1.test
+F test/drop-many.test 30dd091a4fd0a04b1a38e70c93f69c55749e62a3d895ac5e09277cd97caa5bbf
 F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
 F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
 F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50
@@ -2177,8 +2177,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 803481f25020f3c25941f1e7d1a8071937820dea951e8798198b0b0fa3fb48ce
-R b06b7d333b1bcab630a4dab891f8b26c
+P 2266086cf08ee710338667d1cf0b1e81ce7380101707db272ce27124404068a0
+R d3490d0df600a6062bf18828bf499fc3
 U drh
-Z 594e686b84606bfb7b18560464880c6c
+Z 68bbccadbf2f82f26c1558f6e4711d24
 # Remove this line to create a well-formed Fossil manifest.
index c56c4d0e0a31f80333798c19c1a34e17a0fbfd83..7cbde2128229e98218e92aa156a57e26c2a559cd 100644 (file)
@@ -1 +1 @@
-2266086cf08ee710338667d1cf0b1e81ce7380101707db272ce27124404068a0
\ No newline at end of file
+02f9fc73eef80f528097581580977aae46942baac2d7fb205c52f7f25472f2a8
\ No newline at end of file
index 9302e0d195b756b010515d96f719cbd55abc2983..dbad6443044a6891abae0a991821e442475f3b0e 100644 (file)
@@ -3477,11 +3477,11 @@ static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
 */
 void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
   Table *pTab;
-  Vdbe *v;
   sqlite3 *db = pParse->db;
   int iDb;
   int ii;
 
+  (void)sqlite3GetVdbe(pParse);
   sqlite3ReadSchema(pParse);
   assert( pName!=0 || pParse->nErr!=0 );
   for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
@@ -3572,17 +3572,41 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
       break;
     }
 #endif
+    /* If this table or view has appeared previously in the list of tables
+    ** or views to be dropped, then the prior appearance is sufficient so
+    ** skip this one. */
+    if( ii>0 ){
+      int jj;
+      for(jj=0; jj<ii && pName->a[jj].pTab!=pTab; jj++){}
+      if( jj<ii ) continue;
+    }
 
-    /* Generate code to remove the table from the schema table
-    ** on disk.
-    */
-    v = sqlite3GetVdbe(pParse);
-    if( v ){
+    /* Remember the table for use in the second pass */
+    pName->a[ii].pTab = pTab;
+    pTab->nTabRef++;
+  }
+
+  for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
+    pTab = pName->a[ii].pTab;
+    if( pTab ){
+      iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+    
+      /* Generate code to clear this table from sqlite_statN and to
+      ** cascade foreign key constraints.
+      */
       sqlite3BeginWriteOperation(pParse, 1, iDb);
-      if( !isView ){
+      if( IsOrdinaryTable(pTab) ){
         sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
-        sqlite3FkDropTable(pParse, pName, pTab);
+        sqlite3FkDropTable(pParse, &pName->a[ii], pTab);
       }
+    }
+  }
+
+  /* Generate code to actually delete the tables/views in a second pass. */
+  for(ii=0; pParse->nErr==0 && ii<pName->nSrc; ii++){
+    pTab = pName->a[ii].pTab;
+    if( pTab ){
+      iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
       sqlite3CodeDropTable(pParse, pTab, iDb, isView);
     }
   }
@@ -4586,8 +4610,8 @@ void sqlite3DefaultRowEst(Index *pIdx){
 */
 void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
   Index *pIndex;
-  Vdbe *v;
   sqlite3 *db = pParse->db;
+  Vdbe *v;
   int iDb;
   int ii;
 
@@ -4635,20 +4659,32 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
     }
 #endif
 
+    /* Skip over redundant DROP INDEXes */
+    if( ii>0 ){
+      int jj;
+      for(jj=0; jj<ii; jj++){
+        if( pName->a[jj].addrFillSub!=iDb ) continue;
+        if( pName->a[jj].regReturn!=pIndex->tnum ) continue;
+        break;
+      }
+      if( jj<ii ) continue;
+    }
+    pName->a[ii].addrFillSub = iDb;
+    pName->a[ii].regReturn = pIndex->tnum;
+
     /* Generate code to remove the index and from the schema table */
     v = sqlite3GetVdbe(pParse);
-    if( v ){
-      sqlite3BeginWriteOperation(pParse, 1, iDb);
-      sqlite3NestedParse(pParse,
-         "DELETE FROM %Q." LEGACY_SCHEMA_TABLE
-         " WHERE name=%Q AND type='index'",
-         db->aDb[iDb].zDbSName, pIndex->zName
-      );
-      sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
-      sqlite3ChangeCookie(pParse, iDb);
-      destroyRootPage(pParse, pIndex->tnum, iDb);
-      sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
-    }
+    if( v==0 ) break;
+    sqlite3BeginWriteOperation(pParse, 1, iDb);
+    sqlite3NestedParse(pParse,
+       "DELETE FROM %Q." LEGACY_SCHEMA_TABLE
+       " WHERE name=%Q AND type='index'",
+       db->aDb[iDb].zDbSName, pIndex->zName
+    );
+    sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
+    sqlite3ChangeCookie(pParse, iDb);
+    destroyRootPage(pParse, pIndex->tnum, iDb);
+    sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
   }
   sqlite3SrcListDelete(db, pName);
 }
index bace1ae5e2d3b57285ad7c983083faf75bacb08a..82c25b67dae4711503891b286787f853e72506e5 100644 (file)
@@ -732,11 +732,12 @@ void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){
 ** the table from the database. Triggers are disabled while running this
 ** DELETE, but foreign key actions are not.
 */
-void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
+void sqlite3FkDropTable(Parse *pParse, SrcItem *pName, Table *pTab){
   sqlite3 *db = pParse->db;
   if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
     int iSkip = 0;
     Vdbe *v = sqlite3GetVdbe(pParse);
+    SrcList *pSrc;
 
     assert( v );                  /* VDBE has already been allocated */
     assert( IsOrdinaryTable(pTab) );
@@ -756,7 +757,12 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
     }
 
     pParse->disableTriggers = 1;
-    sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
+    pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
+    if( pSrc ){
+      pSrc->a[0].zDatabase = sqlite3DbStrDup(db, pName->zDatabase);
+      pSrc->a[0].zName = sqlite3DbStrDup(db, pName->zName);
+      sqlite3DeleteFrom(pParse, pSrc, 0, 0, 0);
+    }
     pParse->disableTriggers = 0;
 
     /* If the DELETE has generated immediate foreign key constraint 
index f5920748ba3ed39a930325d095bfdf2e1fe27b5d..9a9a13f3766986579357140e3071efdfca5a6eef 100644 (file)
@@ -3314,6 +3314,7 @@ struct SrcItem {
   union {
     Index *pIBIndex;  /* Index structure corresponding to u1.zIndexedBy */
     CteUse *pCteUse;  /* CTE Usage info when fg.isCte is true */
+    Trigger *pTrig;   /* Trigger in argument list of DROP TRIGGER */
   } u2;
 };
 
@@ -5574,7 +5575,7 @@ const char *sqlite3JournalModename(int);
 */
 #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
   void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
-  void sqlite3FkDropTable(Parse*, SrcList *, Table*);
+  void sqlite3FkDropTable(Parse*, SrcItem*, Table*);
   void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
   int sqlite3FkRequired(Parse*, Table*, int*, int);
   u32 sqlite3FkOldmask(Parse*, Table*);
index c388bacfbe419840a35f2cf73126a1d6c7813f52..8fe95c32c74d3966059e2a518269b5c09eda08b4 100644 (file)
@@ -639,6 +639,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
       pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
       if( pTrigger ) break;
     }
+    pName->a[ii].u2.pTrig = pTrigger;
     if( !pTrigger ){
       if( !noErr ){
         sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a+ii);
@@ -648,9 +649,16 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
       testcase( ii>0 );
       testcase( ii+1<pName->nSrc );
       pParse->checkSchema = 1;
-    }else{
-      sqlite3DropTriggerPtr(pParse, pTrigger);
+      continue;
+    }
+    if( ii>0 ){
+      int jj;
+      for(jj=0; jj<ii; jj++){
+        if( pName->a[jj].u2.pTrig==pTrigger ) break;
+      }
+      if( jj<ii ) continue;
     }
+    sqlite3DropTriggerPtr(pParse, pTrigger);
   }
   sqlite3SrcListDelete(db, pName);
 }