test88.cxx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include <iostream>
  2. #include <pqxx/subtransaction>
  3. #include <pqxx/transaction>
  4. #include "test_helpers.hxx"
  5. // Test program for libpqxx. Attempt to perform nested transactions.
  6. namespace
  7. {
  8. void test_088()
  9. {
  10. pqxx::connection conn;
  11. pqxx::work tx0{conn};
  12. pqxx::test::create_pqxxevents(tx0);
  13. // Trivial test: create subtransactions, and commit/abort
  14. std::cout << tx0.exec1("SELECT 'tx0 starts'")[0].c_str() << std::endl;
  15. pqxx::subtransaction T0a(static_cast<pqxx::dbtransaction &>(tx0), "T0a");
  16. T0a.commit();
  17. pqxx::subtransaction T0b(static_cast<pqxx::dbtransaction &>(tx0), "T0b");
  18. T0b.abort();
  19. std::cout << tx0.exec1("SELECT 'tx0 ends'")[0].c_str() << std::endl;
  20. tx0.commit();
  21. // Basic functionality: perform query in subtransaction; abort, continue
  22. pqxx::work tx1{conn, "tx1"};
  23. std::cout << tx1.exec1("SELECT 'tx1 starts'")[0].c_str() << std::endl;
  24. pqxx::subtransaction tx1a{tx1, "tx1a"};
  25. std::cout << tx1a.exec1("SELECT ' a'")[0].c_str() << std::endl;
  26. tx1a.commit();
  27. pqxx::subtransaction tx1b{tx1, "tx1b"};
  28. std::cout << tx1b.exec1("SELECT ' b'")[0].c_str() << std::endl;
  29. tx1b.abort();
  30. pqxx::subtransaction tx1c{tx1, "tx1c"};
  31. std::cout << tx1c.exec1("SELECT ' c'")[0].c_str() << std::endl;
  32. tx1c.commit();
  33. std::cout << tx1.exec1("SELECT 'tx1 ends'")[0].c_str() << std::endl;
  34. tx1.commit();
  35. // Commit/rollback functionality
  36. pqxx::work tx2{conn, "tx2"};
  37. std::string const Table{"test088"};
  38. tx2.exec0("CREATE TEMP TABLE " + Table + "(no INTEGER, text VARCHAR)");
  39. tx2.exec0("INSERT INTO " + Table + " VALUES(1,'tx2')");
  40. pqxx::subtransaction tx2a{tx2, "tx2a"};
  41. tx2a.exec0("INSERT INTO " + Table + " VALUES(2,'tx2a')");
  42. tx2a.commit();
  43. pqxx::subtransaction tx2b{tx2, "tx2b"};
  44. tx2b.exec0("INSERT INTO " + Table + " VALUES(3,'tx2b')");
  45. tx2b.abort();
  46. pqxx::subtransaction tx2c{tx2, "tx2c"};
  47. tx2c.exec0("INSERT INTO " + Table + " VALUES(4,'tx2c')");
  48. tx2c.commit();
  49. auto const R{tx2.exec("SELECT * FROM " + Table + " ORDER BY no")};
  50. for (auto const &i : R)
  51. std::cout << '\t' << i[0].c_str() << '\t' << i[1].c_str() << std::endl;
  52. PQXX_CHECK_EQUAL(std::size(R), 3, "Wrong number of results.");
  53. int expected[3]{1, 2, 4};
  54. for (pqxx::result::size_type n{0}; n < std::size(R); ++n)
  55. PQXX_CHECK_EQUAL(
  56. R[n][0].as<int>(), expected[n], "Hit unexpected row number.");
  57. tx2.abort();
  58. // Auto-abort should only roll back the subtransaction.
  59. pqxx::work tx3{conn, "tx3"};
  60. pqxx::subtransaction tx3a(tx3, "tx3a");
  61. PQXX_CHECK_THROWS(
  62. tx3a.exec("SELECT * FROM nonexistent_table WHERE nonattribute=0"),
  63. pqxx::sql_error, "Bogus query did not fail.");
  64. // Subtransaction can only be aborted now, because there was an error.
  65. tx3a.abort();
  66. // We're back in our top-level transaction. This did not abort.
  67. tx3.exec1("SELECT count(*) FROM pqxxevents");
  68. // Make sure we can commit exactly one more level of transaction.
  69. tx3.commit();
  70. }
  71. } // namespace
  72. PQXX_REGISTER_TEST(test_088);