diff --git a/CHANGELOG.md b/CHANGELOG.md index 17dd1f1d..23b6c219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update googletest to v1.18.0 (#583) - Improve tests for `Savepoint::rollbackTo()` and scope-exit rollback semantics (#584) - Fix link errors in supplied assertion handlers and add handler-enabled CI coverage (#587) +- Make column type constants usable in constant expressions (ABI change) (#609) ### Removed diff --git a/include/SQLiteCpp/Column.h b/include/SQLiteCpp/Column.h index 25f02f2c..64559a6c 100644 --- a/include/SQLiteCpp/Column.h +++ b/include/SQLiteCpp/Column.h @@ -24,11 +24,12 @@ struct sqlite3_stmt; namespace SQLite { -SQLITECPP_API extern const int INTEGER; ///< SQLITE_INTEGER -SQLITECPP_API extern const int FLOAT; ///< SQLITE_FLOAT -SQLITECPP_API extern const int TEXT; ///< SQLITE_TEXT -SQLITECPP_API extern const int BLOB; ///< SQLITE_BLOB -SQLITECPP_API extern const int Null; ///< SQLITE_NULL +/// SQLite result type codes, usable in constant expressions without including sqlite3.h. +inline constexpr int INTEGER = 1; ///< SQLITE_INTEGER +inline constexpr int FLOAT = 2; ///< SQLITE_FLOAT +inline constexpr int TEXT = 3; ///< SQLITE_TEXT +inline constexpr int BLOB = 4; ///< SQLITE_BLOB +inline constexpr int Null = 5; ///< SQLITE_NULL /** * @brief Encapsulation of a Column in a row of the result pointed by the prepared Statement. diff --git a/src/Column.cpp b/src/Column.cpp index c4ca912a..cd4e813c 100644 --- a/src/Column.cpp +++ b/src/Column.cpp @@ -17,11 +17,11 @@ namespace SQLite { -const int INTEGER = SQLITE_INTEGER; -const int FLOAT = SQLITE_FLOAT; -const int TEXT = SQLITE_TEXT; -const int BLOB = SQLITE_BLOB; -const int Null = SQLITE_NULL; +static_assert(INTEGER == SQLITE_INTEGER, "SQLite::INTEGER must match SQLITE_INTEGER"); +static_assert(FLOAT == SQLITE_FLOAT, "SQLite::FLOAT must match SQLITE_FLOAT"); +static_assert(TEXT == SQLITE_TEXT, "SQLite::TEXT must match SQLITE_TEXT"); +static_assert(BLOB == SQLITE_BLOB, "SQLite::BLOB must match SQLITE_BLOB"); +static_assert(Null == SQLITE_NULL, "SQLite::Null must match SQLITE_NULL"); // Encapsulation of a Column in a row of the result pointed by the prepared Statement. diff --git a/tests/Column_test.cpp b/tests/Column_test.cpp index 4831ca57..0c640ac4 100644 --- a/tests/Column_test.cpp +++ b/tests/Column_test.cpp @@ -19,6 +19,41 @@ #include +TEST(Column, typeConstantsAsCaseLabels) +{ + SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); + SQLite::Statement query(db, "SELECT 42, 1.5, 'text', X'1234', NULL"); + + ASSERT_TRUE(query.executeStep()); + ASSERT_EQ(5, query.getColumnCount()); + + // Each label must be a constant expression, and each code must match SQLite's runtime type. + for (int i = 0; i < query.getColumnCount(); ++i) + { + switch (query.getColumn(i).getType()) + { + case SQLite::INTEGER: + EXPECT_EQ(0, i); + break; + case SQLite::FLOAT: + EXPECT_EQ(1, i); + break; + case SQLite::TEXT: + EXPECT_EQ(2, i); + break; + case SQLite::BLOB: + EXPECT_EQ(3, i); + break; + case SQLite::Null: + EXPECT_EQ(4, i); + break; + default: + FAIL() << "Unexpected type for column " << i; + } + } +} + + static void test_column_basis(bool utf16) { // Create a new database