1 | #include "catch.hpp" |
2 | #include "test_helpers.hpp" |
3 | |
4 | using namespace duckdb; |
5 | using namespace std; |
6 | |
7 | TEST_CASE("Test temporary catalog entry creation" , "[catalog]" ) { |
8 | unique_ptr<QueryResult> result; |
9 | |
10 | DuckDB db(nullptr); |
11 | Connection con(db); |
12 | |
13 | // basic temp table creation works |
14 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE integers(i INTEGER) ON COMMIT PRESERVE ROWS" )); |
15 | // we can (but never are required to) prefix temp tables with "temp" schema |
16 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE integersx(i INTEGER)" )); |
17 | // we can't prefix temp tables with a schema that is not "temp" |
18 | REQUIRE_FAIL(con.Query("CREATE TEMPORARY TABLE asdf.integersy(i INTEGER)" )); |
19 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE s1 AS SELECT 42" )); |
20 | |
21 | REQUIRE_FAIL(con.Query("CREATE TABLE temp.integersy(i INTEGER)" )); |
22 | |
23 | REQUIRE_FAIL(con.Query("CREATE SCHEMA temp" )); |
24 | |
25 | REQUIRE_FAIL(con.Query("DROP TABLE main.integersx" )); |
26 | REQUIRE_NO_FAIL(con.Query("DROP TABLE integersx" )); |
27 | |
28 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE temp.integersx(i INTEGER)" )); |
29 | REQUIRE_NO_FAIL(con.Query("DROP TABLE temp.integersx" )); |
30 | |
31 | // unsupported because stupid |
32 | REQUIRE_FAIL(con.Query("CREATE TEMPORARY TABLE integers2(i INTEGER) ON COMMIT DELETE ROWS" )); |
33 | |
34 | // temp table already exists |
35 | REQUIRE_FAIL(con.Query("CREATE TEMPORARY TABLE integers(i INTEGER)" )); |
36 | |
37 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers VALUES (42)" )); |
38 | result = con.Query("SELECT i from integers" ); |
39 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
40 | |
41 | // temp table survives commit |
42 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION" )); |
43 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE integers2(i INTEGER)" )); |
44 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY SEQUENCE seq" )); |
45 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY VIEW v1 AS SELECT 42" )); |
46 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers2 VALUES (42)" )); |
47 | result = con.Query("SELECT i from integers2" ); |
48 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
49 | result = con.Query("SELECT nextval('seq')" ); |
50 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
51 | result = con.Query("SELECT * from v1" ); |
52 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
53 | REQUIRE_NO_FAIL(con.Query("COMMIT" )); |
54 | |
55 | result = con.Query("SELECT i from integers2" ); |
56 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
57 | result = con.Query("SELECT nextval('seq')" ); |
58 | REQUIRE(CHECK_COLUMN(result, 0, {2})); |
59 | result = con.Query("SELECT * from v1" ); |
60 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
61 | |
62 | // temp table does not survive rollback |
63 | REQUIRE_NO_FAIL(con.Query("BEGIN TRANSACTION" )); |
64 | REQUIRE_NO_FAIL(con.Query("CREATE TEMPORARY TABLE integers3(i INTEGER)" )); |
65 | REQUIRE_NO_FAIL(con.Query("INSERT INTO integers3 VALUES (42)" )); |
66 | result = con.Query("SELECT i from integers3" ); |
67 | REQUIRE(CHECK_COLUMN(result, 0, {42})); |
68 | REQUIRE_NO_FAIL(con.Query("ROLLBACK" )); |
69 | |
70 | REQUIRE_FAIL(con.Query("SELECT i from integers3" )); |
71 | |
72 | Connection con2(db); |
73 | // table is not visible to other cons |
74 | REQUIRE_FAIL(con2.Query("INSERT INTO integers VALUES (42)" )); |
75 | } |
76 | |
77 | TEST_CASE("Test persistent temporary structures" , "[catalog]" ) { |
78 | unique_ptr<QueryResult> result; |
79 | |
80 | // see if temp tables survive restart |
81 | FileSystem fs; |
82 | string db_folder = TestCreatePath("temptbls" ); |
83 | |
84 | { |
85 | DuckDB db_p(db_folder); |
86 | Connection con_p(db_p); |
87 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY TABLE temp.a (i INTEGER)" )); |
88 | REQUIRE_NO_FAIL(con_p.Query("INSERT INTO a VALUES (42)" )); |
89 | REQUIRE_NO_FAIL(con_p.Query("DELETE FROM a" )); |
90 | REQUIRE_NO_FAIL(con_p.Query("DELETE FROM temp.a" )); |
91 | REQUIRE_FAIL(con_p.Query("DELETE FROM asdf.a" )); |
92 | |
93 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY SEQUENCE seq" )); |
94 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY SEQUENCE seq2" )); |
95 | REQUIRE_NO_FAIL(con_p.Query("DROP SEQUENCE seq2" )); |
96 | |
97 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY VIEW v1 AS SELECT 42" )); |
98 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY VIEW v2 AS SELECT 42" )); |
99 | REQUIRE_NO_FAIL(con_p.Query("DROP VIEW v2" )); |
100 | |
101 | REQUIRE_NO_FAIL(con_p.Query("INSERT INTO temp.a VALUES (43)" )); |
102 | |
103 | REQUIRE_NO_FAIL(con_p.Query("UPDATE temp.a SET i = 44" )); |
104 | REQUIRE_NO_FAIL(con_p.Query("UPDATE a SET i = 45" )); |
105 | |
106 | REQUIRE_NO_FAIL(con_p.Query("ALTER TABLE a RENAME COLUMN i TO k" )); |
107 | |
108 | result = con_p.Query("SELECT COUNT(k) from a" ); |
109 | REQUIRE(CHECK_COLUMN(result, 0, {1})); |
110 | } |
111 | |
112 | { |
113 | DuckDB db_p(db_folder); |
114 | Connection con_p(db_p); |
115 | REQUIRE_FAIL(con_p.Query("SELECT * FROM a" )); |
116 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY TABLE a (i INTEGER)" )); |
117 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY SEQUENCE seq" )); |
118 | REQUIRE_NO_FAIL(con_p.Query("CREATE TEMPORARY VIEW v1 AS SELECT 42" )); |
119 | |
120 | result = con_p.Query("SELECT COUNT(*) from a" ); |
121 | REQUIRE(CHECK_COLUMN(result, 0, {0})); |
122 | } |
123 | } |
124 | |