Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added convenience functions for constructing objects from a row #114

Merged
merged 1 commit into from
Feb 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/SQLiteCpp/Column.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,5 +260,22 @@ class Column
*/
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn);

#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
// Create an instance of T from the first N columns, see declaration in Statement.h for full details
template<typename T, int N>
T Statement::getColumns()
{
checkRow();
checkIndex(N - 1);
return getColumns<T>(std::make_integer_sequence<int, N>{});
}

// Helper function called by getColums<typename T, int N>
template<typename T, const int... Is>
T Statement::getColumns(const std::integer_sequence<int, Is...>)
{
return T(Column(mStmtPtr, Is)...);
}
#endif

} // namespace SQLite
34 changes: 34 additions & 0 deletions include/SQLiteCpp/Statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,40 @@ class Statement
*/
Column getColumn(const char* apName);

#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
/**
* @brief Return an instance of T constructed from copies of the first N columns
*
* Can be used to access the data of the current row of result when applicable,
* while the executeStep() method returns true.
*
* Throw an exception if there is no row to return a Column from:
* - if provided column count is out of bound
* - before any executeStep() call
* - after the last executeStep() returned false
* - after a reset() call
*
* Throw an exception if the specified column count is out of the [0, getColumnCount()) range.
*
* @tparam T Object type to construct
* @tparam N Number of columns
*
* @note Requires std=C++14
*/
template<typename T, int N>
T getColumns();

private:
/**
* @brief Helper function used by getColumns<typename T, int N> to expand an integer_sequence used to generate
* the required Column objects
*/
template<typename T, const int... Is>
T getColumns(const std::integer_sequence<int, Is...>);

public:
#endif

/**
* @brief Test if the column value is NULL
*
Expand Down
57 changes: 57 additions & 0 deletions tests/Statement_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,3 +651,60 @@ TEST(Statement, getName) {
EXPECT_EQ("msg", oname1);
#endif
}

#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
TEST(Statement, getColumns) {
struct GetRowTestStruct
{
int id;
std::string msg;
int integer;
double real;
GetRowTestStruct(int _id, std::string _msg, int _integer, double _real)
: id(_id), msg(_msg), integer(_integer), real(_real)
{}

GetRowTestStruct(int _id, const std::string& _msg)
: id(_id), msg(_msg), integer(-1), real(0.0)
{}
};

// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());

// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());

// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());

// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
query.executeStep();
EXPECT_TRUE(query.isOk());
EXPECT_FALSE(query.isDone());

// Get all columns
auto testStruct = query.getColumns<GetRowTestStruct, 4>();
EXPECT_EQ(1, testStruct.id);
EXPECT_EQ("first", testStruct.msg);
EXPECT_EQ(123, testStruct.integer);
EXPECT_EQ(0.123, testStruct.real);

// Get only the first 2 columns
auto testStruct2 = query.getColumns<GetRowTestStruct, 2>();
EXPECT_EQ(1, testStruct2.id);
EXPECT_EQ("first", testStruct2.msg);
EXPECT_EQ(-1, testStruct2.integer);
EXPECT_EQ(0.0, testStruct2.real);
}
#endif