From 8bbf544747d4b458f301b8aa08d20c29fb5a61d1 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 23 Aug 2016 17:02:28 +0000 Subject: [PATCH] Add a new method to sessions - sqlite3sessions_fullchangeset() - to return a changeset that always contains values for all old.* fields. Update changebatch to use these values to more reliably detect multi-column UNIQUE constraint violations. FossilOrigin-Name: efa761b2f509844b9212dd20bf0d082c6338e83f --- ext/session/changebatch1.test | 149 ++++++++++++++++++++++--------- ext/session/sqlite3changebatch.c | 29 ++++-- ext/session/sqlite3session.c | 56 ++++++++---- ext/session/sqlite3session.h | 13 +++ ext/session/test_session.c | 25 +++--- manifest | 20 ++--- manifest.uuid | 2 +- 7 files changed, 208 insertions(+), 86 deletions(-) diff --git a/ext/session/changebatch1.test b/ext/session/changebatch1.test index 056512aca3..fc3f50ab4c 100644 --- a/ext/session/changebatch1.test +++ b/ext/session/changebatch1.test @@ -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; -} - -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; -} { - INSERT INTO t1 VALUES(2, 2); +proc do_changebatch_test2 {tn args} { + uplevel do_changebatch_test $tn fullchangeset $args } #------------------------------------------------------------------------- -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'); -} - -do_changebatch_test 2.1 { - DELETE FROM x1 WHERE b=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 } { - UPDATE x1 SET c='b' WHERE b=3; + 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_changebatch_test 2.2 { - DELETE FROM x1 WHERE b=1; -} { - INSERT INTO x1 VALUES(1, 5, 'a'); +#------------------------------------------------------------------------- +# 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_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 +} {} + + + finish_test - diff --git a/ext/session/sqlite3changebatch.c b/ext/session/sqlite3changebatch.c index c0f9b28340..5672a574c5 100644 --- a/ext/session/sqlite3changebatch.c +++ b/ext/session/sqlite3changebatch.c @@ -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 && inCol; 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 && inCol; 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; diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 70ca840dae..22728d0b97 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -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; inChange; i++){ SessionChange *p; for(p=pTab->apChange[i]; p; p=p->pNext){ diff --git a/ext/session/sqlite3session.h b/ext/session/sqlite3session.h index 23d9a33aef..91ba511936 100644 --- a/ext/session/sqlite3session.h +++ b/ext/session/sqlite3session.h @@ -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 ** diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 3f4cdd3c34..02274c7f84 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -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; diff --git a/manifest b/manifest index d16bdf85a5..8e6e0945fc 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index f8bc749f9d..cecdca57cb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -207d970b7956c38af42c389b91a741a68b2c4eec \ No newline at end of file +efa761b2f509844b9212dd20bf0d082c6338e83f \ No newline at end of file