1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
|
# 2015-11-07
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the WITH clause.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix with3
ifcapable {!cte} {
finish_test
return
}
# Test problems found by Kostya Serebryany using
# LibFuzzer. (http://llvm.org/docs/LibFuzzer.html)
#
do_catchsql_test 1.0 {
WITH i(x) AS (
WITH j AS (SELECT 10)
SELECT 5 FROM t0 UNION SELECT 8 FROM m
)
SELECT * FROM i;
} {1 {no such table: m}}
# 2019-11-09 dbfuzzcheck find
do_catchsql_test 1.1 {
CREATE VIEW v1(x,y) AS
WITH t1(a,b) AS (VALUES(1,2))
SELECT * FROM nosuchtable JOIN t1;
SELECT * FROM v1;
} {1 {no such table: main.nosuchtable}}
# Additional test cases that came out of the work to
# fix for Kostya's problem.
#
do_execsql_test 2.0 {
WITH
x1 AS (SELECT 10),
x2 AS (SELECT 11),
x3 AS (
SELECT * FROM x1 UNION ALL SELECT * FROM x2
),
x4 AS (
WITH
x1 AS (SELECT 12),
x2 AS (SELECT 13)
SELECT * FROM x3
)
SELECT * FROM x4;
} {10 11}
do_execsql_test 2.1 {
CREATE TABLE t1(x);
WITH
x1(a) AS (values(100))
INSERT INTO t1(x)
SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
SELECT * FROM t1;
} {200}
#-------------------------------------------------------------------------
# Test that the planner notices LIMIT clauses on recursive WITH queries.
#
ifcapable analyze {
do_execsql_test 3.1.1 {
CREATE TABLE y1(a, b);
CREATE INDEX y1a ON y1(a);
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000)
INSERT INTO y1 SELECT i%10, i FROM cnt;
ANALYZE;
}
do_eqp_test 3.1.2 {
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
SELECT * FROM cnt, y1 WHERE i=a
} [string map {"\n " \n} {
QUERY PLAN
|--CO-ROUTINE cnt
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
| `--SCAN cnt
|--SCAN cnt
`--SEARCH y1 USING INDEX y1a (a=?)
}]
do_eqp_test 3.1.3 {
WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1000000)
SELECT * FROM cnt, y1 WHERE i=a
} [string map {"\n " \n} {
QUERY PLAN
|--CO-ROUTINE cnt
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
| `--SCAN cnt
|--SCAN y1
|--BLOOM FILTER ON cnt (i=?)
`--SEARCH cnt USING AUTOMATIC COVERING INDEX (i=?)
}]
}
do_execsql_test 3.2.1 {
CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER);
CREATE TABLE w2(pk INTEGER PRIMARY KEY);
}
do_eqp_test 3.2.2 {
WITH RECURSIVE c(w,id) AS (SELECT 0, (SELECT pk FROM w2 LIMIT 1)
UNION ALL SELECT c.w + 1, x FROM w1, c LIMIT 1)
SELECT * FROM c, w2, w1
WHERE c.id=w2.pk AND c.id=w1.pk;
} {
QUERY PLAN
|--CO-ROUTINE c
| |--SETUP
| | |--SCAN CONSTANT ROW
| | `--SCALAR SUBQUERY xxxxxx
| | `--SCAN w2
| `--RECURSIVE STEP
| |--SCAN w1
| `--SCAN c
|--SCAN c
|--SEARCH w2 USING INTEGER PRIMARY KEY (rowid=?)
`--SEARCH w1 USING INTEGER PRIMARY KEY (rowid=?)
}
do_execsql_test 4.0 {
WITH t5(t5col1) AS (
SELECT (
WITH t3(t3col1) AS (
WITH t2 AS (
WITH t1 AS (SELECT 1 AS c1 GROUP BY 1)
SELECT a.c1 FROM t1 AS a, t1 AS b
WHERE anoncol1 = 1
)
SELECT (SELECT 1 FROM t2) FROM t2
)
SELECT t3col1 FROM t3 WHERE t3col1
) FROM (SELECT 1 AS anoncol1)
)
SELECT t5col1, t5col1 FROM t5
} {1 1}
do_execsql_test 4.1 {
SELECT EXISTS (
WITH RECURSIVE Table0 AS (
WITH RECURSIVE Table0(Col0) AS (SELECT ALL 1 )
SELECT ALL (
WITH RECURSIVE Table0 AS (
WITH RECURSIVE Table0 AS (
WITH RECURSIVE Table0 AS (SELECT DISTINCT 1 GROUP BY 1 )
SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0
WHERE Col0 = 1
)
SELECT ALL (SELECT DISTINCT * FROM Table0) FROM Table0 WHERE Col0 = 1
)
SELECT ALL * FROM Table0 NATURAL INNER JOIN Table0
) FROM Table0 )
SELECT DISTINCT * FROM Table0 NATURAL INNER JOIN Table0
);
} {1}
# 2020-01-18 chrome ticket 1043236
# Correct handling of the sequence:
# OP_OpenEphem
# OP_OpenDup
# Op_OpenEphem
# OP_OpenDup
#
do_execsql_test 4.2 {
SELECT (
WITH t1(a) AS (VALUES(1))
SELECT (
WITH t2(b) AS (
WITH t3(c) AS (
WITH t4(d) AS (VALUES('elvis'))
SELECT t4a.d FROM t4 AS t4a JOIN t4 AS t4b LEFT JOIN t4 AS t4c
)
SELECT c FROM t3 WHERE a = 1
)
SELECT t2a.b FROM t2 AS t2a JOIN t2 AS t2x
)
FROM t1 GROUP BY 1
)
GROUP BY 1;
} {elvis}
# 2021-02-13
# Avoid manifesting the same CTE multiple times.
#
do_eqp_test 5.1 {
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
ORDER BY 1;
} {
QUERY PLAN
|--MATERIALIZE c
| |--SETUP
| | `--SCAN CONSTANT ROW
| `--RECURSIVE STEP
| `--SCAN c
|--SCAN x1
|--SCAN x2
|--SCAN x3
|--SCAN x4
`--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 5.2 {
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
ORDER BY 1;
} {0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111}
#-------------------------------------------------------------------------
# At one point this would incorrectly report "circular reference: cte1"
#
do_catchsql_test 6.0 {
with
cte1(x, y) AS ( select 1, 2, 3 ),
cte2(z) as ( select 1 from cte1 )
select * from cte2, cte1;
} {1 {table cte1 has 3 values for 2 columns}}
do_catchsql_test 6.1 {
with
cte1(x, y) AS ( select 1, 2, 3 ),
cte2(z) as ( select 1 from cte1 UNION ALL SELECT z+1 FROM cte2 WHERE z<5)
select * from cte2, cte1;
} {1 {table cte1 has 3 values for 2 columns}}
finish_test
|