Add start of fault-injection tests for session module. Fix some bugs related to the same.
FossilOrigin-Name: 32e95164d1192b87b1ab019549fd2394642cd3fe
This commit is contained in:
parent
27453faef8
commit
12ca0b5695
@ -28,67 +28,6 @@ proc test_reset {} {
|
||||
sqlite3 db2 test.db2
|
||||
}
|
||||
|
||||
proc do_common_sql {sql} {
|
||||
execsql $sql db
|
||||
execsql $sql db2
|
||||
}
|
||||
proc xConflict args { return "OMIT" }
|
||||
|
||||
proc do_then_apply_sql {sql {dbname main}} {
|
||||
|
||||
sqlite3session S db $dbname
|
||||
db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
|
||||
S attach $name
|
||||
}
|
||||
|
||||
db eval $sql
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
S delete
|
||||
}
|
||||
|
||||
proc do_iterator_test {tn tbl_list sql res} {
|
||||
sqlite3session S db main
|
||||
foreach t $tbl_list {S attach $t}
|
||||
execsql $sql
|
||||
|
||||
set r [list]
|
||||
foreach v $res { lappend r $v }
|
||||
|
||||
set x [list]
|
||||
sqlite3session_foreach c [S changeset] { lappend x $c }
|
||||
uplevel do_test $tn [list [list set {} $x]] [list $r]
|
||||
|
||||
S delete
|
||||
}
|
||||
|
||||
# Compare the contents of all tables in [db1] and [db2]. Throw an error if
|
||||
# they are not identical, or return an empty string if they are.
|
||||
#
|
||||
proc compare_db {db1 db2} {
|
||||
|
||||
set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name}
|
||||
set lot1 [$db1 eval $sql]
|
||||
set lot2 [$db2 eval $sql]
|
||||
|
||||
if {$lot1 != $lot2} { error "databases contain different tables" }
|
||||
|
||||
foreach tbl $lot1 {
|
||||
set col1 [list]
|
||||
set col2 [list]
|
||||
|
||||
$db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
|
||||
if {$col1 != $col2} { error "table $tbl schema mismatch" }
|
||||
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
|
||||
set data1 [$db1 eval $sql]
|
||||
set data2 [$db2 eval $sql]
|
||||
if {$data1 != $data2} { error "table $tbl data mismatch" }
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# End of proc definitions. Start of tests.
|
||||
##########################################################################
|
||||
@ -105,12 +44,13 @@ do_iterator_test 1.1 t1 {
|
||||
{DELETE t1 {t i t one} {}}
|
||||
{INSERT t1 {} {t ii t two}}
|
||||
}
|
||||
do_iterator_test 1.1 t1 {
|
||||
do_iterator_test 1.2 t1 {
|
||||
INSERT INTO t1 VALUES(1.5, 99.9)
|
||||
} {
|
||||
{INSERT t1 {} {f 1.5 f 99.9}}
|
||||
}
|
||||
|
||||
|
||||
# Execute each of the following blocks of SQL on database [db1]. Collect
|
||||
# changes using a session object. Apply the resulting changeset to
|
||||
# database [db2]. Then check that the contents of the two databases are
|
||||
@ -178,6 +118,38 @@ set set_of_tests {
|
||||
12 {
|
||||
INSERT INTO %T2% VALUES(NULL, NULL);
|
||||
}
|
||||
|
||||
13 {
|
||||
DELETE FROM %T1% WHERE 1;
|
||||
|
||||
-- Insert many rows with real primary keys. Enough to force the session
|
||||
-- objects hash table to resize.
|
||||
INSERT INTO %T1% VALUES(0.1, 0.1);
|
||||
INSERT INTO %T1% SELECT a+0.1, b+0.1 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+0.2, b+0.2 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+0.4, b+0.4 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+0.8, b+0.8 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+1.6, b+1.6 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+3.2, b+3.2 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+6.4, b+6.4 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+12.8, b+12.8 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+25.6, b+25.6 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+51.2, b+51.2 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+102.4, b+102.4 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+204.8, b+204.8 FROM %T1%;
|
||||
}
|
||||
|
||||
14 {
|
||||
DELETE FROM %T1% WHERE 1;
|
||||
}
|
||||
|
||||
15 {
|
||||
INSERT INTO %T1% VALUES(1, 1);
|
||||
INSERT INTO %T1% SELECT a+2, b+2 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+4, b+4 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+8, b+8 FROM %T1%;
|
||||
INSERT INTO %T1% SELECT a+256, b+256 FROM %T1%;
|
||||
}
|
||||
}
|
||||
|
||||
test_reset
|
||||
@ -189,7 +161,7 @@ do_common_sql {
|
||||
|
||||
foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] {
|
||||
do_then_apply_sql $sql
|
||||
do_test 1.$tn { compare_db db db2 } {}
|
||||
do_test 2.$tn { compare_db db db2 } {}
|
||||
}
|
||||
|
||||
# The following block of tests is similar to the last, except that the
|
||||
@ -200,7 +172,7 @@ foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3} $set_of_tests] {
|
||||
test_reset
|
||||
forcedelete test.db3
|
||||
sqlite3 db3 test.db3
|
||||
do_test 2.0 {
|
||||
do_test 3.0 {
|
||||
execsql {
|
||||
ATTACH 'test.db3' AS 'aux';
|
||||
CREATE TABLE t1(a, b PRIMARY KEY);
|
||||
@ -224,7 +196,7 @@ foreach {tn sql} [
|
||||
string map {%T1% aux.t1 %T2% aux.t2 %T3% aux.t3} $set_of_tests
|
||||
] {
|
||||
do_then_apply_sql $sql aux
|
||||
do_test 2.$tn { compare_db db3 db2 } {}
|
||||
do_test 3.$tn { compare_db db3 db2 } {}
|
||||
}
|
||||
catch {db3 close}
|
||||
|
||||
@ -234,7 +206,7 @@ catch {db3 close}
|
||||
# handled correctly by the session module.
|
||||
#
|
||||
test_reset
|
||||
do_execsql_test 3.0 {
|
||||
do_execsql_test 4.0 {
|
||||
CREATE TABLE t1(a PRIMARY KEY);
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(c, b));
|
||||
CREATE TABLE t3(a, b INTEGER PRIMARY KEY);
|
||||
@ -272,7 +244,7 @@ foreach {tn sql changeset} {
|
||||
9 { DELETE FROM t2 WHERE 1 } { {DELETE t2 {i 1 i 2 i 3} {}} }
|
||||
|
||||
} {
|
||||
do_iterator_test 3.$tn {t1 t2 t3} $sql $changeset
|
||||
do_iterator_test 4.$tn {t1 t2 t3} $sql $changeset
|
||||
}
|
||||
|
||||
|
||||
|
106
ext/session/session_common.tcl
Normal file
106
ext/session/session_common.tcl
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
proc do_conflict_test {tn args} {
|
||||
proc xConflict {args} {
|
||||
lappend ::xConflict $args
|
||||
return ""
|
||||
}
|
||||
proc bgerror {args} { set ::background_error $args }
|
||||
|
||||
|
||||
set O(-tables) [list]
|
||||
set O(-sql) [list]
|
||||
set O(-conflicts) [list]
|
||||
|
||||
array set V $args
|
||||
foreach key [array names V] {
|
||||
if {![info exists O($key)]} {error "no such option: $key"}
|
||||
}
|
||||
array set O $args
|
||||
|
||||
sqlite3session S db main
|
||||
foreach t $O(-tables) { S attach $t }
|
||||
execsql $O(-sql)
|
||||
|
||||
set ::xConflict [list]
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
|
||||
set conflicts [list]
|
||||
foreach c $O(-conflicts) {
|
||||
lappend conflicts $c
|
||||
}
|
||||
|
||||
after 1 {set go 1}
|
||||
vwait go
|
||||
|
||||
uplevel do_test $tn [list { set ::xConflict }] [list $conflicts]
|
||||
S delete
|
||||
}
|
||||
|
||||
proc do_common_sql {sql} {
|
||||
execsql $sql db
|
||||
execsql $sql db2
|
||||
}
|
||||
|
||||
proc do_then_apply_sql {sql {dbname main}} {
|
||||
proc xConflict args { return "OMIT" }
|
||||
|
||||
set rc [catch {
|
||||
sqlite3session S db $dbname
|
||||
db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
|
||||
S attach $name
|
||||
}
|
||||
db eval $sql
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
} msg]
|
||||
|
||||
catch { S delete }
|
||||
|
||||
if {$rc} {error $msg}
|
||||
}
|
||||
|
||||
proc do_iterator_test {tn tbl_list sql res} {
|
||||
sqlite3session S db main
|
||||
foreach t $tbl_list {S attach $t}
|
||||
execsql $sql
|
||||
|
||||
set r [list]
|
||||
foreach v $res { lappend r $v }
|
||||
|
||||
set x [list]
|
||||
sqlite3session_foreach c [S changeset] { lappend x $c }
|
||||
uplevel do_test $tn [list [list set {} $x]] [list $r]
|
||||
|
||||
S delete
|
||||
}
|
||||
|
||||
# Compare the contents of all tables in [db1] and [db2]. Throw an error if
|
||||
# they are not identical, or return an empty string if they are.
|
||||
#
|
||||
proc compare_db {db1 db2} {
|
||||
|
||||
set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name}
|
||||
set lot1 [$db1 eval $sql]
|
||||
set lot2 [$db2 eval $sql]
|
||||
|
||||
if {$lot1 != $lot2} { error "databases contain different tables" }
|
||||
|
||||
foreach tbl $lot1 {
|
||||
set col1 [list]
|
||||
set col2 [list]
|
||||
|
||||
$db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name }
|
||||
$db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name }
|
||||
if {$col1 != $col2} { error "table $tbl schema mismatch" }
|
||||
|
||||
set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]"
|
||||
set data1 [$db1 eval $sql]
|
||||
set data2 [$db2 eval $sql]
|
||||
if {$data1 != $data2} { error "table $tbl data mismatch" }
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
|
85
ext/session/sessionfault.test
Normal file
85
ext/session/sessionfault.test
Normal file
@ -0,0 +1,85 @@
|
||||
# 2011 Mar 21
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# The focus of this file is testing the session module.
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set testprefix sessionfault
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
do_common_sql {
|
||||
CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
db2 close
|
||||
|
||||
# Test OOM error handling when collecting and applying a simple changeset.
|
||||
#
|
||||
do_faultsim_test pagerfault-1 -faults oom-* -prep {
|
||||
catch {db2 close}
|
||||
catch {db close}
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3 db2 test.db2
|
||||
} -body {
|
||||
do_then_apply_sql {
|
||||
INSERT INTO t1 VALUES(7, 8, 9);
|
||||
UPDATE t1 SET c = 10 WHERE a = 1;
|
||||
DELETE FROM t1 WHERE a = 4;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
faultsim_integrity_check
|
||||
if {$testrc==0} { compare_db db db2 }
|
||||
}
|
||||
|
||||
# This test case is designed so that a malloc() failure occurs while
|
||||
# resizing the session object hash-table from 256 to 512 buckets. This
|
||||
# is not an error, just a sub-optimal condition.
|
||||
#
|
||||
do_faultsim_test pagerfault-2 -faults oom-* -prep {
|
||||
catch {db2 close}
|
||||
catch {db close}
|
||||
faultsim_restore_and_reopen
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
sqlite3session S db main
|
||||
S attach t1
|
||||
execsql { BEGIN }
|
||||
for {set i 0} {$i < 125} {incr i} {
|
||||
execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 10+$i)}
|
||||
}
|
||||
} -body {
|
||||
for {set i 125} {$i < 133} {incr i} {
|
||||
execsql {INSERT INTO t1 VALUES(10+$i, 10+$i, 1-+$i)}
|
||||
}
|
||||
S changeset
|
||||
set {} {}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
if {$testrc==0} {
|
||||
sqlite3changeset_apply db2 [S changeset] xConflict
|
||||
compare_db db db2
|
||||
}
|
||||
catch { S delete }
|
||||
faultsim_integrity_check
|
||||
}
|
||||
|
||||
finish_test
|
@ -305,6 +305,7 @@ static unsigned int sessionPreupdateHash(
|
||||
}else{
|
||||
rc = sqlite3_preupdate_old(db, i, &pVal);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
eType = sqlite3_value_type(pVal);
|
||||
h = HASH_APPEND(h, eType);
|
||||
@ -424,33 +425,35 @@ static int sessionPreupdateEqual(
|
||||
}
|
||||
if( rc!=SQLITE_OK || sqlite3_value_type(pVal)!=eType ) return rc;
|
||||
|
||||
switch( eType ){
|
||||
case SQLITE_INTEGER:
|
||||
case SQLITE_FLOAT: {
|
||||
i64 iVal = sessionGetI64(a);
|
||||
a += 8;
|
||||
if( eType==SQLITE_INTEGER ){
|
||||
if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK;
|
||||
}else{
|
||||
double rVal;
|
||||
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
|
||||
memcpy(&rVal, &iVal, 8);
|
||||
if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK;
|
||||
}
|
||||
break;
|
||||
/* A SessionChange object never has a NULL value in a PK column */
|
||||
assert( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT
|
||||
|| eType==SQLITE_BLOB || eType==SQLITE_TEXT
|
||||
);
|
||||
|
||||
if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
||||
i64 iVal = sessionGetI64(a);
|
||||
a += 8;
|
||||
if( eType==SQLITE_INTEGER ){
|
||||
if( sqlite3_value_int64(pVal)!=iVal ) return SQLITE_OK;
|
||||
}else{
|
||||
double rVal;
|
||||
assert( sizeof(iVal)==8 && sizeof(rVal)==8 );
|
||||
memcpy(&rVal, &iVal, 8);
|
||||
if( sqlite3_value_double(pVal)!=rVal ) return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_TEXT:
|
||||
case SQLITE_BLOB: {
|
||||
int n;
|
||||
const u8 *z;
|
||||
a += sessionVarintGet(a, &n);
|
||||
if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK;
|
||||
z = eType==SQLITE_TEXT ?
|
||||
sqlite3_value_text(pVal) : sqlite3_value_blob(pVal);
|
||||
if( memcmp(a, z, n) ) return SQLITE_OK;
|
||||
a += n;
|
||||
break;
|
||||
}else{
|
||||
int n;
|
||||
const u8 *z;
|
||||
a += sessionVarintGet(a, &n);
|
||||
if( sqlite3_value_bytes(pVal)!=n ) return SQLITE_OK;
|
||||
if( eType==SQLITE_TEXT ){
|
||||
z = sqlite3_value_text(pVal);
|
||||
}else{
|
||||
z = sqlite3_value_blob(pVal);
|
||||
}
|
||||
if( memcmp(a, z, n) ) return SQLITE_OK;
|
||||
a += n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -734,20 +737,22 @@ static void sessionPreupdateOneChange(
|
||||
rc = sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte);
|
||||
}
|
||||
}
|
||||
pChange->nRecord = nByte;
|
||||
|
||||
/* If an error has occurred, mark the session object as failed. */
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(pChange);
|
||||
pSession->rc = rc;
|
||||
}else{
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Add the change back to the hash-table */
|
||||
pChange->nRecord = nByte;
|
||||
pChange->bInsert = (op==SQLITE_INSERT);
|
||||
pChange->pNext = pTab->apChange[iHash];
|
||||
pTab->apChange[iHash] = pChange;
|
||||
}else{
|
||||
sqlite3_free(pChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If an error has occurred, mark the session object as failed. */
|
||||
if( rc!=SQLITE_OK ){
|
||||
pSession->rc = rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1345,7 +1350,7 @@ int sqlite3session_changeset(
|
||||
}
|
||||
|
||||
nNoop = buf.nBuf;
|
||||
for(i=0; i<pTab->nChange; i++){
|
||||
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){
|
||||
@ -1366,13 +1371,14 @@ int sqlite3session_changeset(
|
||||
sessionAppendByte(&buf, SQLITE_DELETE, &rc);
|
||||
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
|
||||
}
|
||||
rc = sqlite3_reset(pSel);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_reset(pSel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(pSel);
|
||||
|
||||
if( buf.nBuf==nNoop ){
|
||||
buf.nBuf = nRewind;
|
||||
}
|
||||
@ -1674,7 +1680,9 @@ int sqlite3changeset_conflict(
|
||||
int sqlite3changeset_finalize(sqlite3_changeset_iter *p){
|
||||
int i; /* Used to iterate through p->apValue[] */
|
||||
int rc = p->rc; /* Return code */
|
||||
for(i=0; i<p->nCol*2; i++) sqlite3ValueFree(p->apValue[i]);
|
||||
if( p->apValue ){
|
||||
for(i=0; i<p->nCol*2; i++) sqlite3ValueFree(p->apValue[i]);
|
||||
}
|
||||
sqlite3_free(p->apValue);
|
||||
sqlite3_free(p);
|
||||
return rc;
|
||||
@ -2316,7 +2324,8 @@ int sqlite3changeset_apply(
|
||||
SessionApplyCtx sApply; /* changeset_apply() context object */
|
||||
|
||||
memset(&sApply, 0, sizeof(sApply));
|
||||
sqlite3changeset_start(&pIter, nChangeset, pChangeset);
|
||||
rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
sqlite3_mutex_enter(sqlite3_db_mutex(db));
|
||||
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
|
||||
|
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Clarify\shandling\sof\sNULL\svalues\sin\sPK\scolumns\sin\ssqlite3session.h.\sAdd\stests\sand\sfixes\sfor\sthe\ssame.
|
||||
D 2011-03-21T11:55:07
|
||||
C Add\sstart\sof\sfault-injection\stests\sfor\ssession\smodule.\sFix\ssome\sbugs\srelated\sto\sthe\ssame.
|
||||
D 2011-03-21T16:17:42
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -100,8 +100,10 @@ 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 3ef304f660b2a929e6bfec2df125c1809f5501ff
|
||||
F ext/session/sqlite3session.c 70b19f80eadf7060836eaa90928f08a58aa3b35f
|
||||
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/sqlite3session.h 2c071ee5925e82c21c7c9c296a0422c039607106
|
||||
F ext/session/test_session.c 2559ef68e421c7fb83e2c19ef08a17343b70d535
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
@ -239,7 +241,7 @@ F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
|
||||
F src/vdbe.c c90edafd941481506f001b17cd8523683fdac853
|
||||
F src/vdbe.h edef9c4f0be83e1f1dccd049da37b40e021b63d9
|
||||
F src/vdbeInt.h 2cf77c1d151a4a54facd596d52be6d60c1cb26e8
|
||||
F src/vdbeapi.c c4692c74b31f4abe638fbcbae3944c52b54e2c36
|
||||
F src/vdbeapi.c 3d620e00cb74b6034343009af42d5ff5eb7c19dc
|
||||
F src/vdbeaux.c 0216b2c37509a44c3833b297765bee7bdd04fa2f
|
||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
@ -921,7 +923,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P a192d04f4e3a9e4960a4d96d1d3ee8635bc1034d
|
||||
R 0282a54a03134becd2cdef1929ff705c
|
||||
P aed4273054cbd150c86b36ea951d17c981633ba0
|
||||
R 3ee0056f48f594a086fa203e62ad6366
|
||||
U dan
|
||||
Z 9cc92283568709d19359195efd9bde16
|
||||
Z 9a232200bb7ff725d52774ff9ca627f1
|
||||
|
@ -1 +1 @@
|
||||
aed4273054cbd150c86b36ea951d17c981633ba0
|
||||
32e95164d1192b87b1ab019549fd2394642cd3fe
|
@ -1348,21 +1348,23 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
||||
|
||||
/* If the old.* record has not yet been loaded into memory, do so now. */
|
||||
if( p->pUnpacked==0 ){
|
||||
u32 nRecord;
|
||||
u8 *aRecord;
|
||||
u32 nRec;
|
||||
u8 *aRec;
|
||||
|
||||
rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRecord);
|
||||
rc = sqlite3BtreeDataSize(p->pCsr->pCursor, &nRec);
|
||||
if( rc!=SQLITE_OK ) goto preupdate_old_out;
|
||||
aRecord = sqlite3DbMallocRaw(db, nRecord);
|
||||
if( !aRecord ) goto preupdate_old_out;
|
||||
rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRecord, aRecord);
|
||||
aRec = sqlite3DbMallocRaw(db, nRec);
|
||||
if( !aRec ) goto preupdate_old_out;
|
||||
rc = sqlite3BtreeData(p->pCsr->pCursor, 0, nRec, aRec);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRec, aRec, 0, 0);
|
||||
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3DbFree(db, aRecord);
|
||||
sqlite3DbFree(db, aRec);
|
||||
goto preupdate_old_out;
|
||||
}
|
||||
|
||||
p->pUnpacked = sqlite3VdbeRecordUnpack(&p->keyinfo, nRecord, aRecord, 0, 0);
|
||||
p->aRecord = aRecord;
|
||||
p->aRecord = aRec;
|
||||
}
|
||||
|
||||
if( iIdx>=p->pUnpacked->nField ){
|
||||
|
Loading…
x
Reference in New Issue
Block a user