Skip to content

Commit 6da299d

Browse files
committed
Replace Statement::Ptr with std::shared_ptr
1 parent edf49ee commit 6da299d

File tree

4 files changed

+109
-200
lines changed

4 files changed

+109
-200
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+
Column(Statement::TStatementPtr& aStmtPtr, int aIndex) noexcept;
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: 26 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <string>
1717
#include <map>
18+
#include <memory>
1819

1920
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
2021
struct sqlite3;
@@ -50,8 +51,6 @@ extern const int OK; ///< SQLITE_OK
5051
*/
5152
class Statement
5253
{
53-
friend class Column; // For access to Statement::Ptr inner class
54-
5554
public:
5655
/**
5756
* @brief Compile and register the SQL query for the provided SQLite Database Connection
@@ -645,52 +644,8 @@ class Statement
645644
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
646645
const char* getErrorMsg() const noexcept;
647646

648-
private:
649-
/**
650-
* @brief Shared pointer to the sqlite3_stmt SQLite Statement Object.
651-
*
652-
* Manage the finalization of the sqlite3_stmt with a reference counter.
653-
*
654-
* This is a internal class, not part of the API (hence full documentation is in the cpp).
655-
*/
656-
// TODO Convert this whole custom pointer to a C++11 std::shared_ptr with a custom deleter
657-
class Ptr
658-
{
659-
public:
660-
// Prepare the statement and initialize its reference counter
661-
Ptr(sqlite3* apSQLite, std::string& aQuery);
662-
// Copy constructor increments the ref counter
663-
Ptr(const Ptr& aPtr);
664-
665-
// Move constructor
666-
Ptr(Ptr&& aPtr);
667-
668-
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
669-
~Ptr();
670-
671-
/// Inline cast operator returning the pointer to SQLite Database Connection Handle
672-
operator sqlite3*() const
673-
{
674-
return mpSQLite;
675-
}
676-
677-
/// Inline cast operator returning the pointer to SQLite Statement Object
678-
operator sqlite3_stmt*() const
679-
{
680-
return mpStmt;
681-
}
682-
683-
private:
684-
/// @{ Unused/forbidden copy/assignment operator
685-
Ptr& operator=(const Ptr& aPtr);
686-
/// @}
687-
688-
private:
689-
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
690-
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
691-
unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt
692-
//!< (to share it with Column objects)
693-
};
647+
/// Shared pointer to SQLite Prepared Statement Object
648+
typedef std::shared_ptr<sqlite3_stmt> TStatementPtr;
694649

695650
private:
696651
/**
@@ -702,7 +657,7 @@ class Statement
702657
{
703658
if (SQLite::OK != aRet)
704659
{
705-
throw SQLite::Exception(mStmtPtr, aRet);
660+
throw SQLite::Exception(mpSQLite, aRet);
706661
}
707662
}
708663

@@ -728,17 +683,33 @@ class Statement
728683
}
729684
}
730685

686+
/**
687+
* @brief Prepare statement object.
688+
*
689+
* @return Shared pointer to prepared statement object
690+
*/
691+
TStatementPtr prepareStatement();
692+
693+
/**
694+
* @brief Return a prepared statement object.
695+
*
696+
* Throw an exception if the statement object was not prepared.
697+
* @return raw pointer to Prepared Statement Object
698+
*/
699+
sqlite3_stmt* getPreparedStatement() const;
700+
731701
private:
732702
/// Map of columns index by name (mutable so getColumnIndex can be const)
733703
typedef std::map<std::string, int> TColumnNames;
734704

735705
private:
736-
std::string mQuery; //!< UTF-8 SQL Query
737-
Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
738-
int mColumnCount; //!< Number of columns in the result of the prepared statement
739-
mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const)
740-
bool mbHasRow; //!< true when a row has been fetched with executeStep()
741-
bool mbDone; //!< true when the last executeStep() had no more row to fetch
706+
std::string mQuery; //!< UTF-8 SQL Query
707+
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
708+
TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object
709+
int mColumnCount{0}; //!< Number of columns in the result of the prepared statement
710+
mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const)
711+
bool mbHasRow{false}; //!< true when a row has been fetched with executeStep()
712+
bool mbDone{false}; //!< true when the last executeStep() had no more row to fetch
742713
};
743714

