]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Store primary key definitions for modified tables in changesets. Add the sqlite3chang...
authordan <dan@noemail.net>
Thu, 24 Mar 2011 11:22:59 +0000 (11:22 +0000)
committerdan <dan@noemail.net>
Thu, 24 Mar 2011 11:22:59 +0000 (11:22 +0000)
FossilOrigin-Name: 54298ee5ed183d1f1c49524f25e8ae1407f3d4b5

ext/session/session1.test
ext/session/session2.test
ext/session/sessionfault.test
ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index 582f802bea7124d3207d010793cf65cdba98cc38..4a2b50e6c6ed8ff53718949a77b0f839ff2a88fd 100644 (file)
@@ -88,14 +88,14 @@ do_test 2.1.1 {
   execsql { INSERT INTO t1 VALUES(3, 'Thonburi') }
 } {}
 do_changeset_test 2.1.2 S {
-  {INSERT t1 0 {} {i 1 t Sukhothai}}
-  {INSERT t1 0 {} {i 2 t Ayutthaya}}
-  {INSERT t1 0 {} {i 3 t Thonburi}}
+  {INSERT t1 0 X. {} {i 1 t Sukhothai}}
+  {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
+  {INSERT t1 0 X. {} {i 3 t Thonburi}}
 }
 do_changeset_invert_test 2.1.3 S {
-  {DELETE t1 0 {i 1 t Sukhothai} {}}
-  {DELETE t1 0 {i 2 t Ayutthaya} {}}
-  {DELETE t1 0 {i 3 t Thonburi} {}}
+  {DELETE t1 0 X. {i 1 t Sukhothai} {}}
+  {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
+  {DELETE t1 0 X. {i 3 t Thonburi} {}}
 }
 do_test 2.1.4 { S delete } {}
 
@@ -105,14 +105,14 @@ do_test 2.2.1 {
   execsql { DELETE FROM t1 WHERE 1 }
 } {}
 do_changeset_test 2.2.2 S {
-  {DELETE t1 0 {i 1 t Sukhothai} {}}
-  {DELETE t1 0 {i 2 t Ayutthaya} {}}
-  {DELETE t1 0 {i 3 t Thonburi} {}}
+  {DELETE t1 0 X. {i 1 t Sukhothai} {}}
+  {DELETE t1 0 X. {i 2 t Ayutthaya} {}}
+  {DELETE t1 0 X. {i 3 t Thonburi} {}}
 }
 do_changeset_invert_test 2.2.3 S {
-  {INSERT t1 0 {} {i 1 t Sukhothai}}
-  {INSERT t1 0 {} {i 2 t Ayutthaya}}
-  {INSERT t1 0 {} {i 3 t Thonburi}}
+  {INSERT t1 0 X. {} {i 1 t Sukhothai}}
+  {INSERT t1 0 X. {} {i 2 t Ayutthaya}}
+  {INSERT t1 0 X. {} {i 3 t Thonburi}}
 }
 do_test 2.2.4 { S delete } {}
 
@@ -131,19 +131,19 @@ do_test 2.3.1 {
 } {}
 
 do_changeset_test 2.3.2 S {
-  {INSERT t1 0 {} {i 10 t Sukhothai}} 
-  {DELETE t1 0 {i 1 t Sukhothai} {}} 
-  {UPDATE t1 0 {i 2 t Ayutthaya} {{} {} t Surin}} 
-  {DELETE t1 0 {i 3 t Thonburi} {}} 
-  {INSERT t1 0 {} {i 20 t Thapae}} 
+  {INSERT t1 0 X. {} {i 10 t Sukhothai}} 
+  {DELETE t1 0 X. {i 1 t Sukhothai} {}} 
+  {UPDATE t1 0 X. {i 2 t Ayutthaya} {{} {} t Surin}} 
+  {DELETE t1 0 X. {i 3 t Thonburi} {}} 
+  {INSERT t1 0 X. {} {i 20 t Thapae}} 
 }
 
 do_changeset_invert_test 2.3.3 S {
-  {DELETE t1 0 {i 10 t Sukhothai} {}} 
-  {INSERT t1 0 {} {i 1 t Sukhothai}} 
-  {UPDATE t1 0 {{} {} t Surin} {i 2 t Ayutthaya}} 
-  {INSERT t1 0 {} {i 3 t Thonburi}} 
-  {DELETE t1 0 {i 20 t Thapae} {}}
+  {DELETE t1 0 X. {i 10 t Sukhothai} {}} 
+  {INSERT t1 0 X. {} {i 1 t Sukhothai}} 
+  {UPDATE t1 0 X. {{} {} t Surin} {i 2 t Ayutthaya}} 
+  {INSERT t1 0 X. {} {i 3 t Thonburi}} 
+  {DELETE t1 0 X. {i 20 t Thapae} {}}
 }
 do_test 2.3.4 { S delete } {}
 
index d6cb2846593e1a0fb052d999c280c6de481cbf8e..a4776d80e5b87730aa914f1bf858d07684c28d9f 100644 (file)
@@ -41,13 +41,13 @@ do_iterator_test 1.1 t1 {
   DELETE FROM t1 WHERE a = 'i';
   INSERT INTO t1 VALUES('ii', 'two');
 } {
-  {DELETE t1 0 {t i t one} {}} 
-  {INSERT t1 0 {} {t ii t two}}
+  {DELETE t1 0 X. {t i t one} {}} 
+  {INSERT t1 0 X. {} {t ii t two}}
 }
 do_iterator_test 1.2 t1 {
   INSERT INTO t1 VALUES(1.5, 99.9)
 } {
-  {INSERT t1 0 {} {f 1.5 f 99.9}}
+  {INSERT t1 0 X. {} {f 1.5 f 99.9}}
 }
 
 
@@ -228,15 +228,15 @@ foreach {tn sql changeset} {
     INSERT INTO t1 VALUES(NULL);
     INSERT INTO t1 VALUES(456);
   } {
-    {INSERT t1 0 {} {i 456}} 
-    {INSERT t1 0 {} {i 123}}
+    {INSERT t1 0 {} {i 456}} 
+    {INSERT t1 0 {} {i 123}}
   }
 
   2 {
     UPDATE t1 SET a = NULL;
   } {
-    {DELETE t1 0 {i 456} {}}
-    {DELETE t1 0 {i 123} {}}
+    {DELETE t1 0 {i 456} {}}
+    {DELETE t1 0 {i 123} {}}
   }
 
   3 { DELETE FROM t1 } { }
@@ -244,14 +244,14 @@ foreach {tn sql changeset} {
   4 { 
     INSERT INTO t3 VALUES(NULL, NULL)
   } {
-    {INSERT t3 0 {} {n {} i 1}} 
+    {INSERT t3 0 .X {} {n {} i 1}} 
   }
 
   5 { INSERT INTO t2 VALUES(1, 2, NULL) }    { }
   6 { INSERT INTO t2 VALUES(1, NULL, 3) }    { }
   7 { INSERT INTO t2 VALUES(1, NULL, NULL) } { }
-  8 { INSERT INTO t2 VALUES(1, 2, 3) }       { {INSERT t2 0 {} {i 1 i 2 i 3}} }
-  9 { DELETE FROM t2 WHERE 1 }               { {DELETE t2 0 {i 1 i 2 i 3} {}} }
+  8 { INSERT INTO t2 VALUES(1, 2, 3) }    { {INSERT t2 0 .XX {} {i 1 i 2 i 3}} }
+  9 { DELETE FROM t2 WHERE 1 }            { {DELETE t2 0 .XX {i 1 i 2 i 3} {}} }
 
 } {
   do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset
@@ -269,14 +269,14 @@ do_execsql_test 5.0 {
 }
 
 foreach {tn sql changeset} {
-  1 { INSERT INTO t1 VALUES(35) }     { {INSERT t1 0 {} {i 35}} }
-  2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 {} {i 36 i 37}} }
+  1 { INSERT INTO t1 VALUES(35) }     { {INSERT t1 0 {} {i 35}} }
+  2 { INSERT INTO t2 VALUES(36, 37) } { {INSERT t2 0 .X {} {i 36 i 37}} }
   3 { 
     DELETE FROM t1 WHERE 1;
     UPDATE t2 SET x = 34;
   } { 
-    {UPDATE t2 0 {i 36 i 37} {i 34 {} {}}}
-    {DELETE t1 0 {i 35} {}}
+    {UPDATE t2 0 .X {i 36 i 37} {i 34 {} {}}}
+    {DELETE t1 0 {i 35} {}}
   }
 } {
   do_iterator_test 5.$tn * $sql $changeset
@@ -314,9 +314,9 @@ do_iterator_test 6.1.1 * {
   SELECT indirect(0);
   INSERT INTO t1 VALUES(3, 'three', 'iii');
 } {
-  {INSERT t1 0 {} {i 1 t one t i}}
-  {INSERT t1 1 {} {i 2 t two t ii}}
-  {INSERT t1 0 {} {i 3 t three t iii}}
+  {INSERT t1 0 X.. {} {i 1 t one t i}}
+  {INSERT t1 1 X.. {} {i 2 t two t ii}}
+  {INSERT t1 0 X.. {} {i 3 t three t iii}}
 }
 
 do_iterator_test 6.1.2 * {
@@ -324,7 +324,7 @@ do_iterator_test 6.1.2 * {
   UPDATE t1 SET c = 'I' WHERE a = 1;
   SELECT indirect(0);
 } {
-  {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}}
+  {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}}
 }
 do_iterator_test 6.1.3 * {
   SELECT indirect(1);
@@ -332,7 +332,7 @@ do_iterator_test 6.1.3 * {
   SELECT indirect(0);
   UPDATE t1 SET c = 'o' WHERE a = 1;
 } {
-  {UPDATE t1 0 {i 1 {} {} t I} {{} {} {} {} t o}}
+  {UPDATE t1 0 X.. {i 1 {} {} t I} {{} {} {} {} t o}}
 }
 do_iterator_test 6.1.4 * {
   SELECT indirect(0);
@@ -340,7 +340,7 @@ do_iterator_test 6.1.4 * {
   SELECT indirect(1);
   UPDATE t1 SET c = 'i' WHERE a = 1;
 } {
-  {UPDATE t1 0 {i 1 {} {} t o} {{} {} {} {} t i}}
+  {UPDATE t1 0 X.. {i 1 {} {} t o} {{} {} {} {} t i}}
 }
 do_iterator_test 6.1.4 * {
   SELECT indirect(1);
@@ -348,14 +348,14 @@ do_iterator_test 6.1.4 * {
   SELECT indirect(1);
   UPDATE t1 SET c = 'I' WHERE a = 1;
 } {
-  {UPDATE t1 1 {i 1 {} {} t i} {{} {} {} {} t I}}
+  {UPDATE t1 1 X.. {i 1 {} {} t i} {{} {} {} {} t I}}
 }
 
 do_iterator_test 6.1.5 * {
   INSERT INTO t2 VALUES(1, 'x');
 } {
-  {INSERT t2 0 {} {i 1 t x}}
-  {INSERT t2 1 {} {i 2 n {}}}
+  {INSERT t2 0 X. {} {i 1 t x}}
+  {INSERT t2 1 X. {} {i 2 n {}}}
 }
 
 do_iterator_test 6.1.6 * {
@@ -364,8 +364,8 @@ do_iterator_test 6.1.6 * {
   SELECT indirect(0);
   UPDATE t2 SET y = 'y' WHERE x>2;
 } {
-  {INSERT t2 0 {} {i 3 t y}}
-  {INSERT t2 0 {} {i 4 t y}}
+  {INSERT t2 0 X. {} {i 3 t y}}
+  {INSERT t2 0 X. {} {i 4 t y}}
 }
 
 do_iterator_test 6.1.7 * {
@@ -374,7 +374,7 @@ do_iterator_test 6.1.7 * {
   SELECT indirect(0);
   INSERT INTO t2 VALUES(4, 'new');
 } {
-  {UPDATE t2 0 {i 4 t y} {{} {} t new}}
+  {UPDATE t2 0 X. {i 4 t y} {{} {} t new}}
 }
 
 finish_test
index 04ac8b8b88c9224a0021b46f4f08763b2d9266eb..e1c2980b7992801f5fe088793868f2e3183c1c7b 100644 (file)
@@ -243,9 +243,9 @@ do_faultsim_test 5 -faults oom* -body {
     set x [list]
     sqlite3session_foreach c $::inverse { lappend x $c }
     foreach c {
-        {DELETE t1 0 {t xxx t yyy} {}} 
-        {INSERT t1 0 {} {t string i 1}} 
-        {UPDATE t1 0 {i 20 {} {}} {i 4 i 2}}
+        {DELETE t1 0 .X {t xxx t yyy} {}} 
+        {INSERT t1 0 .X {} {t string i 1}} 
+        {UPDATE t1 0 .X {i 20 {} {}} {i 4 i 2}}
     } { lappend y $c }
     if {$x != $y} { error "changeset no good" }
   }
index ff28487d3cece73a2c48595d7fc42ef0fab0ac8e..4ab8bb32ce815195fe9872afa702410a67a5a6fa 100644 (file)
@@ -39,6 +39,7 @@ struct sqlite3_changeset_iter {
   int nCol;                       /* Number of columns in zTab */
   int op;                         /* Current operation */
   int bIndirect;                  /* True if current change was indirect */
+  u8 *abPK;                       /* Primary key array */
   sqlite3_value **apValue;        /* old.* and new.* values */
 };
 
@@ -1357,6 +1358,7 @@ int sqlite3session_changeset(
       /* Write a table header */
       sessionAppendByte(&buf, 'T', &rc);
       sessionAppendVarint(&buf, nCol, &rc);
+      sessionAppendBlob(&buf, pTab->abPK, nCol, &rc);
       sessionAppendBlob(&buf, (u8 *)zName, strlen(zName)+1, &rc);
 
       /* Build and compile a statement to execute: */
@@ -1575,6 +1577,8 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){
   if( c=='T' ){
     int nByte;                    /* Bytes to allocate for apValue */
     aChange += sessionVarintGet(aChange, &p->nCol);
+    p->abPK = (u8 *)aChange;
+    aChange += p->nCol;
     p->zTab = (char *)aChange;
     aChange += (strlen((char *)aChange) + 1);
     p->op = *(aChange++);
@@ -1611,7 +1615,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *p){
 }
 
 /*
-** The following three functions extract information on the current change
+** The following function extracts information on the current change
 ** from a changeset iterator. They may only be called after changeset_next()
 ** has returned SQLITE_ROW.
 */
@@ -1629,6 +1633,16 @@ int sqlite3changeset_op(
   return SQLITE_OK;
 }
 
+int sqlite3changeset_pk(
+  sqlite3_changeset_iter *pIter,  /* Iterator object */
+  unsigned char **pabPK,          /* OUT: Array of boolean - true for PK cols */
+  int *pnCol                      /* OUT: Number of entries in output array */
+){
+  *pabPK = pIter->abPK;
+  if( pnCol ) *pnCol = pIter->nCol;
+  return SQLITE_OK;
+}
+
 /*
 ** This function may only be called while the iterator is pointing to an
 ** SQLITE_UPDATE or SQLITE_DELETE change (see sqlite3changeset_op()).
@@ -1764,7 +1778,15 @@ int sqlite3changeset_invert(
     u8 eType = aIn[i];
     switch( eType ){
       case 'T': {
+        /* A 'table' record consists of:
+        **
+        **   * A constant 'T' character,
+        **   * Number of columns in said table (a varint),
+        **   * An array of nCol bytes (abPK),
+        **   * A nul-terminated table name.
+        */
         int nByte = 1 + sessionVarintGet(&aIn[i+1], &nCol);
+        nByte += nCol;
         nByte += 1 + strlen((char *)&aIn[i+nByte]);
         memcpy(&aOut[i], &aIn[i], nByte);
         i += nByte;
index ee0402bffaefb1fd20499bc4079e20b7faf383b3..b6ea72522d8c877d07b4f8d61faaffb4def67b18 100644 (file)
@@ -341,6 +341,37 @@ int sqlite3changeset_op(
   int *pbIndirect                 /* OUT: True for an 'indirect' change */
 );
 
+/*
+** CAPI3REF: Obtain The Primary Key Definition Of A Table
+**
+** For each modified table, a changeset includes the following:
+**
+** <ul>
+**   <li> The number of columns in the table, and
+**   <li> Which of those columns make up the tables PRIMARY KEY.
+** </ul>
+**
+** This function is used to find which columns comprise the PRIMARY KEY of
+** the table modified by the change that iterator pIter currently points to.
+** If successful, *pabPK is set to point to an array of nCol entries, where
+** nCol is the number of columns in the table. Elements of *pabPK are set to
+** 0x01 if the corresponding column is part of the tables primary key, or
+** 0x00 if it is not.
+**
+** If argumet pnCol is not NULL, then *pnCol is set to the number of columns
+** in the table.
+**
+** If this function is called when the iterator does not point to a valid
+** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise,
+** SQLITE_OK is returned and the output variables populated as described
+** above.
+*/
+int sqlite3changeset_pk(
+  sqlite3_changeset_iter *pIter,  /* Iterator object */
+  unsigned char **pabPK,          /* OUT: Array of boolean - true for PK cols */
+  int *pnCol                      /* OUT: Number of entries in output array */
+);
+
 /*
 ** CAPI3REF: Obtain old.* Values From A Changeset Iterator
 **
index fee52d7f9cb022f3b8e14a82d558b77a1c76926a..e3d6d60c22c56f45f34cb98aafa88fa4612b4005 100644 (file)
@@ -408,6 +408,10 @@ static int test_sqlite3session_foreach(
     Tcl_Obj *pNew;                /* Vector of new.* values */
     int bIndirect;
 
+    char *zPK;
+    unsigned char *abPK;
+    int i;
+
     sqlite3changeset_op(pIter, &zTab, &nCol, &op, &bIndirect);
     pVar = Tcl_NewObj();
     Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(
@@ -415,9 +419,19 @@ static int test_sqlite3session_foreach(
           op==SQLITE_UPDATE ? "UPDATE" : 
           "DELETE", -1
     ));
+
     Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zTab, -1));
     Tcl_ListObjAppendElement(0, pVar, Tcl_NewBooleanObj(bIndirect));
 
+    zPK = ckalloc(nCol+1);
+    memset(zPK, 0, nCol+1);
+    sqlite3changeset_pk(pIter, &abPK, 0);
+    for(i=0; i<nCol; i++){
+      zPK[i] = (abPK[i] ? 'X' : '.');
+    }
+    Tcl_ListObjAppendElement(0, pVar, Tcl_NewStringObj(zPK, -1));
+    ckfree(zPK);
+
     pOld = Tcl_NewObj();
     if( op!=SQLITE_INSERT ){
       int i;
index 0f7a903c77cb6a7378c8c109c6793ec16b45b568..edccb68924349cf375b8d7746db96812e8baf6e2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Merge\sin\sall\sthe\slatest\schanges\sfrom\sthe\strunk,\sand\sespecially\sthe\sinterface\nchanges\sto\sthe\sSystemCall\smethods\sof\sthe\sVFS.
-D 2011-03-23T22:48:46.969
+C Store\sprimary\skey\sdefinitions\sfor\smodified\stables\sin\schangesets.\sAdd\sthe\ssqlite3changeset_pk()\sAPI\sto\sextract\sthis\sdata\sfrom\sa\schangeset\siterator.
+D 2011-03-24T11:22:59
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -102,13 +99,13 @@ F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
 F ext/rtree/sqlite3rtree.h 1af0899c63a688e272d69d8e746f24e76f10a3f0
 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
 F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
-F ext/session/session1.test bca38efbc34c0cdecc10e599246962860e3f664b
-F ext/session/session2.test b0d305ee1397d7c17f9743126f636e97ddf88542
+F ext/session/session1.test b2da15b9d727d7f4e5fe95599b32b92d93b5a970
+F ext/session/session2.test 8da094318ac88953478c43d0bfb0aa723ee0e379
 F ext/session/session_common.tcl fb91560b6dbd086010df8b3a137a452f1ac21a28
-F ext/session/sessionfault.test 4489a49d2d44c74c24251d5802b2cc011dbdac21
-F ext/session/sqlite3session.c 0c2e8f6a6d9872943edd04d0a19bf7b05db9df83
-F ext/session/sqlite3session.h 000c1ed86322d9d8e8118cd5ba815269aac608f2
-F ext/session/test_session.c 0fcfbd51e3f5885b958fbc8cdd8cba01b85b8b16
+F ext/session/sessionfault.test d7e6154a30e85622d0733b1a1e3c63e9b8b7004b
+F ext/session/sqlite3session.c 886827f10de75576baf9f9d860414fa155e1c8c1
+F ext/session/sqlite3session.h 8d3e00c0a2e323e6f47b1204ec9ff714ca3bee4a
+F ext/session/test_session.c e0f500ec5e20478afc2c7998133e8acea7ec5104
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F main.mk ae0868e05c76eaa8a0ae3d6927a949b1c8e810d7
@@ -926,14 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 1feaf2d35fd9ec777319717ae2c2929d66fe7baa e059152adce3a8fb693f082b82b5669a238c8d6f
-R b36ce5552543fc5931a9682eb2d51184
-U drh
-Z 274ed2e4f92b071af1545dccfb5f4fc3
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFNinjSoxKgR168RlERAnfoAJ4yQL1bxQ/2pBGeyDlRWD9l+4WVNwCfXQdV
-nYGZvp774EBPS1/20z/kF+M=
-=eCFJ
------END PGP SIGNATURE-----
+P 9c3a6e479988e96086bef00c79dbce508a14da0d
+R f502a856cffb82507c875b00a2fb9d4d
+U dan
+Z 3fdb3d84abab55a6e9fe1eeceb839a7c
index 928103a89fd5da77aceceddcfd40e1e8e67bca5a..12934424cdf9ad7f59f6a66209e84e3cafb822ee 100644 (file)
@@ -1 +1 @@
-9c3a6e479988e96086bef00c79dbce508a14da0d
\ No newline at end of file
+54298ee5ed183d1f1c49524f25e8ae1407f3d4b5
\ No newline at end of file