9#include <hiredis/hiredis.h>
30 : context_(nullptr), host_(
"localhost"), port_(6379)
44 redisContext* ctx = redisConnect(
host_.c_str(),
port_);
45 if (ctx ==
nullptr || ctx->err) {
47 last_error_ = std::string(
"Connection error: ") + ctx->errstr;
54 return kcenon::common::error_info{
65 redisReply* reply =
static_cast<redisReply*
>(
66 redisCommand(ctx,
"AUTH %s", config.
password.c_str()));
67 if (reply ==
nullptr || reply->type == REDIS_REPLY_ERROR) {
70 if (reply) freeReplyObject(reply);
73 return kcenon::common::error_info{
79 freeReplyObject(reply);
83 redisReply* ping_reply =
static_cast<redisReply*
>(redisCommand(ctx,
"PING"));
84 if (ping_reply ==
nullptr || ping_reply->type == REDIS_REPLY_ERROR) {
87 if (ping_reply) freeReplyObject(ping_reply);
90 return kcenon::common::error_info{
96 freeReplyObject(ping_reply);
99 return kcenon::common::ok();
100 }
catch (
const std::exception& e) {
101 last_error_ = std::string(
"Connection error: ") + e.what();
105 logger_.warning(
"Redis support not compiled. Mock mode enabled.");
108 return kcenon::common::ok();
114 return kcenon::common::error_info{
131 redisFree(
static_cast<redisContext*
>(
context_));
137 return kcenon::common::ok();
142 std::string& value)
const
145 std::istringstream ss(query_string);
147 std::vector<std::string> parts;
149 while (std::getline(ss, part,
':')) {
150 parts.push_back(part);
153 if (parts.size() >= 1) key = parts[0];
154 if (parts.size() >= 2) value = parts[1];
163 return kcenon::common::error_info{
175 return kcenon::common::error_info{
184 std::string key = query_string;
186 redisContext* ctx =
static_cast<redisContext*
>(
context_);
187 redisReply* reply =
static_cast<redisReply*
>(
188 redisCommand(ctx,
"GET %s", key.c_str()));
190 if (reply !=
nullptr && reply->type != REDIS_REPLY_ERROR &&
191 reply->type != REDIS_REPLY_NIL) {
195 if (reply->type == REDIS_REPLY_STRING) {
196 row[
"value"] = std::string(reply->str, reply->len);
197 }
else if (reply->type == REDIS_REPLY_INTEGER) {
198 row[
"value"] =
static_cast<int64_t
>(reply->integer);
200 row[
"value"] = std::string(
"");
203 result.push_back(std::move(row));
206 if (reply) freeReplyObject(reply);
207 }
catch (
const std::exception& e) {
208 last_error_ = std::string(
"Select error: ") + e.what();
210 return kcenon::common::error_info{
217 logger_.warning(
"Redis support not compiled. Select query: " + query_string.substr(0, 20) +
"...");
219 if (!query_string.empty()) {
221 mock_row[
"key"] = query_string;
222 mock_row[
"value"] = std::string(
"redis_mock_value");
223 result.push_back(mock_row);
235 return kcenon::common::error_info{
246 return kcenon::common::error_info{
255 redisContext* ctx =
static_cast<redisContext*
>(
context_);
256 redisReply* reply =
static_cast<redisReply*
>(
257 redisCommand(ctx,
"%s", query_string.c_str()));
259 if (reply ==
nullptr) {
260 last_error_ = std::string(
"Command failed: ") + ctx->errstr;
262 return kcenon::common::error_info{
270 if (reply->type == REDIS_REPLY_ERROR) {
271 last_error_ = std::string(
"Execute error: ") + reply->str;
276 freeReplyObject(reply);
279 return kcenon::common::error_info{
287 return kcenon::common::ok();
288 }
catch (
const std::exception& e) {
289 last_error_ = std::string(
"Execute error: ") + e.what();
291 return kcenon::common::error_info{
299 logger_.info(
"Redis support not compiled. Mock execute: " + query_string);
301 return kcenon::common::ok();
309 return kcenon::common::error_info{
318 return kcenon::common::error_info{
327 if (result.is_err()) {
333 return kcenon::common::ok();
340 return kcenon::common::error_info{
349 return kcenon::common::error_info{
358 if (result.is_err()) {
364 return kcenon::common::ok();
371 return kcenon::common::error_info{
380 return kcenon::common::ok();
387 if (result.is_err()) {
392 return kcenon::common::ok();
407 std::map<std::string, std::string> info;
408 info[
"backend"] =
"redis";
409 info[
"host"] =
host_;
410 info[
"port"] = std::to_string(
port_);
Centralized logging utility for database backends.
std::string last_error() const override
Get last error message from backend.
kcenon::common::VoidResult rollback_transaction() override
Rollback 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::string host_
Redis host.
kcenon::common::VoidResult commit_transaction() override
Commit the current transaction.
void * context_
Redis context (redisContext*)
kcenon::common::VoidResult begin_transaction() override
Begin a transaction.
std::atomic< bool > in_transaction_
Transaction state (MULTI/EXEC)
redis_backend()
Default constructor.
kcenon::common::Result< core::database_result > select_query(const std::string &query_string) override
Execute a SELECT query.
bool parse_redis_query(const std::string &query_string, std::string &key, std::string &value) const
Parse Redis query string format.
std::mutex redis_mutex_
Mutex for thread safety.
std::string last_error_
Last error message.
bool in_transaction() const override
Check if backend is currently in a transaction.
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.
core::connection_config connection_config_
Cached connection config.
std::atomic< bool > initialized_
bool is_initialized() const override
Helper class for automatic backend registration.
Centralized logging utility for database backends.
std::vector< database_row > database_result
std::map< std::string, database_value > database_row
Redis database backend plugin implementation.
Result<T> type for database_system error handling.
Configuration for database connection.