mirror of
https://github.com/SOCI/soci.git
synced 2026-05-03 09:49:33 -05:00
Start implementing shared BLOB tests
This commit is contained in:
@@ -417,6 +417,12 @@ public:
|
||||
// Returns null by default to indicate that CLOB is not supported.
|
||||
virtual table_creator_base* table_creator_clob(session&) const { return NULL; }
|
||||
|
||||
// Override this to return the table creator for a simple table containing
|
||||
// an integer "id" column and BLOB "b" one.
|
||||
//
|
||||
// Returns null by default to indicate that BLOB is not supported.
|
||||
virtual table_creator_base* table_creator_blob(session&) const { return NULL; }
|
||||
|
||||
// Override this to return the table creator for a simple table containing
|
||||
// an integer "id" column and XML "x" one.
|
||||
//
|
||||
@@ -6364,6 +6370,131 @@ TEST_CASE_METHOD(common_tests, "Into XML vector with several fetches", "[core][x
|
||||
REQUIRE(!st.fetch());
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(common_tests, "BLOB", "[core][blob]")
|
||||
{
|
||||
soci::session sql(backEndFactory_, connectString_);
|
||||
|
||||
auto_table_creator tableCreator(tc_.table_creator_blob(sql));
|
||||
|
||||
if (!tableCreator.get())
|
||||
{
|
||||
try
|
||||
{
|
||||
soci::blob blob(sql);
|
||||
FAIL("BLOB creation should throw, if backend doesn't support BLOBs");
|
||||
} catch (const soci_error &)
|
||||
{
|
||||
// Throwing is expected if the backend doesn't support BLOBs
|
||||
}
|
||||
WARN("BLOB type not supported by the database, skipping the test.");
|
||||
return;
|
||||
}
|
||||
|
||||
const char dummy_data[] = "abcdefghijklmnopüqrstuvwxyz";
|
||||
|
||||
// Cross-DB usage of BLOBs is only possible if the entire lifetime of the blob object
|
||||
// is covered in an active transaction.
|
||||
soci::transaction transaction(sql);
|
||||
{
|
||||
SECTION("Read-access on default-constructed blob")
|
||||
{
|
||||
soci::blob blob(sql);
|
||||
|
||||
CHECK(blob.get_len() == 0);
|
||||
|
||||
char buf[5];
|
||||
std::size_t read_bytes = blob.read_from_start(buf, sizeof(buf));
|
||||
|
||||
// There should be no data that could be read
|
||||
CHECK(read_bytes == 0);
|
||||
|
||||
// Reading from any offset other than zero is invalid
|
||||
CHECK_THROWS_AS(blob.read_from_start(buf, sizeof(buf), 1), soci_error);
|
||||
}
|
||||
SECTION("Write-access on default-constructed blob")
|
||||
{
|
||||
soci::blob blob(sql);
|
||||
|
||||
std::size_t written_bytes = blob.write_from_start(dummy_data, 5);
|
||||
|
||||
CHECK(written_bytes == 5);
|
||||
CHECK(blob.get_len() == 5);
|
||||
|
||||
char buf[5];
|
||||
|
||||
std::size_t read_bytes = blob.read_from_start(buf, sizeof(buf));
|
||||
|
||||
CHECK(read_bytes == 5);
|
||||
|
||||
for (std::size_t i = 0; i < sizeof(buf); ++i)
|
||||
{
|
||||
CHECK(buf[i] == dummy_data[i]);
|
||||
}
|
||||
|
||||
written_bytes = blob.append(dummy_data + 5, 3);
|
||||
|
||||
CHECK(written_bytes == 3);
|
||||
CHECK(blob.get_len() == 8);
|
||||
|
||||
read_bytes = blob.read_from_start(buf, sizeof(buf), 3);
|
||||
|
||||
CHECK(read_bytes == 5);
|
||||
|
||||
for (std::size_t i = 0; i < sizeof(buf); ++i)
|
||||
{
|
||||
CHECK(buf[i] == dummy_data[i + 3]);
|
||||
}
|
||||
|
||||
blob.trim(2);
|
||||
|
||||
CHECK(blob.get_len() == 2);
|
||||
|
||||
read_bytes = blob.read_from_start(buf, sizeof(buf));
|
||||
|
||||
CHECK(read_bytes == 2);
|
||||
|
||||
for (std::size_t i = 0; i < read_bytes; ++i)
|
||||
{
|
||||
CHECK(buf[i] == dummy_data[i]);
|
||||
}
|
||||
|
||||
// Reading from an offset >= the current length of the blob is invalid
|
||||
CHECK_THROWS_AS(blob.read_from_start(buf, sizeof(buf), blob.get_len()), soci_error);
|
||||
|
||||
written_bytes = blob.append("z", 1);
|
||||
|
||||
CHECK(written_bytes == 1);
|
||||
CHECK(blob.get_len() == 3);
|
||||
|
||||
read_bytes = blob.read_from_start(buf, 1, 2);
|
||||
|
||||
CHECK(read_bytes == 1);
|
||||
CHECK(buf[0] == 'z');
|
||||
|
||||
// Writing more than one position beyond the blob is invalid
|
||||
// (Writing exactly one position beyond is the same as appending)
|
||||
CHECK_THROWS_AS(blob.write_from_start(dummy_data, 2, blob.get_len() + 1), soci_error);
|
||||
}
|
||||
SECTION("Inserting default-constructed blob into DB")
|
||||
{
|
||||
soci::blob blob(sql);
|
||||
|
||||
sql << "insert into soci_test (id, b) values(5, :b)", soci::use(blob);
|
||||
}
|
||||
SECTION("Fetching default-constructed blob from DB")
|
||||
{
|
||||
soci::blob blob(sql);
|
||||
soci::indicator ind;
|
||||
|
||||
sql << "select b from soci_test where id = 5", soci::into(blob, ind);
|
||||
|
||||
CHECK(ind == soci::i_ok);
|
||||
CHECK(blob.get_len() == 0);
|
||||
}
|
||||
}
|
||||
transaction.rollback();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(common_tests, "Logger", "[core][log]")
|
||||
{
|
||||
// Logger class used for testing: appends all queries to the provided
|
||||
|
||||
@@ -1307,6 +1307,15 @@ struct TableCreatorCLOB : public tests::table_creator_base
|
||||
}
|
||||
};
|
||||
|
||||
struct TableCreatorBLOB : public tests::table_creator_base
|
||||
{
|
||||
TableCreatorBLOB(soci::session & sql)
|
||||
: tests::table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, b blob)";
|
||||
}
|
||||
};
|
||||
|
||||
struct TableCreatorXML : public tests::table_creator_base
|
||||
{
|
||||
TableCreatorXML(soci::session & sql)
|
||||
@@ -1351,6 +1360,12 @@ class test_context : public tests::test_context_base
|
||||
return new TableCreatorCLOB(s);
|
||||
}
|
||||
|
||||
|
||||
tests::table_creator_base* table_creator_blob(soci::session& s) const override
|
||||
{
|
||||
return new TableCreatorBLOB(s);
|
||||
}
|
||||
|
||||
tests::table_creator_base* table_creator_xml(soci::session& s) const override
|
||||
{
|
||||
return new TableCreatorXML(s);
|
||||
|
||||
@@ -49,6 +49,16 @@ struct table_creator_for_get_affected_rows : table_creator_base
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_blob : public tests::table_creator_base
|
||||
{
|
||||
table_creator_for_blob(soci::session & sql)
|
||||
: tests::table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, b blob)";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Support for SOCI Common Tests
|
||||
//
|
||||
@@ -85,6 +95,11 @@ public:
|
||||
return "\'" + datdt_string + "\'";
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_blob(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_for_blob(s);
|
||||
}
|
||||
|
||||
bool has_fp_bug() const override
|
||||
{
|
||||
// MySQL fails in the common test3() with "1.8000000000000000 !=
|
||||
|
||||
@@ -1480,6 +1480,14 @@ struct table_creator_for_clob : table_creator_base
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_blob : public tests::table_creator_base
|
||||
{
|
||||
table_creator_for_blob(soci::session &sql) : tests::table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, b blob)";
|
||||
}
|
||||
};
|
||||
|
||||
class test_context :public test_context_base
|
||||
{
|
||||
public:
|
||||
@@ -1512,6 +1520,11 @@ public:
|
||||
return new table_creator_for_clob(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_blob(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_for_blob(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_xml(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_for_xml(s);
|
||||
|
||||
@@ -1433,7 +1433,16 @@ struct table_creator_for_clob : table_creator_base
|
||||
}
|
||||
};
|
||||
|
||||
// Common tests context
|
||||
struct table_creator_for_blob : public tests::table_creator_base
|
||||
{
|
||||
table_creator_for_blob(soci::session & sql)
|
||||
: tests::table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, b oid)";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class test_context : public test_context_base
|
||||
{
|
||||
public:
|
||||
@@ -1471,6 +1480,11 @@ public:
|
||||
return new table_creator_for_clob(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_blob(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_for_blob(s);
|
||||
}
|
||||
|
||||
bool has_real_xml_support() const override
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -898,6 +898,15 @@ struct table_creator_from_str : table_creator_base
|
||||
}
|
||||
};
|
||||
|
||||
struct table_creator_for_blob : public tests::table_creator_base
|
||||
{
|
||||
table_creator_for_blob(soci::session & sql)
|
||||
: tests::table_creator_base(sql)
|
||||
{
|
||||
sql << "create table soci_test(id integer, b blob)";
|
||||
}
|
||||
};
|
||||
|
||||
class test_context : public test_context_base
|
||||
{
|
||||
public:
|
||||
@@ -931,6 +940,11 @@ public:
|
||||
"create table soci_test (id integer primary key, val integer)");
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_blob(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_for_blob(s);
|
||||
}
|
||||
|
||||
table_creator_base* table_creator_xml(soci::session& s) const override
|
||||
{
|
||||
return new table_creator_from_str(s,
|
||||
|
||||
Reference in New Issue
Block a user