diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/session/session2.test | 38 | ||||
-rw-r--r-- | ext/session/session3.test | 2 | ||||
-rw-r--r-- | ext/session/session4.test | 5 | ||||
-rw-r--r-- | ext/session/sessionfault.test | 4 | ||||
-rw-r--r-- | ext/session/sqlite3session.c | 66 | ||||
-rw-r--r-- | ext/session/test_session.c | 6 |
6 files changed, 82 insertions, 39 deletions
diff --git a/ext/session/session2.test b/ext/session/session2.test index 6662173d4..7adbfd5b6 100644 --- a/ext/session/session2.test +++ b/ext/session/session2.test @@ -44,12 +44,24 @@ do_iterator_test 1.1 t1 { {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 X. {} {f 1.5 f 99.9}} } +do_iterator_test 1.3 t1 { + UPDATE t1 SET b = 100.1 WHERE a = 1.5; + UPDATE t1 SET b = 99.9 WHERE a = 1.5; +} { } + +do_iterator_test 1.4 t1 { + UPDATE t1 SET b = 100.1 WHERE a = 1.5; +} { + {UPDATE t1 0 X. {f 1.5 f 99.9} {{} {} f 100.1}} +} + # Execute each of the following blocks of SQL on database [db1]. Collect # changes using a session object. Apply the resulting changeset to @@ -520,6 +532,32 @@ do_test 9.3 { execsql { SELECT * FROM t1 } db2 } {x 2} +#------------------------------------------------------------------------- +# +test_reset +db function enable [list S enable] + +do_common_sql { + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('x', 'X'); +} +do_iterator_test 10.1 t1 { + INSERT INTO t1 VALUES('y', 'Y'); + SELECT enable(0); + INSERT INTO t1 VALUES('z', 'Z'); + SELECT enable(1); +} { + {INSERT t1 0 X. {} {t y t Y}} +} + +sqlite3session S db main +do_execsql_test 10.2 { + SELECT enable(0); + SELECT enable(-1); + SELECT enable(1); + SELECT enable(-1); +} {0 0 1 1} +S delete finish_test diff --git a/ext/session/session3.test b/ext/session/session3.test index a0946f309..c7046d9c8 100644 --- a/ext/session/session3.test +++ b/ext/session/session3.test @@ -146,7 +146,7 @@ do_test 2.3 { execsql { INSERT INTO t2 VALUES(1, 2); DROP TABLE t2; - CREATE TABLE t2(a PRIMARY KEY, b, c); + CREATE TABLE t2(a PRIMARY KEY, b); } list [catch { S changeset } msg] $msg } {1 SQLITE_SCHEMA} diff --git a/ext/session/session4.test b/ext/session/session4.test index c69fa85fc..f695c2e46 100644 --- a/ext/session/session4.test +++ b/ext/session/session4.test @@ -59,4 +59,9 @@ do_test 1.2 { list [catch { sqlite3changeset_invert $x } msg] $msg } {1 SQLITE_CORRUPT} +do_test 1.3 { + set x [binary format "ca*" 0 [string range $changeset 1 end]] + list [catch { sqlite3changeset_apply db $x xConflict } msg] $msg +} {1 SQLITE_CORRUPT} + finish_test diff --git a/ext/session/sessionfault.test b/ext/session/sessionfault.test index e1c2980b7..cf155f4f3 100644 --- a/ext/session/sessionfault.test +++ b/ext/session/sessionfault.test @@ -45,7 +45,7 @@ do_faultsim_test 1.1 -faults oom-* -prep { sqlite3 db2 test.db2 } -body { do_then_apply_sql { - INSERT INTO t1 VALUES(7, 8, 9); + INSERT INTO t1 VALUES('a string value', 8, 9); UPDATE t1 SET c = 10 WHERE a = 1; DELETE FROM t1 WHERE a = 4; } @@ -63,7 +63,7 @@ do_faultsim_test 1.2 -faults oom-* -prep { sqlite3session S db main S attach * execsql { - INSERT INTO t1 VALUES(7, 8, 9); + INSERT INTO t1 VALUES('a string value', 8, 9); UPDATE t1 SET c = 10 WHERE a = 1; DELETE FROM t1 WHERE a = 4; } diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 36d83e6b8..75385e5f2 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -1181,10 +1181,10 @@ static void sessionAppendUpdate( break; } - case SQLITE_TEXT: - case SQLITE_BLOB: { + default: { int nByte; int nHdr = 1 + sessionVarintGet(&pCsr[1], &nByte); + assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); nAdvance = nHdr + nByte; if( eType==sqlite3_column_type(pStmt, i) && nByte==sqlite3_column_bytes(pStmt, i) @@ -1260,19 +1260,18 @@ static int sessionSelectBind( sqlite3_stmt *pSelect, int nCol, u8 *abPK, - u8 *aRecord, - int nRecord + SessionChange *pChange ){ int i; int rc = SQLITE_OK; - u8 *a = aRecord; + u8 *a = pChange->aRecord; for(i=0; i<nCol && rc==SQLITE_OK; i++){ int eType = *a++; switch( eType ){ case SQLITE_NULL: - if( abPK[i] ) rc = sqlite3_bind_null(pSelect, i+1); + assert( abPK[i]==0 ); break; case SQLITE_INTEGER: { @@ -1305,8 +1304,9 @@ static int sessionSelectBind( break; } - case SQLITE_BLOB: { + default: { int n; + assert( eType==SQLITE_BLOB ); a += sessionVarintGet(a, &n); if( abPK[i] ){ rc = sqlite3_bind_blob(pSelect, i+1, a, n, SQLITE_TRANSIENT); @@ -1337,14 +1337,17 @@ int sqlite3session_changeset( SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */ int rc; /* Return code */ - sqlite3_mutex_enter(sqlite3_db_mutex(db)); - /* Zero the output variables in case an error occurs. If this session ** object is already in the error state (sqlite3_session.rc != SQLITE_OK), ** this call will be a no-op. */ *pnChangeset = 0; *ppChangeset = 0; - rc = pSession->rc; + + if( pSession->rc ) return pSession->rc; + rc = sqlite3_exec(pSession->db, "SAVEPOINT changeset", 0, 0, 0); + if( rc!=SQLITE_OK ) return rc; + + sqlite3_mutex_enter(sqlite3_db_mutex(db)); for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){ if( pTab->nEntry ){ @@ -1375,37 +1378,31 @@ int sqlite3session_changeset( db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); } - if( rc==SQLITE_OK && nCol!=sqlite3_column_count(pSel) ){ - rc = SQLITE_SCHEMA; - } - nNoop = buf.nBuf; for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ - rc = sessionSelectBind(pSel, nCol, abPK, p->aRecord, p->nRecord); - if( rc==SQLITE_OK ){ - if( sqlite3_step(pSel)==SQLITE_ROW ){ - int iCol; - if( p->bInsert ){ - sessionAppendByte(&buf, SQLITE_INSERT, &rc); - sessionAppendByte(&buf, p->bIndirect, &rc); - for(iCol=0; iCol<nCol; iCol++){ - sessionAppendCol(&buf, pSel, iCol, &rc); - } - }else{ - sessionAppendUpdate(&buf, pSel, p, abPK, &rc); - } - }else if( !p->bInsert ){ - /* A DELETE change */ - sessionAppendByte(&buf, SQLITE_DELETE, &rc); + rc = sessionSelectBind(pSel, nCol, abPK, p); + if( sqlite3_step(pSel)==SQLITE_ROW ){ + int iCol; + if( p->bInsert ){ + sessionAppendByte(&buf, SQLITE_INSERT, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); - sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); - } - if( rc==SQLITE_OK ){ - rc = sqlite3_reset(pSel); + for(iCol=0; iCol<nCol; iCol++){ + sessionAppendCol(&buf, pSel, iCol, &rc); + } + }else{ + sessionAppendUpdate(&buf, pSel, p, abPK, &rc); } + }else if( !p->bInsert ){ + /* A DELETE change */ + sessionAppendByte(&buf, SQLITE_DELETE, &rc); + sessionAppendByte(&buf, p->bIndirect, &rc); + sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_reset(pSel); } } } @@ -1425,6 +1422,7 @@ int sqlite3session_changeset( sqlite3_free(buf.aBuf); } + sqlite3_exec(db, "RELEASE changeset", 0, 0, 0); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } diff --git a/ext/session/test_session.c b/ext/session/test_session.c index 4befd0fe6..a8b73824a 100644 --- a/ext/session/test_session.c +++ b/ext/session/test_session.c @@ -85,7 +85,7 @@ static int test_session_cmd( case 3: { /* enable */ int val; - if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &val) ) return TCL_ERROR; val = sqlite3session_enable(pSession, val); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(val)); break; @@ -436,6 +436,7 @@ static int test_sqlite3session_foreach( while( SQLITE_ROW==sqlite3changeset_next(pIter) ){ int nCol; /* Number of columns in table */ + int nCol2; /* Number of columns in table */ int op; /* SQLITE_INSERT, UPDATE or DELETE */ const char *zTab; /* Name of table change applies to */ Tcl_Obj *pVar; /* Tcl value to set $VARNAME to */ @@ -460,7 +461,8 @@ static int test_sqlite3session_foreach( zPK = ckalloc(nCol+1); memset(zPK, 0, nCol+1); - sqlite3changeset_pk(pIter, &abPK, 0); + sqlite3changeset_pk(pIter, &abPK, &nCol2); + assert( nCol==nCol2 ); for(i=0; i<nCol; i++){ zPK[i] = (abPK[i] ? 'X' : '.'); } |