INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%;
INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%;
}
+
+ 16 {
+ INSERT INTO %T4% VALUES('abc', 'def');
+ INSERT INTO %T4% VALUES('def', 'abc');
+ }
+ 17 { UPDATE %T4% SET b = 1 }
+ 18 { DELETE FROM %T4% WHERE 1 }
}
test_reset
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
+ CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
}
-foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] {
+foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] {
do_then_apply_sql $sql
do_test 2.$tn { compare_db db db2 } {}
}
CREATE TABLE aux.t1(a PRIMARY KEY, b);
CREATE TABLE aux.t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE aux.t3(a, b, c, PRIMARY KEY(a, b));
+ CREATE TABLE aux.t4(a, b, PRIMARY KEY(b, a));
}
execsql {
CREATE TABLE t1(a PRIMARY KEY, b);
CREATE TABLE t2(a, b INTEGER PRIMARY KEY);
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b));
+ CREATE TABLE t4(a, b, PRIMARY KEY(b, a));
} db2
} {}
proc xTrace {args} { puts $args }
foreach {tn sql} [
- string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests
+ string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3 %T4% aux.t4} $set_of_tests
] {
do_then_apply_sql $sql aux
- do_test 3.$tn { compare_db db3 db2 } {}
+ do_test 3.$tn { compare_db db2 db3 } {}
}
catch {db3 close}
int nThis;
int i;
u8 *pAlloc;
- u8 *pFree = 0;
- char **azCol;
+ char **azCol = 0;
u8 *abPK;
- assert( pazCol || pabPK );
+ assert( pazCol && pabPK );
nThis = strlen(zThis);
zPragma = sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
}
}
if( rc==SQLITE_OK ){
- pFree = pAlloc;
- if( pazCol ){
- azCol = (char **)pAlloc;
- pAlloc = (u8 *)&azCol[nCol];
- }
- if( pabPK ){
- abPK = (u8 *)pAlloc;
- pAlloc = &abPK[nCol];
- }
+ azCol = (char **)pAlloc;
+ pAlloc = (u8 *)&azCol[nCol];
+ abPK = (u8 *)pAlloc;
+ pAlloc = &abPK[nCol];
if( pzTab ){
memcpy(pAlloc, zThis, nThis+1);
*pzTab = (char *)pAlloc;
int nName = sqlite3_column_bytes(pStmt, 1);
const unsigned char *zName = sqlite3_column_text(pStmt, 1);
if( zName==0 ) break;
- if( pazCol ){
- memcpy(pAlloc, zName, nName+1);
- azCol[i] = (char *)pAlloc;
- pAlloc += nName+1;
- }
- if( pabPK ) abPK[i] = sqlite3_column_int(pStmt, 5);
+ memcpy(pAlloc, zName, nName+1);
+ azCol[i] = (char *)pAlloc;
+ pAlloc += nName+1;
+ abPK[i] = sqlite3_column_int(pStmt, 5);
i++;
}
rc = sqlite3_reset(pStmt);
** free any allocation made. An error code will be returned in this case.
*/
if( rc==SQLITE_OK ){
- if( pazCol ) *pazCol = (const char **)azCol;
- if( pabPK ) *pabPK = abPK;
+ *pazCol = (const char **)azCol;
+ *pabPK = abPK;
}else{
- if( pazCol ) *pazCol = 0;
- if( pabPK ) *pabPK = 0;
+ *pazCol = 0;
+ *pabPK = 0;
if( pzTab ) *pzTab = 0;
- sqlite3_free(pFree);
+ sqlite3_free(azCol);
}
sqlite3_finalize(pStmt);
return rc;
**
** The DELETE statement looks like this:
**
-** DELETE FROM x WHERE a = :1 AND c = :3 AND :5 OR (b IS :2 AND d IS :4)
+** DELETE FROM x WHERE a = :1 AND c = :3 AND (:5 OR b IS :2 AND d IS :4)
**
** Variable :5 (nCol+1) is a boolean. It should be set to 0 if we require
** matching b and d values, or 1 otherwise. The second case comes up if the
return rc;
}
+/*
+** Iterator pIter must point to an SQLITE_INSERT entry. This function
+** transfers new.* values from the current iterator entry to statement
+** pStmt. The table being inserted into has nCol columns.
+**
+** New.* value $i 0 from the iterator is bound to variable ($i+1) of
+** statement pStmt. If parameter abPK is NULL, all values from 0 to (nCol-1)
+** are transfered to the statement. Otherwise, if abPK is not NULL, it points
+** to an array nCol elements in size. In this case only those values for
+** which abPK[$i] is true are read from the iterator and bound to the
+** statement.
+**
+** An SQLite error code is returned if an error occurs. Otherwise, SQLITE_OK.
+*/
+static int sessionBindValues(
+ sqlite3_changeset_iter *pIter, /* Iterator to read values from */
+ int(*xIterValue)(sqlite3_changeset_iter *, int, sqlite3_value **),
+ int nCol, /* Number of columns */
+ u8 *abPK, /* If not NULL, bind only if true */
+ sqlite3_stmt *pStmt /* Bind values to this statement */
+){
+ int i;
+ int rc = SQLITE_OK;
+ for(i=0; rc==SQLITE_OK && i<nCol; i++){
+ if( !abPK || abPK[i] ){
+ sqlite3_value *pVal;
+ rc = xIterValue(pIter, i, &pVal);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_bind_value(pStmt, i+1, pVal);
+ }
+ }
+ }
+ return rc;
+}
+
/*
** SQL statement pSelect is as generated by the sessionSelectRow() function.
** This function binds the primary key values from the change that changeset
** error occurs, an SQLite error code is returned.
**
** If the iterator currently points to an INSERT record, bind values from the
-** new.* record to the SELECT statement. Or, if it points to a DELETE, bind
-** values from the old.* record. If the changeset iterator points to an
-** UPDATE, bind values from the new.* record, but use old.* values in place
-** of any undefined new.* values.
+** new.* record to the SELECT statement. Or, if it points to a DELETE or
+** UPDATE, bind values from the old.* record.
*/
static int sessionSeekToRow(
sqlite3 *db, /* Database handle */
sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */
){
int rc = SQLITE_OK; /* Return code */
- int i; /* Used to iterate through table columns */
int nCol; /* Number of columns in table */
int op; /* Changset operation (SQLITE_UPDATE etc.) */
const char *zDummy; /* Unused */
sqlite3changeset_op(pIter, &zDummy, &nCol, &op);
-
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- if( abPK[i] ){
- sqlite3_value *pVal = 0;
- if( op!=SQLITE_DELETE ){
- rc = sqlite3changeset_new(pIter, i, &pVal);
- }
- if( pVal==0 ){
- rc = sqlite3changeset_old(pIter, i, &pVal);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(pSelect, i+1, pVal);
- }
- }
- }
+ rc = sessionBindValues(pIter,
+ op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old,
+ nCol, abPK, pSelect
+ );
if( rc==SQLITE_OK ){
rc = sqlite3_step(pSelect);
if( pbReplace ){
rc = sessionSeekToRow(p->db, pIter, p->abPK, p->pSelect);
}else{
- rc = SQLITE_DONE;
+ rc = SQLITE_OK;
}
if( rc==SQLITE_ROW ){
res = xConflict(pCtx, eType, pIter);
pIter->pConflict = 0;
rc = sqlite3_reset(p->pSelect);
- }else{
+ }else if( rc==SQLITE_OK ){
/* No other row with the new.* primary key. */
rc = sqlite3_reset(p->pSelect);
if( rc==SQLITE_OK ){
sqlite3changeset_op(pIter, &zDummy, &nCol, &op);
if( op==SQLITE_DELETE ){
- int i;
/* Bind values to the DELETE statement. */
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- sqlite3_value *pVal;
- rc = sqlite3changeset_old(pIter, i, &pVal);
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(p->pDelete, i+1, pVal);
- }
- }
+ rc = sessionBindValues(pIter, sqlite3changeset_old, nCol, 0, p->pDelete);
if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){
rc = sqlite3_bind_int(p->pDelete, nCol+1, pbRetry==0);
}
);
}else if( rc==SQLITE_CONSTRAINT ){
- /* This may be a CONSTRAINT or CONFLICT error. It is a CONFLICT if
- ** the only problem is a duplicate PRIMARY KEY, or a CONSTRAINT
- ** otherwise. */
- int bPKChange = 0;
-
- /* Check if the PK has been modified. */
- rc = SQLITE_OK;
- for(i=0; i<nCol && rc==SQLITE_OK; i++){
- if( p->abPK[i] ){
- sqlite3_value *pNew;
- rc = sqlite3changeset_new(pIter, i, &pNew);
- if( rc==SQLITE_OK && pNew ){
- bPKChange = 1;
- break;
- }
- }
- }
-
- rc = sessionConflictHandler(SQLITE_CHANGESET_CONFLICT,
- p, pIter, xConflict, pCtx, (bPKChange ? pbReplace : 0)
+ /* This is always a CONSTRAINT conflict. */
+ rc = sessionConflictHandler(
+ SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0
);
}
}else{
- int i;
assert( op==SQLITE_INSERT );
- for(i=0; rc==SQLITE_OK && i<nCol; i++){
- sqlite3_value *pVal;
- rc = sqlite3changeset_new(pIter, i, &pVal);
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(p->pInsert, i+1, pVal);
- }
- }
+ rc = sessionBindValues(pIter, sqlite3changeset_new, nCol, 0, p->pInsert);
if( rc!=SQLITE_OK ) return rc;
sqlite3_step(p->pInsert);
rc = sqlite3_reset(p->pInsert);
- if( rc==SQLITE_CONSTRAINT && xConflict ){
+ if( rc==SQLITE_CONSTRAINT ){
rc = sessionConflictHandler(
SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, pbReplace
);
}
if( bReplace ){
+ assert( pIter->op==SQLITE_INSERT );
rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0);
if( rc==SQLITE_OK ){
- int i;
- for(i=0; i<sApply.nCol; i++){
- if( sApply.abPK[i] ){
- sqlite3_value *pVal;
- rc = sqlite3changeset_new(pIter, i, &pVal);
- if( rc==SQLITE_OK && pVal==0 ){
- rc = sqlite3changeset_old(pIter, i, &pVal);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(sApply.pDelete, i+1, pVal);
- }
- }
- }
+ rc = sessionBindValues(pIter,
+ sqlite3changeset_new, sApply.nCol, sApply.abPK, sApply.pDelete);
sqlite3_bind_int(sApply.pDelete, sApply.nCol+1, 1);
}
if( rc==SQLITE_OK ){
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Merge\sin\sthe\ssqlite3_db_config()\senhancements\sfor\senabling\sand\sdisabling\nFKs\sand\striggers\sfrom\strunk.
-D 2011-03-21T17:17:49.766
+C Remove\ssome\sunreachable\scode\sin\ssqlite3session.c.\sAdd\stest\scases.
+D 2011-03-21T19:41:30
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 3f982c74ee4ba97069917cc35aae25b4ed858e6a
-F ext/session/session2.test 6462c21d3795d9e48ffea2e7550d1b2d6da66dfb
-F ext/session/session_common.tcl 880b554b0bcadcabe1331afb87d58ad1ed2510c4
-F ext/session/sessionfault.test 4190de237b2c76ca7529ef415778a862d7d0fa30
-F ext/session/sqlite3session.c c5a60c2cf21f8892f9ae4850fad2d7859c2c3692
+F ext/session/session1.test 1e8cda2cc8a60171dabc0fbec4124f9f7c943f23
+F ext/session/session2.test 54c3a5ecdc60548a8ab0a86793b136de6f32a255
+F ext/session/session_common.tcl d7bb85c3fd76d53bd9b909da808d5c16f5213111
+F ext/session/sessionfault.test da234166d5d044c91964863174d7171b0561708b
+F ext/session/sqlite3session.c 1ca39db8a10b8bcb973b35a68c0924b6a64c4a97
F ext/session/sqlite3session.h 2c071ee5925e82c21c7c9c296a0422c039607106
F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 32e95164d1192b87b1ab019549fd2394642cd3fe 09e167f9c14625924b17bbb1f292f89ac9ddc93a
-R a0add848dadb7db1c3f35ed60dcfc8d8
-U drh
-Z 2f330aa02552b587cf8d8ca729d4e813
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFNh4hAoxKgR168RlERAlZKAJ9kBWPV0idzBc6FhOD1zal2v2X27gCfZtYB
-1RyGCy9Ef7CucSG+WlvrUDU=
-=TZ5z
------END PGP SIGNATURE-----
+P 2b3c8b9d9aa909f64a29ed8167de24c328c50d85
+R c6506b08e053cfdd0bd616ee1b17add6
+U dan
+Z 4cc9deaf80e50ac14cbc33555ec1ddf1