Skip to content

Commit

Permalink
SQLite update DDL creation to the new db enum
Browse files Browse the repository at this point in the history
  • Loading branch information
Sildra committed Jan 17, 2024
1 parent 8ddddca commit 261a02f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 3 deletions.
10 changes: 9 additions & 1 deletion include/soci/sqlite3/soci-sqlite3.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,23 @@ struct sqlite3_session_backend : details::session_backend
case db_double:
return "real";
case db_date:
return "date";
case db_int8:
return "int1";
case db_uint8:
return "uint1";
case db_int16:
return "int2";
case db_uint16:
return "uint2";
case db_int32:
return "int4";
case db_uint32:
return "uint4";
case db_int64:
return "int8";
case db_uint64:
return "integer";
return "uint8";
case db_blob:
return "blob";
default:
Expand Down
13 changes: 11 additions & 2 deletions src/backends/sqlite3/statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,28 @@ static sqlite3_data_type_map get_data_type_map()

// integer types
m["tinyint"] = db_int8;
m["int1"] = db_int8;

m["uint1"] = db_uint8;

m["smallint"] = db_int16;
m["int2"] = db_int16;

m["uint2"] = db_uint16;

m["boolean"] = db_int32;
m["int"] = db_int32;
m["integer"] = db_int32;
m["int2"] = db_int32;
m["mediumint"] = db_int32;
m["int4"] = db_int32;

m["uint4"] = db_uint32;

m["bigint"] = db_int64;
m["int8"] = db_int64;

m["unsignedbigint"] = db_uint64;
m["unsignedbigint"] = db_uint64;
m["uint8"] = db_uint64;

// db_string
m["char"] = db_string;
Expand Down
95 changes: 95 additions & 0 deletions tests/common-tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,66 @@ std::ostream& operator<<(std::ostream& ostr, const std::vector<MyOptionalString>
return ostr;
}

// The next classes are used for DDL testing
template<typename T>
struct DdlTester {
typedef T val_type;
DdlTester(soci::db_type type, T val, bool expectNull)
: inType(type), inVal(val), expectNull(expectNull) {}

soci::db_type inType;
T inVal;
bool expectNull;
soci::db_type outType;
T outVal;
bool isNull = false;
};

template<typename T>
void check(DdlTester<T> const &val)
{
CHECK(val.inType == val.outType);
CHECK(val.expectNull == val.isNull);
if (val.expectNull)
return;
CHECK(val.inVal == val.outVal);
}

template<>
void check(DdlTester<double> const &val)
{
CHECK(val.inType == val.outType);
CHECK(val.expectNull == val.isNull);
if (val.expectNull)
return;
CHECK(std::fpclassify(val.inVal) == std::fpclassify(val.outVal));
if (std::isnormal(val.inVal) && std::isnormal(val.outVal))
CHECK_THAT(val.inVal, Catch::Matchers::WithinRel(val.outVal));
}

template<typename T>
void map_ddl_tester(T& t, soci::values const &v)
{
std::size_t pos = 0;
t.outType = v.get_properties(pos).get_db_type();
t.isNull = v.get_indicator(pos) == soci::indicator::i_null;
if (t.isNull)
return;
switch (t.outType)
{
case soci::db_int8: t.outVal = static_cast<typename T::val_type>(v.get<std::int8_t>(pos)); break;
case soci::db_uint8: t.outVal = static_cast<typename T::val_type>(v.get<std::uint8_t>(pos)); break;
case soci::db_int16: t.outVal = static_cast<typename T::val_type>(v.get<std::int16_t>(pos)); break;
case soci::db_uint16: t.outVal = static_cast<typename T::val_type>(v.get<std::uint16_t>(pos)); break;
case soci::db_int32: t.outVal = static_cast<typename T::val_type>(v.get<std::int32_t>(pos)); break;
case soci::db_uint32: t.outVal = static_cast<typename T::val_type>(v.get<std::uint32_t>(pos)); break;
case soci::db_int64: t.outVal = static_cast<typename T::val_type>(v.get<std::int64_t>(pos)); break;
case soci::db_uint64: t.outVal = static_cast<typename T::val_type>(v.get<std::uint64_t>(pos)); break;
case soci::db_double: t.outVal = static_cast<typename T::val_type>(v.get<double>(pos)); break;
default: break;
}
}

namespace soci
{

Expand Down Expand Up @@ -288,8 +348,43 @@ template<> struct type_conversion<PhonebookEntry3>
}
};

template<typename T>
struct type_conversion<DdlTester<T>>
{
typedef soci::values base_type;
static void from_base(soci::values const &v, soci::indicator, DdlTester<T>& t)
{
map_ddl_tester(t, v);
}
static void to_base(DdlTester<T> const &t, soci::values &v, soci::indicator&)
{
v.set("VAL", t.inVal);
}
};
} // namespace soci

template<typename T>
void test_limit(soci::session &sql, DdlTester<T>&& tester)
{
const std::string table = "TEST_LIMIT";
try
{
sql.create_table(table).column("VAL", tester.inType);
sql << "INSERT INTO " << table << "(VAL) VALUES (:VAL)", soci::use(tester.inVal);
soci::statement stmt = (sql.prepare << "SELECT * FROM " << table);
stmt.exchange(soci::into(tester));
stmt.define_and_bind();
stmt.execute();
stmt.fetch();
check(tester);
}
catch (const std::exception& e)
{
CHECK_FALSE(e.what());
}
sql << "DROP TABLE " << table;
}

namespace soci
{
namespace tests
Expand Down
15 changes: 15 additions & 0 deletions tests/sqlite3/test-sqlite3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,21 @@ TEST_CASE("SQLite DDL with metadata", "[sqlite][ddl]")
CHECK(ddl_t3_found == false);
}

TEST_CASE("SQLite DDL symmetry", "[sqlite][ddl][symmetry]")
{
soci::session sql(backEnd, connectString);
test_limit(sql, DdlTester<double> (soci::db_double, std::numeric_limits<double>::max(), false));
test_limit(sql, DdlTester<double> (soci::db_double, std::numeric_limits<double>::quiet_NaN(), true));
test_limit(sql, DdlTester<std::int8_t> (soci::db_int8, std::numeric_limits<std::int8_t>::max(), false));
test_limit(sql, DdlTester<std::int16_t> (soci::db_int16, std::numeric_limits<std::int16_t>::max(), false));
test_limit(sql, DdlTester<std::int32_t> (soci::db_int32, std::numeric_limits<std::int32_t>::max(), false));
test_limit(sql, DdlTester<std::int64_t> (soci::db_int64, std::numeric_limits<std::int64_t>::max(), false));
test_limit(sql, DdlTester<std::uint8_t> (soci::db_uint8, std::numeric_limits<std::uint8_t>::max(), false));
test_limit(sql, DdlTester<std::uint16_t>(soci::db_uint16, std::numeric_limits<std::uint16_t>::max(), false));
test_limit(sql, DdlTester<std::uint32_t>(soci::db_uint32, std::numeric_limits<std::uint32_t>::max(), false));
test_limit(sql, DdlTester<std::uint64_t>(soci::db_uint64, std::numeric_limits<std::uint64_t>::max(), false));
}

TEST_CASE("SQLite vector long long", "[sqlite][vector][longlong]")
{
soci::session sql(backEnd, connectString);
Expand Down

0 comments on commit 261a02f

Please sign in to comment.