]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Optimize further cases of restarting an RBU vacuum.
authordan <dan@noemail.net>
Mon, 6 May 2019 20:40:23 +0000 (20:40 +0000)
committerdan <dan@noemail.net>
Mon, 6 May 2019 20:40:23 +0000 (20:40 +0000)
FossilOrigin-Name: 6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2

ext/rbu/rbuvacuum4.test [new file with mode: 0644]
ext/rbu/sqlite3rbu.c
manifest
manifest.uuid

diff --git a/ext/rbu/rbuvacuum4.test b/ext/rbu/rbuvacuum4.test
new file mode 100644 (file)
index 0000000..751d9e9
--- /dev/null
@@ -0,0 +1,86 @@
+# 2019 Jan 3
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file contains tests for the RBU module. More specifically, it
+# contains tests to ensure that the sqlite3rbu_vacuum() API works as
+# expected.
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set testprefix rbuvacuum4
+
+set step 1
+
+do_execsql_test 1.0 {
+  CREATE TABLE t1(a PRIMARY KEY, b, c) WITHOUT ROWID;
+  INSERT INTO t1 VALUES(1, 2, 3);
+  INSERT INTO t1 VALUES(4, 5, 6);
+  INSERT INTO t1 VALUES(7, 8, 9);
+}
+do_rbu_vacuum_test 1.1 1
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 2.0 {
+  CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
+  INSERT INTO t1 VALUES(1, 2, 3);
+  INSERT INTO t1 VALUES(4, 5, 6);
+  INSERT INTO t1 VALUES(7, 8, 9);
+}
+do_rbu_vacuum_test 2.1 1
+do_execsql_test 2.2 {
+  SELECT * FROM t1;
+} {1 2 3 4 5 6 7 8 9}
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 3.0 {
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
+  CREATE INDEX i1 oN t1(b, c);
+  INSERT INTO t1 VALUES(1, 2, 3);
+  INSERT INTO t1 VALUES(4, 5, 6);
+  INSERT INTO t1 VALUES(7, 8, 9);
+}
+
+do_rbu_vacuum_test 3.1 1
+
+do_execsql_test 3.2 {
+  SELECT * FROM t1;
+} {1 2 3 4 5 6 7 8 9}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 4.0 {
+  CREATE TABLE x1(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID;
+  INSERT INTO x1 VALUES(1, 1, 1, 1);
+  INSERT INTO x1 VALUES(1, 1, 2, 1);
+  INSERT INTO x1 VALUES(1, 2, 2, 1);
+
+  INSERT INTO x1 VALUES(NULL, 2, 3, NULL);
+  INSERT INTO x1 VALUES(NULL, 2, 4, NULL);
+  INSERT INTO x1 VALUES(NULL, 2, 5, NULL);
+
+  CREATE INDEX x1ad ON x1(d, a);
+}
+
+do_rbu_vacuum_test 4.1.1 1
+
+do_execsql_test 4.2 {
+  SELECT count(*) fROM x1
+} 6
+
+do_rbu_vacuum_test 4.1.2 0
+
+finish_test
+
+
index 0551706a67498e418507feaaaf57cb915503734b..37acecff003c49d8fa92dbfc9143cc7cc3b6cec2 100644 (file)
@@ -1476,6 +1476,7 @@ static char *rbuVacuumTableStart(
           zSelect = rbuMPrintf(p, "%z%squote(\"%w\")", zSelect, zSep2, zCol);
           zSep = ", ";
           zSep2 = "||','||";
+          break;
         }
       }
       if( i==pIter->nTblCol ) break;
@@ -1503,6 +1504,100 @@ static char *rbuVacuumTableStart(
   return zRet;
 }
 
