test_result_iteration.cxx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include <pqxx/stream_to>
  2. #include <pqxx/transaction>
  3. #include "../test_helpers.hxx"
  4. namespace
  5. {
  6. void test_result_iteration()
  7. {
  8. pqxx::connection conn;
  9. pqxx::work tx{conn};
  10. pqxx::result r{tx.exec("SELECT generate_series(1, 3)")};
  11. PQXX_CHECK(std::end(r) != std::begin(r), "Broken begin/end.");
  12. PQXX_CHECK(std::rend(r) != std::rbegin(r), "Broken rbegin/rend.");
  13. PQXX_CHECK(std::cbegin(r) == std::begin(r), "Wrong cbegin.");
  14. PQXX_CHECK(std::cend(r) == std::end(r), "Wrong cend.");
  15. PQXX_CHECK(std::crbegin(r) == std::rbegin(r), "Wrong crbegin.");
  16. PQXX_CHECK(std::crend(r) == std::rend(r), "Wrong crend.");
  17. PQXX_CHECK_EQUAL(r.front().front().as<int>(), 1, "Unexpected front().");
  18. PQXX_CHECK_EQUAL(r.back().front().as<int>(), 3, "Unexpected back().");
  19. }
  20. void test_result_iter()
  21. {
  22. pqxx::connection conn;
  23. pqxx::work tx{conn};
  24. pqxx::result r{tx.exec("SELECT generate_series(1, 3)")};
  25. int total{0};
  26. for (auto const &[i] : r.iter<int>()) total += i;
  27. PQXX_CHECK_EQUAL(total, 6, "iter() loop did not get the right values.");
  28. }
  29. void test_result_iterator_swap()
  30. {
  31. pqxx::connection conn;
  32. pqxx::work tx{conn};
  33. pqxx::result r{tx.exec("SELECT generate_series(1, 3)")};
  34. auto head{std::begin(r)}, next{head + 1};
  35. head.swap(next);
  36. PQXX_CHECK_EQUAL(head[0].as<int>(), 2, "Result iterator swap is wrong.");
  37. PQXX_CHECK_EQUAL(next[0].as<int>(), 1, "Result iterator swap is crazy.");
  38. auto tail{std::rbegin(r)}, prev{tail + 1};
  39. tail.swap(prev);
  40. PQXX_CHECK_EQUAL(tail[0].as<int>(), 2, "Reverse iterator swap is wrong.");
  41. PQXX_CHECK_EQUAL(prev[0].as<int>(), 3, "Reverse iterator swap is crazy.");
  42. }
  43. void test_result_iterator_assignment()
  44. {
  45. pqxx::connection conn;
  46. pqxx::work tx{conn};
  47. pqxx::result r{tx.exec("SELECT generate_series(1, 3)")};
  48. pqxx::result::const_iterator fwd;
  49. pqxx::result::const_reverse_iterator rev;
  50. fwd = std::begin(r);
  51. PQXX_CHECK_EQUAL(
  52. fwd[0].as<int>(), std::begin(r)[0].as<int>(),
  53. "Result iterator assignment is wrong.");
  54. rev = std::rbegin(r);
  55. PQXX_CHECK_EQUAL(
  56. rev[0].as<int>(), std::rbegin(r)[0].as<int>(),
  57. "Reverse iterator assignment is wrong.");
  58. }
  59. void check_employee(std::string name, int salary)
  60. {
  61. PQXX_CHECK(name == "x" or name == "y" or name == "z", "Unknown name.");
  62. PQXX_CHECK(
  63. salary == 1000 or salary == 1200 or salary == 1500, "Unknown salary.");
  64. }
  65. void test_result_for_each()
  66. {
  67. pqxx::connection conn;
  68. pqxx::work tx{conn};
  69. tx.exec0("CREATE TEMP TABLE employee(name varchar, salary int)");
  70. auto fill{pqxx::stream_to::table(tx, {"employee"}, {"name", "salary"})};
  71. fill.write_values("x", 1000);
  72. fill.write_values("y", 1200);
  73. fill.write_values("z", 1500);
  74. fill.complete();
  75. auto const res{tx.exec("SELECT name, salary FROM employee ORDER BY name")};
  76. // Use for_each with a function.
  77. res.for_each(check_employee);
  78. // Use for_each with a simple lambda.
  79. res.for_each(
  80. [](std::string name, int salary) { check_employee(name, salary); });
  81. // Use for_each with a lambda closure.
  82. std::string names{};
  83. int total{0};
  84. res.for_each([&names, &total](std::string name, int salary) {
  85. names.append(name);
  86. total += salary;
  87. });
  88. PQXX_CHECK_EQUAL(
  89. names, "xyz", "result::for_each did not accumulate names correctly.");
  90. PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500, "Salaries added up wrong.");
  91. // In addition to regular conversions, you can receive arguments as
  92. // string_view, or as references.
  93. names.clear();
  94. total = 0;
  95. res.for_each([&names, &total](std::string_view &&name, int const &salary) {
  96. names.append(name);
  97. total += salary;
  98. });
  99. PQXX_CHECK_EQUAL(
  100. names, "xyz", "result::for_each did not accumulate names correctly.");
  101. PQXX_CHECK_EQUAL(total, 1000 + 1200 + 1500, "Salaries added up wrong.");
  102. }
  103. PQXX_REGISTER_TEST(test_result_iteration);
  104. PQXX_REGISTER_TEST(test_result_iter);
  105. PQXX_REGISTER_TEST(test_result_iterator_swap);
  106. PQXX_REGISTER_TEST(test_result_iterator_assignment);
  107. PQXX_REGISTER_TEST(test_result_for_each);
  108. } // namespace