1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7TEST_CASE("Simple table creation transaction tests", "[transactions]") {
8 unique_ptr<QueryResult> result;
9 DuckDB db(nullptr);
10 // create two connections
11 Connection con_one(db);
12 Connection con_two(db);
13
14 // start transactions
15 result = con_one.Query("BEGIN TRANSACTION");
16 REQUIRE(result->success);
17 result = con_two.Query("BEGIN TRANSACTION");
18 REQUIRE(result->success);
19
20 // create a table on connection one
21 result = con_one.Query("CREATE TABLE integers(i INTEGER)");
22 REQUIRE(result->success);
23 // connection one should be able to query the table
24 result = con_one.Query("SELECT * FROM integers");
25 REQUIRE(result->success);
26 // connection two should not be able to
27 result = con_two.Query("SELECT * FROM integers");
28 REQUIRE(!result->success);
29 // if we rollback, nobody should be able to query the table
30 result = con_one.Query("ROLLBACK");
31 REQUIRE(result->success);
32
33 result = con_one.Query("SELECT * FROM integers");
34 REQUIRE(!result->success);
35 result = con_two.Query("SELECT * FROM integers");
36 REQUIRE(!result->success);
37
38 // now if we commit the table
39 result = con_one.Query("BEGIN TRANSACTION");
40 REQUIRE(result->success);
41 result = con_one.Query("CREATE TABLE integers(i INTEGER)");
42 REQUIRE(result->success);
43 result = con_one.Query("COMMIT");
44 REQUIRE(result->success);
45
46 // con two STILL should not see it because it was started before the
47 // transaction committed
48 result = con_two.Query("SELECT * FROM integers");
49 REQUIRE(!result->success);
50
51 // but if we rollback and start a new transaction it should see it
52 result = con_two.Query("ROLLBACK");
53 REQUIRE(result->success);
54 result = con_two.Query("SELECT * FROM integers");
55 REQUIRE(result->success);
56
57 // serialize conflict
58
59 // start transactions
60 result = con_one.Query("BEGIN TRANSACTION");
61 REQUIRE(result->success);
62 result = con_two.Query("BEGIN TRANSACTION");
63 REQUIRE(result->success);
64
65 // create a table on connection one
66 result = con_one.Query("CREATE TABLE integers2(i INTEGER)");
67 REQUIRE(result->success);
68
69 // create a table on connection two with the same name
70 result = con_one.Query("CREATE TABLE integers2(i INTEGER)");
71 REQUIRE(!result->success);
72}
73
74TEST_CASE("Stacked schema changes", "[transactions]") {
75 unique_ptr<QueryResult> result;
76 DuckDB db(nullptr);
77 // create two connections
78 Connection con(db);
79
80 con.Query("CREATE TABLE a(i INTEGER)");
81 con.Query("INSERT INTO a VALUES (44)");
82 result = con.Query("SELECT i FROM a");
83 REQUIRE(CHECK_COLUMN(result, 0, {44}));
84
85 con.Query("BEGIN TRANSACTION");
86 con.Query("DROP TABLE a");
87 con.Query("CREATE TABLE a(i INTEGER)");
88 con.Query("INSERT INTO a VALUES (45)");
89 result = con.Query("SELECT i FROM a");
90 REQUIRE(CHECK_COLUMN(result, 0, {45}));
91 con.Query("ROLLBACK");
92
93 result = con.Query("SELECT i FROM a");
94 REQUIRE(CHECK_COLUMN(result, 0, {44}));
95
96 con.Query("BEGIN TRANSACTION");
97 con.Query("DROP TABLE a");
98 con.Query("CREATE TABLE a(i INTEGER)");
99 con.Query("INSERT INTO a VALUES (46)");
100 result = con.Query("SELECT i FROM a");
101 REQUIRE(CHECK_COLUMN(result, 0, {46}));
102 result = con.Query("COMMIT");
103
104 result = con.Query("SELECT i FROM a");
105 REQUIRE(CHECK_COLUMN(result, 0, {46}));
106}
107