rbudiff.test 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. # 2015-07-31
  2. #
  3. # The author disclaims copyright to this source code. In place of
  4. # a legal notice, here is a blessing:
  5. #
  6. # May you do good and not evil.
  7. # May you find forgiveness for yourself and forgive others.
  8. # May you share freely, never taking more than you give.
  9. #
  10. #***********************************************************************
  11. #
  12. # Tests for the [sqldiff --rbu] command.
  13. #
  14. #
  15. source [file join [file dirname [info script]] rbu_common.tcl]
  16. if_no_rbu_support { finish_test ; return }
  17. set testprefix rbudiff
  18. set PROG [test_find_sqldiff]
  19. db close
  20. proc get_rbudiff_sql {db1 db2} {
  21. exec $::PROG --rbu $db1 $db2
  22. }
  23. proc get_vtab_rbudiff_sql {db1 db2} {
  24. exec $::PROG --vtab --rbu $db1 $db2
  25. }
  26. proc step_rbu {target rbu} {
  27. while 1 {
  28. sqlite3rbu rbu $target $rbu
  29. set rc [rbu step]
  30. rbu close
  31. if {$rc != "SQLITE_OK"} break
  32. }
  33. set rc
  34. }
  35. proc apply_rbudiff {sql target} {
  36. test_rbucount $sql
  37. forcedelete rbu.db
  38. sqlite3 rbudb rbu.db
  39. rbudb eval $sql
  40. rbudb close
  41. step_rbu $target rbu.db
  42. }
  43. proc sqlesc {id} {
  44. set ret "'[string map {' ''} $id]'"
  45. set ret
  46. }
  47. # The only argument is the output of an [sqldiff -rbu] run. This command
  48. # tests that the contents of the rbu_count table is correct. An exception
  49. # is thrown if it is not.
  50. #
  51. proc test_rbucount {sql} {
  52. sqlite3 tmpdb ""
  53. tmpdb eval $sql
  54. tmpdb eval {
  55. SELECT name FROM sqlite_master WHERE name LIKE 'data%' AND type='table'
  56. } {
  57. set a [tmpdb eval "SELECT count(*) FROM [sqlesc $name]"]
  58. set b [tmpdb eval {SELECT cnt FROM rbu_count WHERE tbl = $name}]
  59. if {$a != $b} {
  60. tmpdb close
  61. error "rbu_count error - tbl = $name"
  62. }
  63. }
  64. tmpdb close
  65. return ""
  66. }
  67. proc rbudiff_cksum {db1} {
  68. set txt ""
  69. sqlite3 dbtmp $db1
  70. foreach tbl [dbtmp eval {SELECT name FROM sqlite_master WHERE type='table'}] {
  71. set cols [list]
  72. dbtmp eval "PRAGMA table_info = [sqlesc $tbl]" {
  73. lappend cols "quote( $name )"
  74. }
  75. append txt [dbtmp eval \
  76. "SELECT [join $cols {||'.'||}] FROM [sqlesc $tbl] ORDER BY 1"
  77. ]
  78. }
  79. dbtmp close
  80. md5 $txt
  81. }
  82. foreach {tn init mod} {
  83. 1 {
  84. CREATE TABLE t1(a PRIMARY KEY, b, c);
  85. INSERT INTO t1 VALUES(1, 2, 3);
  86. INSERT INTO t1 VALUES(4, 5, 6);
  87. CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
  88. INSERT INTO t2 VALUES(1, 2, 3);
  89. INSERT INTO t2 VALUES(4, 5, 6);
  90. } {
  91. INSERT INTO t1 VALUES(7, 8, 9);
  92. DELETE FROM t1 WHERE a=4;
  93. UPDATE t1 SET c = 11 WHERE a = 1;
  94. INSERT INTO t2 VALUES(7, 8, 9);
  95. DELETE FROM t2 WHERE a=4;
  96. UPDATE t2 SET c = 11 WHERE a = 1;
  97. }
  98. 2 {
  99. CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b, c));
  100. INSERT INTO t1 VALUES('u', 'v', 'w');
  101. INSERT INTO t1 VALUES('x', 'y', 'z');
  102. } {
  103. DELETE FROM t1 WHERE a='u';
  104. INSERT INTO t1 VALUES('a', 'b', 'c');
  105. }
  106. 3 {
  107. CREATE TABLE t1(i INTEGER PRIMARY KEY, x);
  108. INSERT INTO t1 VALUES(1,
  109. X'0000000000000000111111111111111122222222222222223333333333333333'
  110. );
  111. CREATE TABLE t2(y INTEGER PRIMARY KEY, x);
  112. INSERT INTO t2 VALUES(1,
  113. X'0000000000000000111111111111111122222222222222223333333333333333'
  114. );
  115. } {
  116. DELETE FROM t1;
  117. INSERT INTO t1 VALUES(1,
  118. X'0000000000000000111111111111111122222555555552223333333333333333'
  119. );
  120. DELETE FROM t2;
  121. INSERT INTO t2 VALUES(1,
  122. X'0000000000000000111111111111111122222222222222223333333FFF333333'
  123. );
  124. }
  125. 4 {
  126. CREATE TABLE x1(a, b, c, PRIMARY KEY(a, b, c));
  127. INSERT INTO x1 VALUES('u', 'v', NULL);
  128. INSERT INTO x1 VALUES('x', 'y', 'z');
  129. INSERT INTO x1 VALUES('a', NULL, 'b');
  130. } {
  131. INSERT INTO x1 VALUES('a', 'b', 'c');
  132. }
  133. 5 {
  134. CREATE TABLE t1(a PRIMARY KEY, b);
  135. INSERT INTO t1 VALUES(1, NULL);
  136. INSERT INTO t1 VALUES(2, X'');
  137. } {
  138. UPDATE t1 SET b = X'' WHERE a=1;
  139. UPDATE t1 SET b = NULL WHERE a=2;
  140. }
  141. } {
  142. catch { db close }
  143. forcedelete test.db test.db2
  144. sqlite3 db test.db
  145. db eval "$init"
  146. sqlite3 db test.db2
  147. db eval "$init ; $mod"
  148. db close
  149. do_test 1.$tn.2 {
  150. set sql [get_rbudiff_sql test.db test.db2]
  151. apply_rbudiff $sql test.db
  152. } {SQLITE_DONE}
  153. do_test 1.$tn.3 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
  154. forcedelete test.db test.db2
  155. sqlite3 db test.db
  156. db eval "$init ; $mod"
  157. sqlite3 db test.db2
  158. db eval "$init"
  159. db close
  160. do_test 1.$tn.4 {
  161. set sql [get_rbudiff_sql test.db test.db2]
  162. apply_rbudiff $sql test.db
  163. } {SQLITE_DONE}
  164. do_test 1.$tn.5 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
  165. }
  166. #-------------------------------------------------------------------------
  167. # Test that if the --vtab switch is present, [sqldiff] handles virtual
  168. # table types fts[345] and rtree correctly.
  169. #
  170. ifcapable fts3&&fts5&&rtree {
  171. foreach {tn init mod} {
  172. 1 {
  173. CREATE VIRTUAL TABLE t1 USING fts5(c);
  174. INSERT INTO t1 VALUES('a b c');
  175. INSERT INTO t1 VALUES('a b c');
  176. } {
  177. DELETE FROM t1 WHERE rowid = 1;
  178. INSERT INTO t1 VALUES('a b c');
  179. }
  180. 2 {
  181. CREATE VIRTUAL TABLE "x y" USING 'rtree'(id, x1, x2);
  182. INSERT INTO "x y" VALUES(1, 2, 3);
  183. INSERT INTO "x y" VALUES(2, 4, 6);
  184. } {
  185. DELETE FROM "x y" WHERE rowid = 1;
  186. INSERT INTO "x y" VALUES(3, 6, 9);
  187. }
  188. 3 {
  189. CREATE VIRTUAL TABLE 'x''y' USING fts3;
  190. INSERT INTO 'x''y' VALUES('one two three');
  191. INSERT INTO 'x''y' VALUES('four five six');
  192. } {
  193. DELETE FROM 'x''y' WHERE rowid = 1;
  194. INSERT INTO 'x''y' VALUES('one two three');
  195. }
  196. } {
  197. forcedelete test.db test.db2
  198. sqlite3 db test.db
  199. db eval "$init"
  200. sqlite3 db test.db2
  201. db eval "$init ; $mod"
  202. db close
  203. do_test 2.$tn.1 {
  204. set sql [get_vtab_rbudiff_sql test.db test.db2]
  205. apply_rbudiff $sql test.db
  206. } {SQLITE_DONE}
  207. do_test 2.$tn.2 { rbudiff_cksum test.db } [rbudiff_cksum test.db2]
  208. }
  209. }
  210. ifcapable fts5 {
  211. foreach {tn init mod} {
  212. 1 {
  213. CREATE VIRTUAL TABLE t1 USING fts5(c);
  214. INSERT INTO t1 VALUES('a b c');
  215. INSERT INTO t1 VALUES('a b c');
  216. } {
  217. DELETE FROM t1 WHERE rowid = 1;
  218. INSERT INTO t1 VALUES('a b c');
  219. }
  220. 2 {
  221. CREATE VIRTUAL TABLE t1 USING FTs5(c);
  222. INSERT INTO t1 VALUES('a b c');
  223. INSERT INTO t1 VALUES('a b c');
  224. } {
  225. DELETE FROM t1 WHERE rowid = 1;
  226. INSERT INTO t1 VALUES('a b c');
  227. }
  228. 3 {
  229. creAte virTUal
  230. tablE t1 USING FTs5(c);
  231. INSERT INTO t1 VALUES('a b c');
  232. INSERT INTO t1 VALUES('a b c');
  233. } {
  234. DELETE FROM t1 WHERE rowid = 1;
  235. INSERT INTO t1 VALUES('a b c');
  236. }
  237. 4 {
  238. creAte virTUal tablE t1 USING FTs5(c);
  239. INSERT INTO t1 VALUES('a b c');
  240. INSERT INTO t1 VALUES('a b c');
  241. } {
  242. DELETE FROM t1 WHERE rowid = 1;
  243. INSERT INTO t1 VALUES('a b c');
  244. }
  245. } {
  246. forcedelete test.db test.db2
  247. sqlite3 db test.db
  248. db eval "$init"
  249. sqlite3 db test.db2
  250. db eval "$init ; $mod"
  251. db eval { INSERT INTO t1(t1) VALUES('optimize') }
  252. db close
  253. do_test 3.$tn.1 {
  254. set sql [get_vtab_rbudiff_sql test.db test.db2]
  255. apply_rbudiff $sql test.db
  256. } {SQLITE_DONE}
  257. sqlite3 db test.db
  258. sqlite3 db2 test.db2
  259. do_test 3.$tn.2 {
  260. db2 eval { SELECT * FROM t1 ORDER BY rowid }
  261. } [db eval { SELECT * FROM t1 ORDER BY rowid }]
  262. do_test 3.$tn.3 {
  263. db2 eval { INSERT INTO t1(t1) VALUES('integrity-check') }
  264. } {}
  265. db close
  266. db2 close
  267. }
  268. }
  269. finish_test