Skip to content

Commit

Permalink
Tighten the checks in get_affected_rows() unit tests
Browse files Browse the repository at this point in the history
Check that a partial update does throw an exception instead of checking
that it may throw it and check that get_affected_rows() returns the
actual number of affected rows instead of returning something non zero.

The only remaining exclusion is the PostgreSQL ODBC driver which just
seems to be buggy, notably in its versions < 13.02 when it inserted
valid rows into the database but still returned fatal error (with later
versions it doesn't insert anything, which is inconsistent with the
other drivers and unhelpful, but not quite as bad).
  • Loading branch information
vadz committed Jan 28, 2025
1 parent 6939029 commit 37535c2
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
24 changes: 9 additions & 15 deletions tests/common/test-common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3256,29 +3256,23 @@ TEST_CASE_METHOD(common_tests, "Get affected rows", "[core][affected-rows]")

CHECK(st5.get_affected_rows() == 5);

if (tc_.has_partial_update_bug())
{
WARN("Skipping partial update test due to a known backend bug");
return;
}

std::vector<std::string> w(2, "1");
w[1] = "a"; // this invalid value may cause an exception.
statement st6 = (sql.prepare <<
"insert into soci_test(val) values(:val)", use(w));
try { st6.execute(true); }
catch(...) {}
CHECK_THROWS_AS(st6.execute(true), soci_error);
CHECK(st6.get_affected_rows() == 1);

// confirm the partial insertion.
int val = 0;
sql << "select count(val) from soci_test", into(val);
if(val != 0)
{
// Notice that some ODBC drivers don't return the number of updated
// rows at all in the case of partially executed statement like this
// one, while MySQL ODBC driver wrongly returns 2 affected rows even
// though only one was actually inserted.
//
// So we can't check for "get_affected_rows() == val" here, it would
// fail in too many cases -- just check that the backend doesn't lie to
// us about no rows being affected at all (even if it just honestly
// admits that it has no idea by returning -1).
CHECK(st6.get_affected_rows() != 0);
}
CHECK(val == 1);
}

// test fix for: Backend is not set properly with connection pool (pull #5)
Expand Down
15 changes: 15 additions & 0 deletions tests/odbc/test-odbc-postgresql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,21 @@ class test_context : public test_context_common
return !m_verDriver.is_initialized() || m_verDriver < odbc_version(9, 3, 400);
}

bool has_partial_update_bug() const override
{
// ODBC driver has version-dependent bugs related to handling array
// parameters: after v13.02, it fails to insert anything, see
// https://github.com/postgresql-interfaces/psqlodbc/issues/89, and
// with the previous versions (e.g. v10.03) it's even worse, as it does
// insert the row with valid values but still returns fatal error at
// ODBC level.
//
// So far there is no known version where it works correctly, but if
// the issue above is fixed, we should check for the version including
// this fix here.
return true;
}

std::string fix_crlf_if_necessary(std::string const& s) const override
{
// Version 9.03.0300 (ancient, but still used on AppVeyor CI) is known
Expand Down
4 changes: 4 additions & 0 deletions tests/test-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ class test_context_base
// *exactly* the same value.
virtual bool has_fp_bug() const { return false; }

// Override this if the backend doesn't handle partial success for
// operations using array parameters correctly.
virtual bool has_partial_update_bug() const { return false; }

// Override this if the backend wrongly returns CR LF when reading a string
// with just LFs from the database to strip the unwanted CRs.
virtual std::string fix_crlf_if_necessary(std::string const& s) const { return s; }
Expand Down

0 comments on commit 37535c2

Please sign in to comment.