closure01.test 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. # 2013-04-25
  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. # Test cases for transitive_closure virtual table.
  13. set testdir [file dirname $argv0]
  14. source $testdir/tester.tcl
  15. set testprefix closure01
  16. ifcapable !vtab { finish_test ; return }
  17. load_static_extension db closure
  18. do_execsql_test 1.0 {
  19. BEGIN;
  20. CREATE TABLE t1(x INTEGER PRIMARY KEY, y INTEGER);
  21. CREATE INDEX t1y ON t1(y);
  22. INSERT INTO t1(x) VALUES(1),(2);
  23. INSERT INTO t1(x) SELECT x+2 FROM t1;
  24. INSERT INTO t1(x) SELECT x+4 FROM t1;
  25. INSERT INTO t1(x) SELECT x+8 FROM t1;
  26. INSERT INTO t1(x) SELECT x+16 FROM t1;
  27. INSERT INTO t1(x) SELECT x+32 FROM t1;
  28. INSERT INTO t1(x) SELECT x+64 FROM t1;
  29. INSERT INTO t1(x) SELECT x+128 FROM t1;
  30. INSERT INTO t1(x) SELECT x+256 FROM t1;
  31. INSERT INTO t1(x) SELECT x+512 FROM t1;
  32. INSERT INTO t1(x) SELECT x+1024 FROM t1;
  33. INSERT INTO t1(x) SELECT x+2048 FROM t1;
  34. INSERT INTO t1(x) SELECT x+4096 FROM t1;
  35. INSERT INTO t1(x) SELECT x+8192 FROM t1;
  36. INSERT INTO t1(x) SELECT x+16384 FROM t1;
  37. INSERT INTO t1(x) SELECT x+32768 FROM t1;
  38. INSERT INTO t1(x) SELECT x+65536 FROM t1;
  39. UPDATE t1 SET y=x/2 WHERE x>1;
  40. COMMIT;
  41. CREATE VIRTUAL TABLE cx
  42. USING transitive_closure(tablename=t1, idcolumn=x, parentcolumn=y);
  43. } {}
  44. # The entire table
  45. do_execsql_test 1.1 {
  46. SELECT count(*), depth FROM cx WHERE root=1 GROUP BY depth ORDER BY 1;
  47. } {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
  48. # descendents of 32768
  49. do_execsql_test 1.2 {
  50. SELECT * FROM cx WHERE root=32768 ORDER BY id;
  51. } {32768 0 65536 1 65537 1 131072 2}
  52. # descendents of 16384
  53. do_execsql_test 1.3 {
  54. SELECT * FROM cx WHERE root=16384 AND depth<=2 ORDER BY id;
  55. } {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
  56. # children of 16384
  57. do_execsql_test 1.4 {
  58. SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
  59. WHERE root=16384
  60. AND depth=1
  61. ORDER BY id;
  62. } {32768 1 {} t1 x y 32769 1 {} t1 x y}
  63. # great-grandparent of 16384
  64. do_execsql_test 1.5 {
  65. SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
  66. WHERE root=16384
  67. AND depth=3
  68. AND idcolumn='Y'
  69. AND parentcolumn='X';
  70. } {2048 3 {} t1 Y X}
  71. # depth<5
  72. do_execsql_test 1.6 {
  73. SELECT count(*), depth FROM cx WHERE root=1 AND depth<5
  74. GROUP BY depth ORDER BY 1;
  75. } {1 0 2 1 4 2 8 3 16 4}
  76. # depth<=5
  77. do_execsql_test 1.7 {
  78. SELECT count(*), depth FROM cx WHERE root=1 AND depth<=5
  79. GROUP BY depth ORDER BY 1;
  80. } {1 0 2 1 4 2 8 3 16 4 32 5}
  81. # depth==5
  82. do_execsql_test 1.8 {
  83. SELECT count(*), depth FROM cx WHERE root=1 AND depth=5
  84. GROUP BY depth ORDER BY 1;
  85. } {32 5}
  86. # depth BETWEEN 3 AND 5
  87. do_execsql_test 1.9 {
  88. SELECT count(*), depth FROM cx WHERE root=1 AND depth BETWEEN 3 AND 5
  89. GROUP BY depth ORDER BY 1;
  90. } {8 3 16 4 32 5}
  91. # depth==5 with min() and max()
  92. do_execsql_test 1.10 {
  93. SELECT count(*), min(id), max(id) FROM cx WHERE root=1 AND depth=5;
  94. } {32 32 63}
  95. # Create a much smaller table t2 with only 32 elements
  96. db eval {
  97. CREATE TABLE t2(x INTEGER PRIMARY KEY, y INTEGER);
  98. INSERT INTO t2 SELECT x, y FROM t1 WHERE x<32;
  99. CREATE INDEX t2y ON t2(y);
  100. CREATE VIRTUAL TABLE c2
  101. USING transitive_closure(tablename=t2, idcolumn=x, parentcolumn=y);
  102. }
  103. # t2 full-table
  104. do_execsql_test 2.1 {
  105. SELECT count(*), min(id), max(id) FROM c2 WHERE root=1;
  106. } {31 1 31}
  107. # t2 root=10
  108. do_execsql_test 2.2 {
  109. SELECT id FROM c2 WHERE root=10;
  110. } {10 20 21}
  111. # t2 root=11
  112. do_execsql_test 2.3 {
  113. SELECT id FROM c2 WHERE root=12;
  114. } {12 24 25}
  115. # t2 root IN [10,12]
  116. do_execsql_test 2.4 {
  117. SELECT id FROM c2 WHERE root IN (10,12) ORDER BY id;
  118. } {10 12 20 21 24 25}
  119. # t2 root IN [10,12] (sorted)
  120. do_execsql_test 2.5 {
  121. SELECT id FROM c2 WHERE root IN (10,12) ORDER BY +id;
  122. } {10 12 20 21 24 25}
  123. # t2 c2up from 20
  124. do_execsql_test 3.0 {
  125. CREATE VIRTUAL TABLE c2up USING transitive_closure(
  126. tablename = t2,
  127. idcolumn = y,
  128. parentcolumn = x
  129. );
  130. SELECT id FROM c2up WHERE root=20;
  131. } {1 2 5 10 20}
  132. # cx as c2up
  133. do_execsql_test 3.1 {
  134. SELECT id FROM cx
  135. WHERE root=20
  136. AND tablename='t2'
  137. AND idcolumn='y'
  138. AND parentcolumn='x';
  139. } {1 2 5 10 20}
  140. # t2 first cousins of 20
  141. do_execsql_test 3.2 {
  142. SELECT DISTINCT id FROM c2
  143. WHERE root IN (SELECT id FROM c2up
  144. WHERE root=20 AND depth<=2)
  145. ORDER BY id;
  146. } {5 10 11 20 21 22 23}
  147. # t2 first cousins of 20
  148. do_execsql_test 3.3 {
  149. SELECT id FROM c2
  150. WHERE root=(SELECT id FROM c2up
  151. WHERE root=20 AND depth=2)
  152. AND depth=2
  153. EXCEPT
  154. SELECT id FROM c2
  155. WHERE root=(SELECT id FROM c2up
  156. WHERE root=20 AND depth=1)
  157. AND depth<=1
  158. ORDER BY id;
  159. } {22 23}
  160. # missing tablename.
  161. do_test 4.1 {
  162. catchsql {
  163. SELECT id FROM cx
  164. WHERE root=20
  165. AND tablename='t3'
  166. AND idcolumn='y'
  167. AND parentcolumn='x';
  168. }
  169. } {1 {no such table: t3}}
  170. # missing idcolumn
  171. do_test 4.2 {
  172. catchsql {
  173. SELECT id FROM cx
  174. WHERE root=20
  175. AND tablename='t2'
  176. AND idcolumn='xyz'
  177. AND parentcolumn='x';
  178. }
  179. } {1 {no such column: t2.xyz}}
  180. # missing parentcolumn
  181. do_test 4.3 {
  182. catchsql {
  183. SELECT id FROM cx
  184. WHERE root=20
  185. AND tablename='t2'
  186. AND idcolumn='x'
  187. AND parentcolumn='pqr';
  188. }
  189. } {1 {no such column: t2.pqr}}
  190. # generic closure
  191. do_execsql_test 5.1 {
  192. CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
  193. SELECT id FROM closure
  194. WHERE root=1
  195. AND depth=3
  196. AND tablename='t1'
  197. AND idcolumn='x'
  198. AND parentcolumn='y'
  199. ORDER BY id;
  200. } {8 9 10 11 12 13 14 15}
  201. finish_test