1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
#include <cstdio>
#include <vector>
#include "test_helpers.hxx"
using namespace PGSTD;
using namespace pqxx;
// Test program for libpqxx. See which fields in a query are null, and figure
// out whether any fields are lexicographically sorted.
namespace
{
template<typename VEC, typename VAL>
void InitVector(VEC &V, typename VEC::size_type s, VAL val)
{
V.resize(s);
for (typename VEC::iterator i = V.begin(); i != V.end(); ++i) *i = val;
}
void test_012(transaction_base &orgT)
{
connection_base &C(orgT.conn());
orgT.abort();
const string Table = "pg_tables";
// Tell C we won't be needing it for a while (not true, but let's pretend)
C.deactivate();
// Now set up some data structures
vector<int> NullFields; // Maps column to no. of null fields
vector<bool> SortedUp, SortedDown; // Does column appear to be sorted?
// ...And reactivate C (not really needed, but it sounds more polite)
C.activate();
work T(C, "test12");
result R( T.exec("SELECT * FROM " + Table) );
InitVector(NullFields, R.columns(), 0);
InitVector(SortedUp, R.columns(), true);
InitVector(SortedDown, R.columns(), true);
for (result::const_iterator i = R.begin(); i != R.end(); i++)
{
PQXX_CHECK_EQUAL(
(*i).rownumber(),
i->rownumber(),
"Inconsistent row numbers for operator*() and operator->().");
PQXX_CHECK_EQUAL(i->size(), R.columns(), "Inconsistent row size.");
// Look for null fields
for (pqxx::tuple::size_type f=0; f<i->size(); ++f)
{
NullFields[f] += i.at(f).is_null();
string A, B;
PQXX_CHECK_EQUAL(
i[f].to(A),
i[f].to(B, string("")),
"Variants of to() disagree on nullness.");
PQXX_CHECK_EQUAL(A, B, "Inconsistent field contents.");
}
// Compare fields to those of preceding row
if (i != R.begin())
{
const result::const_iterator j = i - 1;
// First perform some sanity checks on j vs. i and how libpqxx handles
// their interrelationship...
PQXX_CHECK_EQUAL(i - j, 1, "Iterator is wrong distance from successor.");
PQXX_CHECK(!(j == i), "Iterator equals its successor.");
PQXX_CHECK(j != i, "Iterator inequality is inconsistent.");
PQXX_CHECK(!(j >= i), "Iterator doesn't come before its successor.");
PQXX_CHECK(!(j > i), "Iterator is preceded by its successor.");
PQXX_CHECK(!(i <= j), "Iterator doesn't come after its predecessor.");
PQXX_CHECK(!(i < j), "Iterator is succeded by its predecessor.");
PQXX_CHECK(j <= i, "operator<=() doesn't mirror operator>=().");
PQXX_CHECK(j < i, "operator<() doesn't mirror operator>().");
PQXX_CHECK_EQUAL(1 + j, i, "Adding 1 doesn't reach successor.");
result::const_iterator k(i);
PQXX_CHECK_EQUAL(k--, i, "Post-increment returns wrong iterator.");
PQXX_CHECK_EQUAL(k, j, "Bad iterator position after post-increment.");
result::const_iterator l(i);
PQXX_CHECK_EQUAL(--l, j, "Pre-increment returns wrong iterator.");
PQXX_CHECK_EQUAL(l, j, "Pre-increment sets wrong iterator position.");
PQXX_CHECK_EQUAL(k += 1, i, "Wrong return value from +=.");
PQXX_CHECK_EQUAL(k, i, "Bad iterator position after +=.");
PQXX_CHECK_EQUAL(k -= 1, j, "Wrong return value from -=.");
PQXX_CHECK_EQUAL(k, j, "Bad iterator position after -=.");
// ...Now let's do meaningful stuff with j, such as finding out which
// fields may be sorted. Don't do anything fancy like trying to
// detect numbers and comparing them as such, just compare them as
// simple strings.
for (pqxx::tuple::size_type f = 0; f < R.columns(); ++f)
{
if (!j[f].is_null())
{
const bool U = SortedUp[f],
D = SortedDown[f];
SortedUp[f] = U & (string(j[f].c_str()) <= string(i[f].c_str()));
SortedDown[f] = D & (string(j[f].c_str()) >= string(i[f].c_str()));
}
}
}
}
for (pqxx::tuple::size_type f = 0; f < R.columns(); ++f)
PQXX_CHECK(
NullFields[f] <= int(R.size()),
"Found more nulls than there were rows.");
}
} // namespace
PQXX_REGISTER_TEST_T(test_012, nontransaction)
|