| 1 | #include "catch.hpp" |
| 2 | #include "duckdb/common/file_system.hpp" |
| 3 | #include "dbgen.hpp" |
| 4 | #include "test_helpers.hpp" |
| 5 | |
| 6 | using namespace duckdb; |
| 7 | using namespace std; |
| 8 | |
| 9 | TEST_CASE("Test uncorrelated subqueries" , "[subquery]" ) { |
| 10 | unique_ptr<QueryResult> result; |
| 11 | DuckDB db(nullptr); |
| 12 | Connection con(db); |
| 13 | |
| 14 | con.EnableProfiling(); |
| 15 | con.EnableQueryVerification(); |
| 16 | |
| 17 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i INTEGER)" )); |
| 18 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (1), (2), (3), (NULL)" )); |
| 19 | |
| 20 | // scalar subqueries |
| 21 | result = con.Query("SELECT * FROM integers WHERE i=(SELECT 1)" ); |
| 22 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 23 | result = con.Query("SELECT * FROM integers WHERE i=(SELECT SUM(1))" ); |
| 24 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 25 | result = con.Query("SELECT * FROM integers WHERE i=(SELECT MIN(i) FROM integers)" ); |
| 26 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 27 | result = con.Query("SELECT * FROM integers WHERE i=(SELECT MAX(i) FROM integers)" ); |
| 28 | REQUIRE(CHECK_COLUMN(result, 0, {3})); |
| 29 | result = con.Query("SELECT *, (SELECT MAX(i) FROM integers) FROM integers ORDER BY i" ); |
| 30 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 31 | REQUIRE(CHECK_COLUMN(result, 1, {3, 3, 3, 3})); |
| 32 | // group by on subquery |
| 33 | result = con.Query("SELECT (SELECT 42) AS k, MAX(i) FROM integers GROUP BY k" ); |
| 34 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
| 35 | REQUIRE(CHECK_COLUMN(result, 1, {3})); |
| 36 | // subquery as parameter to aggregate |
| 37 | result = con.Query("SELECT i, MAX((SELECT 42)) FROM integers GROUP BY i ORDER BY i" ); |
| 38 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 39 | REQUIRE(CHECK_COLUMN(result, 1, {42, 42, 42, 42})); |
| 40 | |
| 41 | // scalar subquery returning zero results should result in NULL |
| 42 | result = con.Query("SELECT (SELECT * FROM integers WHERE i>10) FROM integers" ); |
| 43 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), Value(), Value(), Value()})); |
| 44 | |
| 45 | // return more than one row in a scalar subquery |
| 46 | // controversial: in postgres this gives an error |
| 47 | // but SQLite accepts it and just uses the first value |
| 48 | // we choose to agree with SQLite here |
| 49 | result = con.Query("SELECT * FROM integers WHERE i=(SELECT i FROM integers WHERE i IS NOT NULL ORDER BY i)" ); |
| 50 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 51 | // i.e. the above query is equivalent to this query |
| 52 | result = |
| 53 | con.Query("SELECT * FROM integers WHERE i=(SELECT i FROM integers WHERE i IS NOT NULL ORDER BY i LIMIT 1)" ); |
| 54 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 55 | |
| 56 | // returning multiple columns should fail though |
| 57 | REQUIRE_FAIL(con.Query("SELECT * FROM integers WHERE i=(SELECT 1, 2)" )); |
| 58 | REQUIRE_FAIL(con.Query("SELECT * FROM integers WHERE i=(SELECT i, i + 2 FROM integers)" )); |
| 59 | // but not for EXISTS queries! |
| 60 | REQUIRE_NO_FAIL(con.Query("SELECT * FROM integers WHERE EXISTS (SELECT 1, 2)" )); |
| 61 | REQUIRE_NO_FAIL(con.Query("SELECT * FROM integers WHERE EXISTS (SELECT i, i + 2 FROM integers)" )); |
| 62 | // SELECT * should be fine if the star only expands to a single column |
| 63 | result = con.Query("SELECT (SELECT * FROM integers WHERE i=1)" ); |
| 64 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 65 | // but not if the star expands to more than one column! |
| 66 | REQUIRE_FAIL(con.Query("SELECT (SELECT * FROM integers i1, integers i2)" )); |
| 67 | |
| 68 | // uncorrelated subquery in SELECT |
| 69 | result = con.Query("SELECT (SELECT i FROM integers WHERE i=1)" ); |
| 70 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 71 | result = con.Query("SELECT * FROM integers WHERE i > (SELECT i FROM integers WHERE i=1)" ); |
| 72 | REQUIRE(CHECK_COLUMN(result, 0, {2, 3})); |
| 73 | } |
| 74 | |
| 75 | TEST_CASE("Test uncorrelated exists subqueries" , "[subquery]" ) { |
| 76 | unique_ptr<QueryResult> result; |
| 77 | DuckDB db(nullptr); |
| 78 | Connection con(db); |
| 79 | |
| 80 | con.EnableProfiling(); |
| 81 | con.EnableQueryVerification(); |
| 82 | |
| 83 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i INTEGER)" )); |
| 84 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (1), (2), (3), (NULL)" )); |
| 85 | |
| 86 | // uncorrelated EXISTS |
| 87 | result = con.Query("SELECT * FROM integers WHERE EXISTS(SELECT 1) ORDER BY i" ); |
| 88 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 89 | result = con.Query("SELECT * FROM integers WHERE EXISTS(SELECT * FROM integers) ORDER BY i" ); |
| 90 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 91 | result = con.Query("SELECT * FROM integers WHERE NOT EXISTS(SELECT * FROM integers) ORDER BY i" ); |
| 92 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 93 | result = con.Query("SELECT * FROM integers WHERE EXISTS(SELECT NULL) ORDER BY i" ); |
| 94 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 95 | |
| 96 | // exists in SELECT clause |
| 97 | result = con.Query("SELECT EXISTS(SELECT * FROM integers)" ); |
| 98 | REQUIRE(CHECK_COLUMN(result, 0, {true})); |
| 99 | result = con.Query("SELECT EXISTS(SELECT * FROM integers WHERE i>10)" ); |
| 100 | REQUIRE(CHECK_COLUMN(result, 0, {false})); |
| 101 | |
| 102 | // multiple exists |
| 103 | result = con.Query("SELECT EXISTS(SELECT * FROM integers), EXISTS(SELECT * FROM integers)" ); |
| 104 | REQUIRE(CHECK_COLUMN(result, 0, {true})); |
| 105 | REQUIRE(CHECK_COLUMN(result, 1, {true})); |
| 106 | |
| 107 | // exists used in operations |
| 108 | result = con.Query("SELECT EXISTS(SELECT * FROM integers) AND EXISTS(SELECT * FROM integers)" ); |
| 109 | REQUIRE(CHECK_COLUMN(result, 0, {true})); |
| 110 | |
| 111 | // nested EXISTS |
| 112 | result = con.Query("SELECT EXISTS(SELECT EXISTS(SELECT * FROM integers))" ); |
| 113 | REQUIRE(CHECK_COLUMN(result, 0, {true})); |
| 114 | |
| 115 | // uncorrelated IN |
| 116 | result = con.Query("SELECT * FROM integers WHERE 1 IN (SELECT 1) ORDER BY i" ); |
| 117 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 118 | result = con.Query("SELECT * FROM integers WHERE 1 IN (SELECT * FROM integers) ORDER BY i" ); |
| 119 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 120 | result = con.Query("SELECT * FROM integers WHERE 1 IN (SELECT NULL::INTEGER) ORDER BY i" ); |
| 121 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 122 | |
| 123 | // scalar NULL results |
| 124 | result = con.Query("SELECT 1 IN (SELECT NULL::INTEGER) FROM integers" ); |
| 125 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), Value(), Value(), Value()})); |
| 126 | result = con.Query("SELECT NULL IN (SELECT * FROM integers) FROM integers" ); |
| 127 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), Value(), Value(), Value()})); |
| 128 | |
| 129 | // add aggregations after the subquery |
| 130 | result = con.Query("SELECT SUM(i) FROM integers WHERE 1 IN (SELECT * FROM integers)" ); |
| 131 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 132 | } |
| 133 | |
| 134 | TEST_CASE("Test uncorrelated ANY subqueries" , "[subquery]" ) { |
| 135 | unique_ptr<QueryResult> result; |
| 136 | DuckDB db(nullptr); |
| 137 | Connection con(db); |
| 138 | |
| 139 | con.EnableProfiling(); |
| 140 | con.EnableQueryVerification(); |
| 141 | |
| 142 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i INTEGER)" )); |
| 143 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (1), (2), (3), (NULL)" )); |
| 144 | |
| 145 | // uncorrelated ANY |
| 146 | result = con.Query("SELECT i FROM integers WHERE i <= ANY(SELECT i FROM integers)" ); |
| 147 | REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3})); |
| 148 | result = con.Query("SELECT i FROM integers WHERE i > ANY(SELECT i FROM integers)" ); |
| 149 | REQUIRE(CHECK_COLUMN(result, 0, {2, 3})); |
| 150 | result = con.Query("SELECT i, i > ANY(SELECT i FROM integers) FROM integers ORDER BY i" ); |
| 151 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 152 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), Value(), true, true})); |
| 153 | result = con.Query("SELECT i, i > ANY(SELECT i FROM integers WHERE i IS NOT NULL) FROM integers ORDER BY i" ); |
| 154 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 155 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), false, true, true})); |
| 156 | result = con.Query("SELECT i, NULL > ANY(SELECT i FROM integers) FROM integers ORDER BY i" ); |
| 157 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 158 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), Value(), Value(), Value()})); |
| 159 | result = con.Query("SELECT i, NULL > ANY(SELECT i FROM integers WHERE i IS NOT NULL) FROM integers ORDER BY i" ); |
| 160 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 161 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), Value(), Value(), Value()})); |
| 162 | result = con.Query("SELECT i FROM integers WHERE i = ANY(SELECT i FROM integers)" ); |
| 163 | REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3})); |
| 164 | result = con.Query("SELECT i, i = ANY(SELECT i FROM integers WHERE i>2) FROM integers ORDER BY i" ); |
| 165 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 166 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), false, false, true})); |
| 167 | result = con.Query("SELECT i, i = ANY(SELECT i FROM integers WHERE i>2 OR i IS NULL) FROM integers ORDER BY i" ); |
| 168 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 169 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), Value(), Value(), true})); |
| 170 | result = con.Query("SELECT i, i <> ANY(SELECT i FROM integers WHERE i>2) FROM integers ORDER BY i" ); |
| 171 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 172 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), true, true, false})); |
| 173 | result = con.Query("SELECT i, i <> ANY(SELECT i FROM integers WHERE i>2 OR i IS NULL) FROM integers ORDER BY i" ); |
| 174 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 175 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), true, true, Value()})); |
| 176 | // use a bunch of cross products to make bigger data sets (> STANDARD_VECTOR_SIZE) |
| 177 | result = con.Query("SELECT i, i = ANY(SELECT i1.i FROM integers i1, integers i2, integers i3, integers i4, " |
| 178 | "integers i5, integers i6 WHERE i1.i IS NOT NULL) FROM integers ORDER BY i" ); |
| 179 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 180 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), true, true, true})); |
| 181 | result = con.Query("SELECT i, i = ANY(SELECT i1.i FROM integers i1, integers i2, integers i3, integers i4, " |
| 182 | "integers i5, integers i6 WHERE i1.i IS NOT NULL AND i1.i <> 2) FROM integers ORDER BY i" ); |
| 183 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 184 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), true, false, true})); |
| 185 | result = con.Query("SELECT i, i >= ANY(SELECT i1.i FROM integers i1, integers i2, integers i3, integers i4, " |
| 186 | "integers i5, integers i6 WHERE i1.i IS NOT NULL) FROM integers ORDER BY i" ); |
| 187 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 188 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), true, true, true})); |
| 189 | result = |
| 190 | con.Query("SELECT i, i >= ANY(SELECT i1.i FROM integers i1, integers i2, integers i3, integers i4, integers " |
| 191 | "i5, integers i6 WHERE i1.i IS NOT NULL AND i1.i <> 1 LIMIT 1) FROM integers ORDER BY i" ); |
| 192 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 193 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), false, true, true})); |
| 194 | } |
| 195 | |
| 196 | TEST_CASE("Test uncorrelated ALL subqueries" , "[subquery]" ) { |
| 197 | unique_ptr<QueryResult> result; |
| 198 | DuckDB db(nullptr); |
| 199 | Connection con(db); |
| 200 | |
| 201 | con.EnableProfiling(); |
| 202 | con.EnableQueryVerification(); |
| 203 | |
| 204 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i INTEGER)" )); |
| 205 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (1), (2), (3), (NULL)" )); |
| 206 | |
| 207 | // uncorrelated ALL |
| 208 | result = con.Query("SELECT i FROM integers WHERE i >= ALL(SELECT i FROM integers)" ); |
| 209 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 210 | result = con.Query("SELECT i, i >= ALL(SELECT i FROM integers) FROM integers ORDER BY i" ); |
| 211 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 212 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), false, false, Value()})); |
| 213 | result = con.Query("SELECT i FROM integers WHERE i >= ALL(SELECT i FROM integers WHERE i IS NOT NULL)" ); |
| 214 | REQUIRE(CHECK_COLUMN(result, 0, {3})); |
| 215 | result = con.Query("SELECT i, i >= ALL(SELECT i FROM integers WHERE i IS NOT NULL) FROM integers ORDER BY i" ); |
| 216 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 217 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), false, false, true})); |
| 218 | |
| 219 | result = con.Query("SELECT i FROM integers WHERE i >= ALL(SELECT i FROM integers WHERE i IS NOT NULL)" ); |
| 220 | REQUIRE(CHECK_COLUMN(result, 0, {3})); |
| 221 | result = con.Query("SELECT i FROM integers WHERE i > ALL(SELECT MIN(i) FROM integers)" ); |
| 222 | REQUIRE(CHECK_COLUMN(result, 0, {2, 3})); |
| 223 | result = con.Query("SELECT i FROM integers WHERE i < ALL(SELECT MAX(i) FROM integers)" ); |
| 224 | REQUIRE(CHECK_COLUMN(result, 0, {1, 2})); |
| 225 | result = con.Query("SELECT i FROM integers WHERE i <= ALL(SELECT i FROM integers)" ); |
| 226 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 227 | result = con.Query("SELECT i FROM integers WHERE i <= ALL(SELECT i FROM integers WHERE i IS NOT NULL)" ); |
| 228 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 229 | result = con.Query("SELECT i FROM integers WHERE i = ALL(SELECT i FROM integers WHERE i=1)" ); |
| 230 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 231 | result = con.Query("SELECT i FROM integers WHERE i <> ALL(SELECT i FROM integers WHERE i=1)" ); |
| 232 | REQUIRE(CHECK_COLUMN(result, 0, {2, 3})); |
| 233 | result = con.Query("SELECT i FROM integers WHERE i = ALL(SELECT i FROM integers WHERE i IS NOT NULL)" ); |
| 234 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 235 | result = con.Query("SELECT i FROM integers WHERE i <> ALL(SELECT i FROM integers WHERE i IS NOT NULL)" ); |
| 236 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 237 | // zero results always results in TRUE for ALL, even if "i" is NULL |
| 238 | result = con.Query("SELECT i FROM integers WHERE i <> ALL(SELECT i FROM integers WHERE i>10) ORDER BY i;" ); |
| 239 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 240 | result = con.Query("SELECT i, i <> ALL(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 241 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 242 | REQUIRE(CHECK_COLUMN(result, 1, {true, true, true, true})); |
| 243 | // zero results always results in FALSE for ANY |
| 244 | result = con.Query("SELECT i, i > ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 245 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 246 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 247 | result = con.Query("SELECT i, i = ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 248 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 249 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 250 | result = con.Query("SELECT i, i >= ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 251 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 252 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 253 | result = con.Query("SELECT i, i <= ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 254 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 255 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 256 | result = con.Query("SELECT i, i < ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 257 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 258 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 259 | result = con.Query("SELECT i, i <> ANY(SELECT i FROM integers WHERE i>10) FROM integers ORDER BY i;" ); |
| 260 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 261 | REQUIRE(CHECK_COLUMN(result, 1, {false, false, false, false})); |
| 262 | |
| 263 | // nested uncorrelated subqueries |
| 264 | result = con.Query("SELECT (SELECT (SELECT (SELECT 42)))" ); |
| 265 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
| 266 | result = con.Query("SELECT (SELECT EXISTS(SELECT * FROM integers WHERE i>2)) FROM integers;" ); |
| 267 | REQUIRE(CHECK_COLUMN(result, 0, {true, true, true, true})); |
| 268 | |
| 269 | result = con.Query("SELECT (SELECT MAX(i) FROM integers) AS k, SUM(i) FROM integers GROUP BY k;" ); |
| 270 | REQUIRE(CHECK_COLUMN(result, 0, {3})); |
| 271 | REQUIRE(CHECK_COLUMN(result, 1, {6})); |
| 272 | |
| 273 | // subqueries in GROUP BY clause |
| 274 | result = con.Query("SELECT i >= ALL(SELECT i FROM integers WHERE i IS NOT NULL) AS k, SUM(i) FROM integers GROUP " |
| 275 | "BY k ORDER BY k;" ); |
| 276 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), false, true})); |
| 277 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 3, 3})); |
| 278 | |
| 279 | result = con.Query( |
| 280 | "SELECT SUM(i) FROM integers GROUP BY (i >= ALL(SELECT i FROM integers WHERE i IS NOT NULL)) ORDER BY 1;" ); |
| 281 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 3, 3})); |
| 282 | |
| 283 | result = con.Query("SELECT i >= ALL(SELECT MIN(i) FROM integers WHERE i IS NOT NULL) AS k, SUM(i) FROM integers " |
| 284 | "GROUP BY k ORDER BY k;" ); |
| 285 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), true})); |
| 286 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 6})); |
| 287 | |
| 288 | // subquery in CASE statement |
| 289 | result = con.Query("SELECT i, SUM(CASE WHEN (i >= ALL(SELECT i FROM integers WHERE i=2)) THEN 1 ELSE 0 END) FROM " |
| 290 | "integers GROUP BY i ORDER BY i;" ); |
| 291 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
| 292 | REQUIRE(CHECK_COLUMN(result, 1, {0, 0, 1, 1})); |
| 293 | |
| 294 | // subquery in HAVING |
| 295 | result = |
| 296 | con.Query("SELECT i % 2 AS k, SUM(i) FROM integers GROUP BY k HAVING SUM(i) > (SELECT MAX(i) FROM integers)" ); |
| 297 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 298 | REQUIRE(CHECK_COLUMN(result, 1, {4})); |
| 299 | |
| 300 | result = con.Query("SELECT i FROM integers WHERE NOT(i IN (SELECT i FROM integers WHERE i>1));" ); |
| 301 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 302 | |
| 303 | // multiple subqueries in select without FROM |
| 304 | result = con.Query("SELECT (SELECT SUM(i) FROM integers), (SELECT 42)" ); |
| 305 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 306 | REQUIRE(CHECK_COLUMN(result, 1, {42})); |
| 307 | } |
| 308 | |
| 309 | TEST_CASE("Test uncorrelated VARCHAR subqueries" , "[subquery]" ) { |
| 310 | unique_ptr<QueryResult> result; |
| 311 | DuckDB db(nullptr); |
| 312 | Connection con(db); |
| 313 | |
| 314 | con.EnableProfiling(); |
| 315 | con.EnableQueryVerification(); |
| 316 | |
| 317 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE integers(i INTEGER)" )); |
| 318 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (1), (2), (3), (NULL)" )); |
| 319 | |
| 320 | // varchar tests |
| 321 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE strings(v VARCHAR)" )); |
| 322 | REQUIRE_NO_FAIL(con.Query("INSERT INTO strings VALUES ('hello'), ('world'), (NULL)" )); |
| 323 | // ANY |
| 324 | result = con.Query("SELECT NULL IN (SELECT * FROM strings)" ); |
| 325 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
| 326 | result = con.Query("SELECT 'hello' IN (SELECT * FROM strings)" ); |
| 327 | REQUIRE(CHECK_COLUMN(result, 0, {true})); |
| 328 | result = con.Query("SELECT 'bla' IN (SELECT * FROM strings)" ); |
| 329 | REQUIRE(CHECK_COLUMN(result, 0, {Value()})); |
| 330 | result = con.Query("SELECT 'bla' IN (SELECT * FROM strings WHERE v IS NOT NULL)" ); |
| 331 | REQUIRE(CHECK_COLUMN(result, 0, {false})); |
| 332 | // EXISTS |
| 333 | result = con.Query("SELECT * FROM strings WHERE EXISTS(SELECT NULL)" ); |
| 334 | REQUIRE(CHECK_COLUMN(result, 0, {"hello" , "world" , Value()})); |
| 335 | result = con.Query("SELECT * FROM strings WHERE EXISTS(SELECT v FROM strings WHERE v='bla')" ); |
| 336 | REQUIRE(CHECK_COLUMN(result, 0, {})); |
| 337 | // scalar query |
| 338 | result = con.Query("SELECT (SELECT v FROM strings WHERE v='hello') FROM strings" ); |
| 339 | REQUIRE(CHECK_COLUMN(result, 0, {"hello" , "hello" , "hello" })); |
| 340 | result = con.Query("SELECT (SELECT v FROM strings WHERE v='bla') FROM strings" ); |
| 341 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), Value(), Value()})); |
| 342 | } |
| 343 | |
| 344 | TEST_CASE("Test subqueries from the paper 'Unnesting Arbitrary Subqueries'" , "[subquery]" ) { |
| 345 | unique_ptr<QueryResult> result; |
| 346 | DuckDB db(nullptr); |
| 347 | Connection con(db); |
| 348 | con.EnableQueryVerification(); |
| 349 | con.EnableProfiling(); |
| 350 | |
| 351 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE students(id INTEGER, name VARCHAR, major VARCHAR, year INTEGER)" )); |
| 352 | REQUIRE_NO_FAIL( |
| 353 | con.Query("CREATE TABLE exams(sid INTEGER, course VARCHAR, curriculum VARCHAR, grade INTEGER, year INTEGER)" )); |
| 354 | |
| 355 | REQUIRE_NO_FAIL(con.Query("INSERT INTO students VALUES (1, 'Mark', 'CS', 2017)" )); |
| 356 | REQUIRE_NO_FAIL(con.Query("INSERT INTO students VALUES (2, 'Dirk', 'CS', 2017)" )); |
| 357 | REQUIRE_NO_FAIL(con.Query("INSERT INTO exams VALUES (1, 'Database Systems', 'CS', 10, 2015)" )); |
| 358 | REQUIRE_NO_FAIL(con.Query("INSERT INTO exams VALUES (1, 'Graphics', 'CS', 9, 2016)" )); |
| 359 | REQUIRE_NO_FAIL(con.Query("INSERT INTO exams VALUES (2, 'Database Systems', 'CS', 7, 2015)" )); |
| 360 | REQUIRE_NO_FAIL(con.Query("INSERT INTO exams VALUES (2, 'Graphics', 'CS', 7, 2016)" )); |
| 361 | |
| 362 | result = con.Query("SELECT s.name, e.course, e.grade FROM students s, exams e WHERE s.id=e.sid AND e.grade=(SELECT " |
| 363 | "MAX(e2.grade) FROM exams e2 WHERE s.id=e2.sid) ORDER BY name, course;" ); |
| 364 | REQUIRE(CHECK_COLUMN(result, 0, {"Dirk" , "Dirk" , "Mark" })); |
| 365 | REQUIRE(CHECK_COLUMN(result, 1, {"Database Systems" , "Graphics" , "Database Systems" })); |
| 366 | REQUIRE(CHECK_COLUMN(result, 2, {7, 7, 10})); |
| 367 | |
| 368 | result = con.Query("SELECT s.name, e.course, e.grade FROM students s, exams e WHERE s.id=e.sid AND (s.major = 'CS' " |
| 369 | "OR s.major = 'Games Eng') AND e.grade <= (SELECT AVG(e2.grade) - 1 FROM exams e2 WHERE " |
| 370 | "s.id=e2.sid OR (e2.curriculum=s.major AND s.year>=e2.year)) ORDER BY name, course;" ); |
| 371 | REQUIRE(CHECK_COLUMN(result, 0, {"Dirk" , "Dirk" })); |
| 372 | REQUIRE(CHECK_COLUMN(result, 1, {"Database Systems" , "Graphics" })); |
| 373 | REQUIRE(CHECK_COLUMN(result, 2, {7, 7})); |
| 374 | |
| 375 | result = con.Query("SELECT name, major FROM students s WHERE EXISTS(SELECT * FROM exams e WHERE e.sid=s.id AND " |
| 376 | "grade=10) OR s.name='Dirk' ORDER BY name" ); |
| 377 | REQUIRE(CHECK_COLUMN(result, 0, {"Dirk" , "Mark" })); |
| 378 | REQUIRE(CHECK_COLUMN(result, 1, {"CS" , "CS" })); |
| 379 | } |
| 380 | |