session5.test 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. # 2011 April 13
  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. # This file implements regression tests for the session module.
  12. # Specifically, for the sqlite3changeset_concat() command.
  13. #
  14. if {![info exists testdir]} {
  15. set testdir [file join [file dirname [info script]] .. .. test]
  16. }
  17. source [file join [file dirname [info script]] session_common.tcl]
  18. source $testdir/tester.tcl
  19. ifcapable !session {finish_test; return}
  20. set testprefix session5
  21. # Organization of tests:
  22. #
  23. # session5-1.*: Simple tests to check the concat() function produces
  24. # correct results.
  25. #
  26. # session5-2.*: More complicated tests.
  27. #
  28. # session5-3.*: Schema mismatch errors.
  29. #
  30. # session5-4.*: Test the concat cases that indicate that the database
  31. # was modified in between recording of the two changesets
  32. # being concatenated (i.e. two changesets that INSERT rows
  33. # with the same PK values).
  34. #
  35. proc do_concat_test {tn args} {
  36. set subtest 0
  37. foreach sql $args {
  38. incr subtest
  39. sqlite3session S db main ; S attach *
  40. execsql $sql
  41. set c [S changeset]
  42. if {[info commands s_prev] != ""} {
  43. set c_concat [sqlite3changeset_concat $c_prev $c]
  44. set c_two [s_prev changeset]
  45. s_prev delete
  46. set h_concat [changeset_to_list $c_concat]
  47. set h_two [changeset_to_list $c_two]
  48. do_test $tn.$subtest [list set {} $h_concat] $h_two
  49. }
  50. set c_prev $c
  51. rename S s_prev
  52. }
  53. catch { s_prev delete }
  54. }
  55. #-------------------------------------------------------------------------
  56. # Test cases session5-1.* - simple tests.
  57. #
  58. do_execsql_test 1.0 {
  59. CREATE TABLE t1(a PRIMARY KEY, b);
  60. }
  61. do_concat_test 1.1.1 {
  62. INSERT INTO t1 VALUES(1, 'one');
  63. } {
  64. INSERT INTO t1 VALUES(2, 'two');
  65. }
  66. do_concat_test 1.1.2 {
  67. UPDATE t1 SET b = 'five' WHERE a = 1;
  68. } {
  69. UPDATE t1 SET b = 'six' WHERE a = 2;
  70. }
  71. do_concat_test 1.1.3 {
  72. DELETE FROM t1 WHERE a = 1;
  73. } {
  74. DELETE FROM t1 WHERE a = 2;
  75. }
  76. # 1.2.1: INSERT + DELETE -> (none)
  77. # 1.2.2: INSERT + UPDATE -> INSERT
  78. #
  79. # 1.2.3: DELETE + INSERT (matching data) -> (none)
  80. # 1.2.4: DELETE + INSERT (non-matching data) -> UPDATE
  81. #
  82. # 1.2.5: UPDATE + UPDATE (matching data) -> (none)
  83. # 1.2.6: UPDATE + UPDATE (non-matching data) -> UPDATE
  84. # 1.2.7: UPDATE + DELETE -> DELETE
  85. #
  86. do_concat_test 1.2.1 {
  87. INSERT INTO t1 VALUES('x', 'y');
  88. } {
  89. DELETE FROM t1 WHERE a = 'x';
  90. }
  91. do_concat_test 1.2.2 {
  92. INSERT INTO t1 VALUES(5.0, 'five');
  93. } {
  94. UPDATE t1 SET b = 'six' WHERE a = 5.0;
  95. }
  96. do_execsql_test 1.2.3.1 "INSERT INTO t1 VALUES('I', 'one')"
  97. do_concat_test 1.2.3.2 {
  98. DELETE FROM t1 WHERE a = 'I';
  99. } {
  100. INSERT INTO t1 VALUES('I', 'one');
  101. }
  102. do_concat_test 1.2.4 {
  103. DELETE FROM t1 WHERE a = 'I';
  104. } {
  105. INSERT INTO t1 VALUES('I', 'two');
  106. }
  107. do_concat_test 1.2.5 {
  108. UPDATE t1 SET b = 'five' WHERE a = 'I';
  109. } {
  110. UPDATE t1 SET b = 'two' WHERE a = 'I';
  111. }
  112. do_concat_test 1.2.6 {
  113. UPDATE t1 SET b = 'six' WHERE a = 'I';
  114. } {
  115. UPDATE t1 SET b = 'seven' WHERE a = 'I';
  116. }
  117. do_concat_test 1.2.7 {
  118. UPDATE t1 SET b = 'eight' WHERE a = 'I';
  119. } {
  120. DELETE FROM t1 WHERE a = 'I';
  121. }
  122. #-------------------------------------------------------------------------
  123. # Test cases session5-2.* - more complex tests.
  124. #
  125. db function indirect indirect
  126. proc indirect {{x -1}} {
  127. S indirect $x
  128. s_prev indirect $x
  129. }
  130. do_concat_test 2.1 {
  131. CREATE TABLE abc(a, b, c PRIMARY KEY);
  132. INSERT INTO abc VALUES(NULL, NULL, 1);
  133. INSERT INTO abc VALUES('abcdefghijkl', NULL, 2);
  134. } {
  135. DELETE FROM abc WHERE c = 1;
  136. UPDATE abc SET c = 1 WHERE c = 2;
  137. } {
  138. INSERT INTO abc VALUES('abcdefghijkl', NULL, 2);
  139. INSERT INTO abc VALUES(1.0, 2.0, 3);
  140. } {
  141. UPDATE abc SET a = a-1;
  142. } {
  143. CREATE TABLE def(d, e, f, PRIMARY KEY(e, f));
  144. INSERT INTO def VALUES('x', randomblob(11000), 67);
  145. INSERT INTO def SELECT d, e, f+1 FROM def;
  146. INSERT INTO def SELECT d, e, f+2 FROM def;
  147. INSERT INTO def SELECT d, e, f+4 FROM def;
  148. } {
  149. DELETE FROM def WHERE rowid>4;
  150. } {
  151. INSERT INTO def SELECT d, e, f+4 FROM def;
  152. } {
  153. INSERT INTO abc VALUES(22, 44, -1);
  154. } {
  155. UPDATE abc SET c=-2 WHERE c=-1;
  156. UPDATE abc SET c=-3 WHERE c=-2;
  157. } {
  158. UPDATE abc SET c=-4 WHERE c=-3;
  159. } {
  160. UPDATE abc SET a=a+1 WHERE c=-3;
  161. UPDATE abc SET a=a+1 WHERE c=-3;
  162. } {
  163. UPDATE abc SET a=a+1 WHERE c=-3;
  164. UPDATE abc SET a=a+1 WHERE c=-3;
  165. } {
  166. INSERT INTO abc VALUES('one', 'two', 'three');
  167. } {
  168. SELECT indirect(1);
  169. UPDATE abc SET a='one point five' WHERE c = 'three';
  170. } {
  171. SELECT indirect(0);
  172. UPDATE abc SET a='one point six' WHERE c = 'three';
  173. } {
  174. CREATE TABLE x1(a, b, PRIMARY KEY(a));
  175. SELECT indirect(1);
  176. INSERT INTO x1 VALUES(1, 2);
  177. } {
  178. SELECT indirect(1);
  179. UPDATE x1 SET b = 3 WHERE a = 1;
  180. }
  181. catch {db close}
  182. forcedelete test.db
  183. sqlite3 db test.db
  184. do_concat_test 2.2 {
  185. CREATE TABLE t1(a, b, PRIMARY KEY(b));
  186. CREATE TABLE t2(a PRIMARY KEY, b);
  187. INSERT INTO t1 VALUES('string', 1);
  188. INSERT INTO t1 VALUES(4, 2);
  189. INSERT INTO t1 VALUES(X'FFAAFFAAFFAA', 3);
  190. } {
  191. INSERT INTO t2 VALUES('one', 'two');
  192. INSERT INTO t2 VALUES(1, NULL);
  193. UPDATE t1 SET a = 5 WHERE a = 2;
  194. } {
  195. DELETE FROM t2 WHERE a = 1;
  196. UPDATE t1 SET a = 4 WHERE a = 2;
  197. INSERT INTO t2 VALUES('x', 'y');
  198. }
  199. do_test 2.3.0 {
  200. catch {db close}
  201. forcedelete test.db
  202. sqlite3 db test.db
  203. set sql1 ""
  204. set sql2 ""
  205. for {set i 1} {$i < 120} {incr i} {
  206. append sql1 "INSERT INTO x1 VALUES($i*4, $i);"
  207. }
  208. for {set i 1} {$i < 120} {incr i} {
  209. append sql2 "DELETE FROM x1 WHERE a = $i*4;"
  210. }
  211. set {} {}
  212. } {}
  213. do_concat_test 2.3 {
  214. CREATE TABLE x1(a PRIMARY KEY, b)
  215. } $sql1 $sql2 $sql1 $sql2
  216. do_concat_test 2.4 {
  217. CREATE TABLE x2(a PRIMARY KEY, b);
  218. CREATE TABLE x3(a PRIMARY KEY, b);
  219. INSERT INTO x2 VALUES('a', 'b');
  220. INSERT INTO x2 VALUES('x', 'y');
  221. INSERT INTO x3 VALUES('a', 'b');
  222. } {
  223. INSERT INTO x2 VALUES('c', 'd');
  224. INSERT INTO x3 VALUES('e', 'f');
  225. INSERT INTO x3 VALUES('x', 'y');
  226. }
  227. do_concat_test 2.5 {
  228. UPDATE x3 SET b = 'Y' WHERE a = 'x'
  229. } {
  230. DELETE FROM x3 WHERE a = 'x'
  231. } {
  232. DELETE FROM x2 WHERE a = 'a'
  233. } {
  234. INSERT INTO x2 VALUES('a', 'B');
  235. }
  236. for {set k 1} {$k <=10} {incr k} {
  237. do_test 2.6.$k.1 {
  238. drop_all_tables
  239. set sql1 ""
  240. set sql2 ""
  241. for {set i 1} {$i < 120} {incr i} {
  242. append sql1 "INSERT INTO x1 VALUES(randomblob(20+(random()%10)), $i);"
  243. }
  244. for {set i 1} {$i < 120} {incr i} {
  245. append sql2 "DELETE FROM x1 WHERE rowid = $i;"
  246. }
  247. set {} {}
  248. } {}
  249. do_concat_test 2.6.$k {
  250. CREATE TABLE x1(a PRIMARY KEY, b)
  251. } $sql1 $sql2 $sql1 $sql2
  252. }
  253. for {set k 1} {$k <=10} {incr k} {
  254. do_test 2.7.$k.1 {
  255. drop_all_tables
  256. set sql1 ""
  257. set sql2 ""
  258. for {set i 1} {$i < 120} {incr i} {
  259. append sql1 {
  260. INSERT INTO x1 VALUES(
  261. CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END,
  262. CASE WHEN random()%2 THEN random() ELSE randomblob(20+random()%10) END
  263. );
  264. }
  265. }
  266. for {set i 1} {$i < 120} {incr i} {
  267. append sql2 "DELETE FROM x1 WHERE rowid = $i;"
  268. }
  269. set {} {}
  270. } {}
  271. do_concat_test 2.7.$k {
  272. CREATE TABLE x1(a PRIMARY KEY, b)
  273. } $sql1 $sql2 $sql1 $sql2
  274. }
  275. #-------------------------------------------------------------------------
  276. # Test that schema incompatibilities are detected correctly.
  277. #
  278. # session5-3.1: Incompatible number of columns.
  279. # session5-3.2: Incompatible PK definition.
  280. #
  281. do_test 3.1 {
  282. db close
  283. forcedelete test.db
  284. sqlite3 db test.db
  285. execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
  286. set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }]
  287. execsql {
  288. DROP TABLE t1;
  289. CREATE TABLE t1(a PRIMARY KEY, b, c);
  290. }
  291. set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3, 4) }]
  292. list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
  293. } {1 SQLITE_SCHEMA}
  294. do_test 3.2 {
  295. db close
  296. forcedelete test.db
  297. sqlite3 db test.db
  298. execsql { CREATE TABLE t1(a PRIMARY KEY, b) }
  299. set c1 [changeset_from_sql { INSERT INTO t1 VALUES(1, 2) }]
  300. execsql {
  301. DROP TABLE t1;
  302. CREATE TABLE t1(a, b PRIMARY KEY);
  303. }
  304. set c2 [changeset_from_sql { INSERT INTO t1 VALUES(2, 3) }]
  305. list [catch { sqlite3changeset_concat $c1 $c2 } msg] $msg
  306. } {1 SQLITE_SCHEMA}
  307. #-------------------------------------------------------------------------
  308. # Test that concat() handles these properly:
  309. #
  310. # session5-4.1: INSERT + INSERT
  311. # session5-4.2: UPDATE + INSERT
  312. # session5-4.3: DELETE + UPDATE
  313. # session5-4.4: DELETE + DELETE
  314. #
  315. proc do_concat_test2 {tn sql1 sqlX sql2 expected} {
  316. sqlite3session S db main ; S attach *
  317. execsql $sql1
  318. set ::c1 [S changeset]
  319. S delete
  320. execsql $sqlX
  321. sqlite3session S db main ; S attach *
  322. execsql $sql2
  323. set ::c2 [S changeset]
  324. S delete
  325. uplevel do_test $tn [list {
  326. changeset_to_list [sqlite3changeset_concat $::c1 $::c2]
  327. }] [list [normalize_list $expected]]
  328. }
  329. drop_all_tables db
  330. do_concat_test2 4.1 {
  331. CREATE TABLE t1(a PRIMARY KEY, b);
  332. INSERT INTO t1 VALUES('key', 'value');
  333. } {
  334. DELETE FROM t1 WHERE a = 'key';
  335. } {
  336. INSERT INTO t1 VALUES('key', 'xxx');
  337. } {
  338. {INSERT t1 0 X. {} {t key t value}}
  339. }
  340. do_concat_test2 4.2 {
  341. UPDATE t1 SET b = 'yyy';
  342. } {
  343. DELETE FROM t1 WHERE a = 'key';
  344. } {
  345. INSERT INTO t1 VALUES('key', 'value');
  346. } {
  347. {UPDATE t1 0 X. {t key t xxx} {{} {} t yyy}}
  348. }
  349. do_concat_test2 4.3 {
  350. DELETE FROM t1 WHERE a = 'key';
  351. } {
  352. INSERT INTO t1 VALUES('key', 'www');
  353. } {
  354. UPDATE t1 SET b = 'valueX' WHERE a = 'key';
  355. } {
  356. {DELETE t1 0 X. {t key t value} {}}
  357. }
  358. do_concat_test2 4.4 {
  359. DELETE FROM t1 WHERE a = 'key';
  360. } {
  361. INSERT INTO t1 VALUES('key', 'ttt');
  362. } {
  363. DELETE FROM t1 WHERE a = 'key';
  364. } {
  365. {DELETE t1 0 X. {t key t valueX} {}}
  366. }
  367. finish_test