Commit 85159db6 authored by Vadim Zeitlin's avatar Vadim Zeitlin

Refactor: move XML and CLOB tests to common code

Don't duplicate them for PostgreSQL and Oracle, especially because they
will be needed for other backends in the future too.
parent 4744c170
......@@ -326,6 +326,25 @@ public:
virtual table_creator_base* table_creator_3(session&) const = 0;
virtual table_creator_base* table_creator_4(session&) const = 0;
// Override this to return the table creator for a simple table containing
// an integer "id" column and CLOB "s" one.
//
// 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 XML "x" one.
//
// Returns null by default to indicate that XML is not supported.
virtual table_creator_base* table_creator_xml(session&) const { return NULL; }
// Return the casts that must be used to convert the between the database
// XML type and the query parameters.
//
// By default no special casts are done.
virtual std::string to_xml(std::string const& x) const { return x; }
virtual std::string from_xml(std::string const& x) const { return x; }
// Override this if the backend doesn't handle floating point values
// correctly, i.e. writing a value and reading it back doesn't return
// *exactly* the same value.
......@@ -4260,6 +4279,97 @@ TEST_CASE_METHOD(common_tests, "String length", "[core][string][length]")
CHECK(vout[2].length() == 20);
}
// Helper function used in two tests below.
static std::string make_long_xml_string()
{
std::string s;
s.reserve(6 + 200*26 + 7);
s += "<file>";
for (int i = 0; i != 200; ++i)
{
s += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
s += "</file>";
return s;
}
TEST_CASE_METHOD(common_tests, "CLOB", "[core][clob]")
{
soci::session sql(backEndFactory_, connectString_);
auto_table_creator tableCreator(tc_.table_creator_clob(sql));
if (!tableCreator.get())
{
WARN("CLOB type not supported by the database, skipping the test.");
return;
}
long_string s1; // empty
sql << "insert into soci_test(id, s) values (1, :s)", use(s1);
long_string s2;
s2.value = "hello";
sql << "select s from soci_test where id = 1", into(s2);
CHECK(s2.value.size() == 0);
s1.value = make_long_xml_string();
sql << "update soci_test set s = :s where id = 1", use(s1);
sql << "select s from soci_test where id = 1", into(s2);
CHECK(s2.value == s1.value);
}
TEST_CASE_METHOD(common_tests, "XML", "[core][xml]")
{
soci::session sql(backEndFactory_, connectString_);
auto_table_creator tableCreator(tc_.table_creator_xml(sql));
if (!tableCreator.get())
{
WARN("XML type not supported by the database, skipping the test.");
return;
}
int id = 1;
xml_type xml;
// The extra new line is a special hack for Oracle: its getCLOBVal()
// seems to reformat the returned XML and, in particular, appends a new
// line to it if its last line doesn't contain one already. So if we didn't
// append it here the check for round trip below would fail because of the
// extra new line.
xml.value = make_long_xml_string() + "\n";
sql << "insert into soci_test (id, x) values (:1, "
<< tc_.to_xml(":2")
<< ")",
use(id), use(xml);
xml_type xml2;
sql << "select "
<< tc_.from_xml("x")
<< " from soci_test where id = :1",
into(xml2), use(id);
CHECK(xml.value == xml2.value);
sql << "update soci_test set x = null where id = :1", use(id);
indicator ind;
sql << "select "
<< tc_.from_xml("x")
<< " from soci_test where id = :1",
into(xml2, ind), use(id);
CHECK(ind == i_null);
}
} // namespace test_cases
} // namespace tests
......
......@@ -1421,64 +1421,6 @@ TEST_CASE("Bulk iterators", "[oracle][bulkiters]")
sql << "drop table t";
}
// XML and big string test
TEST_CASE("XML and big string", "[oracle][xml]")
{
session sql(backEnd, connectString);
sql << "create table xml_test (id integer, x xmltype)";
int id = 1;
xml_type xml;
xml.value = "<file>";
for (int i = 0; i != 200; ++i)
{
xml.value += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
xml.value += "</file>";
sql << "insert into xml_test (id, x) values (:1, xmltype(:2))", use(id), use(xml);
xml_type xml2;
sql << "select t.x.getCLOBVal() from xml_test t where id = :1", into(xml2), use(id);
// note: getCLOBVal() returns XML value with newline added at the end
CHECK(xml.value + '\n' == xml2.value);
sql << "update xml_test set x = null where id = :1", use(id);
indicator ind;
sql << "select t.x.getCLOBVal() from xml_test t where id = :1", into(xml2, ind), use(id);
CHECK(ind == i_null);
sql << "drop table xml_test";
// additional test for empty and non-empty long_string
sql << "create table long_string_test (id integer, s clob)";
long_string s1; // empty
sql << "insert into long_string_test(id, s) values (1, :s)", use(s1);
long_string s2;
s2.value = "hello";
sql << "select s from long_string_test where id = 1", into(s2);
CHECK(s2.value.size() == 0);
s1.value = xml.value; // some long value
sql << "update long_string_test set s = :s where id = 1", use(s1);
sql << "select s from long_string_test where id = 1", into(s2);
CHECK(s2.value == xml.value);
sql << "drop table long_string_test";
}
//
// Support for soci Common Tests
//
......@@ -1524,6 +1466,24 @@ struct table_creator_four : public table_creator_base
}
};
struct table_creator_for_xml : table_creator_base
{
table_creator_for_xml(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, x xmltype)";
}
};
struct table_creator_for_clob : table_creator_base
{
table_creator_for_clob(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, s clob)";
}
};
class test_context :public test_context_base
{
public:
......@@ -1551,6 +1511,28 @@ public:
return new table_creator_four(s);
}
table_creator_base* table_creator_clob(soci::session& s) const
{
return new table_creator_for_clob(s);
}
table_creator_base* table_creator_xml(soci::session& s) const
{
return new table_creator_for_xml(s);
}
std::string to_xml(std::string const& x) const
{
return "xmltype(" + x + ")";
}
std::string from_xml(std::string const& x) const
{
// Notice that using just x.getCLOBVal() doesn't work, only
// table.x.getCLOBVal() or (x).getCLOBVal(), as used here, does.
return "(" + x + ").getCLOBVal()";
}
std::string to_date_time(std::string const &datdt_string) const
{
return "to_date('" + datdt_string + "', 'YYYY-MM-DD HH24:MI:SS')";
......
......@@ -1038,56 +1038,6 @@ TEST_CASE("Bulk iterators", "[postgresql][bulkiters]")
sql << "drop table t";
}
// Test support for XML and long string wrapper types
TEST_CASE("XML wrapper type", "[postgresql][xml]")
{
session sql(backEnd, connectString);
sql << "create table xml_test (id integer, x xml)";
int id = 1;
xml_type xml;
xml.value = "<file>";
for (int i = 0; i != 200; ++i)
{
xml.value += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
xml.value += "</file>";
sql << "insert into xml_test (id, x) values (:1, :2)", use(id), use(xml);
xml_type xml2;
sql << "select x from xml_test where id = :1", into(xml2), use(id);
CHECK(xml.value == xml2.value);
sql << "drop table xml_test";
// additional test for empty and non-empty long_string
sql << "create table long_string_test (id integer, s text)";
long_string s1; // empty
sql << "insert into long_string_test(id, s) values (1, :s)", use(s1);
long_string s2;
s2.value = "hello";
sql << "select s from long_string_test where id = 1", into(s2);
CHECK(s2.value.size() == 0);
s1.value = xml.value; // some long value
sql << "update long_string_test set s = :s where id = 1", use(s1);
sql << "select s from long_string_test where id = 1", into(s2);
CHECK(s2.value == xml.value);
sql << "drop table long_string_test";
}
//
// Support for soci Common Tests
//
......@@ -1135,6 +1085,24 @@ struct table_creator_for_get_affected_rows : table_creator_base
}
};
struct table_creator_for_xml : table_creator_base
{
table_creator_for_xml(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, x xml)";
}
};
struct table_creator_for_clob : table_creator_base
{
table_creator_for_clob(soci::session& sql)
: table_creator_base(sql)
{
sql << "create table soci_test(id integer, s text)";
}
};
// Common tests context
class test_context : public test_context_base
{
......@@ -1163,6 +1131,16 @@ public:
return new table_creator_for_get_affected_rows(s);
}
table_creator_base* table_creator_xml(soci::session& s) const
{
return new table_creator_for_xml(s);
}
table_creator_base* table_creator_clob(soci::session& s) const
{
return new table_creator_for_clob(s);
}
std::string to_date_time(std::string const &datdt_string) const
{
return "timestamptz(\'" + datdt_string + "\')";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment