]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix sessions module conflict handling for the sqlite_stat1 table.
authordan <dan@noemail.net>
Thu, 18 Jan 2018 16:42:11 +0000 (16:42 +0000)
committerdan <dan@noemail.net>
Thu, 18 Jan 2018 16:42:11 +0000 (16:42 +0000)
FossilOrigin-Name: f05ee74e05c401eb075a1ba65179662a08a5c3d5b55fc81f2acc841e841dd055

ext/session/sessionstat1.test
ext/session/sqlite3session.c
manifest
manifest.uuid

index 22b2de8dbcd3fe19ed36b474268fcb97258ca390..082c02bcf1969fe3eb3ed7b5720b0deb25f69785 100644 (file)
@@ -226,9 +226,86 @@ do_scc_test 3.7.1 {
   {INSERT sqlite_stat1 0 XX. {} {t t2 b {} t 6}}
 }
 
+#-------------------------------------------------------------------------
+catch { db2 close }
+reset_db
+forcedelete test.db2
+sqlite3 db2 test.db2
+
+do_test 4.1.0 {
+  do_common_sql {
+    CREATE TABLE t1(a, b);
+    CREATE INDEX i1 ON t1(a);
+    CREATE INDEX i2 ON t1(b);
+    INSERT INTO t1 VALUES(1,1), (2,2);
+    ANALYZE;
+  }
+  execsql { DELETE FROM sqlite_stat1 }
+} {}
 
+do_test 4.1.1 {
+  execsql { INSERT INTO t1 VALUES(3,3); }
+  set C [changeset_from_sql {ANALYZE}]
+  set ::c [list]
+  proc xConflict {args} {
+    lappend ::c $args
+    return "OMIT"
+  }
+  sqlite3changeset_apply db2 $C xConflict
+  set ::c
+} [list {*}{
+  {INSERT sqlite_stat1 CONFLICT {t t1 t i1 t {3 1}} {t t1 t i1 t {2 1}}}
+  {INSERT sqlite_stat1 CONFLICT {t t1 t i2 t {3 1}} {t t1 t i2 t {2 1}}}
+}]
+
+do_execsql_test -db db2 4.1.2 {
+  SELECT * FROM sqlite_stat1 ORDER BY 1,2;
+} {t1 i1 {2 1} t1 i2 {2 1}}
+
+do_test 4.1.3 {
+  proc xConflict {args} {
+    return "REPLACE"
+  }
+  sqlite3changeset_apply db2 $C xConflict
+  execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
+} {t1 i1 {3 1} t1 i2 {3 1}}
+
+do_test 4.2.0 {
+  do_common_sql { 
+    DROP TABLE t1;
+    CREATE TABLE t3(x,y);
+    INSERT INTO t3 VALUES('a','a');
+    INSERT INTO t3 VALUES('b','b');
+    ANALYZE;
+  }
+  execsql { DELETE FROM sqlite_stat1 }
+} {}
+do_test 4.2.1 {
+  execsql { INSERT INTO t3 VALUES('c','c'); }
+  set C [changeset_from_sql {ANALYZE}]
+  set ::c [list]
+  proc xConflict {args} {
+    lappend ::c $args
+    return "OMIT"
+  }
+  sqlite3changeset_apply db2 $C xConflict
+  set ::c
+} [list {*}{
+  {INSERT sqlite_stat1 CONFLICT {t t3 b {} t 3} {t t3 b {} t 2}}
+}]
 
+db2 null null
+do_execsql_test -db db2 4.2.2 {
+  SELECT * FROM sqlite_stat1 ORDER BY 1,2;
+} {t3 null 2}
 
+do_test 4.2.3 {
+  proc xConflict {args} {
+    return "REPLACE"
+  }
+  sqlite3changeset_apply db2 $C xConflict
+  execsql { SELECT * FROM sqlite_stat1 ORDER BY 1,2 } db2
+} {t3 null 3}
 
 finish_test
 
index fa7dd677a11a49ea591b5d4722d6049cef219a71..ec1a93e08ef5e8957b82ab063a97ed06504c68f0 100644 (file)
@@ -3378,7 +3378,7 @@ struct SessionApplyCtx {
   int nCol;                       /* Size of azCol[] and abPK[] arrays */
   const char **azCol;             /* Array of column names */
   u8 *abPK;                       /* Boolean array - true if column is in PK */
-
+  int bStat1;                     /* True if table is sqlite_stat1 */
   int bDeferConstraints;          /* True to defer constraints */
   SessionBuffer constraints;      /* Deferred constraints are stored here */
 };
