Skip to content

Commit 826a17f

Browse files
committed
Move RowIterator to RowExecutor
1 parent be1d031 commit 826a17f

8 files changed

Lines changed: 183 additions & 147 deletions

File tree

include/SQLiteCpp/Column.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class Column
5252
*
5353
* @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object.
5454
* @param[in] aIndex Index of the column in the row of result, starting at 0
55+
*
56+
* @throws Exception is thrown in case of error, then the Column object is NOT constructed.
5557
*/
5658
explicit Column(const RowExecutor::TStatementPtr& aStmtPtr, int aIndex);
5759

include/SQLiteCpp/Row.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @file Row.h
33
* @ingroup SQLiteCpp
4-
* @brief TODO:
4+
* @brief Container for SQLite Statement Object step
55
*
66
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
77
* Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com)
@@ -11,18 +11,27 @@
1111
*/
1212
#pragma once
1313

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

16+
#include <memory>
1617
#include <string>
1718

19+
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
20+
struct sqlite3_stmt;
21+
1822
namespace SQLite
1923
{
2024

21-
25+
/**
26+
* @brief CLASS IS WIP!
27+
*/
2228
class Row
2329
{
30+
/// Weak pointer to SQLite Prepared Statement Object
31+
using TStatementWeakPtr = std::weak_ptr<sqlite3_stmt>;
32+
2433
public:
25-
Row(RowExecutor::TStatementWeakPtr apRow, std::size_t aID);
34+
Row(TStatementWeakPtr apRow, std::size_t aID);
2635

2736
std::size_t getRowNumber() const
2837
{
@@ -49,7 +58,7 @@ class Row
4958
const char* getText(uint32_t aColumnID) const noexcept;
5059

5160
private:
52-
RowExecutor::TStatementWeakPtr mpRow;
61+
TStatementWeakPtr mpRow;
5362
std::size_t ID;
5463
};
5564

include/SQLiteCpp/RowExecutor.h

Lines changed: 117 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
*/
1212
#pragma once
1313

14-
//#include <SQLiteCpp/Database.h>
15-
#include <SQLiteCpp/Exception.h>
14+
#include <SQLiteCpp/Row.h>
15+
#include <SQLiteCpp/Exception.h>
1616

1717
#include <memory>
1818
#include <string>
@@ -26,7 +26,21 @@ namespace SQLite
2626

2727
extern const int OK; ///< SQLITE_OK
2828

29-
29+
/**
30+
* @brief Base class for prepared SQLite Statement.
31+
*
32+
* You should use SQLite::Statement or (if you had a reson)
33+
* inherit this class to create your own Statement executor class.
34+
* Either way you should look at SQLite::Statement documentation
35+
*
36+
* Thread-safety: a RowExecutor object shall not be shared by multiple threads, because :
37+
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
38+
* provided that no single database connection is used simultaneously in two or more threads."
39+
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
40+
* because of the way it shares the underling SQLite precompiled statement
41+
* in a custom shared pointer (See the inner class "Statement::Ptr").
42+
* TODO Test Serialized mode after all changes to pointers
43+
*/
3044
class RowExecutor
3145
{
3246
public:
@@ -41,7 +55,7 @@ class RowExecutor
4155

4256
/// Weak pointer to SQLite RowExecutor
4357
using TRowWeakPtr = std::weak_ptr<RowExecutor>;
44-
58+
4559
/// Type to store columns names and indexes
4660
using TColumnsMap = std::map<std::string, int, std::less<>>;
4761

@@ -112,25 +126,6 @@ class RowExecutor
112126

113127
////////////////////////////////////////////////////////////////////////////
114128

115-
/**
116-
* @brief Execute a step of the prepared query to fetch one row of results.
117-
*
118-
* While true is returned, a row of results is available, and can be accessed
119-
* through the getColumn() method
120-
*
121-
* @see exec() execute a one-step prepared statement with no expected result
122-
* @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
123-
* @see Database::exec() is a shortcut to execute one or multiple statements without results
124-
*
125-
* @return - true (SQLITE_ROW) if there is another row ready : you can call getColumn(N) to get it
126-
* then you have to call executeStep() again to fetch more rows until the query is finished
127-
* - false (SQLITE_DONE) if the query has finished executing : there is no (more) row of result
128-
* (case of a query with no result, or after N rows fetched successfully)
129-
*
130-
* @throw SQLite::Exception in case of error
131-
*/
132-
const TColumnsMap& getColumnsNames() const;
133-
134129
/// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
135130
int getChanges() const noexcept;
136131

@@ -139,6 +134,13 @@ class RowExecutor
139134
{
140135
return mColumnCount;
141136
}
137+
138+
/// Get columns names with theirs ids
139+
const TColumnsMap& getColumnsNames() const
140+
{
141+
return mColumnNames;
142+
}
143+
142144
/// true when a row has been fetched with executeStep()
143145
bool hasRow() const noexcept
144146
{
@@ -161,10 +163,92 @@ class RowExecutor
161163
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
162164
const char* getErrorMsg() const noexcept;
163165

164-
protected:
166+
////////////////////////////////////////////////////////////////////////////
167+
165168
/**
166-
*
169+
* @brief InputIterator for statement steps.
170+
*
171+
* Remember that this iterator is changing state of RowExecutor.
167172
*/
173+
class RowIterator
174+
{
175+
public:
176+
using iterator_category = std::input_iterator_tag;
177+
using value_type = Row;
178+
using reference = const Row&;
179+
using pointer = const Row*;
180+
using difference_type = std::ptrdiff_t;
181+
182+
RowIterator() = default;
183+
RowIterator(TStatementWeakPtr apStatement, TRowWeakPtr apRow, uint16_t aID) :
184+
mpStatement(apStatement), mpRow(apRow), mID(aID), mRow(apStatement, aID) {}
185+
186+
reference operator*() const
187+
{
188+
return mRow;
189+
}
190+
pointer operator->() const noexcept
191+
{
192+
return &mRow;
193+
}
194+
195+
reference operator++() noexcept
196+
{
197+
mRow = Row(mpStatement, ++mID);
198+
advance();
199+
return mRow;
200+
}
201+
value_type operator++(int)
202+
{
203+
Row copy{ mRow };
204+
mRow = Row(mpStatement, ++mID);
205+
advance();
206+
return copy;
207+
}
208+
209+
bool operator==(const RowIterator& aIt) const;
210+
bool operator!=(const RowIterator& aIt) const
211+
{
212+
return !(*this == aIt);
213+
}
214+
215+
private:
216+
/// Executing next statement step
217+
void advance() noexcept;
218+
219+
TStatementWeakPtr mpStatement{}; //!< Weak pointer to SQLite Statement Object
220+
TRowWeakPtr mpRow{}; //!< Weak pointer to RowExecutor Object
221+
uint16_t mID{}; //!< Current row number
222+
223+
/// Internal row object storage
224+
Row mRow{ mpStatement, mID };
225+
};
226+
227+
/**
228+
* @brief Start execution of SQLite Statement Object and return iterator to first row.
229+
*
230+
* This function calls resets SQLite Statement Object.
231+
*
232+
* @return RowIterator for first row of this prepared statement
233+
*
234+
* @throws Exception is thrown in case of error, then the RowIterator object is NOT constructed.
235+
*/
236+
RowIterator begin();
237+
238+
/**
239+
* @return RowIterator to non-exisitng step
240+
*/
241+
RowIterator end();
242+
243+
protected:
244+
/**
245+
* @brief Proteced construtor to ensure that this class is only created in derived objects
246+
*
247+
* @param[in] apSQLite the SQLite Database Connection
248+
* @param[in] aQuery an UTF-8 encoded query string
249+
*
250+
* @throws Exception is thrown in case of error, then the RowExecutor object is NOT constructed.
251+
*/
168252
explicit RowExecutor(sqlite3* apSQLite, const std::string& aQuery);
169253

170254
/**
@@ -176,15 +260,15 @@ class RowExecutor
176260
{
177261
return mpStatement;
178262
}
179-
263+
180264
/**
181265
* @brief Return a prepared SQLite Statement Object.
182266
*
183267
* Throw an exception if the statement object was not prepared.
184268
* @return raw pointer to Prepared Statement Object
185269
*/
186270
sqlite3_stmt* getPreparedStatement() const;
187-
271+
188272
/**
189273
* @brief Return a prepared SQLite Statement Object.
190274
*
@@ -236,20 +320,20 @@ class RowExecutor
236320
private:
237321
/// Create prepared SQLite Statement Object
238322
void prepareStatement(const std::string& aQuery);
239-
323+
240324
/// Get column number and create map with columns names
241325
void createColumnInfo();
242326

243-
sqlite3* mpSQLite{}; //!< Pointer to SQLite Database Connection Handle
244-
TStatementPtr mpStatement{}; //!< Shared Pointer to the prepared SQLite Statement Object
327+
sqlite3* mpSQLite{}; //!< Pointer to SQLite Database Connection Handle
328+
TStatementPtr mpStatement{}; //!< Shared Pointer to the prepared SQLite Statement Object
245329

246330
/// Shared Pointer to this object.
247331
/// Allows RowIterator to execute next step
248332
TRowPtr mpRowExecutor{};
249333

250-
int mColumnCount = 0; //!< Number of columns in the result of the prepared statement
251-
bool mbHasRow = false; //!< true when a row has been fetched with executeStep()
252-
bool mbDone = false; //!< true when the last executeStep() had no more row to fetch
334+
int mColumnCount = 0; //!< Number of columns in the result of the prepared statement
335+
bool mbHasRow = false; //!< true when a row has been fetched with executeStep()
336+
bool mbDone = false; //!< true when the last executeStep() had no more row to fetch
253337

254338
/// Map of columns index by name (mutable so getColumnIndex can be const)
255339
mutable TColumnsMap mColumnNames{};

include/SQLiteCpp/Statement.h

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#pragma once
1212

1313
#include <SQLiteCpp/RowExecutor.h>
14-
#include <SQLiteCpp/Row.h>
1514
#include <SQLiteCpp/Exception.h>
1615
#include <SQLiteCpp/Utils.h> // SQLITECPP_PURE_FUNC
1716

@@ -56,7 +55,7 @@ class Statement : public RowExecutor
5655
* @param[in] aDatabase the SQLite Database Connection
5756
* @param[in] aQuery an UTF-8 encoded query string
5857
*
59-
* Exception is thrown in case of error, then the Statement object is NOT constructed.
58+
* @throws Exception is thrown in case of error, then the Statement object is NOT constructed.
6059
*/
6160
Statement(const Database& aDatabase, const std::string& aQuery);
6261

@@ -541,62 +540,6 @@ class Statement : public RowExecutor
541540
/// Return the number of bind parameters in the statement
542541
int getBindParameterCount() const noexcept;
543542

544-
////////////////////////////////////////////////////////////////////////////
545-
546-
class RowIterator
547-
{
548-
public:
549-
using iterator_category = std::input_iterator_tag;
550-
using value_type = Row;
551-
using reference = const Row&;
552-
using pointer = const Row*;
553-
using difference_type = std::ptrdiff_t;
554-
555-
RowIterator() = default;
556-
RowIterator(TStatementWeakPtr apStatement, TRowWeakPtr apRow, uint16_t aID) :
557-
mpStatement(apStatement), mpRow(apRow), mID(aID), mRow(apStatement, aID) {}
558-
559-
reference operator*() const
560-
{
561-
return mRow;
562-
}
563-
pointer operator->() const noexcept
564-
{
565-
return &mRow;
566-
}
567-
568-
reference operator++() noexcept
569-
{
570-
mRow = Row(mpStatement, ++mID);
571-
advance();
572-
return mRow;
573-
}
574-
value_type operator++(int)
575-
{
576-
Row copy{ mRow };
577-
mRow = Row(mpStatement, ++mID);
578-
advance();
579-
return copy;
580-
}
581-
582-
bool operator==(const RowIterator& aIt) const;
583-
bool operator!=(const RowIterator& aIt) const
584-
{
585-
return !(*this == aIt);
586-
}
587-
588-
private:
589-
void advance() noexcept;
590-
591-
TStatementWeakPtr mpStatement{};
592-
TRowWeakPtr mpRow{};
593-
uint16_t mID{};
594-
Row mRow{ mpStatement, mID };
595-
};
596-
597-
RowIterator begin();
598-
RowIterator end();
599-
600543
private:
601544
std::string mQuery; //!< UTF-8 SQL Query,
602545
};

src/Row.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @file Row.cpp
33
* @ingroup SQLiteCpp
4-
* @brief TODO:
4+
* @brief Container for SQLite Statement Object step
55
*
66
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
77
* Copyright (c) 2015-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com)
@@ -19,7 +19,7 @@ namespace SQLite
1919
{
2020

2121

22-
Row::Row(RowExecutor::TStatementWeakPtr apRow, std::size_t aID) :
22+
Row::Row(TStatementWeakPtr apRow, std::size_t aID) :
2323
mpRow(apRow), ID(aID)
2424
{
2525
}

0 commit comments

Comments
 (0)