Skip to content

Commit 9158225

Browse files
authored
Merge pull request #349 from Kacperos155/refactoring-Statement&Column
Refactoring of Statement and Column classes
2 parents 454a2e2 + c5b3aa8 commit 9158225

File tree

6 files changed

+190
-289
lines changed

6 files changed

+190
-289
lines changed

include/SQLiteCpp/Column.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#include <SQLiteCpp/Exception.h>
1515

1616
#include <string>
17+
#include <memory>
1718
#include <climits> // For INT_MAX
1819

20+
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
21+
struct sqlite3_stmt;
1922

2023
namespace SQLite
2124
{
@@ -26,7 +29,6 @@ extern const int TEXT; ///< SQLITE_TEXT
2629
extern const int BLOB; ///< SQLITE_BLOB
2730
extern const int Null; ///< SQLITE_NULL
2831

29-
3032
/**
3133
* @brief Encapsulation of a Column in a row of the result pointed by the prepared Statement.
3234
*
@@ -52,7 +54,7 @@ class Column
5254
* @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object.
5355
* @param[in] aIndex Index of the column in the row of result, starting at 0
5456
*/
55-
Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept;
57+
explicit Column(const Statement::TStatementPtr& aStmtPtr, int aIndex);
5658

5759
// default destructor: the finalization will be done by the destructor of the last shared pointer
5860
// default copy constructor and assignment operator are perfectly suited :
@@ -250,8 +252,8 @@ class Column
250252
}
251253

252254
private:
253-
Statement::Ptr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
254-
int mIndex; ///< Index of the column in the row of result, starting at 0
255+
Statement::TStatementPtr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
256+
int mIndex; ///< Index of the column in the row of result, starting at 0
255257
};
256258

