]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a new method to sessions - sqlite3sessions_fullchangeset() - to return a changese...
authordan <dan@noemail.net>
Tue, 23 Aug 2016 17:02:28 +0000 (17:02 +0000)
committerdan <dan@noemail.net>
Tue, 23 Aug 2016 17:02:28 +0000 (17:02 +0000)
FossilOrigin-Name: efa761b2f509844b9212dd20bf0d082c6338e83f

ext/session/changebatch1.test
ext/session/sqlite3changebatch.c
ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index 056512aca352fbadcc70f76d1c5aeab7be38cda9..fc3f50ab4c8247b8b2a6f3687626f0911625843a 100644 (file)
@@ -19,14 +19,19 @@ ifcapable !session {finish_test; return}
 
 set testprefix changebatch1
 
-proc do_changebatch_test {tn args} {
+proc sql_to_changeset {method sql} {
+  sqlite3session S db main
+  S attach *
+  execsql $sql
+  set ret [S $method]
+  S delete
+  return $ret
+}
+
+proc do_changebatch_test {tn method args} {
   set C [list]
   foreach a $args {
-    sqlite3session S db main
-    S attach *
-    execsql $a
-    lappend C [S changeset]
-    S delete
+    lappend C [sql_to_changeset $method $a]
   }
 
   sqlite3changebatch cb db
@@ -42,49 +47,111 @@ proc do_changebatch_test {tn args} {
   cb delete
 }
 
-do_execsql_test 1.0 {
-  CREATE TABLE t1(a PRIMARY KEY, b);
+proc do_changebatch_test1 {tn args} {
+  uplevel do_changebatch_test $tn changeset $args
 }
-
-do_changebatch_test 1.1 {
-  INSERT INTO t1 VALUES(1, 1);
-} {
-  DELETE FROM t1 WHERE a=1;
+proc do_changebatch_test2 {tn args} {
+  uplevel do_changebatch_test $tn fullchangeset $args
 }
 
-do_execsql_test 1.2.0 {
-  INSERT INTO t1 VALUES(1, 1);
-  INSERT INTO t1 VALUES(2, 2);
-  INSERT INTO t1 VALUES(3, 3);
-}
-do_changebatch_test 1.2.1 {
-  DELETE FROM t1 WHERE a=2;
+#-------------------------------------------------------------------------
+# The body of the following loop contains tests for database schemas
+# that do not feature multi-column UNIQUE constraints. In this case
+# it doesn't matter if the changesets are generated using
+# sqlite3session_changeset() or sqlite3session_fullchangeset().
+#
+foreach {tn testfunction} {
+  1 do_changebatch_test1
+  2 do_changebatch_test2
 } {
-  INSERT INTO t1 VALUES(2, 2);
+  reset_db
+
+  #-------------------------------------------------------------------------
+  #
+  do_execsql_test $tn.1.0 {
+    CREATE TABLE t1(a PRIMARY KEY, b);
+  }
+  
+  $testfunction $tn.1.1 {
+    INSERT INTO t1 VALUES(1, 1);
+  } {
+    DELETE FROM t1 WHERE a=1;
+  }
+  
+  do_execsql_test $tn.1.2.0 {
+    INSERT INTO t1 VALUES(1, 1);
+    INSERT INTO t1 VALUES(2, 2);
+    INSERT INTO t1 VALUES(3, 3);
+  }
+  $testfunction $tn.1.2.1 {
+    DELETE FROM t1 WHERE a=2;
+  } {
+    INSERT INTO t1 VALUES(2, 2);
+  }
+  
+  #-------------------------------------------------------------------------
+  #
+  do_execsql_test $tn.2.0 {
+    CREATE TABLE x1(a, b PRIMARY KEY, c UNIQUE);
+    CREATE TABLE x2(a PRIMARY KEY, b UNIQUE, c UNIQUE);
+  
+    INSERT INTO x1 VALUES(1, 1, 'a');
+    INSERT INTO x1 VALUES(1, 2, 'b');
+    INSERT INTO x1 VALUES(1, 3, 'c');
+  }
+  
+  $testfunction $tn.2.1 {
+    DELETE FROM x1 WHERE b=2;
+  } {
+    UPDATE x1 SET c='b' WHERE b=3;
+  }
+  
+  $testfunction $tn.2.2 {
+    DELETE FROM x1 WHERE b=1;
+  } {
+    INSERT INTO x1 VALUES(1, 5, 'a');
+  }
 }
 
 #-------------------------------------------------------------------------
-do_execsql_test 2.0 {
-  CREATE TABLE x1(a, b PRIMARY KEY, c UNIQUE);
-  CREATE TABLE x2(a PRIMARY KEY, b UNIQUE, c UNIQUE);
-
-  INSERT INTO x1 VALUES(1, 1, 'a');
-  INSERT INTO x1 VALUES(1, 2, 'b');
-  INSERT INTO x1 VALUES(1, 3, 'c');
+# Test some multi-column UNIQUE constraints. First Using _changeset() to
+# demonstrate the problem, then using _fullchangeset() to show that it has
+# been fixed.
+#
+reset_db
+do_execsql_test 3.0 {
+  CREATE TABLE y1(a PRIMARY KEY, b, c, UNIQUE(b, c));
+  INSERT INTO y1 VALUES(1, 1, 1);
+  INSERT INTO y1 VALUES(2, 2, 2);
+  INSERT INTO y1 VALUES(3, 3, 3);
+  INSERT INTO y1 VALUES(4, 3, 4);
+  BEGIN;
 }
 
-do_changebatch_test 2.1 {
-  DELETE FROM x1 WHERE b=2;
-} {
-  UPDATE x1 SET c='b' WHERE b=3;
-}
+do_test 3.1.1 {
+  set c1 [sql_to_changeset changeset { DELETE FROM y1 WHERE a=4    }]
+  set c2 [sql_to_changeset changeset { UPDATE y1 SET c=4 WHERE a=3 }]
+  sqlite3changebatch cb db
+  cb add $c1
+  cb add $c2
+} {SQLITE_OK}
+do_test 3.1.2 {
+  cb delete
+  execsql ROLLBACK
+} {}
+
+do_test 3.1.1 {
+  set c1 [sql_to_changeset fullchangeset { DELETE FROM y1 WHERE a=4    }]
+  set c2 [sql_to_changeset fullchangeset { UPDATE y1 SET c=4 WHERE a=3 }]
+  sqlite3changebatch cb db
+  cb add $c1
+  cb add $c2
+} {SQLITE_CONSTRAINT}
+do_test 3.1.2 {
+  cb delete
+} {}
 
-do_changebatch_test 2.2 {
-  DELETE FROM x1 WHERE b=1;
-} {
-  INSERT INTO x1 VALUES(1, 5, 'a');
-}
 
-finish_test
 
+finish_test
 
index c0f9b28340049f465402e36057c3080622b5c608..5672a574c521614e920e5960a761405873fc8143 100644 (file)
@@ -240,11 +240,26 @@ static int cbFindTable(
   return rc;
 }
 
+static int cbGetChangesetValue(
+  sqlite3_changeset_iter *pIter, 
+  int (*xVal)(sqlite3_changeset_iter*,int,sqlite3_value**),
+  int (*xFallback)(sqlite3_changeset_iter*,int,sqlite3_value**),
+  int iVal,
+  sqlite3_value **ppVal
+){
+  int rc = xVal(pIter, iVal, ppVal);
+  if( rc==SQLITE_OK && *ppVal==0 && xFallback ){
+    rc = xFallback(pIter, iVal, ppVal);
+  }
+  return rc;
+}
+
 static int cbAddToHash(
   sqlite3_changebatch *p, 
   sqlite3_changeset_iter *pIter, 
   BatchIndex *pIdx, 
   int (*xVal)(sqlite3_changeset_iter*,int,sqlite3_value**),
+  int (*xFallback)(sqlite3_changeset_iter*,int,sqlite3_value**),
   int *pbConf
 ){
   BatchIndexEntry *pNew;
@@ -255,12 +270,10 @@ static int cbAddToHash(
 
   for(i=0; rc==SQLITE_OK && i<pIdx->nCol; i++){
     sqlite3_value *pVal;
-    rc = xVal(pIter, pIdx->aiCol[i], &pVal);
+    rc = cbGetChangesetValue(pIter, xVal, xFallback, pIdx->aiCol[i], &pVal);
     if( rc==SQLITE_OK ){
       int eType = 0;
-      if( pVal ){
-        eType = sqlite3_value_type(pVal);
-      }
+      if( pVal ) eType = sqlite3_value_type(pVal);
       switch( eType ){
         case 0:
         case SQLITE_NULL:
@@ -289,7 +302,7 @@ static int cbAddToHash(
 
     for(i=0; rc==SQLITE_OK && i<pIdx->nCol; i++){
       sqlite3_value *pVal;
-      rc = xVal(pIter, pIdx->aiCol[i], &pVal);
+      rc = cbGetChangesetValue(pIter, xVal, xFallback, pIdx->aiCol[i], &pVal);
       if( rc==SQLITE_OK ){
         int eType = sqlite3_value_type(pVal);
         pNew->aRecord[iOut++] = eType;
@@ -381,10 +394,12 @@ int sqlite3changebatch_add(sqlite3_changebatch *p, void *pBuf, int nBuf){
       for(pIdx=pTab->pIdx; pIdx && rc==SQLITE_OK; pIdx=pIdx->pNext){
         if( op==SQLITE_UPDATE && pIdx->bPk ) continue;
         if( op==SQLITE_UPDATE || op==SQLITE_DELETE ){
-          rc = cbAddToHash(p, pIter, pIdx, sqlite3changeset_old, &bConf);
+          rc = cbAddToHash(p, pIter, pIdx, sqlite3changeset_old, 0, &bConf);
         }
         if( op==SQLITE_UPDATE || op==SQLITE_INSERT ){
-          rc = cbAddToHash(p, pIter, pIdx, sqlite3changeset_new, &bConf);
+          rc = cbAddToHash(p, pIter, pIdx, 
+              sqlite3changeset_new, sqlite3changeset_old, &bConf
+          );
         }
       }
       if( rc!=SQLITE_OK ) break;
index 70ca840dae769947a9e63d0b0b4981786145951d..22728d0b97f2a3a39b5669aa15dace753205a650 100644 (file)
@@ -25,6 +25,13 @@ typedef struct SessionInput SessionInput;
 # endif
 #endif
 
+/*
+** The three different types of changesets generated.
+*/
+#define SESSIONS_PATCHSET      0
+#define SESSIONS_CHANGESET     1
+#define SESSIONS_FULLCHANGESET 2
+
 typedef struct SessionHook SessionHook;
 struct SessionHook {
   void *pCtx;
@@ -1934,7 +1941,7 @@ static void sessionAppendCol(
 */ 
 static int sessionAppendUpdate(
   SessionBuffer *pBuf,            /* Buffer to append to */
-  int bPatchset,                  /* True for "patchset", 0 for "changeset" */
+  int ePatchset,                  /* True for "patchset", 0 for "changeset" */
   sqlite3_stmt *pStmt,            /* Statement handle pointing at new row */
   SessionChange *p,               /* Object containing old values */
   u8 *abPK                        /* Boolean array - true for PK columns */
@@ -1997,8 +2004,8 @@ static int sessionAppendUpdate(
 
     /* Add a field to the old.* record. This is omitted if this modules is
     ** currently generating a patchset. */
-    if( bPatchset==0 ){
-      if( bChanged || abPK[i] ){
+    if( ePatchset!=SESSIONS_PATCHSET ){
+      if( ePatchset==SESSIONS_FULLCHANGESET || bChanged || abPK[i] ){
         sessionAppendBlob(pBuf, pCsr, nAdvance, &rc);
       }else{
         sessionAppendByte(pBuf, 0, &rc);
@@ -2007,7 +2014,7 @@ static int sessionAppendUpdate(
 
     /* Add a field to the new.* record. Or the only record if currently
     ** generating a patchset.  */
-    if( bChanged || (bPatchset && abPK[i]) ){
+    if( bChanged || (ePatchset==SESSIONS_PATCHSET && abPK[i]) ){
       sessionAppendCol(&buf2, pStmt, i, &rc);
     }else{
       sessionAppendByte(&buf2, 0, &rc);
@@ -2033,7 +2040,7 @@ static int sessionAppendUpdate(
 */
 static int sessionAppendDelete(
   SessionBuffer *pBuf,            /* Buffer to append to */
-  int bPatchset,                  /* True for "patchset", 0 for "changeset" */
+  int eChangeset,                 /* One of SESSIONS_CHANGESET etc. */
   SessionChange *p,               /* Object containing old values */
   int nCol,                       /* Number of columns in table */
   u8 *abPK                        /* Boolean array - true for PK columns */
@@ -2043,7 +2050,7 @@ static int sessionAppendDelete(
   sessionAppendByte(pBuf, SQLITE_DELETE, &rc);
   sessionAppendByte(pBuf, p->bIndirect, &rc);
 
-  if( bPatchset==0 ){
+  if( eChangeset!=SESSIONS_PATCHSET ){
     sessionAppendBlob(pBuf, p->aRecord, p->nRecord, &rc);
   }else{
     int i;
@@ -2202,12 +2209,12 @@ static int sessionSelectBind(
 */
 static void sessionAppendTableHdr(
   SessionBuffer *pBuf,            /* Append header to this buffer */
-  int bPatchset,                  /* Use the patchset format if true */
+  int ePatchset,                  /* Use the patchset format if true */
   SessionTable *pTab,             /* Table object to append header for */
   int *pRc                        /* IN/OUT: Error code */
 ){
   /* Write a table header */
-  sessionAppendByte(pBuf, (bPatchset ? 'P' : 'T'), pRc);
+  sessionAppendByte(pBuf, (ePatchset==SESSIONS_PATCHSET) ? 'P' : 'T', pRc);
   sessionAppendVarint(pBuf, pTab->nCol, pRc);
   sessionAppendBlob(pBuf, pTab->abPK, pTab->nCol, pRc);
   sessionAppendBlob(pBuf, (u8 *)pTab->zName, (int)strlen(pTab->zName)+1, pRc);
@@ -2225,7 +2232,7 @@ static void sessionAppendTableHdr(
 */
 static int sessionGenerateChangeset(
   sqlite3_session *pSession,      /* Session object */
-  int bPatchset,                  /* True for patchset, false for changeset */
+  int ePatchset,                  /* One of SESSIONS_CHANGESET etc. */
   int (*xOutput)(void *pOut, const void *pData, int nData),
   void *pOut,                     /* First argument for xOutput */
   int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
@@ -2270,7 +2277,7 @@ static int sessionGenerateChangeset(
       }
 
       /* Write a table header */
-      sessionAppendTableHdr(&buf, bPatchset, pTab, &rc);
+      sessionAppendTableHdr(&buf, ePatchset, pTab, &rc);
 
       /* Build and compile a statement to execute: */
       if( rc==SQLITE_OK ){
@@ -2294,10 +2301,10 @@ static int sessionGenerateChangeset(
                 sessionAppendCol(&buf, pSel, iCol, &rc);
               }
             }else{
-              rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
+              rc = sessionAppendUpdate(&buf, ePatchset, pSel, p, abPK);
             }
           }else if( p->op!=SQLITE_INSERT ){
-            rc = sessionAppendDelete(&buf, bPatchset, p, nCol, abPK);
+            rc = sessionAppendDelete(&buf, ePatchset, p, nCol, abPK);
           }
           if( rc==SQLITE_OK ){
             rc = sqlite3_reset(pSel);
@@ -2354,7 +2361,8 @@ int sqlite3session_changeset(
   int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
   void **ppChangeset              /* OUT: Buffer containing changeset */
 ){
-  return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
+  return sessionGenerateChangeset(
+      pSession, SESSIONS_CHANGESET, 0, 0, pnChangeset, ppChangeset);
 }
 
 /*
@@ -2365,7 +2373,8 @@ int sqlite3session_changeset_strm(
   int (*xOutput)(void *pOut, const void *pData, int nData),
   void *pOut
 ){
-  return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0);
+  return sessionGenerateChangeset(
+      pSession, SESSIONS_CHANGESET, xOutput, pOut, 0, 0);
 }
 
 /*
@@ -2376,7 +2385,8 @@ int sqlite3session_patchset_strm(
   int (*xOutput)(void *pOut, const void *pData, int nData),
   void *pOut
 ){
-  return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0);
+  return sessionGenerateChangeset(
+      pSession, SESSIONS_PATCHSET, xOutput, pOut, 0, 0);
 }
 
 /*
@@ -2391,9 +2401,20 @@ int sqlite3session_patchset(
   int *pnPatchset,                /* OUT: Size of buffer at *ppChangeset */
   void **ppPatchset               /* OUT: Buffer containing changeset */
 ){
-  return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset);
+  return sessionGenerateChangeset(
+      pSession, SESSIONS_PATCHSET, 0, 0, pnPatchset, ppPatchset);
 }
 
+int sqlite3session_fullchangeset(
+  sqlite3_session *pSession,      /* Session object */
+  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
+  void **ppChangeset              /* OUT: Buffer containing changeset */
+){
+  return sessionGenerateChangeset(
+      pSession, SESSIONS_FULLCHANGESET, 0, 0, pnChangeset, ppChangeset);
+}
+
+
 /*
 ** Enable or disable the session object passed as the first argument.
 */
@@ -4463,10 +4484,11 @@ static int sessionChangegroupOutput(
   ** hash tables attached to the SessionTable objects in list p->pList. 
   */
   for(pTab=pGrp->pList; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
+    int eChangeset = pGrp->bPatch ? SESSIONS_PATCHSET : SESSIONS_CHANGESET;
     int i;
     if( pTab->nEntry==0 ) continue;
 
-    sessionAppendTableHdr(&buf, pGrp->bPatch, pTab, &rc);
+    sessionAppendTableHdr(&buf, eChangeset, pTab, &rc);
     for(i=0; i<pTab->nChange; i++){
       SessionChange *p;
       for(p=pTab->apChange[i]; p; p=p->pNext){
index 23d9a33aef15a2f6a55b14ae9c16ad7091ac0627..91ba511936c111a31877990f97f45690c46b6c73 100644 (file)
@@ -281,6 +281,19 @@ int sqlite3session_changeset(
   void **ppChangeset              /* OUT: Buffer containing changeset */
 );
 
+/*
+** CAPI3REF: Generate A Full Changeset From A Session Object
+**
+** This function is similar to sqlite3session_changeset(), except that for
+** each row affected by an UPDATE statement, all old.* values are recorded
+** as part of the changeset, not just those modified.
+*/
+int sqlite3session_fullchangeset(
+  sqlite3_session *pSession,      /* Session object */
+  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
+  void **ppChangeset              /* OUT: Buffer containing changeset */
+);
+
 /*
 ** CAPI3REF: Load The Difference Between Tables Into A Session 
 **
index 3f4cdd3c34f4a065c98ba88fecf9513352119e70..02274c7f84ece81163b22ca683a1f3fc2a38ef74 100644 (file)
@@ -113,6 +113,7 @@ static int testStreamOutput(
 **          $session indirect INTEGER
 **          $session patchset
 **          $session table_filter SCRIPT
+**          $session fullchangeset
 */
 static int SQLITE_TCLAPI test_session_cmd(
   void *clientData,
@@ -126,17 +127,17 @@ static int SQLITE_TCLAPI test_session_cmd(
     const char *zSub;
     int nArg;
     const char *zMsg;
-    int iSub;
   } aSub[] = {
-    { "attach",       1, "TABLE",      }, /* 0 */
-    { "changeset",    0, "",           }, /* 1 */
-    { "delete",       0, "",           }, /* 2 */
-    { "enable",       1, "BOOL",       }, /* 3 */
-    { "indirect",     1, "BOOL",       }, /* 4 */
-    { "isempty",      0, "",           }, /* 5 */
-    { "table_filter", 1, "SCRIPT",     }, /* 6 */
+    { "attach",       1, "TABLE"       }, /* 0 */
+    { "changeset",    0, ""            }, /* 1 */
+    { "delete",       0, ""            }, /* 2 */
+    { "enable",       1, "BOOL"        }, /* 3 */
+    { "indirect",     1, "BOOL"        }, /* 4 */
+    { "isempty",      0, ""            }, /* 5 */
+    { "table_filter", 1, "SCRIPT"      }, /* 6 */
     { "patchset",     0, "",           }, /* 7 */
-    { "diff",         2, "FROMDB TBL", }, /* 8 */
+    { "diff",         2, "FROMDB TBL"  }, /* 8 */
+    { "fullchangeset",0, ""            }, /* 9 */
     { 0 }
   };
   int iSub;
@@ -166,10 +167,11 @@ static int SQLITE_TCLAPI test_session_cmd(
       break;
     }
 
+    case 9:        /* fullchangeset */
     case 7:        /* patchset */
     case 1: {      /* changeset */
       TestSessionsBlob o = {0, 0};
-      if( test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
+      if( iSub!=9 && test_tcl_integer(interp, SESSION_STREAM_TCL_VAR) ){
         void *pCtx = (void*)&o;
         if( iSub==7 ){
           rc = sqlite3session_patchset_strm(pSession, testStreamOutput, pCtx);
@@ -179,6 +181,8 @@ static int SQLITE_TCLAPI test_session_cmd(
       }else{
         if( iSub==7 ){
           rc = sqlite3session_patchset(pSession, &o.n, &o.p);
+        }else if( iSub==9 ){
+          rc = sqlite3session_fullchangeset(pSession, &o.n, &o.p);
         }else{
           rc = sqlite3session_changeset(pSession, &o.n, &o.p);
         }
@@ -193,6 +197,7 @@ static int SQLITE_TCLAPI test_session_cmd(
       break;
     }
 
+
     case 2:        /* delete */
       Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
       break;
index d16bdf85a5f3769c888d160e307c41c48f9b6cff..8e6e0945fc6794b56ba98c56a3804672c451c94d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\scouple\sof\sextra\stests\sto\schangebatch1.test.
-D 2016-08-22T21:01:39.413
+C Add\sa\snew\smethod\sto\ssessions\s-\ssqlite3sessions_fullchangeset()\s-\sto\sreturn\sa\schangeset\sthat\salways\scontains\svalues\sfor\sall\sold.*\sfields.\sUpdate\schangebatch\sto\suse\sthese\svalues\sto\smore\sreliably\sdetect\smulti-column\sUNIQUE\sconstraint\sviolations.
+D 2016-08-23T17:02:28.920
 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
@@ -281,7 +281,7 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
 F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
-F ext/session/changebatch1.test b2d1a8c8b8f86881f50b481eae233f8abfb61436
+F ext/session/changebatch1.test f3e5462189ebe238b57ddf31f17e5f6cb410f895
 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
 F ext/session/session1.test 98f384736e2bc21ccf5ed81bdadcff4ad863393b
 F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
@@ -301,11 +301,11 @@ F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
 F ext/session/session_common.tcl a1293167d14774b5e728836720497f40fe4ea596
 F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
 F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
-F ext/session/sqlite3changebatch.c 37fb1c87d7b3ccaff194411ff8344d9cc056bd98
+F ext/session/sqlite3changebatch.c 7ddd1b44422508306c50c37056bb13d5e0492bd0
 F ext/session/sqlite3changebatch.h 50a302e4fc535324309607b13a1993bca074758b
-F ext/session/sqlite3session.c 37485891b4add26cf61495df193c419f36556a32
-F ext/session/sqlite3session.h 69bf73cfd71e58f2ae5d2aa935b2c1a541aee555
-F ext/session/test_session.c 24968972a5709d2ccf5d570f1a13ce009fbc0d86
+F ext/session/sqlite3session.c e5591f76aea6058720e04f78ae9e88487eb56c6b
+F ext/session/sqlite3session.h c772b5440f41af44631891aa7f352e9a44b740ad
+F ext/session/test_session.c 9e6a4313dc94b053edd33f54c3ffc053aeddff45
 F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
@@ -1514,7 +1514,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 0c9fd6b723041955b5182caa430312e5124fdc83
-R 0bf0e85497e377afe1f85fb7abd8225d
+P 207d970b7956c38af42c389b91a741a68b2c4eec
+R fcf84064b854d920af796eb5c195b948
 U dan
-Z cf85cb19b321088cfc5e96ee875ee34c
+Z e2f66a65ddf5985dbdfd723a07f7b7cc
index f8bc749f9d3b6181db0a4ab4c291101ab80ebf15..cecdca57cbaa92dcdc6c387a4ebafee65b3f8cd5 100644 (file)
@@ -1 +1 @@
-207d970b7956c38af42c389b91a741a68b2c4eec
\ No newline at end of file
+efa761b2f509844b9212dd20bf0d082c6338e83f
\ No newline at end of file