]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove some redundant code from sqlite3rbu.c. Add test cases for RBU vacuum. rbu-opt
authordan <dan@noemail.net>
Tue, 7 May 2019 16:28:50 +0000 (16:28 +0000)
committerdan <dan@noemail.net>
Tue, 7 May 2019 16:28:50 +0000 (16:28 +0000)
FossilOrigin-Name: 7b051698d8a763d9db190fd662931266d24a4982f34f100a28641934c222e37b

ext/rbu/rbuvacuum4.test
ext/rbu/sqlite3rbu.c
manifest
manifest.uuid

index 751d9e925049b5390df4a988ffceef9ec34623d2..9984c9120a8413b890fc2db7afee45faa24e6a6b 100644 (file)
@@ -71,6 +71,7 @@ do_execsql_test 4.0 {
   INSERT INTO x1 VALUES(NULL, 2, 5, NULL);
 
   CREATE INDEX x1ad ON x1(d, a);
+  CREATE INDEX x1null ON x1(d, a) WHERE d>15;
 }
 
 do_rbu_vacuum_test 4.1.1 1
@@ -81,6 +82,26 @@ do_execsql_test 4.2 {
 
 do_rbu_vacuum_test 4.1.2 0
 
-finish_test
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 5.0 {
+  CREATE TABLE "a b c"(a, "b b" PRIMARY KEY, "c c");
+  CREATE INDEX abc1 ON "a b c"(a, "c c");
+
+  INSERT INTO "a b c" VALUES(NULL, 'a', NULL);
+  INSERT INTO "a b c" VALUES(NULL, 'b', NULL);
+  INSERT INTO "a b c" VALUES(NULL, 'c', NULL);
+
+  INSERT INTO "a b c" VALUES(1, 2, 3);
+  INSERT INTO "a b c" VALUES(3, 9, 1);
+  INSERT INTO "a b c" VALUES('aaa', 'bbb', 'ccc');
 
+  CREATE TABLE x(a);
+  INSERT INTO x VALUES('a'), ('b'), ('d');
+  CREATE UNIQUE INDEX y ON x(a);
+}
+
+do_rbu_vacuum_test 5.1 1
+
+finish_test
 
index 37acecff003c49d8fa92dbfc9143cc7cc3b6cec2..0ed2837ca713af2d6327e434643080a1c1897a2a 100644 (file)
@@ -930,7 +930,8 @@ static void rbuTargetNameFunc(
   zIn = (const char*)sqlite3_value_text(argv[0]);
   if( zIn ){
     if( rbuIsVacuum(p) ){
-      if( argc==1 || 0==sqlite3_value_int(argv[1]) ){
+      assert( argc==2 );
+      if( 0==sqlite3_value_int(argv[1]) ){
         sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC);
       }
     }else{
@@ -1417,10 +1418,18 @@ static char *rbuObjIterGetCollist(
   return zList;
 }
 
+/*
+** Return a comma separated list of the quoted PRIMARY KEY column names,
+** in order, for the current table. Before each column name, add the text
+** zPre. After each column name, add the zPost text. Use zSeparator as
+** the separator text (usually ", ").
+*/
 static char *rbuObjIterGetPkList(
   sqlite3rbu *p,                  /* RBU object */
   RbuObjIter *pIter,              /* Object iterator for column names */
-  const char *zExtra
+  const char *zPre,               /* Before each quoted column name */
+  const char *zSeparator,         /* Separator to use between columns */
+  const char *zPost               /* After each quoted column name */
 ){
   int iPk = 1;
   char *zRet = 0;
@@ -1430,8 +1439,9 @@ static char *rbuObjIterGetPkList(
     for(i=0; i<pIter->nTblCol; i++){
       if( (int)pIter->abTblPk[i]==iPk ){
         const char *zCol = pIter->azTblCol[i];
-        zRet = rbuMPrintf(p, "%z%s\"%w\"%s", zRet, zSep, zCol, zExtra);
-        zSep = ", ";
+        zRet = rbuMPrintf(p, "%z%s%s\"%w\"%s", zRet, zSep, zPre, zCol, zPost);
+        zSep = zSeparator;
+        break;
       }
     }
     if( i==pIter->nTblCol ) break;
@@ -1440,11 +1450,30 @@ static char *rbuObjIterGetPkList(
   return zRet;
 }
 
+/*
+** This function is called as part of restarting an RBU vacuum within 
+** stage 1 of the process (while the *-oal file is being built) while
+** updating a table (not an index). The table may be a rowid table or
+** a WITHOUT ROWID table. It queries the target database to find the 
+** largest key that has already been written to the target table and
+** constructs a WHERE clause that can be used to extract the remaining
+** rows from the source table. For a rowid table, the WHERE clause
+** is of the form:
+**
+**     "WHERE _rowid_ > ?"
+**
+** and for WITHOUT ROWID tables:
+**
+**     "WHERE (key1, key2) > (?, ?)"
+**
+** Instead of "?" placeholders, the actual WHERE clauses created by
+** this function contain literal SQL values.
+*/
 static char *rbuVacuumTableStart(
-  sqlite3rbu *p, 
-  RbuObjIter *pIter,
-  int bRowid,
-  const char *zWrite
+  sqlite3rbu *p,                  /* RBU handle */
+  RbuObjIter *pIter,              /* RBU iterator object */
+  int bRowid,                     /* True for a rowid table */
+  const char *zWrite              /* Target table name prefix */
 ){
   sqlite3_stmt *pMax = 0;
   char *zRet = 0;
@@ -1460,28 +1489,9 @@ static char *rbuVacuumTableStart(
     }
     rbuFinalize(p, pMax);
   }else{
-    char *zOrder = 0;
-    char *zSelect = 0;
-    char *zList = 0;
-    int iPk = 1;
-    const char *zSep = "";
-    const char *zSep2 = "";
-    while( 1 ){
-      int i;
-      for(i=0; i<pIter->nTblCol; i++){
-        if( (int)pIter->abTblPk[i]==iPk ){
-          const char *zCol = pIter->azTblCol[i];
-          zOrder = rbuMPrintf(p, "%z%s\"%w\" DESC", zOrder, zSep, zCol);
-          zList = rbuMPrintf(p, "%z%s\"%w\"", zList, zSep, zCol);
-          zSelect = rbuMPrintf(p, "%z%squote(\"%w\")", zSelect, zSep2, zCol);
-          zSep = ", ";
-          zSep2 = "||','||";
-          break;
-        }
-      }
-      if( i==pIter->nTblCol ) break;
-      iPk++;
-    }
+    char *zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", " DESC");
+    char *zSelect = rbuObjIterGetPkList(p, pIter, "quote(", "||','||", ")");
+    char *zList = rbuObjIterGetPkList(p, pIter, "", ", ", "");
 
     if( p->rc==SQLITE_OK ){
       p->rc = prepareFreeAndCollectError(p->dbMain, &pMax, &p->zErrmsg, 
@@ -1504,9 +1514,31 @@ static char *rbuVacuumTableStart(
   return zRet;
 }
 
+/*
+** This function is called as part of restating an RBU vacuum when the
+** current operation is writing content to an index. If possible, it
+** queries the target index b-tree for the largest key already written to
+** it, then composes and returns an expression that can be used in a WHERE 
+** clause to select the remaining required rows from the source table. 
+** It is only possible to return such an expression if:
+**
+**   * The index contains no DESC columns, and
+**   * The last key written to the index before the operation was 
+**     suspended does not contain any NULL values.
+**
+** The expression is of the form:
+**
+**   (index-field1, index-field2, ...) > (?, ?, ...)
+**
+** except that the "?" placeholders are replaced with literal values.
+**
+** If the expression cannot be created, NULL is returned. In this case,
+** the caller has to use an OFFSET clause to extract only the required 
+** rows from the sourct table, just as it does for an RBU update operation.
+*/
 char *rbuVacuumIndexStart(
-  sqlite3rbu *p, 
-  RbuObjIter *pIter
+  sqlite3rbu *p,                  /* RBU handle */
+  RbuObjIter *pIter               /* RBU iterator object */
 ){
   char *zOrder = 0;
   char *zLhs = 0;
@@ -2274,7 +2306,7 @@ static int rbuObjIterPrepareAll(
       if( p->rc==SQLITE_OK ){
         char *zSql;
         if( rbuIsVacuum(p) ){
-          const char *zStart = 0;
+          char *zStart = 0;
           if( nOffset ){
             zStart = rbuVacuumIndexStart(p, pIter);
             if( zStart ){
@@ -2435,7 +2467,7 @@ static int rbuObjIterPrepareAll(
           if( bRbuRowid ){
             zOrder = rbuMPrintf(p, "_rowid_");
           }else{
-            zOrder = rbuObjIterGetPkList(p, pIter, "");
+            zOrder = rbuObjIterGetPkList(p, pIter, "", ", ", "");
           }
         }
 
index 44ed7b69cafbdb1b38d9b2206fe047d46a396d19..69f1d68b6dd64caaefcb4e3bab1003f03cb9dbca 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Optimize\sfurther\scases\sof\srestarting\san\sRBU\svacuum.
-D 2019-05-06T20:40:23.801
+C Remove\ssome\sredundant\scode\sfrom\ssqlite3rbu.c.\sAdd\stest\scases\sfor\sRBU\svacuum.
+D 2019-05-07T16:28:50.534
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -359,8 +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/rbuvacuum4.test fcae689344a28acf1013c9e2563d334f15ef741f5a16396945701ab90799e877
-F ext/rbu/sqlite3rbu.c e2669fb2a716615f38628a0477ecd665a040970501cba2511e9dffe066e2c9c8
+F ext/rbu/rbuvacuum4.test 08abd9e18d8aee5bb812de0d6a928cc8bbacae58ecb1f150637e80f4c93c8afa
+F ext/rbu/sqlite3rbu.c ec93d28c5cef16ccef7ed76c2b6c410e8eb078c73705b6e7b683f88f722228f2
 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -1824,7 +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 cdc09867ed6522026ae7bfac1f59cd79b60fba6d07d49b99b030a501a7059ee4
-R aeb9fedb3c4f55c16b474638fcef63d3
+P 6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2
+R 4a715a784b4b470a8ebf2ddbf655a0cc
 U dan
-Z ccdab55de99d2c516e9414504dca1a30
+Z c393b32565e9671e4034603b54f16352
index 049d28edef536405a8d42c489d5a9c8714df7373..366634c67e2f4a02d8c859582343c6823adbfb81 100644 (file)
@@ -1 +1 @@
-6b3261bfa1d762aa29a57244a30cf5e35655f1fe9c30ee682c186dec29d7a2c2
\ No newline at end of file
+7b051698d8a763d9db190fd662931266d24a4982f34f100a28641934c222e37b
\ No newline at end of file