@@ -3981,11 +3981,25 @@ static int sessionApplyOneOp(
 
   }else{
     assert( op==SQLITE_INSERT );
-    rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
-    if( rc!=SQLITE_OK ) return rc;
+    if( p->bStat1 ){
+      /* Check if there is a conflicting row. For sqlite_stat1, this needs
+      ** to be done using a SELECT, as there is no PRIMARY KEY in the 
+      ** database schema to throw an exception if a duplicate is inserted.  */
+      rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
+      if( rc==SQLITE_ROW ){
+        rc = SQLITE_CONSTRAINT;
+        sqlite3_reset(p->pSelect);
+      }
+    }
+
+    if( rc==SQLITE_OK ){
+      rc = sessionBindRow(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
+      if( rc!=SQLITE_OK ) return rc;
+
+      sqlite3_step(p->pInsert);
+      rc = sqlite3_reset(p->pInsert);
+    }
 
-    sqlite3_step(p->pInsert);
-    rc = sqlite3_reset(p->pInsert);
     if( (rc&0xff)==SQLITE_CONSTRAINT ){
       rc = sessionConflictHandler(
           SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace
@@ -4222,13 +4236,16 @@ static int sessionChangesetApply(
             if( (rc = sessionStat1Sql(db, &sApply) ) ){
               break;
             }
-          }else
-          if((rc = sessionSelectRow(db, zTab, &sApply))
-          || (rc = sessionUpdateRow(db, zTab, &sApply))
-          || (rc = sessionDeleteRow(db, zTab, &sApply))
-          || (rc = sessionInsertRow(db, zTab, &sApply))
-          ){
-            break;
+            sApply.bStat1 = 1;
+          }else{
+            if((rc = sessionSelectRow(db, zTab, &sApply))
+                || (rc = sessionUpdateRow(db, zTab, &sApply))
+                || (rc = sessionDeleteRow(db, zTab, &sApply))
+                || (rc = sessionInsertRow(db, zTab, &sApply))
+              ){
+              break;
+            }
+            sApply.bStat1 = 0;
           }
         }
         nTab = sqlite3Strlen30(zTab);
index 8c535b94095b66766526b55fd0787b5770c2c56e..1dd8d9aec309a3ff9f59f2fbf0724adb689ebf41 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Simplify\sthe\ssessions\spreupdate-hook\slogic\sfor\stransforming\sNULL\sto\sX''\sfor\ncolumn\ssqlite_stat1.idx.
-D 2018-01-18T15:06:23.750
+C Fix\ssessions\smodule\sconflict\shandling\sfor\sthe\ssqlite_stat1\stable.
+D 2018-01-18T16:42:11.152
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 38f84f301cbef443b2d269f67a74b8cc536469831f70df7c3e912acc04932cc2
@@ -398,9 +398,9 @@ F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28
 F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
 F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
-F ext/session/sessionstat1.test 16268a9bf62ab19c9bc9e41404bf7a13b5fd37c9cb6cf278a472f0c6c50d7ac1
+F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
 F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
-F ext/session/sqlite3session.c 55f20fa4a9b6acc338e11867439633c7faa3d18809cdd826fde6abf9a75dd7a0
+F ext/session/sqlite3session.c 989466bba4dff0ede8d4c450b1fc65ca222b87e31193eddbf3931b88bf898a57
 F ext/session/sqlite3session.h cb4d860101ba6d3ac810f18684539b766d24d668fa2436cdde90d711af9464fb
 F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
@@ -1700,7 +1700,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 25bf734be1b3883fccf12ac4d93d50289aa307fb60a52e0e32df12f7ee4edc7a
-R f7c998dd2622eae2189b630c53aa0780
+P 089d7cecaaa47db58320b216a111a5e56123d022008be6c81bc0746148bbdb58
+R b26168110a43028fdb5773dcda862810
 U dan
-Z 3f8bd6ff445f731b364c070e53a9b8ca
+Z 3667003c7f66cdcf6e4cbccaf82894fb
index 0823a466b216ce6e4c0c9414ff7883444f700c3b..fd362a9c44a39631a4582cfe84f553793491946c 100644 (file)
@@ -1 +1 @@
-089d7cecaaa47db58320b216a111a5e56123d022008be6c81bc0746148bbdb58
\ No newline at end of file
+f05ee74e05c401eb075a1ba65179662a08a5c3d5b55fc81f2acc841e841dd055
\ No newline at end of file