| 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 not equals join" , "[join]" ) { |
| 10 | unique_ptr<QueryResult> result; |
| 11 | DuckDB db(nullptr); |
| 12 | Connection con(db); |
| 13 | con.EnableQueryVerification(); |
| 14 | |
| 15 | REQUIRE_NO_FAIL(con.Query("create table a (i integer)" )); |
| 16 | REQUIRE_NO_FAIL(con.Query( |
| 17 | "insert into a values " |
| 18 | "('28579'),('16098'),('25281'),('28877'),('18048'),('26820'),('26971'),('22812'),('11757'),('21851'),('27752')," |
| 19 | "('28354'),('29843'),('28828'),('16668'),('20534'),('28222'),('24244'),('28877'),('20150'),('23451'),('23683')," |
| 20 | "('20419'),('28048'),('24244'),('28605'),('25752'),('24466'),('26557'),('16098'),('29454'),('24854'),('13298')," |
| 21 | "('29584'),('13394'),('24843'),('22477'),('14593'),('24244'),('28722'),('25124'),('16668'),('26787'),('28877')," |
| 22 | "('27752'),('28482'),('24408'),('25752'),('24136'),('28222'),('17683'),('24244'),('19275'),('21087'),('26594')," |
| 23 | "('22293'),('25281'),('12898'),('23451'),('12898'),('21757'),('20965'),('25709'),('26614'),('10399'),('28773')," |
| 24 | "('11933'),('29584'),('29003'),('26871'),('17746'),('24092'),('26192'),('19310'),('10965'),('29275'),('20191')," |
| 25 | "('29101'),('28059'),('29584'),('20399'),('24338'),('26192'),('25124'),('28605'),('13003'),('16668'),('23511')," |
| 26 | "('26534'),('24107')" )); |
| 27 | |
| 28 | REQUIRE_NO_FAIL(con.Query("create table b (j integer)" )); |
| 29 | REQUIRE_NO_FAIL(con.Query("insert into b values " |
| 30 | "('31904'),('31904'),('31904'),('31904'),('35709'),('31904'),('31904'),('35709'),('31904'" |
| 31 | "),('31904'),('31904'),('31904')" )); |
| 32 | |
| 33 | result = con.Query("select count(*) from a,b where i <> j" ); |
| 34 | REQUIRE(CHECK_COLUMN(result, 0, {1080})); |
| 35 | } |
| 36 | |
| 37 | TEST_CASE("Test less than join" , "[join][.]" ) { |
| 38 | unique_ptr<QueryResult> result; |
| 39 | DuckDB db(nullptr); |
| 40 | Connection con(db); |
| 41 | con.EnableQueryVerification(); |
| 42 | |
| 43 | REQUIRE_NO_FAIL(con.Query("create table a (i integer)" )); |
| 44 | for (idx_t i = 0; i < 2000; i++) { |
| 45 | REQUIRE_NO_FAIL(con.Query("insert into a values ($1)" , (int32_t)i + 1)); |
| 46 | } |
| 47 | |
| 48 | result = con.Query("select count(*) from a, (SELECT 2000 AS j) b where i < j" ); |
| 49 | REQUIRE(CHECK_COLUMN(result, 0, {1999})); |
| 50 | |
| 51 | result = con.Query("select count(*) from a, (SELECT 2000 AS j) b where i <= j" ); |
| 52 | REQUIRE(CHECK_COLUMN(result, 0, {2000})); |
| 53 | |
| 54 | result = con.Query("select count(*) from a, (SELECT 1 AS j) b where i > j" ); |
| 55 | REQUIRE(CHECK_COLUMN(result, 0, {1999})); |
| 56 | |
| 57 | result = con.Query("select count(*) from a, (SELECT 1 AS j) b where i >= j" ); |
| 58 | REQUIRE(CHECK_COLUMN(result, 0, {2000})); |
| 59 | } |
| 60 | |
| 61 | TEST_CASE("Test joins with different types" , "[join]" ) { |
| 62 | unique_ptr<QueryResult> result; |
| 63 | DuckDB db(nullptr); |
| 64 | Connection con(db); |
| 65 | con.EnableQueryVerification(); |
| 66 | |
| 67 | // numeric types |
| 68 | vector<string> numeric_types = {"tinyint" , "smallint" , "integer" , "bigint" , "real" , "double" }; |
| 69 | for (auto &type : numeric_types) { |
| 70 | REQUIRE_NO_FAIL(con.Query("begin transaction" )); |
| 71 | REQUIRE_NO_FAIL(con.Query("create table a (i " + type + ")" )); |
| 72 | for (idx_t i = 0; i < 100; i++) { |
| 73 | REQUIRE_NO_FAIL(con.Query("insert into a values ($1)" , (int32_t)i + 1)); |
| 74 | } |
| 75 | // range joins |
| 76 | result = con.Query("select count(*), sum(i) from a, (SELECT 100::" + type + " AS j) b where i < j" ); |
| 77 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 78 | REQUIRE(CHECK_COLUMN(result, 1, {4950})); |
| 79 | result = con.Query("select count(*) from a, (SELECT 100::" + type + " AS j) b where i <= j" ); |
| 80 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
| 81 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i > j" ); |
| 82 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 83 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i >= j" ); |
| 84 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
| 85 | // inequality join |
| 86 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i <> j" ); |
| 87 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 88 | // equality join |
| 89 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i = j" ); |
| 90 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 91 | // no results on one side |
| 92 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i > j AND i>1000" ); |
| 93 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
| 94 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i <> j AND i>1000" ); |
| 95 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
| 96 | result = con.Query("select count(*) from a, (SELECT 1::" + type + " AS j) b where i = j AND i>1000" ); |
| 97 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
| 98 | |
| 99 | REQUIRE_NO_FAIL(con.Query("rollback" )); |
| 100 | } |
| 101 | // strings |
| 102 | REQUIRE_NO_FAIL(con.Query("begin transaction" )); |
| 103 | REQUIRE_NO_FAIL(con.Query("create table a (i VARCHAR)" )); |
| 104 | REQUIRE_NO_FAIL(con.Query("insert into a values ('a'), ('b'), ('c'), ('d'), ('e'), ('f')" )); |
| 105 | |
| 106 | // range joins |
| 107 | result = con.Query("select count(*) from a, (SELECT 'f' AS j) b where i < j" ); |
| 108 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 109 | result = con.Query("select count(*) from a, (SELECT 'f' AS j) b where i <= j" ); |
| 110 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 111 | result = con.Query("select count(*) from a, (SELECT 'a' AS j) b where i > j" ); |
| 112 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 113 | result = con.Query("select count(*) from a, (SELECT 'a' AS j) b where i >= j" ); |
| 114 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 115 | result = con.Query("select count(*) from a, (SELECT 'a' AS j) b where i <> j" ); |
| 116 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 117 | result = con.Query("select count(*) from a, (SELECT 'a' AS j) b where i = j" ); |
| 118 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 119 | |
| 120 | REQUIRE_NO_FAIL(con.Query("rollback" )); |
| 121 | } |
| 122 | |
| 123 | TEST_CASE("Test mark join with different types" , "[join]" ) { |
| 124 | unique_ptr<QueryResult> result; |
| 125 | DuckDB db(nullptr); |
| 126 | Connection con(db); |
| 127 | con.EnableQueryVerification(); |
| 128 | |
| 129 | // numeric types |
| 130 | vector<string> numeric_types = {"tinyint" , "smallint" , "integer" , "bigint" , "real" , "double" }; |
| 131 | for (auto &type : numeric_types) { |
| 132 | REQUIRE_NO_FAIL(con.Query("begin transaction" )); |
| 133 | REQUIRE_NO_FAIL(con.Query("create table a (i " + type + ")" )); |
| 134 | std::vector<int32_t> values; |
| 135 | for (idx_t i = 0; i < 100; i++) { |
| 136 | values.push_back(i + 1); |
| 137 | } |
| 138 | std::random_shuffle(values.begin(), values.end()); |
| 139 | for (idx_t i = 0; i < values.size(); i++) { |
| 140 | REQUIRE_NO_FAIL(con.Query("insert into a values ($1)" , values[i])); |
| 141 | } |
| 142 | |
| 143 | // range joins |
| 144 | result = con.Query("select count(*) from a WHERE i > ANY((SELECT 1::" + type + "))" ); |
| 145 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 146 | result = con.Query("select count(*) from a WHERE i >= ANY((SELECT 1::" + type + "))" ); |
| 147 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
| 148 | result = con.Query("select count(*) from a WHERE i < ANY((SELECT 100::" + type + "))" ); |
| 149 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 150 | result = con.Query("select count(*) from a WHERE i <= ANY((SELECT 100::" + type + "))" ); |
| 151 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
| 152 | result = con.Query("select count(*) from a WHERE i = ANY((SELECT 1::" + type + "))" ); |
| 153 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 154 | result = con.Query("select count(*) from a WHERE i <> ANY((SELECT 1::" + type + "))" ); |
| 155 | REQUIRE(CHECK_COLUMN(result, 0, {99})); |
| 156 | |
| 157 | // now with a filter |
| 158 | result = con.Query("select count(*) from (select * from a where i % 2 = 0) a WHERE i > ANY((SELECT 2::" + type + |
| 159 | "))" ); |
| 160 | REQUIRE(CHECK_COLUMN(result, 0, {49})); |
| 161 | result = con.Query( |
| 162 | "select count(*) from (select * from a where i % 2 = 0) a WHERE i >= ANY((SELECT 2::" + type + "))" ); |
| 163 | REQUIRE(CHECK_COLUMN(result, 0, {50})); |
| 164 | result = con.Query( |
| 165 | "select count(*) from (select * from a where i % 2 = 0) a WHERE i < ANY((SELECT 100::" + type + "))" ); |
| 166 | REQUIRE(CHECK_COLUMN(result, 0, {49})); |
| 167 | result = con.Query( |
| 168 | "select count(*) from (select * from a where i % 2 = 0) a WHERE i <= ANY((SELECT 100::" + type + "))" ); |
| 169 | REQUIRE(CHECK_COLUMN(result, 0, {50})); |
| 170 | result = con.Query("select * from (select * from a where i % 2 = 0) a WHERE i = ANY((SELECT 2::" + type + "))" ); |
| 171 | REQUIRE(CHECK_COLUMN(result, 0, {2})); |
| 172 | result = con.Query( |
| 173 | "select count(*) from (select * from a where i % 2 = 0) a WHERE i <> ANY((SELECT 2::" + type + "))" ); |
| 174 | REQUIRE(CHECK_COLUMN(result, 0, {49})); |
| 175 | |
| 176 | // now select the actual values, instead of only the count |
| 177 | result = con.Query("select * from (select * from a where i % 2 = 0) a WHERE i <= ANY((SELECT 10::" + type + |
| 178 | ")) ORDER BY 1" ); |
| 179 | REQUIRE(CHECK_COLUMN(result, 0, {2, 4, 6, 8, 10})); |
| 180 | result = con.Query("select * from (select * from a where i % 2 = 0) a WHERE i >= ANY((SELECT 90::" + type + |
| 181 | ")) ORDER BY 1" ); |
| 182 | REQUIRE(CHECK_COLUMN(result, 0, {90, 92, 94, 96, 98, 100})); |
| 183 | result = con.Query("select * from (select * from a where i > 90) a WHERE i <> ANY((SELECT 96::" + type + |
| 184 | ")) ORDER BY 1" ); |
| 185 | REQUIRE(CHECK_COLUMN(result, 0, {91, 92, 93, 94, 95, 97, 98, 99, 100})); |
| 186 | |
| 187 | REQUIRE_NO_FAIL(con.Query("rollback" )); |
| 188 | } |
| 189 | // strings |
| 190 | REQUIRE_NO_FAIL(con.Query("begin transaction" )); |
| 191 | REQUIRE_NO_FAIL(con.Query("create table a (i VARCHAR)" )); |
| 192 | REQUIRE_NO_FAIL(con.Query("insert into a values ('a'), ('b'), ('c'), ('d'), ('e'), ('f')" )); |
| 193 | |
| 194 | // range joins |
| 195 | result = con.Query("select count(*) from a WHERE i < ANY((SELECT 'f'))" ); |
| 196 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 197 | result = con.Query("select count(*) from a WHERE i <= ANY((SELECT 'f' AS j))" ); |
| 198 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 199 | result = con.Query("select count(*) from a WHERE i > ANY((SELECT 'a'))" ); |
| 200 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 201 | result = con.Query("select count(*) from a WHERE i >= ANY((SELECT 'a'))" ); |
| 202 | REQUIRE(CHECK_COLUMN(result, 0, {6})); |
| 203 | result = con.Query("select count(*) from a WHERE i <> ANY((SELECT 'a'))" ); |
| 204 | REQUIRE(CHECK_COLUMN(result, 0, {5})); |
| 205 | result = con.Query("select count(*) from a WHERE i = ANY((SELECT 'a'))" ); |
| 206 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
| 207 | |
| 208 | REQUIRE_NO_FAIL(con.Query("rollback" )); |
| 209 | } |
| 210 | |