xref: /sqlite-3.40.0/test/closure01.test (revision 7aa3ebee)
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
14set testdir [file dirname $argv0]
15source $testdir/tester.tcl
16set testprefix closure01
17
18ifcapable !vtab||!cte { finish_test ; return }
19
20load_static_extension db closure
21
22do_execsql_test 1.0 {
23  BEGIN;
24  CREATE TABLE t1(x INTEGER PRIMARY KEY, y INTEGER);
25  WITH RECURSIVE
26    cnt(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM cnt LIMIT 131072)
27  INSERT INTO t1(x, y) SELECT i, nullif(i,1)/2 FROM cnt;
28  CREATE INDEX t1y ON t1(y);
29  COMMIT;
30  CREATE VIRTUAL TABLE cx
31   USING transitive_closure(tablename=t1, idcolumn=x, parentcolumn=y);
32} {}
33
34# The entire table
35do_timed_execsql_test 1.1 {
36  SELECT count(*), depth FROM cx WHERE root=1 GROUP BY depth ORDER BY 1;
37} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
38do_timed_execsql_test 1.1-cte {
39  WITH RECURSIVE
40    below(id,depth) AS (
41      VALUES(1,0)
42       UNION ALL
43      SELECT t1.x, below.depth+1
44        FROM t1 JOIN below on t1.y=below.id
45    )
46  SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
47} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
48
49# descendents of 32768
50do_timed_execsql_test 1.2 {
51  SELECT * FROM cx WHERE root=32768 ORDER BY id;
52} {32768 0 65536 1 65537 1 131072 2}
53do_timed_execsql_test 1.2-cte {
54  WITH RECURSIVE
55    below(id,depth) AS (
56      VALUES(32768,0)
57       UNION ALL
58      SELECT t1.x, below.depth+1
59        FROM t1 JOIN below on t1.y=below.id
60       WHERE below.depth<2
61    )
62  SELECT id, depth FROM below ORDER BY id;
63} {32768 0 65536 1 65537 1 131072 2}
64
65# descendents of 16384
66do_timed_execsql_test 1.3 {
67  SELECT * FROM cx WHERE root=16384 AND depth<=2 ORDER BY id;
68} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
69do_timed_execsql_test 1.3-cte {
70  WITH RECURSIVE
71    below(id,depth) AS (
72      VALUES(16384,0)
73       UNION ALL
74      SELECT t1.x, below.depth+1
75        FROM t1 JOIN below on t1.y=below.id
76       WHERE below.depth<2
77    )
78  SELECT id, depth FROM below ORDER BY id;
79} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
80
81# children of 16384
82do_execsql_test 1.4 {
83  SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
84   WHERE root=16384
85     AND depth=1
86   ORDER BY id;
87} {32768 1 {} t1 x y 32769 1 {} t1 x y}
88
89# great-grandparent of 16384
90do_timed_execsql_test 1.5 {
91  SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
92   WHERE root=16384
93     AND depth=3
94     AND idcolumn='Y'
95     AND parentcolumn='X';
96} {2048 3 {} t1 Y X}
97do_timed_execsql_test 1.5-cte {
98  WITH RECURSIVE
99    above(id,depth) AS (
100      VALUES(16384,0)
101      UNION ALL
102      SELECT t1.y, above.depth+1
103        FROM t1 JOIN above ON t1.x=above.id
104       WHERE above.depth<3
105    )
106  SELECT id FROM above WHERE depth=3;
107} {2048}
108
109# depth<5
110do_timed_execsql_test 1.6 {
111  SELECT count(*), depth FROM cx WHERE root=1 AND depth<5
112   GROUP BY depth ORDER BY 1;
113} {1 0 2 1 4 2 8 3 16 4}
114do_timed_execsql_test 1.6-cte {
115  WITH RECURSIVE
116    below(id,depth) AS (
117      VALUES(1,0)
118      UNION ALL
119      SELECT t1.x, below.depth+1
120        FROM t1 JOIN below ON t1.y=below.id
121       WHERE below.depth<4
122    )
123  SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
124} {1 0 2 1 4 2 8 3 16 4}
125
126# depth<=5
127do_execsql_test 1.7 {
128  SELECT count(*), depth FROM cx WHERE root=1 AND depth<=5
129   GROUP BY depth ORDER BY 1;
130} {1 0 2 1 4 2 8 3 16 4 32 5}
131
132# depth==5
133do_execsql_test 1.8 {
134  SELECT count(*), depth FROM cx WHERE root=1 AND depth=5
135   GROUP BY depth ORDER BY 1;
136} {32 5}
137
138# depth BETWEEN 3 AND 5
139do_execsql_test 1.9 {
140  SELECT count(*), depth FROM cx WHERE root=1 AND depth BETWEEN 3 AND 5
141   GROUP BY depth ORDER BY 1;
142} {8 3 16 4 32 5}
143
144# depth==5 with min() and max()
145do_timed_execsql_test 1.10 {
146  SELECT count(*), min(id), max(id) FROM cx WHERE root=1 AND depth=5;
147} {32 32 63}
148do_timed_execsql_test 1.10-cte {
149  WITH RECURSIVE
150    below(id,depth) AS (
151      VALUES(1,0)
152      UNION ALL
153      SELECT t1.x, below.depth+1
154        FROM t1 JOIN below ON t1.y=below.id
155       WHERE below.depth<5
156    )
157  SELECT count(*), min(id), max(id) FROM below WHERE depth=5;
158} {32 32 63}
159
160# Create a much smaller table t2 with only 32 elements
161db eval {
162  CREATE TABLE t2(x INTEGER PRIMARY KEY, y INTEGER);
163  INSERT INTO t2 SELECT x, y FROM t1 WHERE x<32;
164  CREATE INDEX t2y ON t2(y);
165  CREATE VIRTUAL TABLE c2
166   USING transitive_closure(tablename=t2, idcolumn=x, parentcolumn=y);
167}
168
169# t2 full-table
170do_execsql_test 2.1 {
171  SELECT count(*), min(id), max(id) FROM c2 WHERE root=1;
172} {31 1 31}
173# t2 root=10
174do_execsql_test 2.2 {
175  SELECT id FROM c2 WHERE root=10;
176} {10 20 21}
177# t2 root=11
178do_execsql_test 2.3 {
179  SELECT id FROM c2 WHERE root=12;
180} {12 24 25}
181# t2 root IN [10,12]
182do_execsql_test 2.4 {
183  SELECT id FROM c2 WHERE root IN (10,12) ORDER BY id;
184} {10 12 20 21 24 25}
185# t2 root IN [10,12] (sorted)
186do_execsql_test 2.5 {
187  SELECT id FROM c2 WHERE root IN (10,12) ORDER BY +id;
188} {10 12 20 21 24 25}
189
190# t2 c2up from 20
191do_execsql_test 3.0 {
192  CREATE VIRTUAL TABLE c2up USING transitive_closure(
193    tablename = t2,
194    idcolumn = y,
195    parentcolumn = x
196  );
197  SELECT id FROM c2up WHERE root=20;
198} {1 2 5 10 20}
199
200# cx as c2up
201do_execsql_test 3.1 {
202  SELECT id FROM cx
203   WHERE root=20
204     AND tablename='t2'
205     AND idcolumn='y'
206     AND parentcolumn='x';
207} {1 2 5 10 20}
208
209# t2 first cousins of 20
210do_execsql_test 3.2 {
211  SELECT DISTINCT id FROM c2
212   WHERE root IN (SELECT id FROM c2up
213                   WHERE root=20 AND depth<=2)
214   ORDER BY id;
215} {5 10 11 20 21 22 23}
216
217# t2 first cousins of 20
218do_execsql_test 3.3 {
219  SELECT id FROM c2
220   WHERE root=(SELECT id FROM c2up
221               WHERE root=20 AND depth=2)
222     AND depth=2
223  EXCEPT
224  SELECT id FROM c2
225   WHERE root=(SELECT id FROM c2up
226               WHERE root=20 AND depth=1)
227     AND depth<=1
228   ORDER BY id;
229} {22 23}
230
231# missing tablename.
232do_test 4.1 {
233  catchsql {
234    SELECT id FROM cx
235     WHERE root=20
236       AND tablename='t3'
237       AND idcolumn='y'
238       AND parentcolumn='x';
239  }
240} {1 {no such table: t3}}
241
242# missing idcolumn
243do_test 4.2 {
244  catchsql {
245    SELECT id FROM cx
246     WHERE root=20
247       AND tablename='t2'
248       AND idcolumn='xyz'
249       AND parentcolumn='x';
250  }
251} {1 {no such column: t2.xyz}}
252
253# missing parentcolumn
254do_test 4.3 {
255  catchsql {
256    SELECT id FROM cx
257     WHERE root=20
258       AND tablename='t2'
259       AND idcolumn='x'
260       AND parentcolumn='pqr';
261  }
262} {1 {no such column: t2.pqr}}
263
264# generic closure
265do_execsql_test 5.1 {
266  CREATE VIRTUAL TABLE temp.closure USING transitive_closure;
267  SELECT id FROM closure
268   WHERE root=1
269     AND depth=3
270     AND tablename='t1'
271     AND idcolumn='x'
272     AND parentcolumn='y'
273  ORDER BY id;
274} {8 9 10 11 12 13 14 15}
275
276finish_test
277