9#include <mongocxx/client.hpp>
10#include <mongocxx/database.hpp>
11#include <mongocxx/collection.hpp>
12#include <mongocxx/instance.hpp>
13#include <mongocxx/uri.hpp>
14#include <bsoncxx/json.hpp>
15#include <bsoncxx/builder/stream/document.hpp>
16#include <bsoncxx/document/view.hpp>
37 : client_(nullptr), database_(nullptr)
51 static mongocxx::instance instance{};
54 mongocxx::uri uri{conn_uri};
57 auto client = std::make_unique<mongocxx::client>(uri);
61 auto* mongo_client =
static_cast<mongocxx::client*
>(
client_);
62 auto db = std::make_unique<mongocxx::database>((*mongo_client)[
db_name_]);
66 auto* mongo_db =
static_cast<mongocxx::database*
>(
database_);
67 auto result = mongo_db->run_command(bsoncxx::builder::stream::document{} <<
"ping" << 1 << bsoncxx::builder::stream::finalize);
70 return kcenon::common::ok();
71 }
catch (
const std::exception& e) {
72 last_error_ = std::string(
"Connection error: ") + e.what();
76 logger_.warning(
"MongoDB support not compiled. Mock mode enabled.");
79 return kcenon::common::ok();
83 last_error_ =
"Failed to connect to MongoDB server";
85 return kcenon::common::error_info{
102 delete static_cast<mongocxx::database*
>(
database_);
106 delete static_cast<mongocxx::client*
>(
client_);
112 return kcenon::common::ok();
116 std::string& collection,
118 std::string& update)
const
121 std::istringstream ss(query_string);
123 std::vector<std::string> parts;
125 while (std::getline(ss, part,
':')) {
126 parts.push_back(part);
129 if (parts.size() >= 1) collection = parts[0];
130 if (parts.size() >= 2) filter = parts[1];
131 if (parts.size() >= 3) update = parts[2];
133 return !collection.empty();
140 return kcenon::common::error_info{
152 return kcenon::common::error_info{
160 std::string collection_name, filter_json, unused;
163 return kcenon::common::error_info{
170 auto* mongo_db =
static_cast<mongocxx::database*
>(
database_);
171 auto collection = (*mongo_db)[collection_name];
174 bsoncxx::document::value filter_doc = filter_json.empty() ?
175 bsoncxx::builder::stream::document{} << bsoncxx::builder::stream::finalize :
176 bsoncxx::from_json(filter_json);
178 auto cursor = collection.find(filter_doc.view());
180 for (
auto&& doc : cursor) {
184 auto json_string = bsoncxx::to_json(doc);
185 row[
"_document"] = json_string;
188 auto view = doc.view();
190 row[
"_id"] = bsoncxx::to_json(view[
"_id"].get_value());
194 for (
auto&& element : view) {
195 std::string key = element.key().to_string();
197 row[key] = bsoncxx::to_json(element.get_value());
201 result.push_back(std::move(row));
203 }
catch (
const std::exception& e) {
204 last_error_ = std::string(
"Select error: ") + e.what();
206 return kcenon::common::error_info{
213 logger_.warning(
"MongoDB support not compiled. Select query: " + query_string.substr(0, 20) +
"...");
216 mock_row[
"_id"] = std::string(
"mock_object_id");
217 mock_row[
"name"] = std::string(
"mongodb_mock_data");
218 mock_row[
"_document"] = std::string(
"{\"_id\":\"mock_object_id\",\"name\":\"mongodb_mock_data\"}");
219 result.push_back(mock_row);
230 return kcenon::common::error_info{
241 return kcenon::common::error_info{
250 auto* mongo_db =
static_cast<mongocxx::database*
>(
database_);
254 auto command_doc = bsoncxx::from_json(query_string);
255 auto result = mongo_db->run_command(command_doc.view());
257 return kcenon::common::ok();
258 }
catch (
const std::exception&) {
260 std::string collection_name = query_string;
261 auto collection = (*mongo_db)[collection_name];
262 auto doc = bsoncxx::builder::stream::document{} <<
"test" <<
"creation" << bsoncxx::builder::stream::finalize;
263 collection.insert_one(doc.view());
264 collection.delete_one(doc.view());
266 return kcenon::common::ok();
268 }
catch (
const std::exception& e) {
269 last_error_ = std::string(
"Execute error: ") + e.what();
271 return kcenon::common::error_info{
279 logger_.info(
"MongoDB support not compiled. Mock execute: " + query_string);
281 return kcenon::common::ok();
289 return kcenon::common::error_info{
298 return kcenon::common::error_info{
309 return kcenon::common::ok();
316 return kcenon::common::error_info{
325 return kcenon::common::error_info{
334 return kcenon::common::ok();
341 return kcenon::common::error_info{
350 return kcenon::common::ok();
355 return kcenon::common::ok();
370 std::map<std::string, std::string> info;
371 info[
"backend"] =
"mongodb";
383 std::ostringstream oss;
397 if (!config.
host.empty()) {
404 if (config.
port > 0) {
405 oss <<
":" << config.
port;
419 for (
const auto& [key, value] : config.
options) {
423 oss << key <<
"=" << value;
Centralized logging utility for database backends.
void * client_
MongoDB client (mongocxx::client*)
kcenon::common::VoidResult rollback_transaction() override
Rollback the current transaction.
kcenon::common::Result< core::database_result > select_query(const std::string &query_string) override
Execute a SELECT query.
bool parse_query_string(const std::string &query_string, std::string &collection, std::string &filter, std::string &update) const
Parse query string format.
mongodb_backend()
Default constructor.
std::mutex mongo_mutex_
Mutex for thread safety.
kcenon::common::VoidResult begin_transaction() override
Begin a transaction.
std::string build_connection_uri(const core::connection_config &config) const
Convert connection_config to MongoDB connection URI.
std::string last_error() const override
Get last error message from backend.
std::string last_error_
Last error message.
void * database_
MongoDB database (mongocxx::database*)
bool in_transaction() const override
Check if backend is currently in a transaction.
std::string db_name_
Database name.
std::map< std::string, std::string > connection_info() const override
Get backend-specific connection information.
kcenon::common::VoidResult do_initialize(const core::connection_config &config)
Database-specific initialization logic.
std::atomic< bool > in_transaction_
Transaction state.
core::connection_config connection_config_
Cached connection config.
kcenon::common::VoidResult commit_transaction() override
Commit the current transaction.
kcenon::common::VoidResult execute_query(const std::string &query_string) override
Execute a general SQL query (DDL, DML)
kcenon::common::VoidResult do_shutdown()
Database-specific shutdown logic.
std::atomic< bool > initialized_
bool is_initialized() const override
Helper class for automatic backend registration.
Centralized logging utility for database backends.
MongoDB database backend plugin implementation.
std::vector< database_row > database_result
std::map< std::string, database_value > database_row
Result<T> type for database_system error handling.
Configuration for database connection.
std::map< std::string, std::string > options