Few improvements

v3.0_track_transaction_param_state_4907
Rahim Kanji 10 months ago
parent 9559703a02
commit 7c7cbd0bc1

@ -1,112 +1,112 @@
#ifndef PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H
#define PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H
#include <string>
#include <vector>
#include <algorithm>
#include "proxysql.h"
#include "cpp.h"
#include "PgSQL_Connection.h"
#ifndef PROXYJSON
#define PROXYJSON
#include "../deps/json/json_fwd.hpp"
#endif // PROXYJSON
/**
* @struct PgSQL_Variable_Snapshot
* @brief Represents a snapshot of PostgreSQL variables during a transaction.
*
* This structure is used to store the state of PostgreSQL variables, including
* their values and hash representations, at a specific point in time during a transaction.
*/
typedef struct PgSQL_Variable_Snapshot {
char* var_value[PGSQL_NAME_LAST_HIGH_WM] = {};
uint32_t var_hash[PGSQL_NAME_LAST_HIGH_WM] = {};
} PgSQL_Variable_Snapshot_t;
/**
* @struct TxnCmd
* @brief Represents a transaction command type begin executed and its associated metadata.
*
*/
struct TxnCmd {
/**
* @enum Type
* @brief Enumerates the types of transaction commands.
*/
enum Type {
UNKNOWN = -1,
BEGIN,
COMMIT,
ROLLBACK,
SAVEPOINT,
RELEASE,
ROLLBACK_TO
} type = Type::UNKNOWN;
std::string savepoint; //< The name of the savepoint, if applicable.
};
/**
* @class PgSQL_TxnCmdParser
* @brief Parses transaction-related commands for PostgreSQL.
*
* This class is responsible for tokenizing and interpreting transaction-related
* commands such as BEGIN, COMMIT, ROLLBACK, SAVEPOINT, etc.
*/
class PgSQL_TxnCmdParser {
public:
TxnCmd parse(std::string_view input, bool in_transaction_mode) noexcept;
private:
std::vector<std::string_view> tokens;
TxnCmd parse_rollback(size_t& pos) noexcept;
TxnCmd parse_savepoint(size_t& pos) noexcept;
TxnCmd parse_release(size_t& pos) noexcept;
// Helpers
static std::string to_lower(std::string_view s) noexcept {
std::string s_copy(s);
std::transform(s_copy.begin(), s_copy.end(), s_copy.begin(), ::tolower);
return s_copy;
}
inline static bool contains(std::vector<std::string_view>&& list, std::string_view value) noexcept {
for (const auto& item : list) if (item == value) return true;
return false;
}
};
/**
* @class PgSQL_ExplicitTxnStateMgr
* @brief Manages the state of explicit transactions in PostgreSQL.
*
* This class is responsible for handling explicit transaction commands such as
* BEGIN, COMMIT, ROLLBACK, SAVEPOINT, and managing the associated state.
*/
class PgSQL_ExplicitTxnStateMgr {
public:
PgSQL_ExplicitTxnStateMgr(PgSQL_Session* sess);
~PgSQL_ExplicitTxnStateMgr();
bool handle_transaction(std::string_view input);
int get_savepoint_count() const { return savepoint.size(); }
void fill_internal_session(nlohmann::json& j);
private:
PgSQL_Session* session;
std::vector<PgSQL_Variable_Snapshot_t> transaction_state;
std::vector<std::string> savepoint;
PgSQL_TxnCmdParser tx_parser;
void start_transaction();
void commit();
void rollback();
bool add_savepoint(std::string_view name);
bool rollback_to_savepoint(std::string_view name);
bool release_savepoint(std::string_view name);
static void reset_variable_snapshot(PgSQL_Variable_Snapshot_t& var_snapshot) noexcept;
};
#endif // PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H
#ifndef PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H
#define PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H
#include <string>
#include <vector>
#include <algorithm>
#include "proxysql.h"
#include "cpp.h"
#include "PgSQL_Connection.h"
#ifndef PROXYJSON
#define PROXYJSON
#include "../deps/json/json_fwd.hpp"
#endif // PROXYJSON
/**
* @struct PgSQL_Variable_Snapshot
* @brief Represents a snapshot of PostgreSQL variables during a transaction.
*
* This structure is used to store the state of PostgreSQL variables, including
* their values and hash representations, at a specific point in time during a transaction.
*/
struct PgSQL_Variable_Snapshot {
char* var_value[PGSQL_NAME_LAST_HIGH_WM] = {}; // Not using smart pointers because we need fine-grained control over hashing when values change
uint32_t var_hash[PGSQL_NAME_LAST_HIGH_WM] = {};
};
/**
* @struct TxnCmd
* @brief Represents a transaction command type begin executed and its associated metadata.
*
*/
struct TxnCmd {
/**
* @enum Type
* @brief Enumerates the types of transaction commands.
*/
enum Type {
UNKNOWN = -1,
BEGIN,
COMMIT,
ROLLBACK,
SAVEPOINT,
RELEASE,
ROLLBACK_TO
} type = Type::UNKNOWN;
std::string savepoint; //< The name of the savepoint, if applicable.
};
/**
* @class PgSQL_TxnCmdParser
* @brief Parses transaction-related commands for PostgreSQL.
*
* This class is responsible for tokenizing and interpreting transaction-related
* commands such as BEGIN, COMMIT, ROLLBACK, SAVEPOINT, etc.
*/
class PgSQL_TxnCmdParser {
public:
TxnCmd parse(std::string_view input, bool in_transaction_mode) noexcept;
private:
std::vector<std::string_view> tokens;
TxnCmd parse_rollback(size_t& pos) noexcept;
TxnCmd parse_savepoint(size_t& pos) noexcept;
TxnCmd parse_release(size_t& pos) noexcept;
// Helpers
static std::string to_lower(std::string_view s) noexcept {
std::string s_copy(s);
std::transform(s_copy.begin(), s_copy.end(), s_copy.begin(), ::tolower);
return s_copy;
}
inline static bool contains(std::vector<std::string_view>&& list, std::string_view value) noexcept {
for (const auto& item : list) if (item == value) return true;
return false;
}
};
/**
* @class PgSQL_ExplicitTxnStateMgr
* @brief Manages the state of explicit transactions in PostgreSQL.
*
* This class is responsible for handling explicit transaction commands such as
* BEGIN, COMMIT, ROLLBACK, SAVEPOINT, and managing the associated state.
*/
class PgSQL_ExplicitTxnStateMgr {
public:
PgSQL_ExplicitTxnStateMgr(PgSQL_Session* sess);
~PgSQL_ExplicitTxnStateMgr();
bool handle_transaction(std::string_view input);
int get_savepoint_count() const { return savepoint.size(); }
void fill_internal_session(nlohmann::json& j);
private:
PgSQL_Session* session;
std::vector<PgSQL_Variable_Snapshot> transaction_state;
std::vector<std::string> savepoint;
PgSQL_TxnCmdParser tx_parser;
void start_transaction();
void commit();
void rollback();
bool add_savepoint(std::string_view name);
bool rollback_to_savepoint(std::string_view name);
bool release_savepoint(std::string_view name);
static void reset_variable_snapshot(PgSQL_Variable_Snapshot& var_snapshot) noexcept;
};
#endif // PGSQL_EXPLICIT_TRANSACTION_STATE_MANAGER_H

