sessionrebase.test 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. # 2018 March 14
  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 SQLite library.
  12. #
  13. if {![info exists testdir]} {
  14. set testdir [file join [file dirname [info script]] .. .. test]
  15. }
  16. source [file join [file dirname [info script]] session_common.tcl]
  17. source $testdir/tester.tcl
  18. ifcapable !session {finish_test; return}
  19. set testprefix sessionrebase
  20. set ::lConflict [list]
  21. proc xConflict {args} {
  22. set res [lindex $::lConflict 0]
  23. set ::lConflict [lrange $::lConflict 1 end]
  24. return $res
  25. }
  26. #-------------------------------------------------------------------------
  27. # The following test cases - 1.* - test that the rebase blobs output by
  28. # sqlite3_changeset_apply_v2 look correct in some simple cases. The blob
  29. # is itself a changeset, containing records determined as follows:
  30. #
  31. # * For each conflict resolved with REPLACE, the rebase blob contains
  32. # a DELETE record. All fields other than the PK fields are undefined.
  33. #
  34. # * For each conflict resolved with OMIT, the rebase blob contains an
  35. # INSERT record. For an INSERT or UPDATE operation, the indirect flag
  36. # is clear and all updated fields are defined. For a DELETE operation,
  37. # the indirect flag is set and all non-PK fields left undefined.
  38. #
  39. proc do_apply_v2_test {tn sql modsql conflict_handler res} {
  40. execsql BEGIN
  41. sqlite3session S db main
  42. S attach *
  43. execsql $sql
  44. set changeset [S changeset]
  45. S delete
  46. execsql ROLLBACK
  47. execsql BEGIN
  48. execsql $modsql
  49. set ::lConflict $conflict_handler
  50. set blob [sqlite3changeset_apply_v2 db $changeset xConflict]
  51. execsql ROLLBACK
  52. uplevel [list do_test $tn [list changeset_to_list $blob] [list {*}$res]]
  53. }
  54. set ::lConflict [list]
  55. proc xConflict {args} {
  56. set res [lindex $::lConflict 0]
  57. set ::lConflict [lrange $::lConflict 1 end]
  58. return $res
  59. }
  60. # Take a copy of database test.db in file test.db2. Execute $sql1
  61. # against test.db and $sql2 against test.db2. Capture a changeset
  62. # for each. Then send the test.db2 changeset to test.db and apply
  63. # it with the conflict handlers in $conflict_handler. Patch the
  64. # test.db changeset and then execute it against test.db2. Test that
  65. # the two databases come out the same.
  66. #
  67. proc do_rebase_test {tn sql1 sql2 conflict_handler {testsql ""} {testres ""}} {
  68. for {set i 1} {$i <= 2} {incr i} {
  69. forcedelete test.db2 test.db2-journal test.db2-wal
  70. forcecopy test.db test.db2
  71. sqlite3 db2 test.db2
  72. db eval BEGIN
  73. sqlite3session S1 db main
  74. S1 object_config rowid 1
  75. S1 attach *
  76. execsql $sql1 db
  77. set c1 [S1 changeset]
  78. S1 delete
  79. if {$i==1} {
  80. sqlite3session S2 db2 main
  81. S2 object_config rowid 1
  82. S2 attach *
  83. execsql $sql2 db2
  84. set c2 [S2 changeset]
  85. S2 delete
  86. } else {
  87. set c2 [list]
  88. foreach sql [split $sql2 ";"] {
  89. if {[string is space $sql]} continue
  90. sqlite3session S2 db2 main
  91. S2 object_config rowid 1
  92. S2 attach *
  93. execsql $sql db2
  94. lappend c2 [S2 changeset]
  95. S2 delete
  96. }
  97. }
  98. set ::lConflict $conflict_handler
  99. set rebase [list]
  100. if {$i==1} {
  101. lappend rebase [sqlite3changeset_apply_v2 db $c2 xConflict]
  102. } else {
  103. foreach c $c2 {
  104. #puts "apply_v2: [changeset_to_list $c]"
  105. lappend rebase [sqlite3changeset_apply_v2 db $c xConflict]
  106. }
  107. #puts "llength: [llength $rebase]"
  108. }
  109. #if {$tn=="2.1.4"} { puts [changeset_to_list $rebase] ; breakpoint }
  110. #puts [changeset_to_list [lindex $rebase 0]] ; breakpoint
  111. #puts [llength $rebase]
  112. sqlite3rebaser_create R
  113. foreach r $rebase {
  114. #puts [changeset_to_list $r]
  115. R configure $r
  116. }
  117. set c1r [R rebase $c1]
  118. R delete
  119. #if {$tn=="2.1.4"} { puts [changeset_to_list $c1r] }
  120. sqlite3changeset_apply_v2 db2 $c1r xConflictAbort
  121. if {[string range $tn end end]!="*"} {
  122. uplevel [list do_test $tn.$i.1 [list compare_db db db2] {}]
  123. }
  124. db2 close
  125. if {$testsql!=""} {
  126. uplevel [list do_execsql_test $tn.$i.2 $testsql $testres]
  127. }
  128. db eval ROLLBACK
  129. }
  130. }
  131. do_execsql_test 1.0 {
  132. CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  133. INSERT INTO t1 VALUES(1, 'value A');
  134. }
  135. do_apply_v2_test 1.1.1 {
  136. UPDATE t1 SET b = 'value B' WHERE a=1;
  137. } {
  138. UPDATE t1 SET b = 'value C' WHERE a=1;
  139. } {
  140. OMIT
  141. } {
  142. {INSERT t1 0 X. {} {i 1 t {value B}}}
  143. }
  144. do_apply_v2_test 1.1.2 {
  145. UPDATE t1 SET b = 'value B' WHERE a=1;
  146. } {
  147. UPDATE t1 SET b = 'value C' WHERE a=1;
  148. } {
  149. REPLACE
  150. } {
  151. {INSERT t1 1 X. {} {i 1 t {value B}}}
  152. }
  153. do_apply_v2_test 1.2.1 {
  154. INSERT INTO t1 VALUES(2, 'first');
  155. } {
  156. INSERT INTO t1 VALUES(2, 'second');
  157. } {
  158. OMIT
  159. } {
  160. {INSERT t1 0 X. {} {i 2 t first}}
  161. }
  162. do_apply_v2_test 1.2.2 {
  163. INSERT INTO t1 VALUES(2, 'first');
  164. } {
  165. INSERT INTO t1 VALUES(2, 'second');
  166. } {
  167. REPLACE
  168. } {
  169. {INSERT t1 1 X. {} {i 2 t first}}
  170. }
  171. do_apply_v2_test 1.3.1 {
  172. DELETE FROM t1 WHERE a=1;
  173. } {
  174. UPDATE t1 SET b='value D' WHERE a=1;
  175. } {
  176. OMIT
  177. } {
  178. {DELETE t1 0 X. {i 1 t {value A}} {}}
  179. }
  180. do_apply_v2_test 1.3.2 {
  181. DELETE FROM t1 WHERE a=1;
  182. } {
  183. UPDATE t1 SET b='value D' WHERE a=1;
  184. } {
  185. REPLACE
  186. } {
  187. {DELETE t1 1 X. {i 1 t {value A}} {}}
  188. }
  189. #-------------------------------------------------------------------------
  190. # Test cases 2.* - simple tests of rebasing actual changesets.
  191. #
  192. # 2.1.1 - 1u2u1r
  193. # 2.1.2 - 1u2u2r
  194. # 2.1.3 - 1d2d
  195. # 2.1.4 - 1d2u1r
  196. # 2.1.5 - 1d2u2r !!
  197. # 2.1.6 - 1u2d1r
  198. # 2.1.7 - 1u2d2r
  199. #
  200. # 2.1.8 - 1i2i2r
  201. # 2.1.9 - 1i2i1r
  202. #
  203. proc xConflictAbort {args} {
  204. return "ABORT"
  205. }
  206. reset_db
  207. do_execsql_test 2.1.0 {
  208. CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT);
  209. INSERT INTO t1 VALUES(1, 'one');
  210. INSERT INTO t1 VALUES(2, 'two');
  211. INSERT INTO t1 VALUES(3, 'three');
  212. }
  213. do_rebase_test 2.1.1 {
  214. UPDATE t1 SET b = 'two.1' WHERE a=2
  215. } {
  216. UPDATE t1 SET b = 'two.2' WHERE a=2;
  217. } {
  218. OMIT
  219. } { SELECT * FROM t1 } {1 one 2 two.1 3 three}
  220. do_rebase_test 2.1.2 {
  221. UPDATE t1 SET b = 'two.1' WHERE a=2
  222. } {
  223. UPDATE t1 SET b = 'two.2' WHERE a=2;
  224. } {
  225. REPLACE
  226. } { SELECT * FROM t1 } {1 one 2 two.2 3 three}
  227. do_rebase_test 2.1.3 {
  228. DELETE FROM t1 WHERE a=3
  229. } {
  230. DELETE FROM t1 WHERE a=3;
  231. } {
  232. OMIT
  233. } { SELECT * FROM t1 } {1 one 2 two}
  234. do_rebase_test 2.1.4 {
  235. DELETE FROM t1 WHERE a=1
  236. } {
  237. UPDATE t1 SET b='one.2' WHERE a=1
  238. } {
  239. OMIT
  240. } { SELECT * FROM t1 } {2 two 3 three}
  241. #do_rebase_test 2.1.5 {
  242. # DELETE FROM t1 WHERE a=1;
  243. #} {
  244. # UPDATE t1 SET b='one.2' WHERE a=1
  245. #} {
  246. # REPLACE
  247. #} { SELECT * FROM t1 } {2 two 3 three}
  248. do_rebase_test 2.1.6 {
  249. UPDATE t1 SET b='three.1' WHERE a=3
  250. } {
  251. DELETE FROM t1 WHERE a=3;
  252. } {
  253. OMIT
  254. } { SELECT * FROM t1 } {1 one 2 two 3 three.1}
  255. do_rebase_test 2.1.7 {
  256. UPDATE t1 SET b='three.1' WHERE a=3
  257. } {
  258. DELETE FROM t1 WHERE a=3;
  259. } {
  260. REPLACE
  261. } { SELECT * FROM t1 } {1 one 2 two}
  262. do_rebase_test 2.1.8 {
  263. INSERT INTO t1 VALUES(4, 'four.1')
  264. } {
  265. INSERT INTO t1 VALUES(4, 'four.2');
  266. } {
  267. REPLACE
  268. } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.2}
  269. do_rebase_test 2.1.9 {
  270. INSERT INTO t1 VALUES(4, 'four.1')
  271. } {
  272. INSERT INTO t1 VALUES(4, 'four.2');
  273. } {
  274. OMIT
  275. } { SELECT * FROM t1 } {1 one 2 two 3 three 4 four.1}
  276. do_execsql_test 2.2.0 {
  277. CREATE TABLE t2(x, y, z PRIMARY KEY);
  278. INSERT INTO t2 VALUES('i', 'a', 'A');
  279. INSERT INTO t2 VALUES('ii', 'b', 'B');
  280. INSERT INTO t2 VALUES('iii', 'c', 'C');
  281. CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
  282. INSERT INTO t3 VALUES(-1, 'z', 'Z');
  283. INSERT INTO t3 VALUES(-2, 'y', 'Y');
  284. }
  285. do_rebase_test 2.2.1 {
  286. UPDATE t2 SET x=1 WHERE z='A'
  287. } {
  288. UPDATE t2 SET y='one' WHERE z='A';
  289. } {
  290. } { SELECT * FROM t2 WHERE z='A' } { 1 one A }
  291. do_rebase_test 2.2.2 {
  292. UPDATE t2 SET x=1, y='one' WHERE z='B'
  293. } {
  294. UPDATE t2 SET y='two' WHERE z='B';
  295. } {
  296. REPLACE
  297. } { SELECT * FROM t2 WHERE z='B' } { 1 two B }
  298. do_rebase_test 2.2.3 {
  299. UPDATE t2 SET x=1, y='one' WHERE z='B'
  300. } {
  301. UPDATE t2 SET y='two' WHERE z='B';
  302. } {
  303. OMIT
  304. } { SELECT * FROM t2 WHERE z='B' } { 1 one B }
  305. reset_db
  306. do_execsql_test 2.3.0 {
  307. CREATE TABLE t1 (b TEXT);
  308. INSERT INTO t1(rowid, b) VALUES(1, 'one');
  309. INSERT INTO t1(rowid, b) VALUES(2, 'two');
  310. INSERT INTO t1(rowid, b) VALUES(3, 'three');
  311. }
  312. do_rebase_test 2.3.1 {
  313. UPDATE t1 SET b = 'two.1' WHERE rowid=2
  314. } {
  315. UPDATE t1 SET b = 'two.2' WHERE rowid=2;
  316. } {
  317. OMIT
  318. } { SELECT rowid, * FROM t1 } {1 one 2 two.1 3 three}
  319. do_rebase_test 2.3.2 {
  320. UPDATE t1 SET b = 'two.1' WHERE rowid=2
  321. } {
  322. UPDATE t1 SET b = 'two.2' WHERE rowid=2;
  323. } {
  324. REPLACE
  325. } { SELECT rowid, * FROM t1 } {1 one 2 two.2 3 three}
  326. do_rebase_test 2.3.3 {
  327. DELETE FROM t1 WHERE rowid=3
  328. } {
  329. DELETE FROM t1 WHERE rowid=3;
  330. } {
  331. OMIT
  332. } { SELECT rowid, * FROM t1 } {1 one 2 two}
  333. do_rebase_test 2.3.4 {
  334. DELETE FROM t1 WHERE rowid=1
  335. } {
  336. UPDATE t1 SET b='one.2' WHERE rowid=1
  337. } {
  338. OMIT
  339. } { SELECT rowid, * FROM t1 } {2 two 3 three}
  340. do_rebase_test 2.3.6 {
  341. UPDATE t1 SET b='three.1' WHERE rowid=3
  342. } {
  343. DELETE FROM t1 WHERE rowid=3;
  344. } {
  345. OMIT
  346. } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three.1}
  347. do_rebase_test 2.3.7 {
  348. UPDATE t1 SET b='three.1' WHERE rowid=3
  349. } {
  350. DELETE FROM t1 WHERE rowid=3;
  351. } {
  352. REPLACE
  353. } { SELECT rowid, * FROM t1 } {1 one 2 two}
  354. do_rebase_test 2.3.8 {
  355. INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
  356. } {
  357. INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
  358. } {
  359. REPLACE
  360. } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.2}
  361. do_rebase_test 2.3.9 {
  362. INSERT INTO t1(rowid, b) VALUES(4, 'four.1')
  363. } {
  364. INSERT INTO t1(rowid, b) VALUES(4, 'four.2');
  365. } {
  366. OMIT
  367. } { SELECT rowid, * FROM t1 } {1 one 2 two 3 three 4 four.1}
  368. #-------------------------------------------------------------------------
  369. reset_db
  370. do_execsql_test 3.0 {
  371. CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c));
  372. CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z);
  373. INSERT INTO t3 VALUES(1, 2, 3);
  374. INSERT INTO t3 VALUES(4, 2, 5);
  375. INSERT INTO t3 VALUES(7, 2, 9);
  376. INSERT INTO abcdefghijkl VALUES('a', 'b', 'c');
  377. INSERT INTO abcdefghijkl VALUES('d', 'e', 'f');
  378. INSERT INTO abcdefghijkl VALUES('g', 'h', 'i');
  379. }
  380. breakpoint
  381. # do_rebase_test 3.6.tn {
  382. # UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
  383. # } {
  384. # UPDATE abcdefghijkl SET y=1 WHERE x='d';
  385. # UPDATE abcdefghijkl SET z=1 WHERE x='d';
  386. # } [list REPLACE REPLACE REPLACE]
  387. foreach {tn p} {
  388. 1 OMIT 2 REPLACE
  389. } {
  390. do_rebase_test 3.1.$tn {
  391. INSERT INTO t3 VALUES(1, 1, 1);
  392. UPDATE abcdefghijkl SET y=2;
  393. } {
  394. INSERT INTO t3 VALUES(4, 1, 1);
  395. DELETE FROM abcdefghijkl;
  396. } [list $p $p $p $p $p $p $p $p]
  397. do_rebase_test 3.2.$tn {
  398. INSERT INTO abcdefghijkl SELECT * FROM t3;
  399. UPDATE t3 SET b=b+1;
  400. } {
  401. INSERT INTO t3 VALUES(3, 3, 3);
  402. INSERT INTO abcdefghijkl SELECT * FROM t3;
  403. } [list $p $p $p $p $p $p $p $p]
  404. do_rebase_test 3.3.$tn {
  405. INSERT INTO abcdefghijkl VALUES(22, 23, 24);
  406. } {
  407. INSERT INTO abcdefghijkl VALUES(22, 25, 26);
  408. UPDATE abcdefghijkl SET y=400 WHERE x=22;
  409. } [list $p $p $p $p $p $p $p $p]
  410. do_rebase_test 3.4.$tn {
  411. INSERT INTO abcdefghijkl VALUES(22, 23, 24);
  412. } {
  413. INSERT INTO abcdefghijkl VALUES(22, 25, 26);
  414. UPDATE abcdefghijkl SET y=400 WHERE x=22;
  415. } [list REPLACE $p]
  416. do_rebase_test 3.5.$tn* {
  417. UPDATE abcdefghijkl SET y='X' WHERE x='d';
  418. } {
  419. DELETE FROM abcdefghijkl WHERE x='d';
  420. INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
  421. } [list $p $p $p]
  422. do_rebase_test 3.5.$tn {
  423. UPDATE abcdefghijkl SET y='X' WHERE x='d';
  424. } {
  425. DELETE FROM abcdefghijkl WHERE x='d';
  426. INSERT INTO abcdefghijkl VALUES('d', NULL, NULL);
  427. } [list REPLACE $p $p]
  428. do_rebase_test 3.6.$tn {
  429. UPDATE abcdefghijkl SET z='X', y='X' WHERE x='d';
  430. } {
  431. UPDATE abcdefghijkl SET y=1 WHERE x='d';
  432. UPDATE abcdefghijkl SET z=1 WHERE x='d';
  433. } [list REPLACE $p $p]
  434. }
  435. #-------------------------------------------------------------------------
  436. # Check that apply_v2() does not create a rebase buffer for a patchset.
  437. # And that it is not possible to rebase a patchset.
  438. #
  439. do_execsql_test 4.0 {
  440. CREATE TABLE t5(o PRIMARY KEY, p, q);
  441. INSERT INTO t5 VALUES(1, 2, 3);
  442. INSERT INTO t5 VALUES(4, 5, 6);
  443. }
  444. foreach {tn cmd rebasable} {
  445. 1 patchset 0
  446. 2 changeset 1
  447. } {
  448. proc xConflict {args} { return "OMIT" }
  449. do_test 4.1.$tn {
  450. execsql {
  451. BEGIN;
  452. DELETE FROM t5 WHERE o=4;
  453. }
  454. sqlite3session S db main
  455. S attach *
  456. execsql {
  457. INSERT INTO t5 VALUES(4, 'five', 'six');
  458. }
  459. set P [S $cmd]
  460. S delete
  461. execsql ROLLBACK;
  462. set ::rebase [sqlite3changeset_apply_v2 db $P xConflict]
  463. expr [llength $::rebase]>0
  464. } $rebasable
  465. }
  466. foreach {tn cmd rebasable} {
  467. 1 patchset 0
  468. 2 changeset 1
  469. } {
  470. do_test 4.2.$tn {
  471. sqlite3session S db main
  472. S attach *
  473. execsql {
  474. INSERT INTO t5 VALUES(5+$tn, 'five', 'six');
  475. }
  476. set P [S $cmd]
  477. S delete
  478. sqlite3rebaser_create R
  479. R configure $::rebase
  480. expr [catch {R rebase $P}]==0
  481. } $rebasable
  482. catch { R delete }
  483. }
  484. finish_test