Started working on the sqlite::Iterator

This commit is contained in:
Dr. Patrick Urbanke
2025-04-09 09:58:49 +02:00
parent 2beeb9fe8d
commit c1043ff428
3 changed files with 79 additions and 5 deletions

View File

@@ -34,9 +34,7 @@ class Connection : public sqlgen::Connection {
Result<Nothing> execute(const std::string& _sql) noexcept final;
Result<Ref<IteratorBase>> read(const dynamic::SelectFrom& _query) final {
return error("TODO");
}
Result<Ref<IteratorBase>> read(const dynamic::SelectFrom& _query) final;
std::string to_sql(const dynamic::Statement& _stmt) noexcept final;
@@ -71,8 +69,8 @@ class Connection : public sqlgen::Connection {
std::string type_to_sql(const dynamic::Type& _type) noexcept;
private:
/// A prepared statement - needed for the write operations. Note that we have
/// declared it before conn_, meaning it will be destroyed first.
/// A prepared statement - needed for the read and write operations. Note that
/// we have declared it before conn_, meaning it will be destroyed first.
StmtPtr stmt_;
/// The underlying sqlite3 connection.

View File

@@ -0,0 +1,53 @@
#ifndef SQLGEN_SQLITE_ITERATOR_HPP_
#define SQLGEN_SQLITE_ITERATOR_HPP_
#include <sqlite3.h>
#include <optional>
#include <string>
#include <vector>
#include "../IteratorBase.hpp"
#include "../Ref.hpp"
#include "../Result.hpp"
#include "Connection.hpp"
namespace sqlgen::sqlite {
class Iterator : public sqlgen::IteratorBase {
using ConnPtr = Ref<sqlite3>;
using StmtPtr = Ref<sqlite3_stmt>;
public:
Iterator(const StmtPtr& _stmt, const ConnPtr& _conn)
: rownum_(0), stmt_(_stmt), conn_(_conn) {}
~Iterator() = default;
/// Whether the end of the available data has been reached.
bool end() const final { return false; }
/// Returns the next batch of rows.
/// If _batch_size is greater than the number of rows left, returns all
/// of the rows left.
Result<std::vector<std::vector<std::optional<std::string>>>> next(
const size_t _batch_size) final {
return error("TODO");
}
private:
/// The current rownumber.
size_t rownum_;
/// The prepared statement. Note that we have
/// declared it before conn_, meaning it will be destroyed first.
StmtPtr stmt_;
/// The underlying sqlite3 connection. We have this in here to prevent its
/// destruction for the lifetime of the iterator.
ConnPtr conn_;
};
} // namespace sqlgen::sqlite
#endif

View File

@@ -6,6 +6,7 @@
#include "sqlgen/internal/collect/vector.hpp"
#include "sqlgen/internal/strings/strings.hpp"
#include "sqlgen/sqlite/Iterator.hpp"
namespace sqlgen::sqlite {
@@ -112,6 +113,28 @@ std::string Connection::properties_to_sql(
std::string(_p.nullable ? "" : " NOT NULL");
}
Result<Ref<IteratorBase>> Connection::read(const dynamic::SelectFrom& _query) {
const auto sql = to_sql(_query);
sqlite3_stmt* p_stmt = nullptr;
sqlite3_prepare(conn_.get(), /* Database handle */
sql.c_str(), /* SQL statement, UTF-8 encoded */
sql.size(), /* Maximum length of zSql in bytes. */
&p_stmt, /* OUT: Statement handle */
nullptr /* OUT: Pointer to unused portion of zSql */
);
if (!p_stmt) {
return error(sqlite3_errmsg(conn_.get()));
}
return Ref<sqlite3_stmt>::make(StmtPtr(p_stmt, &sqlite3_finalize))
.transform([&](auto _stmt) -> Ref<IteratorBase> {
return Ref<Iterator>::make(_stmt, conn_);
});
}
std::string Connection::to_sql(const dynamic::Statement& _stmt) noexcept {
return _stmt.visit([&](const auto& _s) -> std::string {
using S = std::remove_cvref_t<decltype(_s)>;