]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If the special "sqlite_rbu_replace_hack" table is present in an RBU database, use...
authordan <Dan Kennedy>
Wed, 11 Aug 2021 18:44:50 +0000 (18:44 +0000)
committerdan <Dan Kennedy>
Wed, 11 Aug 2021 18:44:50 +0000 (18:44 +0000)
FossilOrigin-Name: 4b73e151cdb4b89bdd2f1bab5c0378500234ce6c479cc1d8cd4e006be79d1162

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

diff --git a/ext/rbu/rbuhack.test b/ext/rbu/rbuhack.test
new file mode 100644 (file)
index 0000000..562cfa6
--- /dev/null
@@ -0,0 +1,165 @@
+# 2014 August 30
+#
+# 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.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set ::testprefix rbu1
+
+forcedelete test.db2
+do_execsql_test 1.0 {
+  CREATE TABLE t1(a INTEGER, b, c, PRIMARY KEY(a));
+  CREATE INDEX t1b ON t1(b);         -- root=3
+  CREATE INDEX t1c ON t1(c);         -- root=4
+
+  ATTACH 'test.db2' AS 'rbu';
+  CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
+  INSERT INTO data_t1 VALUES(1, 1, 1, 0);
+  INSERT INTO data_t1 VALUES(2, 2, 2, 0);
+  INSERT INTO data_t1 VALUES(3, 3, 3, 0);
+}
+
+do_test 1.1 {
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 3
+  execsql {
+    CREATE TABLE imp1(b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
+    INSERT INTO imp1 VALUES(2, 2);
+  }
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 3
+} {}
+
+db close
+sqlite3 db test.db
+
+do_test 1.2 {
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 4
+  execsql {
+    CREATE TABLE imp1(b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
+    INSERT INTO imp1 VALUES(3, 3);
+  }
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 4
+} {}
+db close
+db_save
+
+sqlite3 db test.db
+do_catchsql_test 1.3 { PRAGMA integrity_check } {0 {{wrong # of entries in index t1c} {wrong # of entries in index t1b}}}
+db close
+
+do_test 1.4 {
+  sqlite3rbu rbu test.db test.db2
+  while 1 {
+    set rc [rbu step]
+    if {$rc!="SQLITE_OK"} break
+  }
+  list [catch { rbu close } msg] $msg
+} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: t1.b, t1.a}}
+
+db_restore
+sqlite3 db test.db2
+do_execsql_test 1.5 {
+  PRAGMA writable_schema = 1;
+  CREATE TABLE sqlite_rbu_replace_hack('v');
+}
+db close
+
+do_test 1.6 {
+  sqlite3rbu rbu test.db test.db2
+  while 1 {
+    set rc [rbu step]
+    if {$rc!="SQLITE_OK"} break
+  }
+  list [catch { rbu close } msg] $msg
+} {0 SQLITE_DONE}
+
+sqlite3 db test.db
+do_execsql_test 1.7 {
+  PRAGMA integrity_check;
+  SELECT count(*) FROM t1;
+} {ok 3}
+
+#-------------------------------------------------------------------------
+
+reset_db
+forcedelete test.db2
+do_execsql_test 2.0 {
+  CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
+  CREATE INDEX t1c ON t1(c);         -- root=4
+
+  ATTACH 'test.db2' AS 'rbu';
+  CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
+  INSERT INTO data_t1 VALUES(1, 1, 1, 0);
+  INSERT INTO data_t1 VALUES(2, 2, 2, 0);
+  INSERT INTO data_t1 VALUES(3, 3, 3, 0);
+}
+
+do_test 2.1 {
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 3
+  execsql {
+    CREATE TABLE imp1(a, b, id, PRIMARY KEY(b, id)) WITHOUT ROWID;
+    INSERT INTO imp1 VALUES(2, 2, 2);
+  }
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 3
+} {}
+
+db close
+sqlite3 db test.db
+
+do_test 2.2 {
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 4
+  execsql {
+    CREATE TABLE imp1(c, id, PRIMARY KEY(c, id)) WITHOUT ROWID;
+    INSERT INTO imp1 VALUES(3, 3);
+  }
+  sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 4
+} {}
+db close
+db_save
+
+sqlite3 db test.db
+do_catchsql_test 2.3 { PRAGMA integrity_check } {0 {{wrong # of entries in index t1c} {wrong # of entries in index sqlite_autoindex_t1_1}}}
+db close
+
+do_test 2.4 {
+  sqlite3rbu rbu test.db test.db2
+  while 1 {
+    set rc [rbu step]
+    if {$rc!="SQLITE_OK"} break
+  }
+  list [catch { rbu close } msg] $msg
+} {1 {SQLITE_CONSTRAINT - UNIQUE constraint failed: t1.a, t1.b}}
+
+db_restore
+sqlite3 db test.db2
+do_execsql_test 2.5 {
+  PRAGMA writable_schema = 1;
+  CREATE TABLE sqlite_rbu_replace_hack('v');
+}
+db close
+
+do_test 2.6 {
+  sqlite3rbu rbu test.db test.db2
+  while 1 {
+    set rc [rbu step]
+    if {$rc!="SQLITE_OK"} break
+  }
+  list [catch { rbu close } msg] $msg
+} {0 SQLITE_DONE}
+
+sqlite3 db test.db
+do_execsql_test 2.7 {
+  PRAGMA integrity_check;
+  SELECT count(*) FROM t1;
+} {ok 3}
+
+
+
+finish_test
+
index 5c2ae95453c4f75fd25edc2b37d5a072c06ef7c3..614834e245b7dd5efc8b966a7b23b3a1abc1f8ed 100644 (file)
 # define RBU_ENABLE_DELTA_CKSUM 0
 #endif
 
+#define RBU_REPLACE_HACK_TABLE "sqlite_rbu_replace_hack"
+
 /*
 ** Swap two objects of type TYPE.
 */
@@ -376,6 +378,7 @@ struct sqlite3rbu {
   char *zRbu;                     /* Path to rbu db */
   char *zState;                   /* Path to state db (or NULL if zRbu) */
   char zStateDb[5];               /* Db name for state ("stat" or "main") */
+  int bRbuReplaceHack;            /* Do the REPLACE hack */
   int rc;                         /* Value returned by last rbu_step() call */
   char *zErrmsg;                  /* Error message if rc!=SQLITE_OK */
   int nStep;                      /* Rows processed for current object */
@@ -2350,7 +2353,10 @@ static int rbuObjIterPrepareAll(
       if( p->rc==SQLITE_OK ){
         p->rc = prepareFreeAndCollectError(
             p->dbMain, &pIter->pInsert, &p->zErrmsg,
-          sqlite3_mprintf("INSERT INTO \"rbu_imp_%w\" VALUES(%s)", zTbl, zBind)
+          sqlite3_mprintf("%s INTO \"rbu_imp_%w\" VALUES(%s)", 
+            p->bRbuReplaceHack ? "REPLACE" : "INSERT",
+            zTbl, zBind
+          )
         );
       }
 
@@ -2442,7 +2448,8 @@ static int rbuObjIterPrepareAll(
       if( p->rc==SQLITE_OK ){
         p->rc = prepareFreeAndCollectError(p->dbMain, &pIter->pInsert, pz,
             sqlite3_mprintf(
-              "INSERT INTO \"%s%w\"(%s%s) VALUES(%s)", 
+              "%s INTO \"%s%w\"(%s%s) VALUES(%s)", 
+              p->bRbuReplaceHack ? "REPLACE" : "INSERT",
               zWrite, zTbl, zCollist, (bRbuRowid ? ", _rowid_" : ""), zBindings
             )
         );
@@ -2744,6 +2751,24 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
   rc2 = sqlite3_finalize(pStmt);
   if( rc==SQLITE_OK ) rc = rc2;
 
+  /* If this is not a vacuum operation, search for the special table
+  ** "sqlite_rbu_replace_hack". Set the flag if it is found.
+  */
+  if( rc==SQLITE_OK && !rbuIsVacuum(p) ){
+    sqlite3_stmt *pQuery = 0;
+    rc = prepareFreeAndCollectError(p->dbRbu, &pQuery, &p->zErrmsg, 
+        sqlite3_mprintf("SELECT 1 FROM main.sqlite_master WHERE name='%s'",
+          RBU_REPLACE_HACK_TABLE
+        )
+    );
+    if( rc==SQLITE_OK ){
+      if( sqlite3_step(pQuery)==SQLITE_ROW ){
+        p->bRbuReplaceHack = 1;
+      }
+      rc = sqlite3_finalize(pQuery);
+    }
+  }
+
   p->rc = rc;
   return pRet;
 }
index 44f902f667a0b21d7a06a5397fa00eb1ff6c1aec..186b47282b3a86b9244cc422be3a04bb709ca5e1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Version\s3.30.0
-D 2019-10-04T15:03:17.190
+C If\sthe\sspecial\s"sqlite_rbu_replace_hack"\stable\sis\spresent\sin\san\sRBU\sdatabase,\suse\sREPLACE\sinstead\sof\sINSERT\swhen\swriting\sindex\sentries\sto\simposter\stables.
+D 2021-08-11T18:44:50.304
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -353,6 +353,7 @@ F ext/rbu/rbufault2.test c81327a3ac2c385b9b954db3644d4e0df93eeebfc3de9f1f29975a1
 F ext/rbu/rbufault3.test b2fcc9db5c982b869f67d1d4688d8cb515d5b92f58011fff95665f2e62cec179
 F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a
 F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d
+F ext/rbu/rbuhack.test 95e7b35e58d5b2a8d182dde1a404949edf077c07485e6c2bce8a7f582941e729
 F ext/rbu/rbumisc.test 329986cf5dd51890c4eb906c2f960ebb773a79a64bed90f506b7c417825b37eb
 F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9
 F ext/rbu/rbupartial.test f25df014b8dbe3c5345851fba6e66f79ab237f57dc201b2d5f0dbae658ae5a4c
@@ -365,7 +366,7 @@ F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697
 F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
 F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
 F ext/rbu/rbuvacuum4.test a78898e438a44803eb2bc897ba3323373c9f277418e2d6d76e90f2f1dbccfd10
-F ext/rbu/sqlite3rbu.c f3a3e09f575157052813be667d6ab3b54f47fb02e6e1c9f767ad7bb8f1fb90b3
+F ext/rbu/sqlite3rbu.c e8424eb4700fa5c957b78704b76d3167283c17953a41f50413a1d55d48e93cad
 F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
 F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -1846,10 +1847,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7f9a4b6015ac332a04d3e394a6b3210fc95253d8786a261178a5639cb8d9d987
-R f116075cb1c47b7928f41444f3803579
-T +bgcolor * #d0c0ff
-T +sym-release *
-T +sym-version-3.30.0 *
-U drh
-Z edadfb0c72633ac9bcd13396063b6815
+P c20a35336432025445f9f7e289d0cc3e4003fb17f45a4ce74c6269c407c6e09f
+R a8856db772e2bb9949da7c267e1829ab
+T *branch * rbu-replace-hack
+T *sym-rbu-replace-hack *
+T -sym-trunk *
+U dan
+Z aa38f9f5e27caa9871ead4f8e1acfb36
index 59c1946757218ff7060bb5a46678c03119c1251f..e6d31167ac35c03db4f4ad3b423b733b8cf16ff8 100644 (file)
@@ -1 +1 @@
-c20a35336432025445f9f7e289d0cc3e4003fb17f45a4ce74c6269c407c6e09f
\ No newline at end of file
+4b73e151cdb4b89bdd2f1bab5c0378500234ce6c479cc1d8cd4e006be79d1162
\ No newline at end of file