1cf8e9144Sdan# 2014 August 16 2cf8e9144Sdan# 3cf8e9144Sdan# The author disclaims copyright to this source code. In place of 4cf8e9144Sdan# a legal notice, here is a blessing: 5cf8e9144Sdan# 6cf8e9144Sdan# May you do good and not evil. 7cf8e9144Sdan# May you find forgiveness for yourself and forgive others. 8cf8e9144Sdan# May you share freely, never taking more than you give. 9cf8e9144Sdan# 10cf8e9144Sdan#*********************************************************************** 11cf8e9144Sdan# This file focuses on the sqlite3session_diff() function. 12cf8e9144Sdan# 13cf8e9144Sdan 14cf8e9144Sdanif {![info exists testdir]} { 15cf8e9144Sdan set testdir [file join [file dirname [info script]] .. .. test] 16cf8e9144Sdan} 17cf8e9144Sdansource [file join [file dirname [info script]] session_common.tcl] 18cf8e9144Sdansource $testdir/tester.tcl 19cf8e9144Sdanifcapable !session {finish_test; return} 20cf8e9144Sdan 21cf8e9144Sdanset testprefix sessionD 22cf8e9144Sdan 23cf8e9144Sdanproc scksum {db dbname} { 24cf8e9144Sdan 25cf8e9144Sdan if {$dbname=="temp"} { 26cf8e9144Sdan set master sqlite_temp_master 27cf8e9144Sdan } else { 28cf8e9144Sdan set master $dbname.sqlite_master 29cf8e9144Sdan } 30cf8e9144Sdan 31cf8e9144Sdan set alltab [$db eval "SELECT name FROM $master WHERE type='table'"] 32cf8e9144Sdan set txt [$db eval "SELECT * FROM $master ORDER BY type,name,sql"] 33cf8e9144Sdan foreach tab $alltab { 34cf8e9144Sdan set cols [list] 35cf8e9144Sdan db eval "PRAGMA $dbname.table_info = $tab" x { 36cf8e9144Sdan lappend cols "quote($x(name))" 37cf8e9144Sdan } 38cf8e9144Sdan set cols [join $cols ,] 39cf8e9144Sdan append txt [db eval "SELECT $cols FROM $tab ORDER BY $cols"] 40cf8e9144Sdan } 41cf8e9144Sdan return [md5 $txt] 42cf8e9144Sdan} 43cf8e9144Sdan 44cf8e9144Sdanproc do_diff_test {tn setup} { 45cf8e9144Sdan reset_db 46cf8e9144Sdan forcedelete test.db2 47cf8e9144Sdan execsql { ATTACH 'test.db2' AS aux } 48cf8e9144Sdan execsql $setup 49cf8e9144Sdan 50cf8e9144Sdan sqlite3session S db main 51cf8e9144Sdan foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { 52cf8e9144Sdan S attach $tbl 53cf8e9144Sdan S diff aux $tbl 54cf8e9144Sdan } 55cf8e9144Sdan 56cf8e9144Sdan set C [S changeset] 57cf8e9144Sdan S delete 58cf8e9144Sdan 59cf8e9144Sdan sqlite3 db2 test.db2 60cf8e9144Sdan sqlite3changeset_apply db2 $C "" 61cf8e9144Sdan uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok 62cf8e9144Sdan db2 close 63cf8e9144Sdan 64cf8e9144Sdan set cksum [scksum db main] 65cf8e9144Sdan uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum] 66cf8e9144Sdan} 67cf8e9144Sdan 68dd009f83Sdan# Ensure that the diff produced by comparing the current contents of [db] 69dd009f83Sdan# with itself is empty. 70dd009f83Sdanproc do_empty_diff_test {tn} { 71dd009f83Sdan forcedelete test.db2 72dd009f83Sdan forcecopy test.db test.db2 73dd009f83Sdan 74dd009f83Sdan execsql { ATTACH 'test.db2' AS aux } 75dd009f83Sdan sqlite3session S db main 76dd009f83Sdan foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { 77dd009f83Sdan S attach $tbl 78dd009f83Sdan S diff aux $tbl 79dd009f83Sdan } 80dd009f83Sdan 81dd009f83Sdan set ::C [S changeset] 82dd009f83Sdan S delete 83dd009f83Sdan 84dd009f83Sdan uplevel [list do_test $tn {string length $::C} 0] 85dd009f83Sdan} 86dd009f83Sdan 87cf8e9144Sdan 88cf8e9144Sdanforcedelete test.db2 89cf8e9144Sdando_execsql_test 1.0 { 90cf8e9144Sdan CREATE TABLE t2(a PRIMARY KEY, b); 91cf8e9144Sdan INSERT INTO t2 VALUES(1, 'one'); 92cf8e9144Sdan INSERT INTO t2 VALUES(2, 'two'); 93cf8e9144Sdan 94cf8e9144Sdan ATTACH 'test.db2' AS aux; 95cf8e9144Sdan CREATE TABLE aux.t2(a PRIMARY KEY, b); 96cf8e9144Sdan} 97cf8e9144Sdan 98cf8e9144Sdando_test 1.1 { 99cf8e9144Sdan sqlite3session S db main 100cf8e9144Sdan S attach t2 101cf8e9144Sdan S diff aux t2 102cf8e9144Sdan set C [S changeset] 103cf8e9144Sdan S delete 104cf8e9144Sdan} {} 105cf8e9144Sdan 106cf8e9144Sdando_test 1.2 { 107cf8e9144Sdan sqlite3 db2 test.db2 108cf8e9144Sdan sqlite3changeset_apply db2 $C "" 109cf8e9144Sdan db2 close 110cf8e9144Sdan db eval { SELECT * FROM aux.t2 } 111cf8e9144Sdan} {1 one 2 two} 112cf8e9144Sdan 113cf8e9144Sdando_diff_test 2.1 { 114cf8e9144Sdan CREATE TABLE aux.t1(x, y, PRIMARY KEY(y)); 115cf8e9144Sdan CREATE TABLE t1(x, y, PRIMARY KEY(y)); 116cf8e9144Sdan 117cf8e9144Sdan INSERT INTO t1 VALUES(1, 2); 118cf8e9144Sdan INSERT INTO t1 VALUES(NULL, 'xyz'); 119cf8e9144Sdan INSERT INTO t1 VALUES(4.5, 5.5); 120cf8e9144Sdan} 121cf8e9144Sdan 122cf8e9144Sdando_diff_test 2.2 { 123cf8e9144Sdan CREATE TABLE aux.t1(x, y, PRIMARY KEY(y)); 124cf8e9144Sdan CREATE TABLE t1(x, y, PRIMARY KEY(y)); 125cf8e9144Sdan 126cf8e9144Sdan INSERT INTO aux.t1 VALUES(1, 2); 127cf8e9144Sdan INSERT INTO aux.t1 VALUES(NULL, 'xyz'); 128cf8e9144Sdan INSERT INTO aux.t1 VALUES(4.5, 5.5); 129cf8e9144Sdan} 130cf8e9144Sdan 131cf8e9144Sdando_diff_test 2.3 { 132cf8e9144Sdan CREATE TABLE aux.t1(a PRIMARY KEY, b TEXT); 133cf8e9144Sdan CREATE TABLE t1(a PRIMARY KEY, b TEXT); 134cf8e9144Sdan 135cf8e9144Sdan INSERT INTO aux.t1 VALUES(1, 'one'); 136cf8e9144Sdan INSERT INTO aux.t1 VALUES(2, 'two'); 137cf8e9144Sdan INSERT INTO aux.t1 VALUES(3, 'three'); 138cf8e9144Sdan 139cf8e9144Sdan INSERT INTO t1 VALUES(1, 'I'); 140cf8e9144Sdan INSERT INTO t1 VALUES(2, 'two'); 141cf8e9144Sdan INSERT INTO t1 VALUES(3, 'III'); 142cf8e9144Sdan} 143cf8e9144Sdan 144cf8e9144Sdando_diff_test 2.4 { 145cf8e9144Sdan CREATE TABLE aux.t1(a, b, c, d, PRIMARY KEY(c, b, a)); 146cf8e9144Sdan CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, b, a)); 147cf8e9144Sdan 148cf8e9144Sdan INSERT INTO t1 VALUES('hvkzyipambwdqlvwv','',-458331.50,X'DA51ED5E84'); 149cf8e9144Sdan INSERT INTO t1 VALUES(X'C5C6B5DD','jjxrath',40917,830244); 150cf8e9144Sdan INSERT INTO t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88,NULL); 151cf8e9144Sdan INSERT INTO t1 152cf8e9144Sdan VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidhjcbvbppdt',-642987.37); 153cf8e9144Sdan INSERT INTO t1 VALUES(-851726,-161992,-469943,-159541); 154cf8e9144Sdan INSERT INTO t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL); 155cf8e9144Sdan 156cf8e9144Sdan INSERT INTO aux.t1 VALUES(415075.74,'auawczkb',X'',X'57B4FAAF2595'); 157cf8e9144Sdan INSERT INTO aux.t1 VALUES(727637,711560,-181340,'hphuo'); 158cf8e9144Sdan INSERT INTO aux.t1 159cf8e9144Sdan VALUES(-921322.81,662959,'lvlgwdgxaurr','ajjrzrbhqflsutnymgc'); 160cf8e9144Sdan INSERT INTO aux.t1 VALUES(-146061,-377892,X'4E','gepvpvvuhszpxabbb'); 161cf8e9144Sdan INSERT INTO aux.t1 VALUES(-851726,-161992,-469943,-159541); 162cf8e9144Sdan INSERT INTO aux.t1 VALUES(X'4A6A667F858938',185083,X'7A',NULL); 163cf8e9144Sdan INSERT INTO aux.t1 VALUES(-204877.54,X'1704C253D5F3AFA8',155120.88, 4); 164cf8e9144Sdan INSERT INTO aux.t1 165cf8e9144Sdan VALUES('ckmqmzoeuvxisxqy',X'EB5A5D3A1DD22FD1','tidgtsplhjcbvbppdt',-642987.3); 166cf8e9144Sdan} 167cf8e9144Sdan 168dd009f83Sdanreset_db 169dd009f83Sdando_execsql_test 3.0 { 170dd009f83Sdan CREATE TABLE t1(a, b, c, PRIMARY KEY(a)); 171dd009f83Sdan INSERT INTO t1 VALUES(1, 2, 3); 172dd009f83Sdan INSERT INTO t1 VALUES(4, 5, 6); 173dd009f83Sdan INSERT INTO t1 VALUES(7, 8, 9); 174dd009f83Sdan 175dd009f83Sdan CREATE TABLE t2(a, b, c, PRIMARY KEY(a, b)); 176dd009f83Sdan INSERT INTO t2 VALUES(1, 2, 3); 177dd009f83Sdan INSERT INTO t2 VALUES(4, 5, 6); 178dd009f83Sdan INSERT INTO t2 VALUES(7, 8, 9); 179dd009f83Sdan 180dd009f83Sdan CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b, c)); 181dd009f83Sdan INSERT INTO t3 VALUES(1, 2, 3); 182dd009f83Sdan INSERT INTO t3 VALUES(4, 5, 6); 183dd009f83Sdan INSERT INTO t3 VALUES(7, 8, 9); 184dd009f83Sdan} 185dd009f83Sdando_empty_diff_test 3.1 186dd009f83Sdan 1874cc923e3Sdan 1884cc923e3Sdan#------------------------------------------------------------------------- 1894cc923e3Sdan# Test some error cases: 1904cc923e3Sdan# 1914cc923e3Sdan# 1) schema mismatches between the two dbs, and 192b9db9099Sdan# 2) tables with no primary keys. This is not actually an error, but 193b9db9099Sdan# should not add any changes to the session object. 1944cc923e3Sdan# 1954cc923e3Sdanreset_db 1964cc923e3Sdanforcedelete test.db2 1974cc923e3Sdando_execsql_test 4.0 { 1984cc923e3Sdan ATTACH 'test.db2' AS ixua; 1994cc923e3Sdan CREATE TABLE ixua.t1(a, b, c); 2004cc923e3Sdan CREATE TABLE main.t1(a, b, c); 201b9db9099Sdan INSERT INTO main.t1 VALUES(1, 2, 3); 2024cc923e3Sdan 2034cc923e3Sdan CREATE TABLE ixua.t2(a PRIMARY KEY, b, c); 2044cc923e3Sdan CREATE TABLE main.t2(a PRIMARY KEY, b, x); 2054cc923e3Sdan} 2064cc923e3Sdan 207b9db9099Sdando_test 4.1.1 { 2084cc923e3Sdan sqlite3session S db main 2094cc923e3Sdan S attach t1 2104cc923e3Sdan list [catch { S diff ixua t1 } msg] $msg 211b9db9099Sdan} {0 {}} 212b9db9099Sdando_test 4.1.2 { 213b9db9099Sdan string length [S changeset] 214b9db9099Sdan} {0} 215b9db9099SdanS delete 2164cc923e3Sdan 217b9db9099Sdando_test 4.2.2 { 218b9db9099Sdan sqlite3session S db main 2194cc923e3Sdan S attach t2 2204cc923e3Sdan list [catch { S diff ixua t2 } msg] $msg 221b9db9099Sdan} {1 {SQLITE_SCHEMA - table schemas do not match}} 2224cc923e3SdanS delete 2234cc923e3Sdan 224*58713184Sdando_test 4.3.1 { 225*58713184Sdan sqlite3session S db main 226*58713184Sdan S attach t4 227*58713184Sdan execsql { CREATE TABLE t4(i PRIMARY KEY, b) } 228*58713184Sdan list [catch { S diff ixua t4 } msg] $msg 229*58713184Sdan} {1 {SQLITE_SCHEMA - table schemas do not match}} 230*58713184SdanS delete 231*58713184Sdando_catchsql_test 4.3.2 { 232*58713184Sdan SELECT * FROM ixua.t4; 233*58713184Sdan} {1 {no such table: ixua.t4}} 234*58713184Sdan 235*58713184Sdando_test 4.4.1 { 236*58713184Sdan sqlite3session S db main 237*58713184Sdan S attach sqlite_stat1 238*58713184Sdan execsql { ANALYZE } 239*58713184Sdan execsql { DROP TABLE ixua.sqlite_stat1 } 240*58713184Sdan list [catch { S diff ixua sqlite_stat1 } msg] $msg 241*58713184Sdan} {1 {SQLITE_SCHEMA - table schemas do not match}} 242*58713184SdanS delete 243*58713184Sdando_catchsql_test 4.4.2 { 244*58713184Sdan SELECT * FROM ixua.sqlite_stat1; 245*58713184Sdan} {1 {no such table: ixua.sqlite_stat1}} 246*58713184Sdan 247*58713184Sdando_test 4.5.1 { 248*58713184Sdan sqlite3session S db main 249*58713184Sdan S attach t8 250*58713184Sdan list [catch { S diff ixua t8 } msg] $msg 251*58713184Sdan} {0 {}} 252*58713184SdanS delete 253*58713184Sdando_catchsql_test 4.5.2 { 254*58713184Sdan SELECT * FROM ixua.i8; 255*58713184Sdan} {1 {no such table: ixua.i8}} 256*58713184Sdan 257cf8e9144Sdanfinish_test 258