+char *rbuVacuumIndexStart(
+  sqlite3rbu *p, 
+  RbuObjIter *pIter
+){
+  char *zOrder = 0;
+  char *zLhs = 0;
+  char *zSelect = 0;
+  char *zVector = 0;
+  char *zRet = 0;
+  int bFailed = 0;
+
+  if( p->rc==SQLITE_OK ){
+    const char *zSep = "";
+    int iCol = 0;
+    sqlite3_stmt *pXInfo = 0;
+    p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg,
+        sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", pIter->zIdx)
+    );
+    while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
+      int iCid = sqlite3_column_int(pXInfo, 1);
+      const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
+      const char *zCol;
+      if( sqlite3_column_int(pXInfo, 3) ){
+        bFailed = 1;
+        break;
+      }
+
+      if( iCid<0 ){
+        if( pIter->eType==RBU_PK_IPK ){
+          int i;
+          for(i=0; pIter->abTblPk[i]==0; i++);
+          assert( i<pIter->nTblCol );
+          zCol = pIter->azTblCol[i];
+        }else{
+          zCol = "_rowid_";
+        }
+      }else{
+        zCol = pIter->azTblCol[iCid];
+      }
+
+      zLhs = rbuMPrintf(p, "%z%s \"%w\" COLLATE %Q",
+          zLhs, zSep, zCol, zCollate
+      );
+      zOrder = rbuMPrintf(p, "%z%s \"rbu_imp_%d%w\" COLLATE %Q DESC",
+          zOrder, zSep, iCol, zCol, zCollate
+      );
+      zSelect = rbuMPrintf(p, "%z%s quote(\"rbu_imp_%d%w\")",
+          zSelect, zSep, iCol, zCol
+      );
+      zSep = ", ";
+      iCol++;
+    }
+    rbuFinalize(p, pXInfo);
+  }
+  if( bFailed ) goto index_start_out;
+
+  if( p->rc==SQLITE_OK ){
+    int iCol;
+    sqlite3_stmt *pSel = 0;
+
+    if( p->rc==SQLITE_OK ){
+      p->rc = prepareFreeAndCollectError(p->dbMain, &pSel, &p->zErrmsg,
+          sqlite3_mprintf("SELECT %s FROM \"rbu_imp_%w\" ORDER BY %s LIMIT 1",
+            zSelect, pIter->zTbl, zOrder
+          )
+      );
+    }
+    if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){
+      const char *zSep = "";
+      for(iCol=0; iCol<pIter->nCol; iCol++){
+        const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
+        if( zQuoted[0]=='N' ){
+          bFailed = 1;
+          break;
+        }
+        zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
+        zSep = ", ";
+      }
+
+      if( !bFailed ){
+        zRet = rbuMPrintf(p, "(%s) > (%s)", zLhs, zVector);
+      }
+    }
+    rbuFinalize(p, pSel);
+  }
+
+ index_start_out:
+  sqlite3_free(zOrder);
+  sqlite3_free(zSelect);
+  sqlite3_free(zVector);
+  sqlite3_free(zLhs);
+  return zRet;
+}
+
 /*
 ** This function is used to create a SELECT list (the list of SQL 
 ** expressions that follows a SELECT keyword) for a SELECT statement 
@@ -2179,12 +2274,24 @@ static int rbuObjIterPrepareAll(
       if( p->rc==SQLITE_OK ){
         char *zSql;
         if( rbuIsVacuum(p) ){
+          const char *zStart = 0;
+          if( nOffset ){
+            zStart = rbuVacuumIndexStart(p, pIter);
+            if( zStart ){
+              sqlite3_free(zLimit);
+              zLimit = 0;
+            }
+          }
+
           zSql = sqlite3_mprintf(
-              "SELECT %s, 0 AS rbu_control FROM '%q' %s ORDER BY %s%s",
+              "SELECT %s, 0 AS rbu_control FROM '%q' %s %s %s ORDER BY %s%s",
               zCollist, 
               pIter->zDataTbl,
-              zPart, zCollist, zLimit
+              zPart, 
+              (zStart ? (zPart ? "AND" : "WHERE") : ""), zStart,
+              zCollist, zLimit
           );
+          sqlite3_free(zStart);
         }else
 
         if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){
@@ -2207,7 +2314,11 @@ static int rbuObjIterPrepareAll(
               zCollist, zLimit
           );
         }
-        p->rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pSelect, pz, zSql);
+        if( p->rc==SQLITE_OK ){
+          p->rc = prepareFreeAndCollectError(p->dbRbu,&pIter->pSelect,pz,zSql);
+        }else{
+          sqlite3_free(zSql);
+        }
       }
 
       sqlite3_free(zImposterCols);
index 9b38b304dabac39ecfc6c368171364ee5ee3e87d..44ed7b69cafbdb1b38d9b2206fe047d46a396d19 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Optimize\ssome\scases\sof\srestarting\san\sRBU\svacuum.
-D 2019-05-04T20:04:42.728
+C Optimize\sfurther\scases\sof\srestarting\san\sRBU\svacuum.
+D 2019-05-06T20:40:23.801
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -359,7 +359,8 @@ F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce
 F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
 F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
 F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
-F ext/rbu/sqlite3rbu.c 03d4acabf6a51e0714eb4119379e06464f0158ca1d6a0ebd73769b82e7477a11
+F ext/rbu/rbuvacuum4.test fcae689344a28acf1013c9e2563d334f15ef741f5a16396945701ab90799e877
+F ext/rbu/sqlite3rbu.c e2669fb2a716615f38628a0477ecd665a040970501cba2511e9dffe066e2c9c8
 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -1823,10 +1824,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c2e439bccc40825e211bfa9a88e6a251ff066ca7453d4e7cb5eab56ce7332635
-R 837402c2e896349b349ad51f4a993cdf
-T *branch * rbu-opt
-T *sym-rbu-opt *
-T -sym-trunk *
+P cdc09867ed6522026ae7bfac1f59cd79b60fba6d07d49b99b030a501a7059ee4
+R aeb9fedb3c4f55c16b474638fcef63d3
 U dan
-Z 5640124653d86c97ac59112e02d029e7
+Z ccdab55de99d2c516e9414504dca1a30
index ebf5ce1b08b54f205d14a8d245498cda6bb66c0b..049d28edef536405a8d42c489d5a9c8714df7373 100644 (file)
@@ -1 +1 @@
-cdc09867ed6522026ae7bfac1f59cd79b60fba6d07d49b99b030a501a7059ee4
\ No newline at end of file
+6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2
\ No newline at end of file