@ -1,4 +1,4 @@
#include "PgSQL_ExplicitTxnStateMgr.h"
#include "PgSQL_ExplicitTxnStateMgr.h"
#include "proxysql.h"
#include "PgSQL_Session.h"
#include "PgSQL_Data_Stream.h"
@ -18,7 +18,7 @@ PgSQL_ExplicitTxnStateMgr::~PgSQL_ExplicitTxnStateMgr() {
savepoint.clear();
}
void PgSQL_ExplicitTxnStateMgr::reset_variable_snapshot(PgSQL_Variable_Snapshot_t& var_snapshot) noexcept {
void PgSQL_ExplicitTxnStateMgr::reset_variable_snapshot(PgSQL_Variable_Snapshot& var_snapshot) noexcept {
for (int idx = 0; idx < PGSQL_NAME_LAST_HIGH_WM; idx++) {
if (var_snapshot.var_value[idx]) {
free(var_snapshot.var_value[idx]);
@ -50,7 +50,7 @@ void PgSQL_ExplicitTxnStateMgr::start_transaction() {
assert(session->client_myds && session->client_myds->myconn);
PgSQL_Variable_Snapshot_t var_snapshot{};
PgSQL_Variable_Snapshot var_snapshot{};
// check if already in transaction, if yes then do nothing
for (int idx = 0; idx < PGSQL_NAME_LAST_HIGH_WM; idx++) {
@ -96,7 +96,7 @@ void PgSQL_ExplicitTxnStateMgr::rollback() {
assert(session->client_myds && session->client_myds->myconn);
const PgSQL_Variable_Snapshot_t& var_snapshot = transaction_state.front();
const PgSQL_Variable_Snapshot& var_snapshot = transaction_state.front();
for (int idx = 0; idx < PGSQL_NAME_LAST_HIGH_WM; idx++) {
uint32_t hash = var_snapshot.var_hash[idx];
@ -159,7 +159,7 @@ bool PgSQL_ExplicitTxnStateMgr::rollback_to_savepoint(std::string_view name) {
assert(tran_state_idx + 1 < (int)transaction_state.size());
PgSQL_Variable_Snapshot_t& var_snapshot = transaction_state[tran_state_idx+1];
PgSQL_Variable_Snapshot& var_snapshot = transaction_state[tran_state_idx+1];
for (int idx = 0; idx < PGSQL_NAME_LAST_HIGH_WM; idx++) {
uint32_t hash = var_snapshot.var_hash[idx];
if (hash != 0) {
@ -177,6 +177,14 @@ bool PgSQL_ExplicitTxnStateMgr::rollback_to_savepoint(std::string_view name) {
pgsql_variables.server_reset_value(session, idx, false);
}
}
session->client_myds->myconn->reorder_dynamic_variables_idx();
if (session->mybe) {
session->mybe->server_myds->myconn->reorder_dynamic_variables_idx();
verify_server_variables(session);
}
for (size_t idx = tran_state_idx + 1; idx < transaction_state.size(); idx++) {
reset_variable_snapshot(transaction_state[idx]);
}
@ -236,7 +244,7 @@ bool PgSQL_ExplicitTxnStateMgr::add_savepoint(std::string_view name) {
});
if (it != savepoint.end()) return false;
PgSQL_Variable_Snapshot_t var_snapshot{};
PgSQL_Variable_Snapshot var_snapshot{};
for (int idx = 0; idx < PGSQL_NAME_LAST_HIGH_WM; idx++) {
uint32_t hash = pgsql_variables.client_get_hash(session, idx);
@ -344,6 +352,7 @@ TxnCmd PgSQL_TxnCmdParser::parse(std::string_view input, bool in_transaction_mod
if (first == "begin") cmd.type = TxnCmd::BEGIN;
else if (first == "savepoint") cmd = parse_savepoint(pos);
else if (first == "release") cmd = parse_release(pos);
else if (first == "rollback") cmd = parse_rollback(pos);
} else {
if (first == "commit") cmd.type = TxnCmd::COMMIT;
else if (first == "rollback" || (first == "abort")) cmd = parse_rollback(pos);

Loading…
Cancel
Save