Files
jtlPosSync/jtlsrv-cpp/src/db/pool.hpp
2026-07-15 01:25:38 +02:00

99 lines
3.0 KiB
C++

#pragma once
#include <string>
#include <vector>
#include <mutex>
#include <cstdint>
#include <sql.h>
#include <sqlext.h>
#include <uv.h>
enum class CellType { Null, Int64, Double, String, Blob };
struct Cell {
CellType type = CellType::Null;
int64_t i64 = 0;
double dbl = 0.0;
std::string str;
std::vector<uint8_t> blob;
};
using Row = std::vector<Cell>;
using ResultSet = std::vector<Row>;
enum class ParamType { Int, BigInt, Float, Double, NVarChar, Bit, DateTime };
struct Param {
ParamType type;
std::string str_val;
int64_t int_val = 0;
double dbl_val = 0.0;
bool is_null = false;
static Param null_int() { Param p; p.type = ParamType::Int; p.is_null = true; return p; }
static Param null_bigint() { Param p; p.type = ParamType::BigInt; p.is_null = true; return p; }
static Param null_nvarchar() { Param p; p.type = ParamType::NVarChar; p.is_null = true; return p; }
};
class OdbcPool {
public:
struct Connection {
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLHSTMT hstmt = SQL_NULL_HSTMT;
bool in_use = false;
bool in_transaction = false;
};
// RAII checkout guard. Returned by checkout().
struct ConnGuard {
Connection* conn = nullptr;
OdbcPool* pool = nullptr;
ConnGuard() = default;
ConnGuard(Connection* c, OdbcPool* p) : conn(c), pool(p) {}
~ConnGuard() { if (conn && pool) pool->release(conn); }
ConnGuard(const ConnGuard&) = delete;
ConnGuard(ConnGuard&& other) noexcept : conn(other.conn), pool(other.pool) { other.conn = nullptr; }
ConnGuard& operator=(ConnGuard&& other) noexcept {
if (this != &other) {
if (conn && pool) pool->release(conn);
conn = other.conn;
pool = other.pool;
other.conn = nullptr;
}
return *this;
}
Connection* operator->() const { return conn; }
Connection* get() const { return conn; }
explicit operator bool() const { return conn != nullptr; }
};
~OdbcPool();
int connect();
void disconnect();
bool execute(const std::string& sql, const std::vector<Param>& params, ResultSet& out);
bool execute(const std::string& sql, ResultSet& out);
int64_t execute_scalar(const std::string& sql, const std::vector<Param>& params = {}, int64_t fallback = 0);
// Transactional execution on an explicitly checked-out connection.
ConnGuard checkout();
bool execute(Connection* conn, const std::string& sql, const std::vector<Param>& params, ResultSet& out);
bool execute(Connection* conn, const std::string& sql, ResultSet& out);
bool begin(Connection* conn);
bool commit(Connection* conn);
bool rollback(Connection* conn);
void release(Connection* c);
const std::string& last_error() const { return last_error_; }
private:
SQLHENV henv_ = SQL_NULL_HENV;
std::vector<Connection> conns_;
std::mutex mutex_;
std::string last_error_;
Connection* checkout_raw();
};
OdbcPool& get_pool();