123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- proc do_changeset_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- sqlite3session_foreach c [$session changeset] { lappend x [set c] }
- set x
- }]] [list $r]
- }
- proc do_patchset_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- sqlite3session_foreach c [$session patchset] { lappend x [set c] }
- set x
- }]] [list $r]
- }
- proc do_changeset_invert_test {tn session res} {
- set r [list]
- foreach x $res {lappend r $x}
- uplevel do_test $tn [list [subst -nocommands {
- set x [list]
- set changeset [sqlite3changeset_invert [$session changeset]]
- sqlite3session_foreach c [set changeset] { lappend x [set c] }
- set x
- }]] [list $r]
- }
- proc do_conflict_test {tn args} {
- set O(-tables) [list]
- set O(-sql) [list]
- set O(-conflicts) [list]
- set O(-policy) "OMIT"
- array set V $args
- foreach key [array names V] {
- if {![info exists O($key)]} {error "no such option: $key"}
- }
- array set O $args
- proc xConflict {args} [subst -nocommands {
- lappend ::xConflict [set args]
- return $O(-policy)
- }]
- proc bgerror {args} { set ::background_error $args }
- sqlite3session S db main
- S object_config rowid 1
- 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 changeset_from_sql {sql {dbname main}} {
- if {$dbname == "main"} {
- return [sql_exec_changeset db $sql]
- }
- set rc [catch {
- sqlite3session S db $dbname
- S object_config rowid 1
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- db eval $sql
- S changeset
- } changeset]
- catch { S delete }
- if {$rc} {
- error $changeset
- }
- return $changeset
- }
- proc patchset_from_sql {sql {dbname main}} {
- set rc [catch {
- sqlite3session S db $dbname
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- db eval $sql
- S patchset
- } patchset]
- catch { S delete }
- if {$rc} {
- error $patchset
- }
- return $patchset
- }
- # Usage: do_then_apply_sql ?-ignorenoop? SQL ?DBNAME?
- #
- proc do_then_apply_sql {args} {
-
- set bIgnoreNoop 0
- set a1 [lindex $args 0]
- if {[string length $a1]>1 && [string first $a1 -ignorenoop]==0} {
- set bIgnoreNoop 1
- set args [lrange $args 1 end]
- }
- if {[llength $args]!=1 && [llength $args]!=2} {
- error "usage: do_then_apply_sql ?-ignorenoop? SQL ?DBNAME?"
- }
- set sql [lindex $args 0]
- if {[llength $args]==1} {
- set dbname main
- } else {
- set dbname [lindex $args 1]
- }
- set ::n_conflict 0
- proc xConflict args { incr ::n_conflict ; return "OMIT" }
- set rc [catch {
- sqlite3session S db $dbname
- S object_config rowid 1
- db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
- S attach $name
- }
- db eval $sql
- set ::changeset [S changeset]
- sqlite3changeset_apply db2 $::changeset xConflict
- } msg]
- catch { S delete }
- if {$rc} {error $msg}
- if {$bIgnoreNoop} {
- set nSave $::n_conflict
- set ::n_conflict 0
- proc xConflict args { incr ::n_conflict ; return "OMIT" }
- sqlite3changeset_apply_v2 -ignorenoop db2 $::changeset xConflict
- if {$::n_conflict!=$nSave} {
- error "-ignorenoop problem ($::n_conflict $nSave)..."
- }
- }
- }
- proc do_iterator_test {tn tbl_list sql res} {
- sqlite3session S db main
- S object_config rowid 1
- if {[llength $tbl_list]==0} { S attach * }
- foreach t $tbl_list {S attach $t}
- execsql $sql
- set r [list]
- foreach v $res { lappend r $v }
- set x [list]
- # set ::c [S changeset] ; execsql_pp { SELECT quote($::c) }
- 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} {
- puts $lot1
- puts $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} {
- puts "$db1: $data1"
- puts "$db2: $data2"
- error "table $tbl data mismatch"
- }
- }
- return ""
- }
- proc changeset_to_list {c} {
- set list [list]
- sqlite3session_foreach elem $c { lappend list $elem }
- lsort $list
- }
- set ones {zero one two three four five six seven eight nine
- ten eleven twelve thirteen fourteen fifteen sixteen seventeen
- eighteen nineteen}
- set tens {{} ten twenty thirty forty fifty sixty seventy eighty ninety}
- proc number_name {n} {
- if {$n>=1000} {
- set txt "[number_name [expr {$n/1000}]] thousand"
- set n [expr {$n%1000}]
- } else {
- set txt {}
- }
- if {$n>=100} {
- append txt " [lindex $::ones [expr {$n/100}]] hundred"
- set n [expr {$n%100}]
- }
- if {$n>=20} {
- append txt " [lindex $::tens [expr {$n/10}]]"
- set n [expr {$n%10}]
- }
- if {$n>0} {
- append txt " [lindex $::ones $n]"
- }
- set txt [string trim $txt]
- if {$txt==""} {set txt zero}
- return $txt
- }
- proc scksum {db dbname} {
- if {$dbname=="temp"} {
- set master sqlite_temp_master
- } else {
- set master $dbname.sqlite_master
- }
- set alltab [$db eval "SELECT name FROM $master WHERE type='table'"]
- set txt [$db eval "SELECT * FROM $master ORDER BY type,name,sql"]
- foreach tab $alltab {
- set cols [list]
- db eval "PRAGMA $dbname.table_info = $tab" x {
- lappend cols "quote($x(name))"
- }
- set cols [join $cols ,]
- append txt [db eval "SELECT $cols FROM $dbname.$tab ORDER BY $cols"]
- }
- return [md5 $txt]
- }
- proc do_diff_test {tn setup} {
- reset_db
- forcedelete test.db2
- execsql { ATTACH 'test.db2' AS aux }
- execsql $setup
- sqlite3session S db main
- S object_config rowid 1
- foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
- S attach $tbl
- S diff aux $tbl
- }
- set C [S changeset]
- S delete
- sqlite3 db2 test.db2
- sqlite3changeset_apply db2 $C ""
- uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok
- db2 close
- set cksum [scksum db main]
- uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum]
- }
|