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 } {}
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 } {}
} {}
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 } {}
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}}
}
INSERT INTO t1 VALUES(NULL);
INSERT INTO t1 VALUES(456);
} {
- {INSERT t1 0 {} {i 456}}
- {INSERT t1 0 {} {i 123}}
+ {INSERT t1 0 X {} {i 456}}
+ {INSERT t1 0 X {} {i 123}}
}
2 {
UPDATE t1 SET a = NULL;
} {
- {DELETE t1 0 {i 456} {}}
- {DELETE t1 0 {i 123} {}}
+ {DELETE t1 0 X {i 456} {}}
+ {DELETE t1 0 X {i 123} {}}
}
3 { DELETE FROM t1 } { }
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
}
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 X {} {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 X {i 35} {}}
}
} {
do_iterator_test 5.$tn * $sql $changeset
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 * {
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);
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);
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);
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 * {
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 * {
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
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" }
}
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 */
};
/* 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: */
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++);
}
/*
-** 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.
*/
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()).
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;
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
**
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(
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;
------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
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
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
-9c3a6e479988e96086bef00c79dbce508a14da0d
\ No newline at end of file
+54298ee5ed183d1f1c49524f25e8ae1407f3d4b5
\ No newline at end of file