257259
/**
@@ -281,7 +283,7 @@ T Statement::getColumns()
281283
template<typename T, const int... Is>
282284
T Statement::getColumns(const std::integer_sequence<int, Is...>)
283285
{
284-
return T{Column(mStmtPtr, Is)...};
286+
return T{Column(mpPreparedStatement, Is)...};
285287
}
286288

287289
#endif

include/SQLiteCpp/Statement.h

Lines changed: 44 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
#include <string>
1717
#include <map>
18-
#include <climits> // For INT_MAX
18+
#include <memory>
1919

2020
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
2121
struct sqlite3;
@@ -51,8 +51,6 @@ extern const int OK; ///< SQLITE_OK
5151
*/
5252
class Statement
5353
{
54-
friend class Column; // For access to Statement::Ptr inner class
55-
5654
public:
5755
/**
5856
* @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -62,7 +60,7 @@ class Statement
6260
*
6361
* Exception is thrown in case of error, then the Statement object is NOT constructed.
6462
*/
65-
Statement(Database& aDatabase, const char* apQuery);
63+
Statement(const Database& aDatabase, const char* apQuery);
6664

6765
/**
6866
* @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -72,7 +70,7 @@ class Statement
7270
*
7371
* Exception is thrown in case of error, then the Statement object is NOT constructed.
7472
*/
75-
Statement(Database &aDatabase, const std::string& aQuery) :
73+
Statement(const Database& aDatabase, const std::string& aQuery) :
7674
Statement(aDatabase, aQuery.c_str())
7775
{}
7876

@@ -82,6 +80,7 @@ class Statement
8280
* @param[in] aStatement Statement to move
8381
*/
8482
Statement(Statement&& aStatement) noexcept;
83+
Statement& operator=(Statement&& aStatement) noexcept = default;
8584

8685
// Statement is non-copyable
8786
Statement(const Statement&) = delete;
@@ -123,39 +122,20 @@ class Statement
123122
// => if you know what you are doing, use bindNoCopy() instead of bind()
124123

125124
SQLITECPP_PURE_FUNC
126-
int getIndex(const char * const apName);
125+
int getIndex(const char * const apName) const;
127126

128127
/**
129128
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
130129
*/
131-
void bind(const int aIndex, const int aValue);
130+
void bind(const int aIndex, const int32_t aValue);
132131
/**
133132
* @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
134133
*/
135-
void bind(const int aIndex, const unsigned aValue);
136-
137-
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
138-
/**
139-
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
140-
*/
141-
void bind(const int aIndex, const long aValue)
142-
{
143-
bind(aIndex, static_cast<int>(aValue));
144-
}
145-
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
146-
/**
147-
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
148-
*/
149-
void bind(const int aIndex, const long aValue)
150-
{
151-
bind(aIndex, static_cast<long long>(aValue));
152-
}
153-
#endif
154-
134+
void bind(const int aIndex, const uint32_t aValue);
155135
/**
156136
* @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
157137
*/
158-
void bind(const int aIndex, const long long aValue);
138+
void bind(const int aIndex, const int64_t aValue);
159139
/**
160140
* @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
161141
*/
@@ -210,39 +190,21 @@ class Statement
210190
/**
211191
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
212192
*/
213-
void bind(const char* apName, const int aValue)
193+
void bind(const char* apName, const int32_t aValue)
214194
{
215195
bind(getIndex(apName), aValue);
216196
}
217197
/**
218198
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
219199
*/
220-
void bind(const char* apName, const unsigned aValue)
200+
void bind(const char* apName, const uint32_t aValue)
221201
{
222202
bind(getIndex(apName), aValue);
223203
}
224-
225-
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
226-
/**
227-
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
228-
*/
229-
void bind(const char* apName, const long aValue)
230-
{
231-
bind(apName, static_cast<int>(aValue));
232-
}
233-
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
234-
/**
235-
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
236-
*/
237-
void bind(const char* apName, const long aValue)
238-
{
239-
bind(apName, static_cast<long long>(aValue));
240-
}
241-
#endif
242204
/**
243205
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
244206
*/
245-
void bind(const char* apName, const long long aValue)
207+
void bind(const char* apName, const int64_t aValue)
246208
{
247209
bind(getIndex(apName), aValue);
248210
}
@@ -325,46 +287,28 @@ class Statement
325287
/**
326288
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
327289
*/
328-
void bind(const std::string& aName, const int aValue)
290+
void bind(const std::string& aName, const int32_t aValue)
329291
{
330292
bind(aName.c_str(), aValue);
331293
}
332294
/**
333295
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
334296
*/
335-
void bind(const std::string& aName, const unsigned aValue)
297+
void bind(const std::string& aName, const uint32_t aValue)
336298
{
337299
bind(aName.c_str(), aValue);
338300
}
339-
340-
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
341-
/**
342-
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
343-
*/
344-
void bind(const std::string& aName, const long aValue)
345-
{
346-
bind(aName.c_str(), static_cast<int>(aValue));
347-
}
348-
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
349-
/**
350-
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
351-
*/
352-
void bind(const std::string& aName, const long aValue)
353-
{
354-
bind(aName.c_str(), static_cast<long long>(aValue));
355-
}
356-
#endif
357301
/**
358302
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
359303
*/
360-
void bind(const std::string& aName, const long long aValue)
304+
void bind(const std::string& aName, const int64_t aValue)
361305
{
362306
bind(aName.c_str(), aValue);
363307
}
364308
/**
365309
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
366310
*/
367-
void bind(const std::string& aName, const double aValue)
311+
void bind(const std::string& aName, const double aValue)
368312
{
369313
bind(aName.c_str(), aValue);
370314
}
@@ -519,7 +463,7 @@ class Statement
519463
* Thus, you should instead extract immediately its data (getInt(), getText()...)
520464
* and use or copy this data for any later usage.
521465
*/
522-
Column getColumn(const int aIndex);
466+
Column getColumn(const int aIndex) const;
523467

524468
/**
525469
* @brief Return a copy of the column data specified by its column name (less efficient than using an index)
@@ -550,7 +494,7 @@ class Statement
550494
*
551495
* Throw an exception if the specified name is not one of the aliased name of the columns in the result.
552496
*/
553-
Column getColumn(const char* apName);
497+
Column getColumn(const char* apName) const;
554498

555499
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
556500
/**
@@ -673,7 +617,7 @@ class Statement
673617
}
674618

675619
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
676-
std::string getExpandedSQL();
620+
std::string getExpandedSQL() const;
677621

678622
/// Return the number of columns in the result set returned by the prepared statement
679623
int getColumnCount() const
@@ -701,52 +645,8 @@ class Statement
701645
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
702646
const char* getErrorMsg() const noexcept;
703647

704-
private:
705-
/**
706-
* @brief Shared pointer to the sqlite3_stmt SQLite Statement Object.
707-
*
708-
* Manage the finalization of the sqlite3_stmt with a reference counter.
709-
*
710-
* This is a internal class, not part of the API (hence full documentation is in the cpp).
711-
*/
712-
// TODO Convert this whole custom pointer to a C++11 std::shared_ptr with a custom deleter
713-
class Ptr
714-
{
715-
public:
716-
// Prepare the statement and initialize its reference counter
717-
Ptr(sqlite3* apSQLite, std::string& aQuery);
718-
// Copy constructor increments the ref counter
719-
Ptr(const Ptr& aPtr);
720-
721-
// Move constructor
722-
Ptr(Ptr&& aPtr);
723-
724-
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
725-
~Ptr();
726-
727-
/// Inline cast operator returning the pointer to SQLite Database Connection Handle
728-
operator sqlite3*() const
729-
{
730-
return mpSQLite;
731-
}
732-
733-
/// Inline cast operator returning the pointer to SQLite Statement Object
734-
operator sqlite3_stmt*() const
735-
{
736-
return mpStmt;
737-
}
738-
739-
private:
740-
/// @{ Unused/forbidden copy/assignment operator
741-
Ptr& operator=(const Ptr& aPtr);
742-
/// @}
743-
744-
private:
745-
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
746-
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
747-
unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt
748-
//!< (to share it with Column objects)
749-
};
648+
/// Shared pointer to SQLite Prepared Statement Object
649+
using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
750650

751651
private:
752652
/**
@@ -758,7 +658,7 @@ class Statement
758658
{
759659
if (SQLite::OK != aRet)
760660
{
761-
throw SQLite::Exception(mStmtPtr, aRet);
661+
throw SQLite::Exception(mpSQLite, aRet);
762662
}
763663
}
764664

@@ -784,17 +684,30 @@ class Statement
784684
}
785685
}
786686

787-
private:
788-
/// Map of columns index by name (mutable so getColumnIndex can be const)
789-
typedef std::map<std::string, int> TColumnNames;
687+
/**
688+
* @brief Prepare statement object.
689+
*
690+
* @return Shared pointer to prepared statement object
691+
*/
692+
TStatementPtr prepareStatement();
790693

791-
private:
792-
std::string mQuery; //!< UTF-8 SQL Query
793-
Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
794-
int mColumnCount; //!< Number of columns in the result of the prepared statement
795-
mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const)
796-
bool mbHasRow; //!< true when a row has been fetched with executeStep()
797-
bool mbDone; //!< true when the last executeStep() had no more row to fetch
694+
/**
695+
* @brief Return a prepared statement object.
696+
*
697+
* Throw an exception if the statement object was not prepared.
698+
* @return raw pointer to Prepared Statement Object
699+
*/
700+
sqlite3_stmt* getPreparedStatement() const;
701+
702+
std::string mQuery; //!< UTF-8 SQL Query
703+
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
704+
TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object
705+
int mColumnCount{0}; //!< Number of columns in the result of the prepared statement
706+
bool mbHasRow{false}; //!< true when a row has been fetched with executeStep()
707+
bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch
708+
709+
/// Map of columns index by name (mutable so getColumnIndex can be const)
710+
mutable std::map<std::string, int> mColumnNames{};
798711
};
799712

800713

0 commit comments

Comments
 (0)