Fix uint64 vector unit tests

Firebird and SQLite store UINT64_MAX incorrectly, leading to an incorrect
value ordering when retrieving sorted table contents.
This commit is contained in:
Lukas Zanner
2023-01-03 21:35:14 +01:00
parent 4c36213928
commit 88e2cb4ae5
3 changed files with 41 additions and 6 deletions

View File

@@ -466,6 +466,11 @@ public:
// strings (Oracle does this).
virtual bool treats_empty_strings_as_null() const { return false; }
// Override this if the backend does not store values bigger than INT64_MAX
// correctly. This can lead to an unexpected ordering of values as larger
// values might be stored as overflown and therefore negative integer.
virtual bool has_uint64_storage_bug() const { return false; }
// Override this to call commit() if it's necessary for the DDL statements
// to be taken into account (currently this is only the case for Firebird).
virtual void on_after_ddl(session&) const { }
@@ -2406,12 +2411,24 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]")
sql << "select ul from soci_test order by ul", into(v2);
CHECK(v2.size() == 6);
CHECK(v2[0] == (std::numeric_limits<uint64_t>::min)());
CHECK(v2[1] == 0);
CHECK(v2[2] == 1);
CHECK(v2[3] == 123);
CHECK(v2[4] == 1000);
CHECK(v2[5] == (std::numeric_limits<uint64_t>::max)());
if (tc_.has_uint64_storage_bug())
{
CHECK(v2[0] == (std::numeric_limits<uint64_t>::max)());
CHECK(v2[1] == (std::numeric_limits<uint64_t>::min)());
CHECK(v2[2] == 0);
CHECK(v2[3] == 1);
CHECK(v2[4] == 123);
CHECK(v2[5] == 1000);
}
else
{
CHECK(v2[0] == (std::numeric_limits<uint64_t>::min)());
CHECK(v2[1] == 0);
CHECK(v2[2] == 1);
CHECK(v2[3] == 123);
CHECK(v2[4] == 1000);
CHECK(v2[5] == (std::numeric_limits<uint64_t>::max)());
}
}
SECTION("double")

View File

@@ -1339,6 +1339,17 @@ class test_context : public tests::test_context_base
return "'" + datdt_string + "'";
}
bool has_uint64_storage_bug() const override
{
// Firebird does not support unsigned integer types.
// We're using Firebird 3, which does not yet support a data
// type that can correctly store a UINT64_MAX. The biggest
// numeric data type available is numeric(18,0).
// Firebird 4 introduces the data type int128 and numeric(36,0),
// which will be sufficient for that in the future.
return true;
}
void on_after_ddl(soci::session& sql) const override
{
sql.commit();

View File

@@ -665,6 +665,13 @@ public:
return true;
}
bool has_uint64_storage_bug() const override
{
// SQLite processes integers as 8-byte signed values. Values bigger
// than INT64_MAX therefore overflow and are stored as negative values.
return true;
}
bool enable_std_char_padding(soci::session&) const override
{
// SQLite does not support right padded char type.