Skip to content

Commit a1ef1b9

Browse files
committed
Add StatementPtr - better structure for Statement shared_ptr
1 parent 4117377 commit a1ef1b9

12 files changed

+234
-148
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ set(SQLITECPP_SRC
109109
${PROJECT_SOURCE_DIR}/src/Savepoint.cpp
110110
${PROJECT_SOURCE_DIR}/src/Statement.cpp
111111
${PROJECT_SOURCE_DIR}/src/StatementExecutor.cpp
112+
${PROJECT_SOURCE_DIR}/src/StatementPtr.cpp
112113
${PROJECT_SOURCE_DIR}/src/Transaction.cpp
113114
)
114115
source_group(src FILES ${SQLITECPP_SRC})
@@ -125,6 +126,7 @@ set(SQLITECPP_INC
125126
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Savepoint.h
126127
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Statement.h
127128
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/StatementExecutor.h
129+
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/StatementPtr.h
128130
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h
129131
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/VariadicBind.h
130132
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/ExecuteMany.h

include/SQLiteCpp/Column.h

+4-26
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@
1010
*/
1111
#pragma once
1212

13-
#include <SQLiteCpp/Statement.h>
14-
#include <SQLiteCpp/Exception.h>
13+
#include <SQLiteCpp/StatementPtr.h>
1514

15+
#include <ostream>
1616
#include <string>
1717
#include <memory>
1818

19-
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
20-
struct sqlite3_stmt;
2119

2220
namespace SQLite
2321
{
@@ -55,7 +53,7 @@ class Column
5553
*
5654
* @throws Exception is thrown in case of error, then the Column object is NOT constructed.
5755
*/
58-
explicit Column(const StatementExecutor::TStatementPtr& aStmtPtr, int aIndex);
56+
explicit Column(const StatementPtr::TStatementPtr& aStmtPtr, int aIndex);
5957

6058
/**
6159
* @brief Return a pointer to the named assigned to this result column (potentially aliased)
@@ -226,7 +224,7 @@ class Column
226224
}
227225

228226
private:
229-
StatementExecutor::TStatementPtr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
227+
StatementPtr::TStatementPtr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
230228
int mIndex; ///< Index of the column in the row of result, starting at 0
231229
};
232230

@@ -242,25 +240,5 @@ class Column
242240
*/
243241
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn);
244242

245-
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
246-
247-
// Create an instance of T from the first N columns, see declaration in Statement.h for full details
248-
template<typename T, int N>
249-
T Statement::getColumns()
250-
{
251-
checkRow();
252-
checkIndex(N - 1);
253-
return getColumns<T>(std::make_integer_sequence<int, N>{});
254-
}
255-
256-
// Helper function called by getColums<typename T, int N>
257-
template<typename T, const int... Is>
258-
T Statement::getColumns(const std::integer_sequence<int, Is...>)
259-
{
260-
return T{ Column(getStatement(), Is)... };
261-
}
262-
263-
#endif
264-
265243

266244
} // namespace SQLite

include/SQLiteCpp/Database.h

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111
#pragma once
1212

13+
#include <SQLiteCpp/Exception.h>
1314
#include <SQLiteCpp/Column.h>
1415

1516
// c++17: MinGW GCC version > 8

include/SQLiteCpp/Row.h

+3-8
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@
1111
*/
1212
#pragma once
1313

14-
//#include <SQLiteCpp/RowExecutor.h>
14+
#include <SQLiteCpp/StatementPtr.h>
1515

1616
#include <memory>
1717
#include <string>
1818

19-
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
20-
struct sqlite3_stmt;
2119

