diff --git a/include/sqlgen/postgres/Connection.hpp b/include/sqlgen/postgres/Connection.hpp index 8865aaf..d58ea53 100644 --- a/include/sqlgen/postgres/Connection.hpp +++ b/include/sqlgen/postgres/Connection.hpp @@ -43,15 +43,13 @@ class Connection : public sqlgen::Connection { std::string to_sql(const dynamic::Statement& _stmt) noexcept final; Result start_write(const dynamic::Insert& _stmt) final { - return error("TODO"); + return execute(to_sql(_stmt)); } - Result end_write() final { return error("TODO"); } + Result end_write() final; Result write( - const std::vector>>& _data) final { - return error("TODO"); - } + const std::vector>>& _data) final; private: std::string add_not_null_if_necessary( @@ -77,6 +75,9 @@ class Connection : public sqlgen::Connection { std::string select_from_to_sql( const dynamic::SelectFrom& _stmt) const noexcept; + std::string to_buffer( + const std::vector>& _line) const noexcept; + std::string type_to_sql(const dynamic::Type& _type) const noexcept; static std::string wrap_in_quotes(const std::string& _name) noexcept { diff --git a/src/sqlgen/postgres/Connection.cpp b/src/sqlgen/postgres/Connection.cpp index 4200351..9884706 100644 --- a/src/sqlgen/postgres/Connection.cpp +++ b/src/sqlgen/postgres/Connection.cpp @@ -58,6 +58,17 @@ std::string Connection::create_table_to_sql( return stream.str(); } +Result Connection::end_write() { + if (PQputCopyEnd(conn_.get(), NULL) == -1) { + return error(PQerrorMessage(conn_.get())); + } + const auto res = PQgetResult(conn_.get()); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + return error(PQerrorMessage(conn_.get())); + } + return Nothing{}; +} + Result> Connection::exec(const std::string& _sql) const noexcept { const auto res = PQexec(conn_.get(), _sql.c_str()); @@ -142,6 +153,26 @@ std::string Connection::select_from_to_sql( return stream.str(); } +std::string Connection::to_buffer( + const std::vector>& _line) const noexcept { + using namespace std::ranges::views; + + const auto edit_field = + [](const std::optional& _field) -> std::string { + if (!_field) { + return "\e"; + } + if (_field->find("\t") != std::string::npos) { + return "\a" + *_field + "\a"; + } + return *_field; + }; + + return internal::strings::join( + "\t", internal::collect::vector(_line | transform(edit_field))) + + "\n"; +} + std::string Connection::to_sql(const dynamic::Statement& _stmt) noexcept { return _stmt.visit([&](const auto& _s) -> std::string { using S = std::remove_cvref_t; @@ -193,4 +224,18 @@ std::string Connection::type_to_sql(const dynamic::Type& _type) const noexcept { }); } +Result Connection::write( + const std::vector>>& _data) { + for (const auto& line : _data) { + const auto buffer = to_buffer(line); + const auto success = PQputCopyData(conn_.get(), buffer.c_str(), + static_cast(buffer.size())); + if (success != 1) { + PQputCopyEnd(conn_.get(), NULL); + return error("Error occurred while writing data to postgres."); + } + } + return Nothing{}; +} + } // namespace sqlgen::postgres