744715

src/Column.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const int Null = SQLITE_NULL;
2626

2727

2828
// Encapsulation of a Column in a row of the result pointed by the prepared Statement.
29-
Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept :
29+
Column::Column(Statement::TStatementPtr& aStmtPtr, int aIndex) noexcept :
3030
mStmtPtr(aStmtPtr),
3131
mIndex(aIndex)
3232
{
@@ -35,21 +35,21 @@ Column::Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept :
3535
// Return the named assigned to this result column (potentially aliased)
3636
const char* Column::getName() const noexcept
3737
{
38-
return sqlite3_column_name(mStmtPtr, mIndex);
38+
return sqlite3_column_name(mStmtPtr.get(), mIndex);
3939
}
4040

4141
#ifdef SQLITE_ENABLE_COLUMN_METADATA
4242
// Return the name of the table column that is the origin of this result column
4343
const char* Column::getOriginName() const noexcept
4444
{
45-
return sqlite3_column_origin_name(mStmtPtr, mIndex);
45+
return sqlite3_column_origin_name(mStmtPtr.get(), mIndex);
4646
}
4747
#endif
4848

4949
// Return the integer value of the column specified by its index starting at 0
5050
int Column::getInt() const noexcept
5151
{
52-
return sqlite3_column_int(mStmtPtr, mIndex);
52+
return sqlite3_column_int(mStmtPtr.get(), mIndex);
5353
}
5454

5555
// Return the unsigned integer value of the column specified by its index starting at 0
@@ -61,50 +61,50 @@ unsigned Column::getUInt() const noexcept
6161
// Return the 64bits integer value of the column specified by its index starting at 0
6262
long long Column::getInt64() const noexcept
6363
{
64-
return sqlite3_column_int64(mStmtPtr, mIndex);
64+
return sqlite3_column_int64(mStmtPtr.get(), mIndex);
6565
}
6666

6767
// Return the double value of the column specified by its index starting at 0
6868
double Column::getDouble() const noexcept
6969
{
70-
return sqlite3_column_double(mStmtPtr, mIndex);
70+
return sqlite3_column_double(mStmtPtr.get(), mIndex);
7171
}
7272

7373
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
7474
const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept
7575
{
76-
const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr, mIndex));
76+
const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr.get(), mIndex));
7777
return (pText?pText:apDefaultValue);
7878
}
7979

8080
// Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0
8181
const void* Column::getBlob() const noexcept
8282
{
83-
return sqlite3_column_blob(mStmtPtr, mIndex);
83+
return sqlite3_column_blob(mStmtPtr.get(), mIndex);
8484
}
8585

8686
// Return a std::string to a TEXT or BLOB column
8787
std::string Column::getString() const
8888
{
8989
// Note: using sqlite3_column_blob and not sqlite3_column_text
9090
// - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly
91-
const char *data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr, mIndex));
91+
const char *data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr.get(), mIndex));
9292

9393
// SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()"
9494
// Note: std::string is ok to pass nullptr as first arg, if length is 0
95-
return std::string(data, sqlite3_column_bytes(mStmtPtr, mIndex));
95+
return std::string(data, sqlite3_column_bytes(mStmtPtr.get(), mIndex));
9696
}
9797

9898
// Return the type of the value of the column
9999
int Column::getType() const noexcept
100100
{
101-
return sqlite3_column_type(mStmtPtr, mIndex);
101+
return sqlite3_column_type(mStmtPtr.get(), mIndex);
102102
}
103103

104104
// Return the number of bytes used by the text value of the column
105105
int Column::getBytes() const noexcept
106106
{
107-
return sqlite3_column_bytes(mStmtPtr, mIndex);
107+
return sqlite3_column_bytes(mStmtPtr.get(), mIndex);
108108
}
109109

110110
// Standard std::ostream inserter

0 commit comments

Comments
 (0)