mirror of
https://github.com/getml/sqlgen.git
synced 2026-05-19 23:20:12 -05:00
Refactored the write and read function (#61)
This commit is contained in:
committed by
GitHub
parent
3769f50501
commit
9c67ff24e4
@@ -44,10 +44,10 @@ class Session {
|
||||
return conn_->execute(_sql);
|
||||
}
|
||||
|
||||
Result<Nothing> insert(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
return conn_->insert(_stmt, _data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> insert(const dynamic::Insert& _stmt, ItBegin _begin,
|
||||
ItEnd _end) {
|
||||
return conn_->insert(_stmt, _begin, _end);
|
||||
}
|
||||
|
||||
Session& operator=(const Session& _other) = delete;
|
||||
@@ -79,9 +79,9 @@ class Session {
|
||||
|
||||
Result<Nothing> end_write() { return conn_->end_write(); }
|
||||
|
||||
Result<Nothing> write(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
return conn_->write(_data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> write(ItBegin _begin, ItEnd _end) {
|
||||
return conn_->write(_begin, _end);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -55,10 +55,10 @@ class Transaction {
|
||||
return conn_->execute(_sql);
|
||||
}
|
||||
|
||||
Result<Nothing> insert(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
return conn_->insert(_stmt, _data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> insert(const dynamic::Insert& _stmt, ItBegin _begin,
|
||||
ItEnd _end) {
|
||||
return conn_->insert(_stmt, _begin, _end);
|
||||
}
|
||||
|
||||
Transaction& operator=(const Transaction& _other) = delete;
|
||||
@@ -98,9 +98,9 @@ class Transaction {
|
||||
|
||||
Result<Nothing> end_write() { return conn_->end_write(); }
|
||||
|
||||
Result<Nothing> write(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
return conn_->write(_data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> write(ItBegin _begin, ItEnd _end) {
|
||||
return conn_->write(_begin, _end);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -29,27 +29,9 @@ Result<Ref<Connection>> insert_impl(const Ref<Connection>& _conn,
|
||||
const auto insert_stmt =
|
||||
transpilation::to_insert_or_write<T, dynamic::Insert>(_or_replace);
|
||||
|
||||
std::vector<std::vector<std::optional<std::string>>> data;
|
||||
|
||||
for (auto it = _begin; it != _end; ++it) {
|
||||
data.emplace_back(internal::to_str_vec(*it));
|
||||
if (data.size() == SQLGEN_BATCH_SIZE) {
|
||||
const auto res = _conn->insert(insert_stmt, data);
|
||||
if (!res) {
|
||||
return error(res.error().what());
|
||||
}
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() != 0) {
|
||||
const auto res = _conn->insert(insert_stmt, data);
|
||||
if (!res) {
|
||||
return error(res.error().what());
|
||||
}
|
||||
}
|
||||
|
||||
return _conn;
|
||||
return _conn->insert(insert_stmt, _begin, _end).transform([&](const auto&) {
|
||||
return _conn;
|
||||
});
|
||||
}
|
||||
|
||||
template <class ItBegin, class ItEnd, class Connection>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef SQLGEN_INTERNAL_WRITE_OR_INSERT_HPP_
|
||||
#define SQLGEN_INTERNAL_WRITE_OR_INSERT_HPP_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "batch_size.hpp"
|
||||
#include "to_str_vec.hpp"
|
||||
|
||||
namespace sqlgen::internal {
|
||||
|
||||
template <class FuncType, class ItBegin, class ItEnd>
|
||||
Result<Nothing> write_or_insert(const FuncType& _actual_insert, ItBegin _begin,
|
||||
ItEnd _end) noexcept {
|
||||
std::vector<std::vector<std::optional<std::string>>> data;
|
||||
for (auto it = _begin; it != _end; ++it) {
|
||||
data.emplace_back(to_str_vec(*it));
|
||||
if (data.size() == SQLGEN_BATCH_SIZE) {
|
||||
const auto res = _actual_insert(data);
|
||||
if (!res) {
|
||||
return res;
|
||||
}
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
if (data.size() != 0) {
|
||||
return _actual_insert(data);
|
||||
}
|
||||
return Nothing{};
|
||||
}
|
||||
|
||||
} // namespace sqlgen::internal
|
||||
|
||||
#endif
|
||||
@@ -18,48 +18,45 @@ namespace sqlgen {
|
||||
|
||||
/// The concept any connection needs to implements.
|
||||
template <class ConnType>
|
||||
concept is_connection =
|
||||
requires(ConnType c, std::string _sql, dynamic::Statement _stmt,
|
||||
dynamic::SelectFrom _select_from, dynamic::Insert _insert,
|
||||
const dynamic::Write& _write,
|
||||
std::vector<std::vector<std::optional<std::string>>> _data) {
|
||||
/// Begins a transaction.
|
||||
{ c.begin_transaction() } -> std::same_as<Result<Nothing>>;
|
||||
concept is_connection = requires(
|
||||
ConnType c, std::string _sql, dynamic::Statement _stmt,
|
||||
dynamic::SelectFrom _select_from, dynamic::Insert _insert,
|
||||
const dynamic::Write& _write, std::vector<internal::MockTable> _data) {
|
||||
/// Begins a transaction.
|
||||
{ c.begin_transaction() } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Commits a transaction.
|
||||
{ c.commit() } -> std::same_as<Result<Nothing>>;
|
||||
/// Commits a transaction.
|
||||
{ c.commit() } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Executes a statement.
|
||||
{ c.execute(_sql) } -> std::same_as<Result<Nothing>>;
|
||||
/// Executes a statement.
|
||||
{ c.execute(_sql) } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Inserts data into the database using the INSERT statement.
|
||||
/// More minimal approach than write, but can be used inside transactions.
|
||||
{ c.insert(_insert, _data) } -> std::same_as<Result<Nothing>>;
|
||||
/// Inserts data into the database using the INSERT statement.
|
||||
/// More minimal approach than write, but can be used inside transactions.
|
||||
{
|
||||
c.insert(_insert, _data.begin(), _data.end())
|
||||
} -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Reads the results of a SelectFrom statement.
|
||||
{
|
||||
c.template read<std::vector<internal::MockTable>>(_select_from)
|
||||
} -> std::same_as<Result<std::vector<internal::MockTable>>>;
|
||||
/// Reads the results of a SelectFrom statement.
|
||||
{
|
||||
c.template read<std::vector<internal::MockTable>>(_select_from)
|
||||
} -> std::same_as<Result<std::vector<internal::MockTable>>>;
|
||||
|
||||
/// Commits a transaction.
|
||||
{ c.rollback() } -> std::same_as<Result<Nothing>>;
|
||||
/// Commits a transaction.
|
||||
{ c.rollback() } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Transpiles a statement to a particular SQL dialect.
|
||||
{ c.to_sql(_stmt) } -> std::same_as<std::string>;
|
||||
/// Transpiles a statement to a particular SQL dialect.
|
||||
{ c.to_sql(_stmt) } -> std::same_as<std::string>;
|
||||
|
||||
/// Starts the write operation.
|
||||
{ c.start_write(_write) } -> std::same_as<Result<Nothing>>;
|
||||
/// Starts the write operation.
|
||||
{ c.start_write(_write) } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Ends the write operation and thus commits the results.
|
||||
{ c.end_write() } -> std::same_as<Result<Nothing>>;
|
||||
/// Ends the write operation and thus commits the results.
|
||||
{ c.end_write() } -> std::same_as<Result<Nothing>>;
|
||||
|
||||
/// Writes data into a table. Each vector in data MUST have the same
|
||||
/// length as _stmt.columns. You MUST call .start_write(...) first and
|
||||
/// call .end_write() after all the data has been written. You CAN write
|
||||
/// the data in chunks, meaning you can call .write(...) more than once
|
||||
/// between .start_write(...) and .end_write().
|
||||
{ c.write(_data) } -> std::same_as<Result<Nothing>>;
|
||||
};
|
||||
/// Writes data into a table.
|
||||
{ c.write(_data.begin(), _data.end()) } -> std::same_as<Result<Nothing>>;
|
||||
};
|
||||
|
||||
} // namespace sqlgen
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "../dynamic/Statement.hpp"
|
||||
#include "../dynamic/Write.hpp"
|
||||
#include "../internal/to_container.hpp"
|
||||
#include "../internal/write_or_insert.hpp"
|
||||
#include "../is_connection.hpp"
|
||||
#include "../transpilation/value_t.hpp"
|
||||
#include "Credentials.hpp"
|
||||
@@ -48,10 +49,13 @@ class Connection {
|
||||
return exec(conn_, _sql);
|
||||
}
|
||||
|
||||
Result<Nothing> insert(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> insert(const dynamic::Insert& _stmt, ItBegin _begin,
|
||||
ItEnd _end) noexcept {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return insert_impl(_stmt, _data); }, _begin,
|
||||
_end);
|
||||
}
|
||||
|
||||
template <class ContainerType>
|
||||
auto read(const dynamic::SelectFrom& _query) {
|
||||
@@ -68,8 +72,11 @@ class Connection {
|
||||
|
||||
Result<Nothing> start_write(const dynamic::Write& _stmt);
|
||||
|
||||
Result<Nothing> write(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> write(ItBegin _begin, ItEnd _end) {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return write_impl(_data); }, _begin, _end);
|
||||
}
|
||||
|
||||
Result<Nothing> end_write();
|
||||
|
||||
@@ -80,6 +87,11 @@ class Connection {
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data,
|
||||
MYSQL_STMT* _stmt) const noexcept;
|
||||
|
||||
Result<Nothing> insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
|
||||
static ConnPtr make_conn(const Credentials& _credentials);
|
||||
|
||||
Result<StmtPtr> prepare_statement(
|
||||
@@ -88,6 +100,9 @@ class Connection {
|
||||
|
||||
Result<Ref<IteratorBase>> read_impl(const dynamic::SelectFrom& _query);
|
||||
|
||||
Result<Nothing> write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
|
||||
private:
|
||||
/// A prepared statement - needed for the read and write operations. Note that
|
||||
/// we have declared it before conn_, meaning it will be destroyed first.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "../dynamic/Statement.hpp"
|
||||
#include "../dynamic/Write.hpp"
|
||||
#include "../internal/to_container.hpp"
|
||||
#include "../internal/write_or_insert.hpp"
|
||||
#include "../is_connection.hpp"
|
||||
#include "../transpilation/value_t.hpp"
|
||||
#include "Credentials.hpp"
|
||||
@@ -44,10 +45,13 @@ class Connection {
|
||||
return exec(conn_, _sql).transform([](auto&&) { return Nothing{}; });
|
||||
}
|
||||
|
||||
Result<Nothing> insert(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> insert(const dynamic::Insert& _stmt, ItBegin _begin,
|
||||
ItEnd _end) noexcept {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return insert_impl(_stmt, _data); }, _begin,
|
||||
_end);
|
||||
}
|
||||
|
||||
template <class ContainerType>
|
||||
auto read(const dynamic::SelectFrom& _query) {
|
||||
@@ -68,10 +72,18 @@ class Connection {
|
||||
|
||||
Result<Nothing> end_write();
|
||||
|
||||
Result<Nothing> write(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> write(ItBegin _begin, ItEnd _end) {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return write_impl(_data); }, _begin, _end);
|
||||
}
|
||||
|
||||
private:
|
||||
Result<Nothing> insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
|
||||
static ConnPtr make_conn(const std::string& _conn_str);
|
||||
|
||||
Result<Ref<IteratorBase>> read_impl(const dynamic::SelectFrom& _query);
|
||||
@@ -79,6 +91,9 @@ class Connection {
|
||||
std::string to_buffer(
|
||||
const std::vector<std::optional<std::string>>& _line) const noexcept;
|
||||
|
||||
Result<Nothing> write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
|
||||
private:
|
||||
ConnPtr conn_;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../Transaction.hpp"
|
||||
#include "../dynamic/Write.hpp"
|
||||
#include "../internal/to_container.hpp"
|
||||
#include "../internal/write_or_insert.hpp"
|
||||
#include "../is_connection.hpp"
|
||||
#include "../transpilation/value_t.hpp"
|
||||
#include "to_sql.hpp"
|
||||
@@ -39,10 +40,13 @@ class Connection {
|
||||
|
||||
Result<Nothing> execute(const std::string& _sql) noexcept;
|
||||
|
||||
Result<Nothing> insert(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> insert(const dynamic::Insert& _stmt, ItBegin _begin,
|
||||
ItEnd _end) noexcept {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return insert_impl(_stmt, _data); }, _begin,
|
||||
_end);
|
||||
}
|
||||
|
||||
template <class ContainerType>
|
||||
auto read(const dynamic::SelectFrom& _query) {
|
||||
@@ -61,8 +65,11 @@ class Connection {
|
||||
|
||||
Result<Nothing> end_write();
|
||||
|
||||
Result<Nothing> write(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
template <class ItBegin, class ItEnd>
|
||||
Result<Nothing> write(ItBegin _begin, ItEnd _end) {
|
||||
return internal::write_or_insert(
|
||||
[&](const auto& _data) { return write_impl(_data); }, _begin, _end);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Generates the underlying connection.
|
||||
@@ -74,12 +81,22 @@ class Connection {
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data,
|
||||
sqlite3_stmt* _stmt) const noexcept;
|
||||
|
||||
/// Implements the actual insert.
|
||||
Result<Nothing> insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept;
|
||||
|
||||
/// Generates a prepared statment, usually for inserts.
|
||||
Result<StmtPtr> prepare_statement(const std::string& _sql) const noexcept;
|
||||
|
||||
/// Implements the actual read.
|
||||
Result<Ref<IteratorBase>> read_impl(const dynamic::SelectFrom& _query);
|
||||
|
||||
/// Implements the actual write
|
||||
Result<Nothing> write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data);
|
||||
|
||||
private:
|
||||
/// A prepared statement - needed for the read and write operations. Note that
|
||||
/// we have declared it before conn_, meaning it will be destroyed first.
|
||||
|
||||
@@ -35,26 +35,11 @@ Result<Ref<Connection>> write(const Ref<Connection>& _conn, ItBegin _begin,
|
||||
};
|
||||
|
||||
const auto write = [&](const auto&) -> Result<Nothing> {
|
||||
std::vector<std::vector<std::optional<std::string>>> data;
|
||||
for (auto it = _begin; it != _end; ++it) {
|
||||
data.emplace_back(internal::to_str_vec(*it));
|
||||
if (data.size() == SQLGEN_BATCH_SIZE) {
|
||||
const auto res = _conn->write(data);
|
||||
if (!res) {
|
||||
_conn->end_write();
|
||||
return res;
|
||||
}
|
||||
data.clear();
|
||||
}
|
||||
const auto res = _conn->write(_begin, _end);
|
||||
if (!res) {
|
||||
_conn->end_write();
|
||||
}
|
||||
if (data.size() != 0) {
|
||||
const auto res = _conn->write(data);
|
||||
if (!res) {
|
||||
_conn->end_write();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return Nothing{};
|
||||
return res;
|
||||
};
|
||||
|
||||
const auto end_write = [&](const auto&) -> Result<Nothing> {
|
||||
|
||||
@@ -70,7 +70,7 @@ Result<Nothing> Connection::actual_insert(
|
||||
return Nothing{};
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::insert(
|
||||
Result<Nothing> Connection::insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept {
|
||||
@@ -157,7 +157,7 @@ Result<Nothing> Connection::start_write(const dynamic::Write& _write_stmt) {
|
||||
});
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::write(
|
||||
Result<Nothing> Connection::write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
if (!stmt_) {
|
||||
return error(
|
||||
|
||||
@@ -28,7 +28,7 @@ Result<Nothing> Connection::end_write() {
|
||||
return Nothing{};
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::insert(
|
||||
Result<Nothing> Connection::insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept {
|
||||
@@ -139,7 +139,7 @@ std::string Connection::to_buffer(
|
||||
"\n";
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::write(
|
||||
Result<Nothing> Connection::write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
for (const auto& line : _data) {
|
||||
const auto buffer = to_buffer(line);
|
||||
|
||||
@@ -78,7 +78,7 @@ Result<Nothing> Connection::execute(const std::string& _sql) noexcept {
|
||||
return Nothing{};
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::insert(
|
||||
Result<Nothing> Connection::insert_impl(
|
||||
const dynamic::Insert& _stmt,
|
||||
const std::vector<std::vector<std::optional<std::string>>>&
|
||||
_data) noexcept {
|
||||
@@ -158,7 +158,7 @@ Result<Nothing> Connection::start_write(const dynamic::Write& _stmt) {
|
||||
.and_then([&](const auto&) { return begin_transaction(); });
|
||||
}
|
||||
|
||||
Result<Nothing> Connection::write(
|
||||
Result<Nothing> Connection::write_impl(
|
||||
const std::vector<std::vector<std::optional<std::string>>>& _data) {
|
||||
if (!stmt_) {
|
||||
return error(
|
||||
|
||||
Reference in New Issue
Block a user