test07.cxx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include <iostream>
  2. #include <map>
  3. #include <pqxx/transaction>
  4. #include <pqxx/transactor>
  5. #include "test_helpers.hxx"
  6. using namespace pqxx;
  7. // Example program for libpqxx. Modify the database, retaining transactional
  8. // integrity using the transactor framework.
  9. //
  10. // This assumes the existence of a database table "pqxxevents" containing a
  11. // 2-digit "year" field, which is extended to a 4-digit format by assuming all
  12. // year numbers of 70 or higher are in the 20th century, and all others in the
  13. // 21st, and that no years before 1970 are possible.
  14. namespace
  15. {
  16. // Convert year to 4-digit format.
  17. int To4Digits(int Y)
  18. {
  19. int Result{Y};
  20. PQXX_CHECK(Y >= 0, "Negative year: " + to_string(Y));
  21. if (Y < 70)
  22. Result += 2000;
  23. else if (Y < 100)
  24. Result += 1900;
  25. else if (Y < 1970)
  26. PQXX_CHECK_NOTREACHED("Unexpected year: " + to_string(Y));
  27. return Result;
  28. }
  29. void test_007()
  30. {
  31. connection conn;
  32. conn.set_client_encoding("SQL_ASCII");
  33. {
  34. work tx{conn};
  35. test::create_pqxxevents(tx);
  36. tx.commit();
  37. }
  38. // Perform (an instantiation of) the UpdateYears transactor we've defined
  39. // in the code above. This is where the work gets done.
  40. std::map<int, int> conversions;
  41. perform([&conversions, &conn] {
  42. work tx{conn};
  43. // First select all different years occurring in the table.
  44. result R(tx.exec("SELECT year FROM pqxxevents"));
  45. // See if we get reasonable type identifier for this column.
  46. oid const rctype{R.column_type(0)};
  47. PQXX_CHECK_EQUAL(
  48. R.column_type(pqxx::row::size_type(0)), rctype,
  49. "Inconsistent result::column_type().");
  50. std::string const rct{to_string(rctype)};
  51. PQXX_CHECK(rctype > 0, "Got strange type ID for column: " + rct);
  52. std::string const rcol{R.column_name(0)};
  53. PQXX_CHECK(not std::empty(rcol), "Didn't get a name for column.");
  54. oid const rcctype{R.column_type(rcol)};
  55. PQXX_CHECK_EQUAL(
  56. rcctype, rctype, "Column type is not what it is by name.");
  57. oid const rawrcctype{R.column_type(rcol)};
  58. PQXX_CHECK_EQUAL(
  59. rawrcctype, rctype, "Column type by C-style name is different.");
  60. // Note all different years currently occurring in the table, writing
  61. // them and their correct mappings to conversions.
  62. for (auto const &r : R)
  63. {
  64. int Y{0};
  65. // Read year, and if it is non-null, note its converted value
  66. if (r[0] >> Y)
  67. conversions[Y] = To4Digits(Y);
  68. // See if type identifiers are consistent
  69. oid const tctype{r.column_type(0)};
  70. PQXX_CHECK_EQUAL(
  71. tctype, r.column_type(pqxx::row::size_type(0)),
  72. "Inconsistent pqxx::row::column_type()");
  73. PQXX_CHECK_EQUAL(
  74. tctype, rctype,
  75. "pqxx::row::column_type() is inconsistent with "
  76. "result::column_type().");
  77. oid const ctctype{r.column_type(rcol)};
  78. PQXX_CHECK_EQUAL(
  79. ctctype, rctype, "Column type lookup by column name is broken.");
  80. oid const rawctctype{r.column_type(rcol)};
  81. PQXX_CHECK_EQUAL(
  82. rawctctype, rctype, "Column type lookup by C-style name is broken.");
  83. oid const fctype{r[0].type()};
  84. PQXX_CHECK_EQUAL(fctype, rctype, "Field type lookup is broken.");
  85. }
  86. // For each occurring year, write converted date back to whereever it may
  87. // occur in the table. Since we're in a transaction, any changes made by
  88. // others at the same time will not affect us.
  89. for (auto const &c : conversions)
  90. {
  91. auto const query{
  92. "UPDATE pqxxevents "
  93. "SET year=" +
  94. to_string(c.second) +
  95. " "
  96. "WHERE year=" +
  97. to_string(c.first)};
  98. R = tx.exec0(query);
  99. }
  100. });
  101. }
  102. PQXX_REGISTER_TEST(test_007);
  103. } // namespace