Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
database_backend.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
21#pragma once
22
23#include "../database_types.h"
24
25#include <kcenon/common/patterns/result.h>
26
27#include <memory>
28#include <string>
29#include <vector>
30#include <map>
31#include <variant>
32
33namespace database
34{
35namespace core
36{
37
38// Forward declarations for type aliases
39using database_value = std::variant<std::string, int64_t, double, bool, std::nullptr_t>;
40using database_row = std::map<std::string, database_value>;
41using database_result = std::vector<database_row>;
42
51{
52 std::string host;
53 uint16_t port = 0;
54 std::string database;
55 std::string username;
56 std::string password;
57 std::map<std::string, std::string> options; // Additional driver-specific options
58
67 static connection_config from_string(const std::string& connect_string);
68};
69
99{
100public:
101 virtual ~database_backend() = default;
102
107 virtual database_types type() const = 0;
108
120 virtual kcenon::common::VoidResult initialize(const connection_config& config) = 0;
121
132 virtual kcenon::common::VoidResult shutdown() = 0;
133
138 virtual bool is_initialized() const = 0;
139
145 virtual kcenon::common::Result<database_result> select_query(const std::string& query_string) = 0;
146
152 virtual kcenon::common::VoidResult execute_query(const std::string& query_string) = 0;
153
169 [[nodiscard]] virtual kcenon::common::Result<database_result> select_prepared(
170 const std::string& query,
171 const std::vector<database_value>& params)
172 {
173 // Default fallback: substitute params inline (less secure, but functional)
174 auto expanded = expand_params(query, params);
175 return select_query(expanded);
176 }
177
187 [[nodiscard]] virtual kcenon::common::VoidResult execute_prepared(
188 const std::string& query,
189 const std::vector<database_value>& params)
190 {
191 auto expanded = expand_params(query, params);
192 return execute_query(expanded);
193 }
194
199 virtual kcenon::common::VoidResult begin_transaction() = 0;
200
205 virtual kcenon::common::VoidResult commit_transaction() = 0;
206
211 virtual kcenon::common::VoidResult rollback_transaction() = 0;
212
217 virtual bool in_transaction() const = 0;
218
223 virtual std::string last_error() const = 0;
224
231 virtual std::map<std::string, std::string> connection_info() const = 0;
232
233protected:
245 static std::string expand_params(
246 const std::string& query,
247 const std::vector<database_value>& params)
248 {
249 std::string result = query;
250
251 // Replace $N placeholders (PostgreSQL-style, 1-indexed)
252 for (size_t i = params.size(); i > 0; --i) {
253 auto placeholder = "$" + std::to_string(i);
254 auto pos = result.find(placeholder);
255 if (pos != std::string::npos) {
256 result.replace(pos, placeholder.size(), value_to_sql(params[i - 1]));
257 }
258 }
259
260 // Replace ? placeholders (SQLite-style, left-to-right)
261 size_t param_idx = 0;
262 auto pos = result.find('?');
263 while (pos != std::string::npos && param_idx < params.size()) {
264 auto val = value_to_sql(params[param_idx++]);
265 result.replace(pos, 1, val);
266 pos = result.find('?', pos + val.size());
267 }
268
269 return result;
270 }
271
272private:
273 static std::string value_to_sql(const database_value& val)
274 {
275 return std::visit([](const auto& v) -> std::string {
276 using T = std::decay_t<decltype(v)>;
277 if constexpr (std::is_same_v<T, std::nullptr_t>) {
278 return "NULL";
279 } else if constexpr (std::is_same_v<T, bool>) {
280 return v ? "TRUE" : "FALSE";
281 } else if constexpr (std::is_same_v<T, std::string>) {
282 // Basic escaping — backends should override for proper security
283 std::string escaped;
284 escaped.reserve(v.size() + 2);
285 escaped += '\'';
286 for (char c : v) {
287 if (c == '\'') escaped += "''";
288 else escaped += c;
289 }
290 escaped += '\'';
291 return escaped;
292 } else {
293 return std::to_string(v);
294 }
295 }, val);
296 }
297};
298
307using backend_factory_fn = std::unique_ptr<database_backend> (*)();
308
309} // namespace core
310} // namespace database
Abstract base class for database backends.
virtual kcenon::common::VoidResult initialize(const connection_config &config)=0
Initialize the database backend.
virtual std::string last_error() const =0
Get last error message from backend.
virtual kcenon::common::VoidResult rollback_transaction()=0
Rollback the current transaction.
static std::string expand_params(const std::string &query, const std::vector< database_value > &params)
Expand positional parameters into a SQL string (fallback)
virtual bool in_transaction() const =0
Check if backend is currently in a transaction.
virtual kcenon::common::VoidResult begin_transaction()=0
Begin a transaction.
virtual kcenon::common::VoidResult commit_transaction()=0
Commit the current transaction.
virtual bool is_initialized() const =0
Check if backend is initialized and ready.
virtual ~database_backend()=default
virtual std::map< std::string, std::string > connection_info() const =0
Get backend-specific connection information.
virtual kcenon::common::VoidResult shutdown()=0
Shutdown the database backend gracefully.
virtual kcenon::common::VoidResult execute_prepared(const std::string &query, const std::vector< database_value > &params)
Execute a parameterized DML/DDL query (prepared statement)
virtual database_types type() const =0
Get the database type of this backend.
virtual kcenon::common::Result< database_result > select_prepared(const std::string &query, const std::vector< database_value > &params)
Execute a parameterized SELECT query (prepared statement)
virtual kcenon::common::Result< database_result > select_query(const std::string &query_string)=0
Execute a SELECT query.
virtual kcenon::common::VoidResult execute_query(const std::string &query_string)=0
Execute a general SQL query (DDL, DML)
static std::string value_to_sql(const database_value &val)
Defines the enumeration of supported database types.
std::unique_ptr< database_backend >(*)() backend_factory_fn
Factory function type for creating database backends.
std::vector< database_row > database_result
std::map< std::string, database_value > database_row
std::variant< std::string, int64_t, double, bool, std::nullptr_t > database_value
database_types
Represents various database backends or modes.
Configuration for database connection.
std::map< std::string, std::string > options
static connection_config from_string(const std::string &connect_string)
Construct connection_config from legacy connection string.