test_composite.cxx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "../test_helpers.hxx"
  2. #include "pqxx/composite"
  3. #include "pqxx/transaction"
  4. namespace
  5. {
  6. void test_composite()
  7. {
  8. pqxx::connection conn;
  9. pqxx::work tx{conn};
  10. tx.exec0("CREATE TYPE pqxxfoo AS (a integer, b text)");
  11. auto const r{tx.exec1("SELECT '(5,hello)'::pqxxfoo")};
  12. int a;
  13. std::string b;
  14. pqxx::parse_composite(r[0].view(), a, b);
  15. PQXX_CHECK_EQUAL(a, 5, "Integer composite field came back wrong.");
  16. PQXX_CHECK_EQUAL(b, "hello", "String composite field came back wrong.");
  17. }
  18. void test_composite_escapes()
  19. {
  20. pqxx::connection conn;
  21. pqxx::work tx{conn};
  22. pqxx::row r;
  23. tx.exec0("CREATE TYPE pqxxsingle AS (x text)");
  24. std::string s;
  25. r = tx.exec1(R"--(SELECT '("a""b")'::pqxxsingle)--");
  26. pqxx::parse_composite(r[0].view(), s);
  27. PQXX_CHECK_EQUAL(
  28. s, "a\"b", "Double-double-quotes escaping did not parse correctly.");
  29. r = tx.exec1(R"--(SELECT '("a\"b")'::pqxxsingle)--");
  30. pqxx::parse_composite(r[0].view(), s);
  31. PQXX_CHECK_EQUAL(s, "a\"b", "Backslash escaping did not parse correctly.");
  32. }
  33. void test_composite_handles_nulls()
  34. {
  35. pqxx::connection conn;
  36. pqxx::work tx{conn};
  37. pqxx::row r;
  38. tx.exec0("CREATE TYPE pqxxnull AS (a integer)");
  39. int nonnull;
  40. r = tx.exec1("SELECT '()'::pqxxnull");
  41. PQXX_CHECK_THROWS(
  42. pqxx::parse_composite(r[0].view(), nonnull), pqxx::conversion_error,
  43. "No conversion error when reading a null into a nulless variable.");
  44. std::optional<int> nullable{5};
  45. pqxx::parse_composite(r[0].view(), nullable);
  46. PQXX_CHECK(
  47. not nullable.has_value(), "Null integer came out as having a value.");
  48. tx.exec0("CREATE TYPE pqxxnulls AS (a integer, b integer)");
  49. std::optional<int> a{2}, b{4};
  50. r = tx.exec1("SELECT '(,)'::pqxxnulls");
  51. pqxx::parse_composite(r[0].view(), a, b);
  52. PQXX_CHECK(not a.has_value(), "Null first integer stored as value.");
  53. PQXX_CHECK(not b.has_value(), "Null second integer stored as value.");
  54. }
  55. void test_composite_renders_to_string()
  56. {
  57. pqxx::connection conn;
  58. pqxx::work tx{conn};
  59. char buf[1000];
  60. pqxx::composite_into_buf(
  61. std::begin(buf), std::end(buf), 355, "foo", "b\na\\r");
  62. PQXX_CHECK_EQUAL(
  63. std::string{buf}, "(355,\"foo\",\"b\na\\\\r\")",
  64. "Composite was not rendered as expected.");
  65. tx.exec0("CREATE TYPE pqxxcomp AS (a integer, b text, c text)");
  66. auto const r{tx.exec1("SELECT '" + std::string{buf} + "'::pqxxcomp")};
  67. int a;
  68. std::string b, c;
  69. bool const nonnull{r[0].composite_to(a, b, c)};
  70. PQXX_CHECK(nonnull, "Mistaken nullness.");
  71. PQXX_CHECK_EQUAL(a, 355, "Int came back wrong.");
  72. PQXX_CHECK_EQUAL(b, "foo", "Simple string came back wrong.");
  73. PQXX_CHECK_EQUAL(c, "b\na\\r", "Escaping went wrong.");
  74. }
  75. PQXX_REGISTER_TEST(test_composite);
  76. PQXX_REGISTER_TEST(test_composite_escapes);
  77. PQXX_REGISTER_TEST(test_composite_handles_nulls);
  78. PQXX_REGISTER_TEST(test_composite_renders_to_string);
  79. } // namespace