Improve test coverage of session module.
FossilOrigin-Name: f46d4b641d613c39a80b12106e6a6ac0efc8be83
This commit is contained in:
parent
b08a1efae5
commit
6734007d75
@ -443,5 +443,27 @@ do_conflict_test 6.1 -tables {t1 t2} -sql {
|
||||
do_db2_test 6.2 "SELECT * FROM t1" {a b 1 2}
|
||||
do_db2_test 6.3 "SELECT * FROM t2" {a b A B}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that session objects are not confused by changes to table in
|
||||
# other databases.
|
||||
#
|
||||
catch { db2 close }
|
||||
drop_all_tables
|
||||
forcedelete test.db2
|
||||
do_iterator_test 7.1 * {
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE main.t1(x PRIMARY KEY, y);
|
||||
CREATE TABLE aux.t1(x PRIMARY KEY, y);
|
||||
|
||||
INSERT INTO main.t1 VALUES('one', 1);
|
||||
INSERT INTO main.t1 VALUES('two', 2);
|
||||
INSERT INTO aux.t1 VALUES('three', 3);
|
||||
INSERT INTO aux.t1 VALUES('four', 4);
|
||||
} {
|
||||
{INSERT t1 0 X. {} {t two i 2}}
|
||||
{INSERT t1 0 X. {} {t one i 1}}
|
||||
}
|
||||
|
||||
|
||||
catch { db2 close }
|
||||
finish_test
|
||||
|
@ -119,7 +119,6 @@ do_test 2.2.1 {
|
||||
}
|
||||
list [catch { S changeset } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
|
||||
do_test 2.2.2 {
|
||||
S delete
|
||||
sqlite3session S db main
|
||||
@ -135,6 +134,38 @@ do_test 2.2.2 {
|
||||
}
|
||||
list [catch { S changeset } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
do_test 2.2.3 {
|
||||
S delete
|
||||
sqlite3session S db main
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(a, b PRIMARY KEY, c);
|
||||
}
|
||||
S attach t2
|
||||
execsql {
|
||||
INSERT INTO t2 VALUES(1, 2, 3);
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(a, b PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES(4, 5);
|
||||
}
|
||||
list [catch { S changeset } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
do_test 2.2.4 {
|
||||
S delete
|
||||
sqlite3session S db main
|
||||
execsql {
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(a, b PRIMARY KEY, c);
|
||||
}
|
||||
S attach t2
|
||||
execsql {
|
||||
INSERT INTO t2 VALUES(1, 2, 3);
|
||||
DROP TABLE t2;
|
||||
CREATE TABLE t2(a, b PRIMARY KEY, c, d);
|
||||
INSERT INTO t2 VALUES(4, 5, 6, 7);
|
||||
}
|
||||
list [catch { S changeset } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
|
||||
do_test 2.3 {
|
||||
S delete
|
||||
|
@ -30,6 +30,11 @@ set testprefix session5
|
||||
#
|
||||
# session5-3.*: Schema mismatch errors.
|
||||
#
|
||||
# session5-4.*: Test the concat cases that indicate that the database
|
||||
# was modified in between recording of the two changesets
|
||||
# being concatenated (i.e. two changesets that INSERT rows
|
||||
# with the same PK values).
|
||||
#
|
||||
|
||||
proc do_concat_test {tn args} {
|
||||
|
||||
@ -224,7 +229,6 @@ do_test 2.3.0 {
|
||||
for {set i 1} {$i < 120} {incr i} {
|
||||
append sql2 "DELETE FROM x1 WHERE a = $i*4;"
|
||||
}
|
||||
|
||||
set {} {}
|
||||
} {}
|
||||
do_concat_test 2.3 {
|
||||
@ -254,6 +258,47 @@ do_concat_test 2.5 {
|
||||
INSERT INTO x2 VALUES('a', 'B');
|
||||
}
|
||||
|
||||
for {set k 1} {$k <=10} {incr k} {
|
||||
do_test 2.6.$k.1 {
|
||||
drop_all_tables
|
||||
set sql1 ""
|
||||
set sql2 ""
|
||||
for {set i 1} {$i < 120} {incr i} {
|
||||
append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);"
|
||||
}
|
||||
for {set i 1} {$i < 120} {incr i} {
|
||||
append sql2 "DELETE FROM x1 WHERE rowid = $i;"
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
do_concat_test 2.6.$k {
|
||||
CREATE TABLE x1(a PRIMARY KEY, b)
|
||||
} $sql1 $sql2 $sql1 $sql2
|
||||
}
|
||||
|
||||
for {set k 1} {$k <=10} {incr k} {
|
||||
do_test 2.7.$k.1 {
|
||||
drop_all_tables
|
||||
set sql1 ""
|
||||
set sql2 ""
|
||||
for {set i 1} {$i < 120} {incr i} {
|
||||
append sql1 {
|
||||
INSERT INTO x1 VALUES(
|
||||
CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END,
|
||||
CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END
|
||||
);
|
||||
}
|
||||
}
|
||||
for {set i 1} {$i < 120} {incr i} {
|
||||
append sql2 "DELETE FROM x1 WHERE rowid = $i;"
|
||||
}
|
||||
set {} {}
|
||||
} {}
|
||||
do_concat_test 2.7.$k {
|
||||
CREATE TABLE x1(a PRIMARY KEY, b)
|
||||
} $sql1 $sql2 $sql1 $sql2
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that schema incompatibilities are detected correctly.
|
||||
@ -294,5 +339,71 @@ do_test 3.2 {
|
||||
list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
|
||||
} {1 SQLITE_SCHEMA}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that concat() handles these properly:
|
||||
#
|
||||
# session5-4.1: INSERT + INSERT
|
||||
# session5-4.2: UPDATE + INSERT
|
||||
# session5-4.3: DELETE + UPDATE
|
||||
# session5-4.4: DELETE + DELETE
|
||||
#
|
||||
|
||||
proc do_concat_test2 {tn sql1 sqlX sql2 expected} {
|
||||
sqlite3session S db main ; S attach *
|
||||
execsql $sql1
|
||||
set ::c1 [S changeset]
|
||||
S delete
|
||||
|
||||
execsql $sqlX
|
||||
|
||||
sqlite3session S db main ; S attach *
|
||||
execsql $sql2
|
||||
set ::c2 [S changeset]
|
||||
S delete
|
||||
|
||||
uplevel do_test $tn [list {
|
||||
changeset_to_list [sqlite3changeset_concat $::c1 $::c2]
|
||||
}] [list [normalize_list $expected]]
|
||||
}
|
||||
|
||||
drop_all_tables db
|
||||
do_concat_test2 4.1 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES('key', 'value');
|
||||
} {
|
||||
DELETE FROM t1 WHERE a = 'key';
|
||||
} {
|
||||
INSERT INTO t1 VALUES('key', 'xxx');
|
||||
} {
|
||||
{INSERT t1 0 X. {} {t key t value}}
|
||||
}
|
||||
do_concat_test2 4.2 {
|
||||
UPDATE t1 SET b = 'yyy';
|
||||
} {
|
||||
DELETE FROM t1 WHERE a = 'key';
|
||||
} {
|
||||
INSERT INTO t1 VALUES('key', 'value');
|
||||
} {
|
||||
{UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}}
|
||||
}
|
||||
do_concat_test2 4.3 {
|
||||
DELETE FROM t1 WHERE a = 'key';
|
||||
} {
|
||||
INSERT INTO t1 VALUES('key', 'www');
|
||||
} {
|
||||
UPDATE t1 SET b = 'valueX' WHERE a = 'key';
|
||||
} {
|
||||
{DELETE t1 0 X. {t key t value} {}}
|
||||
}
|
||||
do_concat_test2 4.4 {
|
||||
DELETE FROM t1 WHERE a = 'key';
|
||||
} {
|
||||
INSERT INTO t1 VALUES('key', 'ttt');
|
||||
} {
|
||||
DELETE FROM t1 WHERE a = 'key';
|
||||
} {
|
||||
{DELETE t1 0 X. {t key t valueX} {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -265,7 +265,7 @@ do_execsql_test 5.prep1 {
|
||||
INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3);
|
||||
}
|
||||
|
||||
do_test 5.prep2 {
|
||||
do_test 6.prep2 {
|
||||
sqlite3session M db main
|
||||
M attach *
|
||||
set ::c2 [changeset_from_sql {
|
||||
@ -294,4 +294,103 @@ do_faultsim_test 6 -faults oom-* -body {
|
||||
}
|
||||
}
|
||||
|
||||
faultsim_delete_and_reopen
|
||||
do_execsql_test 5.prep1 {
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a));
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
set res [list]
|
||||
for {set ::i 0} {$::i < 480} {incr ::i 4} {
|
||||
lappend res "INSERT t1 0 X. {} {i $::i i $::i}"
|
||||
}
|
||||
set res [lsort $res]
|
||||
do_faultsim_test 7 -faults oom-transient -prep {
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
} -body {
|
||||
for {set ::i 0} {$::i < 480} {incr ::i 4} {
|
||||
execsql {INSERT INTO t1 VALUES($::i, $::i)}
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
if {$testrc==0} {
|
||||
set cres [list [catch {changeset_to_list [S changeset]} msg] $msg]
|
||||
S delete
|
||||
if {$cres != "1 SQLITE_NOMEM" && $cres != "0 {$::res}"} {
|
||||
error "Expected {0 $::res} Got {$cres}"
|
||||
}
|
||||
} else {
|
||||
S changeset
|
||||
S delete
|
||||
}
|
||||
}
|
||||
|
||||
faultsim_delete_and_reopen
|
||||
do_test 8.prep {
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a));
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
}
|
||||
set ::changeset [S changeset]
|
||||
S delete
|
||||
} {}
|
||||
|
||||
set expected [normalize_list {
|
||||
{INSERT t1 0 X. {} {i 1 i 2}}
|
||||
{INSERT t1 0 X. {} {i 3 i 4}}
|
||||
{INSERT t1 0 X. {} {i 5 i 6}}
|
||||
}]
|
||||
do_faultsim_test 8.1 -faults oom* -body {
|
||||
set ::res [list]
|
||||
sqlite3session_foreach -next v $::changeset { lappend ::res $v }
|
||||
normalize_list $::res
|
||||
} -test {
|
||||
faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM}
|
||||
}
|
||||
do_faultsim_test 8.2 -faults oom* -body {
|
||||
set ::res [list]
|
||||
sqlite3session_foreach v $::changeset { lappend ::res $v }
|
||||
normalize_list $::res
|
||||
} -test {
|
||||
faultsim_test_result [list 0 $::expected] {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
faultsim_delete_and_reopen
|
||||
do_test 9.prep {
|
||||
execsql {
|
||||
PRAGMA encoding = 'utf16';
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
}
|
||||
} {}
|
||||
faultsim_save_and_close
|
||||
|
||||
do_faultsim_test 9 -faults oom-transient -prep {
|
||||
catch { unset ::c }
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3session S db main
|
||||
S attach *
|
||||
} -body {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES('abcdefghijklmnopqrstuv', 'ABCDEFGHIJKLMNOPQRSTUV');
|
||||
}
|
||||
set ::c [S changeset]
|
||||
set {} {}
|
||||
} -test {
|
||||
S delete
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 {callback requested query abort}}
|
||||
if {[info exists ::c]} {
|
||||
set expected "{INSERT t1 0 X. {} {t abcdefghijklmnopqrstuv t ABCDEFGHIJKLMNOPQRSTUV}}"
|
||||
if { [changeset_to_list $::c] != $expected } {
|
||||
error "changeset mismatch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -317,34 +317,29 @@ static unsigned int sessionPreupdateHash(
|
||||
|
||||
eType = sqlite3_value_type(pVal);
|
||||
h = HASH_APPEND(h, eType);
|
||||
switch( eType ){
|
||||
case SQLITE_INTEGER:
|
||||
case SQLITE_FLOAT: {
|
||||
i64 iVal;
|
||||
if( eType==SQLITE_INTEGER ){
|
||||
iVal = sqlite3_value_int64(pVal);
|
||||
}else{
|
||||
double rVal = sqlite3_value_double(pVal);
|
||||
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
|
||||
memcpy(&iVal, &rVal, 8);
|
||||
}
|
||||
h = sessionHashAppendI64(h, iVal);
|
||||
break;
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
i64 iVal;
|
||||
if( eType==SQLITE_INTEGER ){
|
||||
iVal = sqlite3_value_int64(pVal);
|
||||
}else{
|
||||
double rVal = sqlite3_value_double(pVal);
|
||||
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
|
||||
memcpy(&iVal, &rVal, 8);
|
||||
}
|
||||
|
||||
case SQLITE_TEXT:
|
||||
case SQLITE_BLOB: {
|
||||
int n = sqlite3_value_bytes(pVal);
|
||||
const u8 *z = eType==SQLITE_TEXT ?
|
||||
sqlite3_value_text(pVal) : sqlite3_value_blob(pVal);
|
||||
h = sessionHashAppendBlob(h, n, z);
|
||||
break;
|
||||
h = sessionHashAppendI64(h, iVal);
|
||||
}else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
|
||||
const u8 *z;
|
||||
if( eType==SQLITE_TEXT ){
|
||||
z = (const u8 *)sqlite3_value_text(pVal);
|
||||
}else{
|
||||
z = (const u8 *)sqlite3_value_blob(pVal);
|
||||
}
|
||||
|
||||
default:
|
||||
assert( eType==SQLITE_NULL );
|
||||
*pbNullPK = 1;
|
||||
return SQLITE_OK;
|
||||
if( !z ) return SQLITE_NOMEM;
|
||||
h = sessionHashAppendBlob(h, sqlite3_value_bytes(pVal), z);
|
||||
}else{
|
||||
assert( eType==SQLITE_NULL );
|
||||
*pbNullPK = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -399,12 +394,12 @@ static unsigned int sessionChangeHash(
|
||||
a++;
|
||||
h = HASH_APPEND(h, eType);
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
if( isPK ) h = sessionHashAppendI64(h, sessionGetI64(a));
|
||||
h = sessionHashAppendI64(h, sessionGetI64(a));
|
||||
a += 8;
|
||||
}else{
|
||||
int n;
|
||||
a += sessionVarintGet(a, &n);
|
||||
if( isPK ) h = sessionHashAppendBlob(h, n, a);
|
||||
h = sessionHashAppendBlob(h, n, a);
|
||||
a += n;
|
||||
}
|
||||
}else{
|
||||
@ -559,7 +554,7 @@ static int sessionMergeUpdate(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sessionPreupdateEqual(
|
||||
static void sessionPreupdateEqual(
|
||||
sqlite3 *db,
|
||||
SessionTable *pTab,
|
||||
SessionChange *pChange,
|
||||
@ -589,14 +584,23 @@ static int sessionPreupdateEqual(
|
||||
}
|
||||
}
|
||||
}else{
|
||||
sqlite3_value *pVal;
|
||||
int rc;
|
||||
sqlite3_value *pVal; /* Value returned by preupdate_new/old */
|
||||
int rc; /* Error code from preupdate_new/old */
|
||||
|
||||
/* The following calls to preupdate_new() and preupdate_old() can not
|
||||
** fail. This is because they cache their return values, and by the
|
||||
** time control flows to here they have already been called once from
|
||||
** within sessionPreupdateHash(). The first two asserts below verify
|
||||
** this (that the method has already been called). */
|
||||
if( bNew ){
|
||||
assert( db->pPreUpdate->pNewUnpacked || db->pPreUpdate->aNew );
|
||||
rc = sqlite3_preupdate_new(db, i, &pVal);
|
||||
}else{
|
||||
assert( db->pPreUpdate->pUnpacked );
|
||||
rc = sqlite3_preupdate_old(db, i, &pVal);
|
||||
}
|
||||
if( rc!=SQLITE_OK || sqlite3_value_type(pVal)!=eType ) return rc;
|
||||
assert( rc==SQLITE_OK );
|
||||
if( sqlite3_value_type(pVal)!=eType ) return;
|
||||
|
||||
/* A SessionChange object never has a NULL value in a PK column */
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
@ -607,24 +611,24 @@ static int sessionPreupdateEqual(
|
||||
i64 iVal = sessionGetI64(a);
|
||||
a += 8;
|
||||
if( eType==SQLITE_INTEGER ){
|
||||
if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK;
|
||||
if( sqlite3_value_int64(pVal)!=iVal ) return;
|
||||
}else{
|
||||
double rVal;
|
||||
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
|
||||
memcpy(&rVal, &iVal, 8);
|
||||
if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK;
|
||||
if( sqlite3_value_double(pVal)!=rVal ) return;
|
||||
}
|
||||
}else{
|
||||
int n;
|
||||
const u8 *z;
|
||||
a += sessionVarintGet(a, &n);
|
||||
if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK;
|
||||
if( sqlite3_value_bytes(pVal)!=n ) return;
|
||||
if( eType==SQLITE_TEXT ){
|
||||
z = sqlite3_value_text(pVal);
|
||||
}else{
|
||||
z = sqlite3_value_blob(pVal);
|
||||
}
|
||||
if( memcmp(a, z, n) ) return SQLITE_OK;
|
||||
if( memcmp(a, z, n) ) return;
|
||||
a += n;
|
||||
break;
|
||||
}
|
||||
@ -632,7 +636,7 @@ static int sessionPreupdateEqual(
|
||||
}
|
||||
|
||||
*pbEqual = 1;
|
||||
return SQLITE_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -854,9 +858,9 @@ static void sessionPreupdateOneChange(
|
||||
rc = sessionPreupdateHash(db, pTab, op==SQLITE_INSERT, &iHash, &bNullPk);
|
||||
if( rc==SQLITE_OK && bNullPk==0 ){
|
||||
SessionChange *pC;
|
||||
for(pC=pTab->apChange[iHash]; rc==SQLITE_OK && pC; pC=pC->pNext){
|
||||
for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){
|
||||
int bEqual;
|
||||
rc = sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual);
|
||||
sessionPreupdateEqual(db, pTab, pC, op==SQLITE_INSERT, &bEqual);
|
||||
if( bEqual ) break;
|
||||
}
|
||||
if( pC==0 ){
|
||||
@ -1278,12 +1282,19 @@ static void sessionAppendCol(
|
||||
sessionAppendBlob(p, aBuf, 8, pRc);
|
||||
}
|
||||
if( eType==SQLITE_BLOB || eType==SQLITE_TEXT ){
|
||||
int nByte = sqlite3_column_bytes(pStmt, iCol);
|
||||
sessionAppendVarint(p, nByte, pRc);
|
||||
sessionAppendBlob(p, eType==SQLITE_BLOB ?
|
||||
sqlite3_column_blob(pStmt, iCol) : sqlite3_column_text(pStmt, iCol),
|
||||
nByte, pRc
|
||||
);
|
||||
u8 *z;
|
||||
if( eType==SQLITE_BLOB ){
|
||||
z = (u8 *)sqlite3_column_blob(pStmt, iCol);
|
||||
}else{
|
||||
z = (u8 *)sqlite3_column_text(pStmt, iCol);
|
||||
}
|
||||
if( z ){
|
||||
int nByte = sqlite3_column_bytes(pStmt, iCol);
|
||||
sessionAppendVarint(p, nByte, pRc);
|
||||
sessionAppendBlob(p, z, nByte, pRc);
|
||||
}else{
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1710,8 +1721,8 @@ static int sessionReadRecord(
|
||||
int nByte;
|
||||
aRec += sessionVarintGet(aRec, &nByte);
|
||||
if( apOut ){
|
||||
int enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
|
||||
sqlite3ValueSetStr(apOut[i], nByte, aRec, enc, SQLITE_STATIC);
|
||||
u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0);
|
||||
sqlite3ValueSetStr(apOut[i], nByte, (char *)aRec, enc, SQLITE_STATIC);
|
||||
}
|
||||
aRec += nByte;
|
||||
}
|
||||
@ -1742,7 +1753,6 @@ static int sessionChangesetNext(
|
||||
){
|
||||
u8 *aChange;
|
||||
int i;
|
||||
u8 c;
|
||||
|
||||
assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
|
||||
|
||||
@ -1818,7 +1828,6 @@ static int sessionChangesetNext(
|
||||
*/
|
||||
int sqlite3changeset_next(sqlite3_changeset_iter *p){
|
||||
return sessionChangesetNext(p, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2987,7 +2996,6 @@ int sqlite3changeset_concat(
|
||||
}
|
||||
}
|
||||
|
||||
concat_out:
|
||||
sessionDeleteTable(pList);
|
||||
return rc;
|
||||
}
|
||||
|
@ -456,13 +456,25 @@ static int test_sqlite3session_foreach(
|
||||
int nChangeSet;
|
||||
sqlite3_changeset_iter *pIter;
|
||||
int rc;
|
||||
Tcl_Obj *pVarname;
|
||||
Tcl_Obj *pCS;
|
||||
Tcl_Obj *pScript;
|
||||
int isCheckNext = 0;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "VARNAME CHANGESET SCRIPT");
|
||||
if( objc>1 ){
|
||||
char *zOpt = Tcl_GetString(objv[1]);
|
||||
isCheckNext = (strcmp(zOpt, "-next")==0);
|
||||
}
|
||||
if( objc!=4+isCheckNext ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
pChangeSet = (void *)Tcl_GetByteArrayFromObj(objv[2], &nChangeSet);
|
||||
pVarname = objv[1+isCheckNext];
|
||||
pCS = objv[2+isCheckNext];
|
||||
pScript = objv[3+isCheckNext];
|
||||
|
||||
pChangeSet = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeSet);
|
||||
rc = sqlite3changeset_start(&pIter, nChangeSet, pChangeSet);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return test_session_error(interp, rc);
|
||||
@ -524,14 +536,21 @@ static int test_sqlite3session_foreach(
|
||||
Tcl_ListObjAppendElement(0, pVar, pOld);
|
||||
Tcl_ListObjAppendElement(0, pVar, pNew);
|
||||
|
||||
Tcl_ObjSetVar2(interp, objv[1], 0, pVar, 0);
|
||||
rc = Tcl_EvalObjEx(interp, objv[3], 0);
|
||||
Tcl_ObjSetVar2(interp, pVarname, 0, pVar, 0);
|
||||
rc = Tcl_EvalObjEx(interp, pScript, 0);
|
||||
if( rc!=TCL_OK && rc!=TCL_CONTINUE ){
|
||||
sqlite3changeset_finalize(pIter);
|
||||
return rc==TCL_BREAK ? TCL_OK : rc;
|
||||
}
|
||||
}
|
||||
rc = sqlite3changeset_finalize(pIter);
|
||||
|
||||
if( isCheckNext ){
|
||||
int rc2 = sqlite3changeset_next(pIter);
|
||||
rc = sqlite3changeset_finalize(pIter);
|
||||
assert( (rc2==SQLITE_DONE && rc==SQLITE_OK) || rc2==rc );
|
||||
}else{
|
||||
rc = sqlite3changeset_finalize(pIter);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
return test_session_error(interp, rc);
|
||||
}
|
||||
|
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C Improve\scoverage\sof\ssession\smodule.
|
||||
D 2011-04-15T19:18:57.799
|
||||
C Improve\stest\scoverage\sof\ssession\smodule.
|
||||
D 2011-04-16T19:23:10.456
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -99,16 +99,16 @@ 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 7a92a2a6f531aef1e9764ffb7f983fb8b315376d
|
||||
F ext/session/session1.test f5d9f2e362abe2563181389509822bda956516ee
|
||||
F ext/session/session2.test c3e5f78d5eb988e35cc2ba9ce3678f706283cfdb
|
||||
F ext/session/session3.test bfa2376db7cbb2ac69496f84d93a8d81b13110d3
|
||||
F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
|
||||
F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84
|
||||
F ext/session/session5.test 525503799d56124a31bedbd7895c1e668d18420d
|
||||
F ext/session/session5.test 8fdfaf9dba28a2f1c6b89b06168bdab1fef2d478
|
||||
F ext/session/session_common.tcl 1539d8973b2aea0025c133eb0cc4c89fcef541a5
|
||||
F ext/session/sessionfault.test 2766cd620f1793f0e54f1e3859a184bcea55bad4
|
||||
F ext/session/sqlite3session.c 4c44da92750d4b31bcbed25428be7167cddccf84
|
||||
F ext/session/sessionfault.test 759060c36ef424919e3900b885b22aa15caf7f39
|
||||
F ext/session/sqlite3session.c 3475df4021c5260f795cf66f67233449795c06ea
|
||||
F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf
|
||||
F ext/session/test_session.c f4d1dca94db71ec2177ee61eab51e718e58476d7
|
||||
F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F main.mk f942406cb7df55d1aec40a88a7ae399b730cd94f
|
||||
@ -697,7 +697,7 @@ F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
|
||||
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
|
||||
F test/tester.tcl 6fa3d2f581b479a3a088b1b5b0d145e548ebe662
|
||||
F test/tester.tcl fc2e27b3a782c5c5b03f7cded15cf498cad9bfef
|
||||
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
|
||||
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
|
||||
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
|
||||
@ -938,7 +938,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P df0b2d21dcd81679e55b24866f97568019932983
|
||||
R b4d7dfa6bf40d53e75863a5a6b9fd8ce
|
||||
P 3dfd1d63bddfa9bd9018eb00bee1d496379630b5
|
||||
R 57f77b8ed5537ccfd8e7f64bd8d648b6
|
||||
U dan
|
||||
Z 2d321dbf5ee44d87c34feecb146a5235
|
||||
Z 35862238c72a43b8ebb72adec800f600
|
||||
|
@ -1 +1 @@
|
||||
3dfd1d63bddfa9bd9018eb00bee1d496379630b5
|
||||
f46d4b641d613c39a80b12106e6a6ac0efc8be83
|
@ -20,7 +20,7 @@
|
||||
# Commands to manipulate the db and the file-system at a high level:
|
||||
#
|
||||
# copy_file FROM TO
|
||||
# drop_all_table ?DB?
|
||||
# drop_all_tables ?DB?
|
||||
# forcedelete FILENAME
|
||||
#
|
||||
# Test the capability of the SQLite version built into the interpreter to
|
||||
@ -362,6 +362,12 @@ proc fix_testname {varname} {
|
||||
set testname "${::testprefix}-$testname"
|
||||
}
|
||||
}
|
||||
|
||||
proc normalize_list {L} {
|
||||
set L2 [list]
|
||||
foreach l $L {lappend L2 $l}
|
||||
set L2
|
||||
}
|
||||
|
||||
proc do_execsql_test {testname sql {result {}}} {
|
||||
fix_testname testname
|
||||
|
Loading…
Reference in New Issue
Block a user