1 #include <pqxx/nontransaction>
2 #include <pqxx/robusttransaction>
3 
4 #include "../test_helpers.hxx"
5 
6 
7 namespace
8 {
test_nontransaction_continues_after_error()9 void test_nontransaction_continues_after_error()
10 {
11   pqxx::connection c;
12   pqxx::nontransaction tx{c};
13 
14   PQXX_CHECK_EQUAL(
15     tx.query_value<int>("SELECT 9"), 9, "Simple query went wrong.");
16   PQXX_CHECK_THROWS(
17     tx.exec("SELECT 1/0"), pqxx::sql_error, "Expected error did not happen.");
18 
19   PQXX_CHECK_EQUAL(
20     tx.query_value<int>("SELECT 5"), 5, "Wrong result after error.");
21 }
22 
23 
24 std::string const table{"pqxx_test_transaction"};
25 
26 
delete_temp_table(pqxx::transaction_base & tx)27 void delete_temp_table(pqxx::transaction_base &tx)
28 {
29   tx.exec0("DROP TABLE IF EXISTS " + table);
30 }
31 
32 
create_temp_table(pqxx::transaction_base & tx)33 void create_temp_table(pqxx::transaction_base &tx)
34 {
35   tx.exec0("CREATE TEMP TABLE " + table + " (x integer)");
36 }
37 
38 
insert_temp_table(pqxx::transaction_base & tx,int value)39 void insert_temp_table(pqxx::transaction_base &tx, int value)
40 {
41   tx.exec0(
42     "INSERT INTO " + table + " (x) VALUES (" + pqxx::to_string(value) + ")");
43 }
44 
count_temp_table(pqxx::transaction_base & tx)45 int count_temp_table(pqxx::transaction_base &tx)
46 {
47   return tx.query_value<int>("SELECT count(*) FROM " + table);
48 }
49 
50 
test_db_transaction_rolls_back()51 template<typename TX> void test_db_transaction_rolls_back()
52 {
53   pqxx::connection c;
54   pqxx::nontransaction tx1{c};
55   delete_temp_table(tx1);
56   create_temp_table(tx1);
57   tx1.commit();
58 
59   TX tx2{c};
60   insert_temp_table(tx2, 32);
61   tx2.abort();
62 
63   pqxx::nontransaction tx3{c};
64   PQXX_CHECK_EQUAL(
65     count_temp_table(tx3), 0,
66     "Abort on " + tx3.classname() + " did not roll back.");
67   delete_temp_table(tx3);
68 }
69 
70 
test_nontransaction_autocommits()71 void test_nontransaction_autocommits()
72 {
73   pqxx::connection c;
74 
75   pqxx::nontransaction tx1{c};
76   delete_temp_table(tx1);
77   create_temp_table(tx1);
78   tx1.commit();
79 
80   pqxx::nontransaction tx2{c};
81   insert_temp_table(tx2, 4);
82   tx2.abort();
83 
84   pqxx::nontransaction tx3{c};
85   PQXX_CHECK_EQUAL(
86     count_temp_table(tx3), 1,
87     "Did not keep effect of aborted nontransaction.");
88   delete_temp_table(tx3);
89 }
90 
91 
test_double_close()92 template<typename TX> void test_double_close()
93 {
94   pqxx::connection c;
95 
96   TX tx1{c};
97   tx1.exec1("SELECT 1");
98   tx1.commit();
99   tx1.commit();
100 
101   TX tx2{c};
102   tx2.exec1("SELECT 2");
103   tx2.abort();
104   tx2.abort();
105 
106   TX tx3{c};
107   tx3.exec1("SELECT 3");
108   tx3.commit();
109   PQXX_CHECK_THROWS(
110     tx3.abort(), pqxx::usage_error, "Abort after commit not caught.");
111   ;
112 
113   TX tx4{c};
114   tx4.exec1("SELECT 4");
115   tx4.abort();
116   PQXX_CHECK_THROWS(
117     tx4.commit(), pqxx::usage_error, "Commit after abort not caught.");
118 }
119 
120 
test_transaction()121 void test_transaction()
122 {
123   test_nontransaction_continues_after_error();
124   test_nontransaction_autocommits();
125   test_double_close<pqxx::transaction<>>();
126   test_double_close<pqxx::read_transaction>();
127   test_double_close<pqxx::nontransaction>();
128   test_double_close<pqxx::robusttransaction<>>();
129 }
130 
131 
132 PQXX_REGISTER_TEST(test_transaction);
133 } // namespace
134