1 | #include "catch.hpp" |
2 | #include "duckdb/common/file_system.hpp" |
3 | #include "test_helpers.hpp" |
4 | #include "duckdb/main/appender.hpp" |
5 | |
6 | using namespace duckdb; |
7 | using namespace std; |
8 | |
9 | TEST_CASE("Test empty startup" , "[storage]" ) { |
10 | auto config = GetTestConfig(); |
11 | unique_ptr<DuckDB> db; |
12 | unique_ptr<QueryResult> result; |
13 | auto storage_database = TestCreatePath("storage_test" ); |
14 | |
15 | // make sure the database does not exist |
16 | DeleteDatabase(storage_database); |
17 | // create a database and close it |
18 | REQUIRE_NOTHROW(db = make_unique<DuckDB>(storage_database, config.get())); |
19 | db.reset(); |
20 | // reload the database |
21 | REQUIRE_NOTHROW(db = make_unique<DuckDB>(storage_database, config.get())); |
22 | db.reset(); |
23 | DeleteDatabase(storage_database); |
24 | } |
25 | |
26 | TEST_CASE("Test empty table" , "[storage]" ) { |
27 | auto config = GetTestConfig(); |
28 | unique_ptr<QueryResult> result; |
29 | |
30 | auto storage_database = TestCreatePath("storage_test" ); |
31 | |
32 | // make sure the database does not exist |
33 | // make sure the database does not exist |
34 | DeleteDatabase(storage_database); |
35 | { |
36 | // create a database and insert values |
37 | DuckDB db(storage_database, config.get()); |
38 | Connection con(db); |
39 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b VARCHAR);" )); |
40 | |
41 | result = con.Query("SELECT COUNT(*) FROM test" ); |
42 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
43 | } |
44 | { |
45 | DuckDB db(storage_database, config.get()); |
46 | Connection con(db); |
47 | result = con.Query("SELECT COUNT(*) FROM test" ); |
48 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
49 | } |
50 | { |
51 | DuckDB db(storage_database, config.get()); |
52 | Connection con(db); |
53 | result = con.Query("SELECT COUNT(*) FROM test" ); |
54 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
55 | } |
56 | } |
57 | |
58 | TEST_CASE("Test simple storage" , "[storage]" ) { |
59 | auto config = GetTestConfig(); |
60 | unique_ptr<QueryResult> result; |
61 | auto storage_database = TestCreatePath("storage_test" ); |
62 | |
63 | // make sure the database does not exist |
64 | DeleteDatabase(storage_database); |
65 | { |
66 | // create a database and insert values |
67 | DuckDB db(storage_database, config.get()); |
68 | Connection con(db); |
69 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);" )); |
70 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (13, 22), (12, 21), (NULL, NULL)" )); |
71 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test2 (a INTEGER);" )); |
72 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test2 VALUES (13), (12), (11)" )); |
73 | } |
74 | // reload the database from disk a few times |
75 | for (idx_t i = 0; i < 2; i++) { |
76 | DuckDB db(storage_database, config.get()); |
77 | Connection con(db); |
78 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
79 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 11, 12, 13})); |
80 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 22, 21, 22})); |
81 | result = con.Query("SELECT * FROM test2 ORDER BY a" ); |
82 | REQUIRE(CHECK_COLUMN(result, 0, {11, 12, 13})); |
83 | } |
84 | DeleteDatabase(storage_database); |
85 | } |
86 | |
87 | TEST_CASE("Test storing NULLs and strings" , "[storage]" ) { |
88 | auto config = GetTestConfig(); |
89 | unique_ptr<QueryResult> result; |
90 | auto storage_database = TestCreatePath("storage_test" ); |
91 | |
92 | // make sure the database does not exist |
93 | DeleteDatabase(storage_database); |
94 | { |
95 | // create a database and insert values |
96 | DuckDB db(storage_database, config.get()); |
97 | Connection con(db); |
98 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b STRING);" )); |
99 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (NULL, 'hello'), " |
100 | "(13, 'abcdefgh'), (12, NULL)" )); |
101 | } |
102 | // reload the database from disk a few times |
103 | for (idx_t i = 0; i < 2; i++) { |
104 | DuckDB db(storage_database, config.get()); |
105 | Connection con(db); |
106 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
107 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 12, 13})); |
108 | REQUIRE(CHECK_COLUMN(result, 1, {"hello" , Value(), "abcdefgh" })); |
109 | } |
110 | DeleteDatabase(storage_database); |
111 | } |
112 | |
113 | TEST_CASE("Test updates/deletes and strings" , "[storage]" ) { |
114 | auto config = GetTestConfig(); |
115 | unique_ptr<QueryResult> result; |
116 | auto storage_database = TestCreatePath("storage_test" ); |
117 | |
118 | // make sure the database does not exist |
119 | DeleteDatabase(storage_database); |
120 | { |
121 | // create a database and insert values |
122 | DuckDB db(storage_database, config.get()); |
123 | Connection con(db); |
124 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b STRING);" )); |
125 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (NULL, 'hello'), " |
126 | "(13, 'abcdefgh'), (12, NULL)" )); |
127 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=NULL WHERE a IS NULL" )); |
128 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test WHERE a=12" )); |
129 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (12, NULL)" )); |
130 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b='test123' WHERE a=12" )); |
131 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET a=a+1" )); |
132 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
133 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 13, 14})); |
134 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), "test123" , "abcdefgh" })); |
135 | } |
136 | // reload the database from disk a few times |
137 | for (idx_t i = 0; i < 2; i++) { |
138 | DuckDB db(storage_database, config.get()); |
139 | Connection con(db); |
140 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
141 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 13, 14})); |
142 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), "test123" , "abcdefgh" })); |
143 | } |
144 | DeleteDatabase(storage_database); |
145 | } |
146 | |
147 | TEST_CASE("Test deletes with storage" , "[storage]" ) { |
148 | auto config = GetTestConfig(); |
149 | unique_ptr<QueryResult> result; |
150 | auto storage_database = TestCreatePath("storage_test" ); |
151 | |
152 | // make sure the database does not exist |
153 | DeleteDatabase(storage_database); |
154 | { |
155 | // create a database and insert values |
156 | DuckDB db(storage_database, config.get()); |
157 | Connection con(db); |
158 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;" )); |
159 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);" )); |
160 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (12, 21), (13, 22), (12, 21)" )); |
161 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test WHERE a=12" )); |
162 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
163 | REQUIRE(CHECK_COLUMN(result, 0, {11, 13})); |
164 | REQUIRE(CHECK_COLUMN(result, 1, {22, 22})); |
165 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
166 | } |
167 | // reload the database from disk |
168 | for (idx_t i = 0; i < 2; i++) { |
169 | DuckDB db(storage_database, config.get()); |
170 | Connection con(db); |
171 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
172 | REQUIRE(CHECK_COLUMN(result, 0, {11, 13})); |
173 | REQUIRE(CHECK_COLUMN(result, 1, {22, 22})); |
174 | } |
175 | DeleteDatabase(storage_database); |
176 | } |
177 | |
178 | TEST_CASE("Test updates with storage" , "[storage]" ) { |
179 | auto config = GetTestConfig(); |
180 | unique_ptr<QueryResult> result; |
181 | auto storage_database = TestCreatePath("storage_test" ); |
182 | |
183 | // make sure the database does not exist |
184 | DeleteDatabase(storage_database); |
185 | { |
186 | // create a database and insert values |
187 | DuckDB db(storage_database, config.get()); |
188 | Connection con(db); |
189 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;" )); |
190 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);" )); |
191 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (13, 22), (12, 21)" )); |
192 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=b+1 WHERE a=11" )); |
193 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=b+1 WHERE a=11" )); |
194 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
195 | } |
196 | // reload the database from disk |
197 | for (idx_t i = 0; i < 2; i++) { |
198 | DuckDB db(storage_database, config.get()); |
199 | Connection con(db); |
200 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
201 | REQUIRE(CHECK_COLUMN(result, 0, {11, 12, 13})); |
202 | REQUIRE(CHECK_COLUMN(result, 1, {24, 21, 22})); |
203 | } |
204 | DeleteDatabase(storage_database); |
205 | } |
206 | |
207 | TEST_CASE("Test mix of updates and deletes with storage" , "[storage]" ) { |
208 | auto config = GetTestConfig(); |
209 | unique_ptr<QueryResult> result; |
210 | auto storage_database = TestCreatePath("storage_test" ); |
211 | |
212 | // make sure the database does not exist |
213 | DeleteDatabase(storage_database); |
214 | { |
215 | // create a database and insert values |
216 | DuckDB db(storage_database, config.get()); |
217 | Connection con(db); |
218 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;" )); |
219 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);" )); |
220 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (13, 22), (12, 21)" )); |
221 | for (size_t i = 0; i < 1000; i++) { |
222 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=b+1 WHERE a=11" )); |
223 | } |
224 | result = con.Query("DELETE FROM test WHERE a=12" ); |
225 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
226 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
227 | } |
228 | // reload the database from disk |
229 | for (idx_t i = 0; i < 2; i++) { |
230 | DuckDB db(storage_database, config.get()); |
231 | Connection con(db); |
232 | result = con.Query("SELECT a, b FROM test ORDER BY a" ); |
233 | REQUIRE(CHECK_COLUMN(result, 0, {11, 13})); |
234 | REQUIRE(CHECK_COLUMN(result, 1, {1022, 22})); |
235 | } |
236 | DeleteDatabase(storage_database); |
237 | } |
238 | |
239 | TEST_CASE("Test large inserts in a single transaction" , "[storage]" ) { |
240 | auto config = GetTestConfig(); |
241 | unique_ptr<QueryResult> result; |
242 | auto storage_database = TestCreatePath("storage_test" ); |
243 | |
244 | // make sure the database does not exist |
245 | int64_t expected_sum_a = 0, expected_sum_b = 0, expected_count = 0; |
246 | DeleteDatabase(storage_database); |
247 | { |
248 | // create a database and insert values |
249 | DuckDB db(storage_database, config.get()); |
250 | Connection con(db); |
251 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;" )); |
252 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER, b INTEGER);" )); |
253 | for (idx_t i = 0; i < 1000; i++) { |
254 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (11, 22), (13, 22), (12, 21)" )); |
255 | expected_sum_a += 11 + 13; |
256 | expected_sum_b += 22 + 22; |
257 | expected_count += 2; |
258 | } |
259 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test WHERE a=12" )); |
260 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
261 | |
262 | result = con.Query("SELECT SUM(a), SUM(b), COUNT(*) FROM test" ); |
263 | REQUIRE(CHECK_COLUMN(result, 0, {Value::BIGINT(expected_sum_a)})); |
264 | REQUIRE(CHECK_COLUMN(result, 1, {Value::BIGINT(expected_sum_b)})); |
265 | REQUIRE(CHECK_COLUMN(result, 2, {Value::BIGINT(expected_count)})); |
266 | } |
267 | // reload the database from disk |
268 | for (idx_t i = 0; i < 2; i++) { |
269 | DuckDB db(storage_database, config.get()); |
270 | Connection con(db); |
271 | result = con.Query("SELECT SUM(a), SUM(b), COUNT(*) FROM test" ); |
272 | REQUIRE(CHECK_COLUMN(result, 0, {Value::BIGINT(expected_sum_a)})); |
273 | REQUIRE(CHECK_COLUMN(result, 1, {Value::BIGINT(expected_sum_b)})); |
274 | REQUIRE(CHECK_COLUMN(result, 2, {Value::BIGINT(expected_count)})); |
275 | } |
276 | DeleteDatabase(storage_database); |
277 | } |
278 | |
279 | TEST_CASE("Test interleaving of insertions/updates/deletes on multiple tables" , "[storage][.]" ) { |
280 | auto config = GetTestConfig(); |
281 | unique_ptr<QueryResult> result; |
282 | auto storage_database = TestCreatePath("storage_test" ); |
283 | |
284 | // make sure the database does not exist |
285 | DeleteDatabase(storage_database); |
286 | { |
287 | // create a database and insert values |
288 | DuckDB db(storage_database, config.get()); |
289 | Connection con(db); |
290 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;" )); |
291 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER);" )); |
292 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test2 (a INTEGER, b INTEGER);" )); |
293 | idx_t test_insert = 0, test_insert2 = 0; |
294 | for (idx_t i = 0; i < 1000; i++) { |
295 | idx_t stage = i % 7; |
296 | switch (stage) { |
297 | case 0: |
298 | for (; test_insert < i; test_insert++) { |
299 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (" + to_string(test_insert) + ")" )); |
300 | } |
301 | break; |
302 | case 1: |
303 | for (; test_insert2 < i; test_insert2++) { |
304 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test2 VALUES (" + to_string(test_insert) + ", " + |
305 | to_string(test_insert) + " + 2)" )); |
306 | } |
307 | break; |
308 | case 2: |
309 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET a = a + 1 WHERE a % 2 = 0" )); |
310 | break; |
311 | case 3: |
312 | REQUIRE_NO_FAIL(con.Query("UPDATE test2 SET a = a + 1 WHERE a % 2 = 0" )); |
313 | break; |
314 | case 4: |
315 | REQUIRE_NO_FAIL(con.Query("UPDATE test2 SET b = b + 1 WHERE b % 2 = 0" )); |
316 | break; |
317 | case 5: |
318 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test WHERE a % 5 = 0" )); |
319 | break; |
320 | default: |
321 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test2 WHERE a % 5 = 0" )); |
322 | break; |
323 | } |
324 | } |
325 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
326 | |
327 | result = con.Query("SELECT SUM(a) FROM test ORDER BY 1" ); |
328 | REQUIRE(CHECK_COLUMN(result, 0, {396008})); |
329 | |
330 | result = con.Query("SELECT SUM(a), SUM(b) FROM test2 ORDER BY 1" ); |
331 | REQUIRE(CHECK_COLUMN(result, 0, {403915})); |
332 | REQUIRE(CHECK_COLUMN(result, 1, {405513})); |
333 | } |
334 | // reload the database from disk |
335 | for (idx_t i = 0; i < 2; i++) { |
336 | DuckDB db(storage_database, config.get()); |
337 | Connection con(db); |
338 | result = con.Query("SELECT SUM(a) FROM test ORDER BY 1" ); |
339 | REQUIRE(CHECK_COLUMN(result, 0, {396008})); |
340 | |
341 | result = con.Query("SELECT SUM(a), SUM(b) FROM test2 ORDER BY 1" ); |
342 | REQUIRE(CHECK_COLUMN(result, 0, {403915})); |
343 | REQUIRE(CHECK_COLUMN(result, 1, {405513})); |
344 | } |
345 | DeleteDatabase(storage_database); |
346 | } |
347 | |
348 | TEST_CASE("Test update/deletes on big table" , "[storage][.]" ) { |
349 | auto config = GetTestConfig(); |
350 | unique_ptr<QueryResult> result; |
351 | auto storage_database = TestCreatePath("storage_test" ); |
352 | |
353 | // make sure the database does not exist |
354 | DeleteDatabase(storage_database); |
355 | { |
356 | // create a big table |
357 | DuckDB db(storage_database, config.get()); |
358 | Connection con(db); |
359 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test (a INTEGER);" )); |
360 | Appender appender(con, "test" ); |
361 | for (int32_t i = 0; i < 100000; i++) { |
362 | appender.BeginRow(); |
363 | appender.Append<int32_t>(i % 1000); |
364 | appender.EndRow(); |
365 | } |
366 | appender.Close(); |
367 | // now perform some updates |
368 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET a=2000 WHERE a=1" )); |
369 | REQUIRE_NO_FAIL(con.Query("DELETE FROM test WHERE a=2 OR a=17" )); |
370 | |
371 | result = con.Query("SELECT SUM(a), COUNT(a) FROM test" ); |
372 | REQUIRE(CHECK_COLUMN(result, 0, {50148000})); |
373 | REQUIRE(CHECK_COLUMN(result, 1, {99800})); |
374 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=0" ); |
375 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
376 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=1" ); |
377 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
378 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=2" ); |
379 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
380 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=17" ); |
381 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
382 | } |
383 | // reload the database from disk |
384 | for (idx_t i = 0; i < 2; i++) { |
385 | DuckDB db(storage_database, config.get()); |
386 | Connection con(db); |
387 | result = con.Query("SELECT SUM(a), COUNT(a) FROM test" ); |
388 | REQUIRE(CHECK_COLUMN(result, 0, {50148000})); |
389 | REQUIRE(CHECK_COLUMN(result, 1, {99800})); |
390 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=0" ); |
391 | REQUIRE(CHECK_COLUMN(result, 0, {100})); |
392 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=1" ); |
393 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
394 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=2" ); |
395 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
396 | result = con.Query("SELECT COUNT(a) FROM test WHERE a=17" ); |
397 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
398 | } |
399 | DeleteDatabase(storage_database); |
400 | } |
401 | |
402 | TEST_CASE("Test updates/deletes/insertions on persistent segments" , "[storage]" ) { |
403 | auto config = GetTestConfig(); |
404 | unique_ptr<QueryResult> result; |
405 | auto storage_database = TestCreatePath("storage_test" ); |
406 | |
407 | // make sure the database does not exist |
408 | DeleteDatabase(storage_database); |
409 | { |
410 | // create a database and insert values |
411 | DuckDB db(storage_database, config.get()); |
412 | Connection con(db); |
413 | REQUIRE_NO_FAIL(con.Query("CREATE TABLE test(a INTEGER, b INTEGER);" )); |
414 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (1, 3), (NULL, NULL)" )); |
415 | } |
416 | // reload the database from disk |
417 | { |
418 | DuckDB db(storage_database, config.get()); |
419 | Connection con(db); |
420 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (2, 2)" )); |
421 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
422 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2})); |
423 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 3, 2})); |
424 | } |
425 | // reload the database from disk, we do this again because checkpointing at startup causes this to follow a |
426 | // different code path |
427 | { |
428 | DuckDB db(storage_database, config.get()); |
429 | Connection con(db); |
430 | REQUIRE_NO_FAIL(con.Query("INSERT INTO test VALUES (3, 3)" )); |
431 | |
432 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=4 WHERE a=1" )); |
433 | |
434 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
435 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
436 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 4, 2, 3})); |
437 | } |
438 | { |
439 | DuckDB db(storage_database, config.get()); |
440 | Connection con(db); |
441 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
442 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 1, 2, 3})); |
443 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 4, 2, 3})); |
444 | |
445 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET a=4, b=4 WHERE a=1" )); |
446 | |
447 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
448 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 2, 3, 4})); |
449 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 3, 4})); |
450 | } |
451 | { |
452 | DuckDB db(storage_database, config.get()); |
453 | Connection con(db); |
454 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
455 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 2, 3, 4})); |
456 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 3, 4})); |
457 | |
458 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=5, a=6 WHERE a=4" )); |
459 | |
460 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
461 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 2, 3, 6})); |
462 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 3, 5})); |
463 | } |
464 | { |
465 | DuckDB db(storage_database, config.get()); |
466 | Connection con(db); |
467 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
468 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 2, 3, 6})); |
469 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 3, 5})); |
470 | |
471 | REQUIRE_NO_FAIL(con.Query("UPDATE test SET b=7 WHERE a=3" )); |
472 | |
473 | result = con.Query("SELECT * FROM test ORDER BY a" ); |
474 | REQUIRE(CHECK_COLUMN(result, 0, {Value(), 2, 3, 6})); |
475 | REQUIRE(CHECK_COLUMN(result, 1, {Value(), 2, 7, 5})); |
476 | } |
477 | DeleteDatabase(storage_database); |
478 | } |
479 | |