| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- #include <iostream>
- #include <map>
- #include <pqxx/transaction>
- #include <pqxx/transactor>
- #include "test_helpers.hxx"
- using namespace pqxx;
- // Example program for libpqxx. Modify the database, retaining transactional
- // integrity using the transactor framework.
- //
- // This assumes the existence of a database table "pqxxevents" containing a
- // 2-digit "year" field, which is extended to a 4-digit format by assuming all
- // year numbers of 70 or higher are in the 20th century, and all others in the
- // 21st, and that no years before 1970 are possible.
- namespace
- {
- // Convert year to 4-digit format.
- int To4Digits(int Y)
- {
- int Result{Y};
- PQXX_CHECK(Y >= 0, "Negative year: " + to_string(Y));
- if (Y < 70)
- Result += 2000;
- else if (Y < 100)
- Result += 1900;
- else if (Y < 1970)
- PQXX_CHECK_NOTREACHED("Unexpected year: " + to_string(Y));
- return Result;
- }
- void test_007()
- {
- connection conn;
- conn.set_client_encoding("SQL_ASCII");
- {
- work tx{conn};
- test::create_pqxxevents(tx);
- tx.commit();
- }
- // Perform (an instantiation of) the UpdateYears transactor we've defined
- // in the code above. This is where the work gets done.
- std::map<int, int> conversions;
- perform([&conversions, &conn] {
- work tx{conn};
- // First select all different years occurring in the table.
- result R(tx.exec("SELECT year FROM pqxxevents"));
- // See if we get reasonable type identifier for this column.
- oid const rctype{R.column_type(0)};
- PQXX_CHECK_EQUAL(
- R.column_type(pqxx::row::size_type(0)), rctype,
- "Inconsistent result::column_type().");
- std::string const rct{to_string(rctype)};
- PQXX_CHECK(rctype > 0, "Got strange type ID for column: " + rct);
- std::string const rcol{R.column_name(0)};
- PQXX_CHECK(not std::empty(rcol), "Didn't get a name for column.");
- oid const rcctype{R.column_type(rcol)};
- PQXX_CHECK_EQUAL(
- rcctype, rctype, "Column type is not what it is by name.");
- oid const rawrcctype{R.column_type(rcol)};
- PQXX_CHECK_EQUAL(
- rawrcctype, rctype, "Column type by C-style name is different.");
- // Note all different years currently occurring in the table, writing
- // them and their correct mappings to conversions.
- for (auto const &r : R)
- {
- int Y{0};
- // Read year, and if it is non-null, note its converted value
- if (r[0] >> Y)
- conversions[Y] = To4Digits(Y);
- // See if type identifiers are consistent
- oid const tctype{r.column_type(0)};
- PQXX_CHECK_EQUAL(
- tctype, r.column_type(pqxx::row::size_type(0)),
- "Inconsistent pqxx::row::column_type()");
- PQXX_CHECK_EQUAL(
- tctype, rctype,
- "pqxx::row::column_type() is inconsistent with "
- "result::column_type().");
- oid const ctctype{r.column_type(rcol)};
- PQXX_CHECK_EQUAL(
- ctctype, rctype, "Column type lookup by column name is broken.");
- oid const rawctctype{r.column_type(rcol)};
- PQXX_CHECK_EQUAL(
- rawctctype, rctype, "Column type lookup by C-style name is broken.");
- oid const fctype{r[0].type()};
- PQXX_CHECK_EQUAL(fctype, rctype, "Field type lookup is broken.");
- }
- // For each occurring year, write converted date back to whereever it may
- // occur in the table. Since we're in a transaction, any changes made by
- // others at the same time will not affect us.
- for (auto const &c : conversions)
- {
- auto const query{
- "UPDATE pqxxevents "
- "SET year=" +
- to_string(c.second) +
- " "
- "WHERE year=" +
- to_string(c.first)};
- R = tx.exec0(query);
- }
- });
- }
- PQXX_REGISTER_TEST(test_007);
- } // namespace
|