2220
namespace SQLite
2321
{
@@ -27,11 +25,8 @@ namespace SQLite
2725
*/
2826
class Row
2927
{
30-
/// Weak pointer to SQLite Prepared Statement Object
31-
using TStatementWeakPtr = std::weak_ptr<sqlite3_stmt>;
32-
3328
public:
34-
Row(TStatementWeakPtr apRow, std::size_t aID);
29+
Row(TRowWeakPtr apStatement, std::size_t aID);
3530

3631
std::size_t getRowNumber() const
3732
{
@@ -58,7 +53,7 @@ class Row
5853
const char* getText(uint32_t aColumnID) const noexcept;
5954

6055
private:
61-
TStatementWeakPtr mpRow;
56+
TRowWeakPtr mpStatement;
6257
std::size_t ID;
6358
};
6459

include/SQLiteCpp/Statement.h

+17-10
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,13 @@ class Statement : public StatementExecutor
5959
*/
6060
Statement(const Database& aDatabase, const std::string& aQuery);
6161

62-
/**
63-
* @brief Move an SQLite statement.
64-
*
65-
* @param[in] aStatement Statement to move
66-
*/
67-
Statement(Statement&& aStatement) noexcept = default;
68-
Statement& operator=(Statement&& aStatement) noexcept = default;
69-
7062
// Statement is non-copyable
7163
Statement(const Statement&) = delete;
7264
Statement& operator=(const Statement&) = delete;
7365

66+
Statement(Statement&& aStatement) = default;
67+
Statement& operator=(Statement&& aStatement) = default;
68+
7469
/// Finalize and unregister the SQL query from the SQLite Database Connection.
7570
/// The finalization will be done by the destructor of the last shared pointer
7671
~Statement() = default;
@@ -440,15 +435,27 @@ class Statement : public StatementExecutor
440435
* @note Requires std=C++14
441436
*/
442437
template<typename T, int N>
443-
T getColumns();
438+
T getColumns()
439+
{
440+
checkRow();
441+
checkIndex(N - 1);
442+
return getColumns<T>(std::make_integer_sequence<int, N>{});
443+
}
444444

445445
private:
446446
/**
447447
* @brief Helper function used by getColumns<typename T, int N> to expand an integer_sequence used to generate
448448
* the required Column objects
449+
*
450+
* @note Requires std=C++14
451+
*
452+
* @return Column object for each column in statement
449453
*/
450454
template<typename T, const int... Is>
451-
T getColumns(const std::integer_sequence<int, Is...>);
455+
T getColumns(const std::integer_sequence<int, Is...>)
456+
{
457+
return T{ Column(getStatement(), Is)... };
458+
}
452459

453460
public:
454461
#endif

include/SQLiteCpp/StatementExecutor.h

+16-31
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
* @ingroup SQLiteCpp
44
* @brief Step executor for SQLite prepared Statement Object
55
*
6-
* Copyright (c) 2015 Shibao HONG ([email protected])
7-
* Copyright (c) 2015-2021 Sebastien Rombauts ([email protected])
6+
* Copyright (c) 2012-2021 Sebastien Rombauts ([email protected])
87
*
98
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
109
* or copy at http://opensource.org/licenses/MIT)
1110
*/
1211
#pragma once
1312

13+
#include <SQLiteCpp/StatementPtr.h>
1414
#include <SQLiteCpp/Row.h>
1515
#include <SQLiteCpp/Exception.h>
1616

1717
#include <memory>
1818
#include <string>
1919
#include <map>
2020

21-
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
22-
struct sqlite3_stmt;
2321

2422
namespace SQLite
2523
{
@@ -44,24 +42,13 @@ extern const int OK; ///< SQLITE_OK
4442
class StatementExecutor
4543
{
4644
public:
47-
/// Shared pointer to SQLite Prepared Statement Object
48-
using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
49-
50-
/// Weak pointer to SQLite Prepared Statement Object
51-
using TStatementWeakPtr = std::weak_ptr<sqlite3_stmt>;
52-
53-
/// Shared pointer to SQLite StatementExecutor
54-
using TRowPtr = std::shared_ptr<StatementExecutor>;
55-
56-
/// Weak pointer to SQLite StatementExecutor
57-
using TRowWeakPtr = std::weak_ptr<StatementExecutor>;
58-
5945
/// Type to store columns names and indexes
6046
using TColumnsMap = std::map<std::string, int, std::less<>>;
6147

6248
StatementExecutor(const StatementExecutor&) = delete;
63-
StatementExecutor(StatementExecutor&&) = default;
6449
StatementExecutor& operator=(const StatementExecutor&) = delete;
50+
51+
StatementExecutor(StatementExecutor&&) = default;
6552
StatementExecutor& operator=(StatementExecutor&&) = default;
6653

6754
/// Reset the statement to make it ready for a new execution. Throws an exception on error.
@@ -180,8 +167,8 @@ class StatementExecutor
180167
using difference_type = std::ptrdiff_t;
181168

182169
RowIterator() = default;
183-
RowIterator(TStatementWeakPtr apStatement, TRowWeakPtr apRow, uint16_t aID) :
184-
mpStatement(apStatement), mpRow(apRow), mID(aID), mRow(apStatement, aID) {}
170+
RowIterator(TRowWeakPtr apStatement, uint16_t aID) :
171+
mpStatement(apStatement), mID(aID), mRow(apStatement, aID) {}
185172

186173
reference operator*() const
187174
{
@@ -216,8 +203,7 @@ class StatementExecutor
216203
/// Executing next statement step
217204
void advance() noexcept;
218205

219-
TStatementWeakPtr mpStatement{}; //!< Weak pointer to SQLite Statement Object
220-
TRowWeakPtr mpRow{}; //!< Weak pointer to StatementExecutor Object
206+
TRowWeakPtr mpStatement{}; //!< Weak pointer to prepared Statement Object
221207
uint16_t mID{}; //!< Current row number
222208

223209
/// Internal row object storage
@@ -256,9 +242,9 @@ class StatementExecutor
256242
*
257243
* @return raw pointer to Statement Object
258244
*/
259-
TStatementPtr getStatement() const noexcept
245+
StatementPtr::TStatementPtr getStatement() const noexcept
260246
{
261-
return mpStatement;
247+
return mpStatement->mpStatement;
262248
}
263249

264250
/**
@@ -277,7 +263,7 @@ class StatementExecutor
277263
*/
278264
TRowWeakPtr getExecutorWeakPtr() const
279265
{
280-
return mpRowExecutor;
266+
return mpStatement;
281267
}
282268

283269
////////////////////////////////////////////////////////////////////////////
@@ -291,7 +277,7 @@ class StatementExecutor
291277
{
292278
if (SQLite::OK != aRet)
293279
{
294-
throw SQLite::Exception(mpSQLite, aRet);
280+
throw SQLite::Exception(mpStatement->mpConnection, aRet);
295281
}
296282
}
297283

@@ -318,18 +304,17 @@ class StatementExecutor
318304
}
319305

320306
private:
321-
/// Create prepared SQLite Statement Object
322-
void prepareStatement(const std::string& aQuery);
323-
324307
/// Get column number and create map with columns names
325308
void createColumnInfo();
326309

327-
sqlite3* mpSQLite{}; //!< Pointer to SQLite Database Connection Handle
328-
TStatementPtr mpStatement{}; //!< Shared Pointer to the prepared SQLite Statement Object
310+
// xD
311+
bool checkReturnCode(int aReturnCode) const;
312+
// xD
313+
bool checkReturnCode(int aReturnCode, int aErrorCode) const;
329314

330315
/// Shared Pointer to this object.
331316
/// Allows RowIterator to execute next step
332-
TRowPtr mpRowExecutor{};
317+
TRowPtr mpStatement{};
333318

334319
int mColumnCount = 0; //!< Number of columns in the result of the prepared statement
335320
bool mbHasRow = false; //!< true when a row has been fetched with executeStep()

include/SQLiteCpp/StatementPtr.h

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @file StatementPtr.h
3+
* @ingroup SQLiteCpp
4+
* @brief Pointer for prepared SQLite Statement Object
5+
*
6+
* Copyright (c) 2022 Sebastien Rombauts ([email protected])
7+
*
8+
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
9+
* or copy at http://opensource.org/licenses/MIT)
10+
*/
11+
#pragma once
12+
13+
#include <memory>
14+
#include <string>
15+
16+
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
17+
struct sqlite3;
18+
struct sqlite3_stmt;
19+
20+
namespace SQLite
21+
{
22+
23+
24+
/**
25+
* @brief Container for SQLite Statement pointer.
26+
*
27+
* You should never create this object unless you are expanding SQLiteCPP API.
28+
*/
29+
struct StatementPtr
30+
{
31+
/**
32+
* @brief Don't create this object unless you are expanding SQLiteCPP API.
33+
*
34+
* @param[in] apSQLite the SQLite Database Connection
35+
* @param[in] aQuery an UTF-8 encoded query string
36+
*
37+
* @throws Exception is thrown in case of error, then the StatementPtr object is NOT constructed.
38+
*/
39+
StatementPtr(sqlite3* apSQLite, const std::string& aQuery);
40+
41+
/// Shared pointer to SQLite prepared Statement Object
42+
using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
43+
44+
sqlite3* const mpConnection; //!< Pointer to SQLite Database Connection Handle
45+
TStatementPtr const mpStatement; //!< Shared Pointer to the prepared SQLite Statement Object
46+
std::size_t mCurrentStep = 0; //!< Current step of prepared Statement Object
47+
48+
/// Resets SQLite Statement Object
49+
int reset() noexcept;
50+
51+
/// Execute next step of SQLite Statement Object
52+
int step() noexcept;
53+
54+
/**
55+
* @brief Returns pointer to prepared SQLite Statement Object.
56+
* Use this ONLY on sqlite3 function!
57+
*
58+
* @return Pointer to SQLite Statement Object
59+
*/
60+
sqlite3_stmt* getPreparedStatement() const;
61+
62+
private:
63+
/// Create prepared SQLite Statement Object
64+
TStatementPtr prepareStatement(sqlite3* apConnection, const std::string& aQuery) const;
65+
};
66+
67+
68+
/// Shared pointer to SQLite StatementPtr
69+
using TRowPtr = std::shared_ptr<StatementPtr>;
70+
71+
/// Weak pointer to SQLite StatementPtr
72+
using TRowWeakPtr = std::weak_ptr<StatementPtr>;
73+
74+
75+
} // namespace SQLite

0 commit comments

Comments
 (0)