112ca0b56Sdan 26dc29e60Sdanproc do_changeset_test {tn session res} { 36dc29e60Sdan set r [list] 46dc29e60Sdan foreach x $res {lappend r $x} 56dc29e60Sdan uplevel do_test $tn [list [subst -nocommands { 66dc29e60Sdan set x [list] 76dc29e60Sdan sqlite3session_foreach c [$session changeset] { lappend x [set c] } 86dc29e60Sdan set x 96dc29e60Sdan }]] [list $r] 106dc29e60Sdan} 116dc29e60Sdan 126c39e6a8Sdanproc do_patchset_test {tn session res} { 136c39e6a8Sdan set r [list] 146c39e6a8Sdan foreach x $res {lappend r $x} 156c39e6a8Sdan uplevel do_test $tn [list [subst -nocommands { 166c39e6a8Sdan set x [list] 176c39e6a8Sdan sqlite3session_foreach c [$session patchset] { lappend x [set c] } 186c39e6a8Sdan set x 196c39e6a8Sdan }]] [list $r] 206c39e6a8Sdan} 216c39e6a8Sdan 226c39e6a8Sdan 236c39e6a8Sdanproc do_changeset_invert_test {tn session res} { 246c39e6a8Sdan set r [list] 256c39e6a8Sdan foreach x $res {lappend r $x} 266c39e6a8Sdan uplevel do_test $tn [list [subst -nocommands { 276c39e6a8Sdan set x [list] 286c39e6a8Sdan set changeset [sqlite3changeset_invert [$session changeset]] 296c39e6a8Sdan sqlite3session_foreach c [set changeset] { lappend x [set c] } 306c39e6a8Sdan set x 316c39e6a8Sdan }]] [list $r] 326c39e6a8Sdan} 336c39e6a8Sdan 3412ca0b56Sdan 3512ca0b56Sdanproc do_conflict_test {tn args} { 3612ca0b56Sdan 3712ca0b56Sdan set O(-tables) [list] 3812ca0b56Sdan set O(-sql) [list] 3912ca0b56Sdan set O(-conflicts) [list] 40ff677b20Sdan set O(-policy) "OMIT" 4112ca0b56Sdan 4212ca0b56Sdan array set V $args 4312ca0b56Sdan foreach key [array names V] { 4412ca0b56Sdan if {![info exists O($key)]} {error "no such option: $key"} 4512ca0b56Sdan } 4612ca0b56Sdan array set O $args 4712ca0b56Sdan 48ff677b20Sdan proc xConflict {args} [subst -nocommands { 49ff677b20Sdan lappend ::xConflict [set args] 50ff677b20Sdan return $O(-policy) 51ff677b20Sdan }] 52ff677b20Sdan proc bgerror {args} { set ::background_error $args } 53ff677b20Sdan 5412ca0b56Sdan sqlite3session S db main 5512ca0b56Sdan foreach t $O(-tables) { S attach $t } 5612ca0b56Sdan execsql $O(-sql) 5712ca0b56Sdan 5812ca0b56Sdan set ::xConflict [list] 5912ca0b56Sdan sqlite3changeset_apply db2 [S changeset] xConflict 6012ca0b56Sdan 6112ca0b56Sdan set conflicts [list] 6212ca0b56Sdan foreach c $O(-conflicts) { 6312ca0b56Sdan lappend conflicts $c 6412ca0b56Sdan } 6512ca0b56Sdan 6612ca0b56Sdan after 1 {set go 1} 6712ca0b56Sdan vwait go 6812ca0b56Sdan 6912ca0b56Sdan uplevel do_test $tn [list { set ::xConflict }] [list $conflicts] 7012ca0b56Sdan S delete 7112ca0b56Sdan} 7212ca0b56Sdan 7312ca0b56Sdanproc do_common_sql {sql} { 7412ca0b56Sdan execsql $sql db 7512ca0b56Sdan execsql $sql db2 7612ca0b56Sdan} 7712ca0b56Sdan 787aa469cdSdanproc changeset_from_sql {sql {dbname main}} { 79a87070a2Sdan if {$dbname == "main"} { 80a87070a2Sdan return [sql_exec_changeset db $sql] 81a87070a2Sdan } 827aa469cdSdan set rc [catch { 837aa469cdSdan sqlite3session S db $dbname 847aa469cdSdan db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { 857aa469cdSdan S attach $name 867aa469cdSdan } 877aa469cdSdan db eval $sql 887aa469cdSdan S changeset 897aa469cdSdan } changeset] 907aa469cdSdan catch { S delete } 917aa469cdSdan 927aa469cdSdan if {$rc} { 937aa469cdSdan error $changeset 947aa469cdSdan } 957aa469cdSdan return $changeset 967aa469cdSdan} 977aa469cdSdan 9844748f27Sdanproc patchset_from_sql {sql {dbname main}} { 9944748f27Sdan set rc [catch { 10044748f27Sdan sqlite3session S db $dbname 10144748f27Sdan db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { 10244748f27Sdan S attach $name 10344748f27Sdan } 10444748f27Sdan db eval $sql 10544748f27Sdan S patchset 10644748f27Sdan } patchset] 10744748f27Sdan catch { S delete } 10844748f27Sdan 10944748f27Sdan if {$rc} { 11044748f27Sdan error $patchset 11144748f27Sdan } 11244748f27Sdan return $patchset 11344748f27Sdan} 11444748f27Sdan 11512ca0b56Sdanproc do_then_apply_sql {sql {dbname main}} { 11612ca0b56Sdan proc xConflict args { return "OMIT" } 11712ca0b56Sdan set rc [catch { 11812ca0b56Sdan sqlite3session S db $dbname 11912ca0b56Sdan db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { 12012ca0b56Sdan S attach $name 12112ca0b56Sdan } 12212ca0b56Sdan db eval $sql 12312ca0b56Sdan sqlite3changeset_apply db2 [S changeset] xConflict 12412ca0b56Sdan } msg] 12512ca0b56Sdan 12612ca0b56Sdan catch { S delete } 12712ca0b56Sdan 12812ca0b56Sdan if {$rc} {error $msg} 12912ca0b56Sdan} 13012ca0b56Sdan 13112ca0b56Sdanproc do_iterator_test {tn tbl_list sql res} { 13212ca0b56Sdan sqlite3session S db main 133ff4d0f41Sdan if {[llength $tbl_list]==0} { S attach * } 13412ca0b56Sdan foreach t $tbl_list {S attach $t} 135ff4d0f41Sdan 13612ca0b56Sdan execsql $sql 13712ca0b56Sdan 13812ca0b56Sdan set r [list] 13912ca0b56Sdan foreach v $res { lappend r $v } 14012ca0b56Sdan 14112ca0b56Sdan set x [list] 14212ca0b56Sdan sqlite3session_foreach c [S changeset] { lappend x $c } 14312ca0b56Sdan uplevel do_test $tn [list [list set {} $x]] [list $r] 14412ca0b56Sdan 14512ca0b56Sdan S delete 14612ca0b56Sdan} 14712ca0b56Sdan 14812ca0b56Sdan# Compare the contents of all tables in [db1] and [db2]. Throw an error if 14912ca0b56Sdan# they are not identical, or return an empty string if they are. 15012ca0b56Sdan# 15112ca0b56Sdanproc compare_db {db1 db2} { 15212ca0b56Sdan 15312ca0b56Sdan set sql {SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name} 15412ca0b56Sdan set lot1 [$db1 eval $sql] 15512ca0b56Sdan set lot2 [$db2 eval $sql] 15612ca0b56Sdan 157db04571cSdan if {$lot1 != $lot2} { 158db04571cSdan puts $lot1 159db04571cSdan puts $lot2 160db04571cSdan error "databases contain different tables" 161db04571cSdan } 16212ca0b56Sdan 16312ca0b56Sdan foreach tbl $lot1 { 16412ca0b56Sdan set col1 [list] 16512ca0b56Sdan set col2 [list] 16612ca0b56Sdan 16712ca0b56Sdan $db1 eval "PRAGMA table_info = $tbl" { lappend col1 $name } 16812ca0b56Sdan $db2 eval "PRAGMA table_info = $tbl" { lappend col2 $name } 16912ca0b56Sdan if {$col1 != $col2} { error "table $tbl schema mismatch" } 17012ca0b56Sdan 17112ca0b56Sdan set sql "SELECT * FROM $tbl ORDER BY [join $col1 ,]" 17212ca0b56Sdan set data1 [$db1 eval $sql] 17312ca0b56Sdan set data2 [$db2 eval $sql] 1747aa469cdSdan if {$data1 != $data2} { 175*5d237bfaSdan puts "$db1: $data1" 176*5d237bfaSdan puts "$db2: $data2" 1777aa469cdSdan error "table $tbl data mismatch" 1787aa469cdSdan } 17912ca0b56Sdan } 18012ca0b56Sdan 18112ca0b56Sdan return "" 18212ca0b56Sdan} 18312ca0b56Sdan 1841756ae10Sdanproc changeset_to_list {c} { 1851756ae10Sdan set list [list] 1861756ae10Sdan sqlite3session_foreach elem $c { lappend list $elem } 1871756ae10Sdan lsort $list 1881756ae10Sdan} 189bd45374cSdan 1903e259bcdSdanset ones {zero one two three four five six seven eight nine 1913e259bcdSdan ten eleven twelve thirteen fourteen fifteen sixteen seventeen 1923e259bcdSdan eighteen nineteen} 1933e259bcdSdanset tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety} 1943e259bcdSdanproc number_name {n} { 1953e259bcdSdan if {$n>=1000} { 1963e259bcdSdan set txt "[number_name [expr {$n/1000}]] thousand" 1973e259bcdSdan set n [expr {$n%1000}] 1983e259bcdSdan } else { 1993e259bcdSdan set txt {} 2003e259bcdSdan } 2013e259bcdSdan if {$n>=100} { 2023e259bcdSdan append txt " [lindex $::ones [expr {$n/100}]] hundred" 2033e259bcdSdan set n [expr {$n%100}] 2043e259bcdSdan } 2053e259bcdSdan if {$n>=20} { 2063e259bcdSdan append txt " [lindex $::tens [expr {$n/10}]]" 2073e259bcdSdan set n [expr {$n%10}] 2083e259bcdSdan } 2093e259bcdSdan if {$n>0} { 2103e259bcdSdan append txt " [lindex $::ones $n]" 2113e259bcdSdan } 2123e259bcdSdan set txt [string trim $txt] 2133e259bcdSdan if {$txt==""} {set txt zero} 2143e259bcdSdan return $txt 2153e259bcdSdan} 216