1#include "catch.hpp"
2#include "test_helpers.hpp"
3
4using namespace duckdb;
5using namespace std;
6
7TEST_CASE("Schema creation/deletion", "[catalog]") {
8 unique_ptr<QueryResult> result;
9 DuckDB db(nullptr);
10 Connection con(db);
11
12 // cannot drop MAIN schema
13 REQUIRE_FAIL(con.Query("DROP SCHEMA main CASCADE;"));
14
15 // create and drop an empty schema
16 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA test;"));
17 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test;"));
18
19 // create the schema again
20 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA test;"));
21 // duplicate schema
22 REQUIRE_FAIL(con.Query("CREATE SCHEMA test;"));
23 // if not exists ignores error
24 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA IF NOT EXISTS test;"));
25
26 // create table inside schema that exists should succeed
27 REQUIRE_NO_FAIL(con.Query("CREATE TABLE test.hello(i INTEGER);"));
28 // create table inside schema that does not exist should fail
29 REQUIRE_FAIL(con.Query("CREATE TABLE test2.hello(i INTEGER);"));
30
31 // use the table in queries
32 // insert into table
33 REQUIRE_NO_FAIL(con.Query("INSERT INTO test.hello VALUES (2), (3), (4)"));
34 // select from table without schema specified should fail
35 REQUIRE_FAIL(con.Query("SELECT * FROM hello"));
36
37 // with schema specified should succeed
38 result = con.Query("SELECT * FROM test.hello");
39 REQUIRE(CHECK_COLUMN(result, 0, {2, 3, 4}));
40
41 // drop schema with dependencies should fail
42 REQUIRE_FAIL(con.Query("DROP SCHEMA test;"));
43 // unless we use cascade to drop
44 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test CASCADE;"));
45 // drop schema if exists should not fail if schema does not exist
46 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA IF EXISTS test;"));
47 // but drop schema without it should fail
48 REQUIRE_FAIL(con.Query("DROP SCHEMA test;"));
49}
50
51TEST_CASE("Schema creation/deletion with transactions", "[catalog]") {
52 unique_ptr<QueryResult> result;
53 DuckDB db(nullptr);
54 Connection con(db);
55
56 // create a schema with a table
57 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA test;"));
58 REQUIRE_NO_FAIL(con.Query("CREATE TABLE test.hello(i INTEGER);"));
59
60 // in one transaction drop the table and then the schema (without cascade)
61 REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;"));
62 REQUIRE_NO_FAIL(con.Query("DROP TABLE test.hello;"));
63 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test;"));
64 REQUIRE_NO_FAIL(con.Query("COMMIT;"));
65
66 // now work with multiple connections
67 Connection con2(db);
68
69 // create the same schema
70 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA test;"));
71 REQUIRE_NO_FAIL(con.Query("CREATE TABLE test.hello(i INTEGER);"));
72 REQUIRE_NO_FAIL(con.Query("INSERT INTO test.hello VALUES (2), (3), (4)"));
73
74 // begin the transactions
75 REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION"));
76 REQUIRE_NO_FAIL(con2.Query("BEGIN TRANSACTION"));
77
78 // con1 drops the schema and commits it
79 REQUIRE_NO_FAIL(con.Query("DROP TABLE test.hello;"));
80 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test;"));
81 REQUIRE_NO_FAIL(con.Query("COMMIT;"));
82
83 // con2 queries the schema (should still work)
84 result = con2.Query("SELECT * FROM test.hello");
85 REQUIRE(CHECK_COLUMN(result, 0, {2, 3, 4}));
86
87 // now con2 finishes the transaction and tries again
88 REQUIRE_NO_FAIL(con2.Query("ROLLBACK;"));
89 REQUIRE_FAIL(con2.Query("SELECT * FROM test.hello"));
90}
91
92TEST_CASE("Catalog conflicts", "[catalog]") {
93 unique_ptr<QueryResult> result;
94 DuckDB db(nullptr);
95 Connection con(db), con2(db);
96
97 REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;"));
98 REQUIRE_NO_FAIL(con2.Query("BEGIN TRANSACTION;"));
99
100 // create the same schema in both connections
101 REQUIRE_NO_FAIL(con.Query("CREATE SCHEMA test;"));
102 // this should cause a conflict
103 REQUIRE_FAIL(con2.Query("CREATE SCHEMA test;"));
104
105 REQUIRE_NO_FAIL(con.Query("COMMIT"));
106 REQUIRE_NO_FAIL(con2.Query("ROLLBACK"));
107
108 // now try the same with DROP SCHEMA
109 REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION;"));
110 REQUIRE_NO_FAIL(con2.Query("BEGIN TRANSACTION;"));
111
112 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test;"));
113 // this should cause a conflict
114 REQUIRE_FAIL(con2.Query("DROP SCHEMA test;"));
115
116 // rollback the drop
117 REQUIRE_NO_FAIL(con.Query("ROLLBACK"));
118 REQUIRE_NO_FAIL(con2.Query("ROLLBACK"));
119
120 // now the schema should still exist, so we can drop it again
121 REQUIRE_NO_FAIL(con.Query("DROP SCHEMA test;"));
122}
123