| 1 | #include "catch.hpp" | 
| 2 | #include "duckdb/common/file_system.hpp" | 
| 3 | #include "dbgen.hpp" | 
| 4 | #include "test_helpers.hpp" | 
| 5 |  | 
| 6 | #include "duckdb.hpp" | 
| 7 | #include "duckdb/parser/parsed_data/create_table_function_info.hpp" | 
| 8 | #include "duckdb/function/table_function.hpp" | 
| 9 | #include "duckdb/function/scalar_function.hpp" | 
| 10 | #include "duckdb/execution/operator/list.hpp" | 
| 11 | #include "duckdb/catalog/catalog_entry/list.hpp" | 
| 12 | #include "duckdb/function/function.hpp" | 
| 13 | #include "duckdb/planner/expression/list.hpp" | 
| 14 | #include "duckdb/parser/expression/function_expression.hpp" | 
| 15 | #include "duckdb/main/client_context.hpp" | 
| 16 | #include "duckdb/function/aggregate_function.hpp" | 
| 17 | #include "duckdb/parser/parsed_data/create_aggregate_function_info.hpp" | 
| 18 |  | 
| 19 | using namespace duckdb; | 
| 20 | using namespace std; | 
| 21 |  | 
| 22 | TEST_CASE("Test scalar lists" , "[nested]" ) { | 
| 23 | 	DuckDB db(nullptr); | 
| 24 | 	Connection con(db); | 
| 25 | 	con.EnableQueryVerification(); | 
| 26 | 	unique_ptr<QueryResult> result; | 
| 27 |  | 
| 28 | 	con.Query("CREATE TABLE list_data (g INTEGER, e INTEGER)" ); | 
| 29 | 	con.Query("INSERT INTO list_data VALUES (1, 1), (1, 2), (2, 3), (2, 4), (2, 5), (3, 6), (5, NULL)" ); | 
| 30 |  | 
| 31 | 	result = con.Query("SELECT LIST_VALUE(1, 2, 3, '4') a, LIST_VALUE('a','b','c') b, LIST_VALUE(42, NULL) c, "  | 
| 32 | 	                   "LIST_VALUE(NULL, NULL, NULL) d, LIST_VALUE() e" ); | 
| 33 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({1, 2, 3, 4})})); | 
| 34 | 	REQUIRE(CHECK_COLUMN(result, 1, {Value::LIST({"a" , "b" , "c" })})); | 
| 35 | 	REQUIRE(CHECK_COLUMN(result, 2, {Value::LIST({42, Value()})})); | 
| 36 | 	REQUIRE(CHECK_COLUMN(result, 3, {Value::LIST({Value(), Value(), Value()})})); | 
| 37 | 	REQUIRE(CHECK_COLUMN(result, 4, {Value::LIST({})})); | 
| 38 |  | 
| 39 | 	result = con.Query( | 
| 40 | 	    "SELECT a FROM (VALUES (LIST_VALUE(1, 2, 3, 4)), (LIST_VALUE()), (LIST_VALUE(NULL)), (LIST_VALUE(42))) lv(a)" ); | 
| 41 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 42 | 	                     {Value::LIST({1, 2, 3, 4}), Value::LIST({}), Value::LIST({Value()}), Value::LIST({42})})); | 
| 43 |  | 
| 44 | 	result = con.Query("SELECT * FROM (VALUES ((LIST_VALUE()), (LIST_VALUE(NULL)), LIST_VALUE(1, 2))) lv(a)" ); | 
| 45 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({})})); | 
| 46 | 	REQUIRE(CHECK_COLUMN(result, 1, {Value::LIST({Value()})})); | 
| 47 | 	REQUIRE(CHECK_COLUMN(result, 2, {Value::LIST({Value::INTEGER(1), Value::INTEGER(2)})})); | 
| 48 |  | 
| 49 | 	result = con.Query("SELECT * FROM (VALUES (LIST_VALUE(1, 2)), (LIST_VALUE()), (LIST_VALUE(NULL))) lv(a)" ); | 
| 50 | 	REQUIRE(CHECK_COLUMN( | 
| 51 | 	    result, 0, {Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}), Value::LIST({}), Value::LIST({Value()})})); | 
| 52 |  | 
| 53 | 	// casting null to list or empty list to something else should work | 
| 54 | 	result = con.Query("SELECT LIST_VALUE(1, 2, 3) UNION ALL SELECT LIST_VALUE(NULL) UNION ALL SELECT LIST_VALUE() "  | 
| 55 | 	                   "UNION ALL SELECT NULL" ); | 
| 56 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({1, 2, 3}), Value::LIST({Value()}), Value::LIST({}), Value()})); | 
| 57 |  | 
| 58 | 	result = con.Query(" SELECT NULL UNION ALL SELECT LIST_VALUE() UNION ALL SELECT LIST_VALUE(NULL) UNION ALL SELECT "  | 
| 59 | 	                   "LIST_VALUE(1, 2, 3)" ); | 
| 60 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value(), Value::LIST({}), Value::LIST({Value()}), Value::LIST({1, 2, 3})})); | 
| 61 |  | 
| 62 | 	// empty list should not abort UNNEST | 
| 63 | 	result = con.Query("SELECT UNNEST(a) ua FROM (VALUES (LIST_VALUE(1, 2, 3, 4)), (LIST_VALUE()), (LIST_VALUE(NULL)), "  | 
| 64 | 	                   "(LIST_VALUE(42))) lv(a)" ); | 
| 65 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 4, Value(), 42})); | 
| 66 |  | 
| 67 | 	// TODO this should work but does not. its also kind of obscure | 
| 68 | 	//	result = con.Query("SELECT UNNEST(a) ua FROM (VALUES (LIST_VALUE()), (LIST_VALUE(1, 2, 3, 4)), | 
| 69 | 	//(LIST_VALUE(NULL)), " | 
| 70 | 	//	                   "(LIST_VALUE(42))) lv(a)"); | 
| 71 | 	//	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 4, Value(), 42})); | 
| 72 | 	// | 
| 73 | 	// list child type mismatch | 
| 74 | 	REQUIRE_FAIL(con.Query("SELECT * FROM (VALUES (LIST_VALUE(1, 2)), (LIST_VALUE()), (LIST_VALUE('a'))) lv(a)" )); | 
| 75 |  | 
| 76 | 	// can't cast lists to stuff | 
| 77 | 	REQUIRE_FAIL(con.Query("SELECT CAST(LIST_VALUE(42) AS INTEGER)" )); | 
| 78 |  | 
| 79 | 	// can't add a number to a list | 
| 80 | 	REQUIRE_FAIL(con.Query("SELECT LIST_VALUE(42) + 4" )); | 
| 81 |  | 
| 82 | 	// can't add a number to a list | 
| 83 | 	REQUIRE_FAIL(con.Query("SELECT LIST_VALUE(42, 'a')" )); | 
| 84 |  | 
| 85 | 	// can have unnest anywhere | 
| 86 | 	result = con.Query("SELECT CAST(UNNEST(LIST_VALUE(42))+2 AS INTEGER)" ); | 
| 87 | 	REQUIRE(CHECK_COLUMN(result, 0, {44})); | 
| 88 |  | 
| 89 | 	result = con.Query("SELECT LIST_VALUE(g, e, 42, NULL) FROM list_data WHERE g > 2" ); | 
| 90 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({3, 6, 42, Value()}), Value::LIST({5, Value(), 42, Value()})})); | 
| 91 |  | 
| 92 | 	result = con.Query("SELECT CASE WHEN g = 2 THEN LIST_VALUE(g, e, 42) ELSE LIST_VALUE(84, NULL) END FROM list_data "  | 
| 93 | 	                   "WHERE g > 1 UNION ALL SELECT LIST_VALUE(NULL)" ); | 
| 94 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 95 | 	                     {Value::LIST({2, 3, 42}), Value::LIST({2, 4, 42}), Value::LIST({2, 5, 42}), | 
| 96 | 	                      Value::LIST({84, Value()}), Value::LIST({84, Value()}), Value::LIST({Value()})})); | 
| 97 |  | 
| 98 | 	// this should fail because the list child types do not match | 
| 99 | 	REQUIRE_FAIL(con.Query( | 
| 100 | 	    "SELECT CASE WHEN g = 2 THEN LIST_VALUE(g, e, 42) ELSE LIST_VALUE('eeek') END FROM list_data	WHERE g > 1" )); | 
| 101 | } | 
| 102 |  | 
| 103 | TEST_CASE("Test filter and projection of nested lists" , "[nested]" ) { | 
| 104 | 	DuckDB db(nullptr); | 
| 105 | 	Connection con(db); | 
| 106 | 	con.EnableQueryVerification(); | 
| 107 | 	unique_ptr<QueryResult> result; | 
| 108 |  | 
| 109 | 	con.Query("CREATE TABLE list_data (g INTEGER, e INTEGER)" ); | 
| 110 | 	con.Query("INSERT INTO list_data VALUES (1, 1), (1, 2), (2, 3), (2, 4), (2, 5), (3, 6), (5, NULL)" ); | 
| 111 |  | 
| 112 | 	result = con.Query("SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 (a)" ); | 
| 113 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)})})); | 
| 114 |  | 
| 115 | 	result = con.Query("SELECT UNNEST(l1) FROM (SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 (a)) t1" ); | 
| 116 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3})); | 
| 117 |  | 
| 118 | 	result = con.Query("SELECT * FROM (SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 (a)) t1, (SELECT LIST(b) l2 "  | 
| 119 | 	                   "FROM (VALUES (4), (5), (6), (7)) AS t2 (b)) t2" ); | 
| 120 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)})})); | 
| 121 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 122 | 	                     {Value::LIST({Value::INTEGER(4), Value::INTEGER(5), Value::INTEGER(6), Value::INTEGER(7)})})); | 
| 123 |  | 
| 124 | 	result = con.Query("SELECT UNNEST(l1) u1, UNNEST(l2) u2 FROM (SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 "  | 
| 125 | 	                   "(a)) t1, (SELECT LIST(b) l2 FROM (VALUES (4), (5), (6), (7)) AS t2 (b)) t2" ); | 
| 126 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, Value()})); | 
| 127 | 	REQUIRE(CHECK_COLUMN(result, 1, {4, 5, 6, 7})); | 
| 128 |  | 
| 129 | 	result = con.Query("SELECT UNNEST(l1), l2 FROM (SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 (a)) t1, 	"  | 
| 130 | 	                   "(SELECT LIST(b) l2 FROM (VALUES (4), (5), (6), (7)) AS t2 (b)) t2" ); | 
| 131 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3})); | 
| 132 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 133 | 	                     {Value::LIST({Value::INTEGER(4), Value::INTEGER(5), Value::INTEGER(6), Value::INTEGER(7)}), | 
| 134 | 	                      Value::LIST({Value::INTEGER(4), Value::INTEGER(5), Value::INTEGER(6), Value::INTEGER(7)}), | 
| 135 | 	                      Value::LIST({Value::INTEGER(4), Value::INTEGER(5), Value::INTEGER(6), Value::INTEGER(7)})})); | 
| 136 |  | 
| 137 | 	result = con.Query("SELECT l1, UNNEST(l2) FROM (SELECT LIST(a) l1 FROM (VALUES (1), (2), (3)) AS t1 (a)) t1, "  | 
| 138 | 	                   "(SELECT LIST(b) l2 FROM (VALUES (4), (5), (6), (7)) AS t2 (b)) t2" ); | 
| 139 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 140 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)}), | 
| 141 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)}), | 
| 142 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)}), | 
| 143 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3)})})); | 
| 144 | 	REQUIRE(CHECK_COLUMN(result, 1, {4, 5, 6, 7})); | 
| 145 |  | 
| 146 | 	result = con.Query("SELECT UNNEST(LIST(e)) ue, LIST(g) from list_data" ); | 
| 147 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 148 | 	                     {Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5), | 
| 149 | 	                      Value::INTEGER(6), Value()})); | 
| 150 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 151 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 152 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 153 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 154 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 155 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 156 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 157 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 158 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 159 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 160 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 161 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 162 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)}), | 
| 163 | 	                      Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 164 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)})})); | 
| 165 |  | 
| 166 | 	result = con.Query("SELECT g, LIST(e) from list_data GROUP BY g ORDER BY g" ); | 
| 167 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 5})); | 
| 168 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 169 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}), | 
| 170 | 	                      Value::LIST({Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5)}), | 
| 171 | 	                      Value::LIST({Value::INTEGER(6)}), Value::LIST({Value()})})); | 
| 172 |  | 
| 173 | 	result = con.Query("SELECT g, LIST(e) l1, LIST(e) l2 from list_data GROUP BY g ORDER BY g" ); | 
| 174 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 5})); | 
| 175 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 176 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}), | 
| 177 | 	                      Value::LIST({Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5)}), | 
| 178 | 	                      Value::LIST({Value::INTEGER(6)}), Value::LIST({Value()})})); | 
| 179 | 	REQUIRE(CHECK_COLUMN(result, 2, | 
| 180 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}), | 
| 181 | 	                      Value::LIST({Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5)}), | 
| 182 | 	                      Value::LIST({Value::INTEGER(6)}), Value::LIST({Value()})})); | 
| 183 |  | 
| 184 | 	result = con.Query("SELECT g, LIST(e/2.0) from list_data GROUP BY g order by g" ); | 
| 185 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 5})); | 
| 186 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 187 | 	                     {Value::LIST({Value::DOUBLE(0.5), Value::DOUBLE(1)}), | 
| 188 | 	                      Value::LIST({Value::DOUBLE(1.5), Value::DOUBLE(2), Value::DOUBLE(2.5)}), | 
| 189 | 	                      Value::LIST({Value::DOUBLE(3)}), Value::LIST({Value()})})); | 
| 190 |  | 
| 191 | 	result = con.Query("SELECT g, LIST(CAST(e AS VARCHAR)) from list_data GROUP BY g order by g" ); | 
| 192 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 5})); | 
| 193 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 194 | 	                     {Value::LIST({Value("1" ), Value("2" )}), Value::LIST({Value("3" ), Value("4" ), Value("5" )}), | 
| 195 | 	                      Value::LIST({Value("6" )}), Value::LIST({Value()})})); | 
| 196 |  | 
| 197 | 	result = con.Query("SELECT LIST(e) from list_data" ); | 
| 198 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 199 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(4), | 
| 200 | 	                                   Value::INTEGER(5), Value::INTEGER(6), Value()})})); | 
| 201 |  | 
| 202 | 	result = con.Query("SELECT UNNEST(LIST(e)) ue from list_data ORDER BY ue" ); | 
| 203 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3, 4, 5, 6})); | 
| 204 |  | 
| 205 | 	result = con.Query("SELECT LIST(e), LIST(g) from list_data" ); | 
| 206 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 207 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(4), | 
| 208 | 	                                   Value::INTEGER(5), Value::INTEGER(6), Value()})})); | 
| 209 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 210 | 	                     {Value::LIST({Value::INTEGER(1), Value::INTEGER(1), Value::INTEGER(2), Value::INTEGER(2), | 
| 211 | 	                                   Value::INTEGER(2), Value::INTEGER(3), Value::INTEGER(5)})})); | 
| 212 |  | 
| 213 | 	result = con.Query("SELECT LIST(42)" ); | 
| 214 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value::LIST({Value::INTEGER(42)})})); | 
| 215 |  | 
| 216 | 	result = con.Query("SELECT LIST(42) FROM list_data" ); | 
| 217 | 	REQUIRE(CHECK_COLUMN(result, 0, | 
| 218 | 	                     {Value::LIST({Value::INTEGER(42), Value::INTEGER(42), Value::INTEGER(42), Value::INTEGER(42), | 
| 219 | 	                                   Value::INTEGER(42), Value::INTEGER(42), Value::INTEGER(42)})})); | 
| 220 |  | 
| 221 | 	result = con.Query("SELECT UNNEST(LIST(42))" ); | 
| 222 | 	REQUIRE(CHECK_COLUMN(result, 0, {42})); | 
| 223 |  | 
| 224 | 	// unlist is alias of unnest for symmetry reasons | 
| 225 | 	result = con.Query("SELECT UNLIST(LIST(42))" ); | 
| 226 | 	REQUIRE(CHECK_COLUMN(result, 0, {42})); | 
| 227 |  | 
| 228 | 	result = con.Query("SELECT UNNEST(LIST(e)) ue, UNNEST(LIST(g)) ug from list_data ORDER BY ue" ); | 
| 229 | 	REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3, 4, 5, 6})); | 
| 230 | 	REQUIRE(CHECK_COLUMN(result, 1, {5, 1, 1, 2, 2, 2, 3})); | 
| 231 |  | 
| 232 | 	result = con.Query("SELECT g, UNNEST(LIST(e)) ue, UNNEST(LIST(e+1)) ue2 from list_data GROUP BY g ORDER BY ue" ); | 
| 233 | 	REQUIRE(CHECK_COLUMN(result, 0, {5, 1, 1, 2, 2, 2, 3})); | 
| 234 | 	REQUIRE(CHECK_COLUMN(result, 1, {Value(), 1, 2, 3, 4, 5, 6})); | 
| 235 | 	REQUIRE(CHECK_COLUMN(result, 2, {Value(), 2, 3, 4, 5, 6, 7})); | 
| 236 |  | 
| 237 | 	result = con.Query("SELECT g, UNNEST(l) u FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1 ORDER BY u" ); | 
| 238 | 	REQUIRE(CHECK_COLUMN(result, 0, {5, 1, 1, 2, 2, 2, 3})); | 
| 239 | 	REQUIRE(CHECK_COLUMN(result, 1, {Value(), 1, 2, 3, 4, 5, 6})); | 
| 240 |  | 
| 241 | 	result = con.Query("SELECT g, UNNEST(l)+1 u FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1 ORDER BY u" ); | 
| 242 | 	REQUIRE(CHECK_COLUMN(result, 0, {5, 1, 1, 2, 2, 2, 3})); | 
| 243 | 	REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 3, 4, 5, 6, 7})); | 
| 244 |  | 
| 245 | 	// omg omg, list of structs, structs of lists | 
| 246 |  | 
| 247 | 	result = | 
| 248 | 	    con.Query("SELECT g, STRUCT_PACK(a := g, b := le) sl FROM (SELECT g, LIST(e) le from list_data GROUP BY g) "  | 
| 249 | 	              "xx WHERE g < 3 ORDER BY g" ); | 
| 250 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2})); | 
| 251 | 	REQUIRE(CHECK_COLUMN( | 
| 252 | 	    result, 1, | 
| 253 | 	    {Value::STRUCT( | 
| 254 | 	         {make_pair("a" , Value::INTEGER(1)), make_pair("b" , Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}))}), | 
| 255 | 	     Value::STRUCT({make_pair("a" , Value::INTEGER(2)), | 
| 256 | 	                    make_pair("b" , Value::LIST({Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5)}))})})); | 
| 257 |  | 
| 258 | 	result = con.Query("SELECT LIST(STRUCT_PACK(a := g, b := le)) mind_blown FROM (SELECT g, LIST(e) le from list_data "  | 
| 259 | 	                   " GROUP BY g ORDER BY g) xx" ); | 
| 260 |  | 
| 261 | 	REQUIRE(CHECK_COLUMN( | 
| 262 | 	    result, 0, | 
| 263 | 	    {Value::LIST( | 
| 264 | 	        {Value::STRUCT({make_pair("a" , Value::INTEGER(1)), | 
| 265 | 	                        make_pair("b" , Value::LIST({Value::INTEGER(1), Value::INTEGER(2)}))}), | 
| 266 | 	         Value::STRUCT({make_pair("a" , Value::INTEGER(2)), | 
| 267 | 	                        make_pair("b" , Value::LIST({Value::INTEGER(3), Value::INTEGER(4), Value::INTEGER(5)}))}), | 
| 268 | 	         Value::STRUCT({make_pair("a" , Value::INTEGER(3)), make_pair("b" , Value::LIST({Value::INTEGER(6)}))}), | 
| 269 | 	         Value::STRUCT({make_pair("a" , Value::INTEGER(5)), make_pair("b" , Value::LIST({Value()}))})})})); | 
| 270 |  | 
| 271 | 	result = con.Query("SELECT g, LIST(STRUCT_PACK(a := e, b := e+1)) ls from list_data GROUP BY g ORDER BY g" ); | 
| 272 | 	REQUIRE(CHECK_COLUMN(result, 0, {1, 2, 3, 5})); | 
| 273 | 	// TODO check second col | 
| 274 |  | 
| 275 | 	result = | 
| 276 | 	    con.Query("SELECT g, LIST(STRUCT_PACK(a := e, b := e+1)) ls from list_data WHERE g > 2GROUP BY g ORDER BY g" ); | 
| 277 | 	REQUIRE(CHECK_COLUMN(result, 0, {3, 5})); | 
| 278 | 	REQUIRE(CHECK_COLUMN( | 
| 279 | 	    result, 1, | 
| 280 | 	    {Value::LIST({Value::STRUCT({make_pair("a" , Value::INTEGER(6)), make_pair("b" , Value::INTEGER(7))})}), | 
| 281 | 	     Value::LIST({Value::STRUCT({make_pair("a" , Value()), make_pair("b" , Value())})})})); | 
| 282 |  | 
| 283 | 	// list of list of int | 
| 284 | 	result = con.Query( | 
| 285 | 	    "SELECT g2, LIST(le) FROM (SELECT g % 2 g2, LIST(e) le from list_data GROUP BY g ORDER BY g) sq 	GROUP "  | 
| 286 | 	    "BY g2 ORDER BY g2" ); | 
| 287 | 	REQUIRE(CHECK_COLUMN(result, 0, {0, 1})); | 
| 288 |  | 
| 289 | 	REQUIRE(CHECK_COLUMN(result, 1, | 
| 290 | 	                     {Value::LIST({Value::LIST({3, 4, 5})}), | 
| 291 | 	                      Value::LIST({Value::LIST({1, 2}), Value::LIST({6}), Value::LIST({Value()})})})); | 
| 292 |  | 
| 293 | 	result = con.Query("SELECT SUM(ue) FROM (SELECT UNNEST(le) ue FROM (SELECT g, LIST(e) le from list_data "  | 
| 294 | 	                   " GROUP BY g ORDER BY g) xx) xy" ); | 
| 295 | 	REQUIRE(CHECK_COLUMN(result, 0, {21})); | 
| 296 | 	// this is technically equivalent but is not supported | 
| 297 | 	REQUIRE_FAIL(con.Query("SELECT SUM(UNNEST(le)) FROM ( SELECT g, LIST(e) le from list_data "  | 
| 298 | 	                       " GROUP BY g ORDER BY g) xx" )); | 
| 299 |  | 
| 300 | 	// you're holding it wrong | 
| 301 | 	REQUIRE_FAIL(con.Query("SELECT LIST(LIST(42))" )); | 
| 302 | 	REQUIRE_FAIL(con.Query("SELECT UNNEST(UNNEST(LIST(42))" )); | 
| 303 |  | 
| 304 | 	REQUIRE_FAIL(con.Query("SELECT LIST()" )); | 
| 305 | 	REQUIRE_FAIL(con.Query("SELECT LIST() FROM list_data" )); | 
| 306 | 	REQUIRE_FAIL(con.Query("SELECT LIST(e, g) FROM list_data" )); | 
| 307 |  | 
| 308 | 	REQUIRE_FAIL(con.Query("SELECT g, UNNEST(l+1) u FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1" )); | 
| 309 | 	REQUIRE_FAIL(con.Query("SELECT g, UNNEST(g) u FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1" )); | 
| 310 | 	REQUIRE_FAIL(con.Query("SELECT g, UNNEST() u FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1" )); | 
| 311 |  | 
| 312 | 	REQUIRE_FAIL(con.Query("SELECT UNNEST(42)" )); | 
| 313 | 	REQUIRE_FAIL(con.Query("SELECT UNNEST()" )); | 
| 314 | 	REQUIRE_FAIL(con.Query("SELECT UNNEST(42) from list_data" )); | 
| 315 | 	REQUIRE_FAIL(con.Query("SELECT UNNEST() from list_data" )); | 
| 316 | 	REQUIRE_FAIL(con.Query("SELECT g FROM (SELECT g, LIST(e) l FROM list_data GROUP BY g) u1 where UNNEST(l) > 42" )); | 
| 317 | } | 
| 318 |  | 
| 319 | TEST_CASE("Test packing and unpacking lineitem into lists" , "[nested][.]" ) { | 
| 320 | 	DuckDB db(nullptr); | 
| 321 | 	Connection con(db); | 
| 322 | 	unique_ptr<MaterializedQueryResult> result; | 
| 323 | 	con.EnableQueryVerification(); // FIXME something odd happening here | 
| 324 | 	auto sf = 0.01; | 
| 325 | 	// TODO this has a small limit in it right now because of performance issues. Fix this. | 
| 326 | 	tpch::dbgen(sf, db, DEFAULT_SCHEMA, "_org" ); | 
| 327 |  | 
| 328 | 	REQUIRE_NO_FAIL(con.Query("CREATE TABLE lineitem_small AS SELECT * FROM lineitem_org LIMIT 1050;" )); | 
| 329 |  | 
| 330 | 	REQUIRE_NO_FAIL(con.Query("CREATE OR REPLACE VIEW lineitem AS SELECT * FROM lineitem_small" )); | 
| 331 | 	// run the regular Q1 on the small lineitem set | 
| 332 | 	result = con.Query(tpch::get_query(1)); | 
| 333 | 	// construct the expected values from the regular query | 
| 334 | 	vector<vector<Value>> expected_values; | 
| 335 | 	for (idx_t col_idx = 0; col_idx < result->sql_types.size(); col_idx++) { | 
| 336 | 		vector<Value> column_list; | 
| 337 | 		for (idx_t row_idx = 0; row_idx < result->collection.count; row_idx++) { | 
| 338 | 			column_list.push_back(result->GetValue(col_idx, row_idx)); | 
| 339 | 		} | 
| 340 | 		expected_values.push_back(column_list); | 
| 341 | 	} | 
| 342 |  | 
| 343 | 	REQUIRE_NO_FAIL(con.Query( | 
| 344 | 	    "CREATE OR REPLACE VIEW lineitem AS SELECT l_orderkey, STRUCT_EXTRACT(struct, 'l_partkey') l_partkey, "  | 
| 345 | 	    "STRUCT_EXTRACT(struct, 'l_suppkey') l_suppkey, STRUCT_EXTRACT(struct, 'l_linenumber') l_linenumber, "  | 
| 346 | 	    "STRUCT_EXTRACT(struct, 'l_quantity') l_quantity, STRUCT_EXTRACT(struct, 'l_extendedprice') l_extendedprice, "  | 
| 347 | 	    "STRUCT_EXTRACT(struct, 'l_discount') l_discount, STRUCT_EXTRACT(struct, 'l_tax') l_tax, "  | 
| 348 | 	    "STRUCT_EXTRACT(struct, 'l_returnflag') l_returnflag, STRUCT_EXTRACT(struct, 'l_linestatus') l_linestatus, "  | 
| 349 | 	    "STRUCT_EXTRACT(struct, 'l_shipdate') l_shipdate, STRUCT_EXTRACT(struct, 'l_commitdate') l_commitdate, "  | 
| 350 | 	    "STRUCT_EXTRACT(struct, 'l_receiptdate') l_receiptdate, STRUCT_EXTRACT(struct, 'l_shipinstruct') "  | 
| 351 | 	    "l_shipinstruct, STRUCT_EXTRACT(struct, 'l_shipmode') l_shipmode, STRUCT_EXTRACT(struct, 'l_comment') "  | 
| 352 | 	    "l_comment FROM (SELECT l_orderkey, UNLIST(rest) struct FROM (SELECT l_orderkey, LIST(STRUCT_PACK(l_partkey "  | 
| 353 | 	    ",l_suppkey ,l_linenumber ,l_quantity ,l_extendedprice ,l_discount ,l_tax ,l_returnflag ,l_linestatus "  | 
| 354 | 	    ",l_shipdate ,l_commitdate ,l_receiptdate ,l_shipinstruct ,l_shipmode ,l_comment)) rest FROM (SELECT * FROM "  | 
| 355 | 	    "lineitem_small ) lss GROUP BY l_orderkey) s1) s2;" )); | 
| 356 | 	result = con.Query(tpch::get_query(1)); | 
| 357 | 	for (idx_t col_idx = 0; col_idx < expected_values.size(); col_idx++) { | 
| 358 | 		REQUIRE(CHECK_COLUMN(result, col_idx, expected_values[col_idx])); | 
| 359 | 	} | 
| 360 |  | 
| 361 | 	// database as-a-value | 
| 362 | 	REQUIRE_NO_FAIL(con.Query( | 
| 363 | 	    "CREATE OR REPLACE VIEW lineitem AS SELECT STRUCT_EXTRACT(ls, 'l_orderkey') l_orderkey, STRUCT_EXTRACT(ls, "  | 
| 364 | 	    "'l_partkey') l_partkey, STRUCT_EXTRACT(ls, 'l_suppkey') l_suppkey, STRUCT_EXTRACT(ls, 'l_linenumber') "  | 
| 365 | 	    "l_linenumber, STRUCT_EXTRACT(ls, 'l_quantity') l_quantity, STRUCT_EXTRACT(ls, 'l_extendedprice') "  | 
| 366 | 	    "l_extendedprice, STRUCT_EXTRACT(ls, 'l_discount') l_discount, STRUCT_EXTRACT(ls, 'l_tax') l_tax, "  | 
| 367 | 	    "STRUCT_EXTRACT(ls, 'l_returnflag') l_returnflag, STRUCT_EXTRACT(ls, 'l_linestatus') l_linestatus, "  | 
| 368 | 	    "STRUCT_EXTRACT(ls, 'l_shipdate') l_shipdate, STRUCT_EXTRACT(ls, 'l_commitdate') l_commitdate, "  | 
| 369 | 	    "STRUCT_EXTRACT(ls, 'l_receiptdate') l_receiptdate, STRUCT_EXTRACT(ls, 'l_shipinstruct') l_shipinstruct, "  | 
| 370 | 	    "STRUCT_EXTRACT(ls, 'l_shipmode') l_shipmode, STRUCT_EXTRACT(ls, 'l_comment') l_comment FROM (SELECT "  | 
| 371 | 	    "UNNEST(lineitem) ls FROM (SELECT LIST(STRUCT_PACK(l_orderkey, l_partkey ,l_suppkey ,l_linenumber ,l_quantity "  | 
| 372 | 	    ",l_extendedprice ,l_discount ,l_tax ,l_returnflag ,l_linestatus ,l_shipdate ,l_commitdate ,l_receiptdate "  | 
| 373 | 	    ",l_shipinstruct ,l_shipmode ,l_comment)) lineitem FROM (SELECT * FROM lineitem_small) s1) s2) s3;" )); | 
| 374 | 	result = con.Query(tpch::get_query(1)); | 
| 375 | 	for (idx_t col_idx = 0; col_idx < expected_values.size(); col_idx++) { | 
| 376 | 		REQUIRE(CHECK_COLUMN(result, col_idx, expected_values[col_idx])); | 
| 377 | 	} | 
| 378 |  | 
| 379 | 	REQUIRE_NO_FAIL(con.Query( | 
| 380 | 	    "CREATE OR REPLACE VIEW lineitem AS SELECT UNNEST(STRUCT_EXTRACT(lineitem, 'll_orderkey')) l_orderkey, "  | 
| 381 | 	    "UNNEST(STRUCT_EXTRACT(lineitem, 'll_partkey')) l_partkey, UNNEST(STRUCT_EXTRACT(lineitem, 'll_suppkey')) "  | 
| 382 | 	    "l_suppkey, UNNEST(STRUCT_EXTRACT(lineitem, 'll_linenumber')) l_linenumber, UNNEST(STRUCT_EXTRACT(lineitem, "  | 
| 383 | 	    "'ll_quantity')) l_quantity, UNNEST(STRUCT_EXTRACT(lineitem, 'll_extendedprice')) l_extendedprice, "  | 
| 384 | 	    "UNNEST(STRUCT_EXTRACT(lineitem, 'll_discount')) l_discount, UNNEST(STRUCT_EXTRACT(lineitem, 'll_tax')) l_tax, "  | 
| 385 | 	    "UNNEST(STRUCT_EXTRACT(lineitem, 'll_returnflag')) l_returnflag, UNNEST(STRUCT_EXTRACT(lineitem, "  | 
| 386 | 	    "'ll_linestatus')) l_linestatus, UNNEST(STRUCT_EXTRACT(lineitem, 'll_shipdate')) l_shipdate, "  | 
| 387 | 	    "UNNEST(STRUCT_EXTRACT(lineitem, 'll_commitdate')) l_commitdate, UNNEST(STRUCT_EXTRACT(lineitem, "  | 
| 388 | 	    "'ll_receiptdate')) l_receiptdate, UNNEST(STRUCT_EXTRACT(lineitem, 'll_shipinstruct')) l_shipinstruct, "  | 
| 389 | 	    "UNNEST(STRUCT_EXTRACT(lineitem, 'll_shipmode')) l_shipmode, UNNEST(STRUCT_EXTRACT(lineitem, 'll_comment')) "  | 
| 390 | 	    "l_comment FROM (SELECT STRUCT_PACK(ll_orderkey:= LIST(l_orderkey), ll_partkey := LIST(l_partkey ), ll_suppkey "  | 
| 391 | 	    ":= LIST(l_suppkey ), ll_linenumber := LIST(l_linenumber ), ll_quantity := LIST(l_quantity ), ll_extendedprice "  | 
| 392 | 	    ":= LIST(l_extendedprice ), ll_discount := LIST(l_discount ), ll_tax := LIST(l_tax ), ll_returnflag := "  | 
| 393 | 	    "LIST(l_returnflag ), ll_linestatus := LIST(l_linestatus ), ll_shipdate := LIST(l_shipdate ), ll_commitdate := "  | 
| 394 | 	    "LIST(l_commitdate ), ll_receiptdate := LIST(l_receiptdate ), ll_shipinstruct := LIST(l_shipinstruct ), "  | 
| 395 | 	    "ll_shipmode := LIST(l_shipmode ), ll_comment:= LIST(l_comment)) lineitem FROM (SELECT * FROM lineitem_small) "  | 
| 396 | 	    "s1) s2;" )); | 
| 397 | 	result = con.Query(tpch::get_query(1)); | 
| 398 | 	for (idx_t col_idx = 0; col_idx < expected_values.size(); col_idx++) { | 
| 399 | 		REQUIRE(CHECK_COLUMN(result, col_idx, expected_values[col_idx])); | 
| 400 | 	} | 
| 401 | } | 
| 402 |  | 
| 403 | // TEST_CASE("Aggregate lists", "[nested]") { | 
| 404 | //	DuckDB db(nullptr); | 
| 405 | //	Connection con(db); | 
| 406 | //	con.EnableQueryVerification(); | 
| 407 | //	unique_ptr<QueryResult> result; | 
| 408 | // | 
| 409 | //	result = con.Query("SELECT SUM(a), b FROM (VALUES (42, LIST_VALUE(1, 2)), (42, LIST_VALUE(3, 4, 5)), (24, | 
| 410 | // LIST_VALUE(1, 2))) lv(a, b) GROUP BY b"); 	result->Print(); | 
| 411 | //} | 
| 412 |  |