diff --git a/include/PgSQL_Connection.h b/include/PgSQL_Connection.h index 2d47c4075..7722e9454 100644 --- a/include/PgSQL_Connection.h +++ b/include/PgSQL_Connection.h @@ -244,7 +244,7 @@ class PgSQL_Connection_userinfo { class PgSQL_Connection { public: - PgSQL_Connection(); + PgSQL_Connection(bool is_client_conn); ~PgSQL_Connection(); PG_ASYNC_ST handler(short event); @@ -312,7 +312,7 @@ public: if (error_info.severity == PGSQL_ERROR_SEVERITY::ERRSEVERITY_FATAL || error_info.severity == PGSQL_ERROR_SEVERITY::ERRSEVERITY_ERROR || error_info.severity == PGSQL_ERROR_SEVERITY::ERRSEVERITY_PANIC) { - return true; + return true; } return false; } @@ -442,6 +442,42 @@ public: bool IsKeepMultiplexEnabledVariables(char* query_digest_text); + /** + * @brief Retrieves startup parameter and it's hash + * + * This function tries to retrieve value and hash of startup paramters if present (provided in connection parameters). + * If value is not found, it falls back to the thread-specific default variables. + * + * @param idx The index of startup parameter to retrieve. + * @return The value and hash of startup parameter. + * + */ + std::pair get_startup_parameter_and_hash(enum pgsql_variable_name idx); + + /** + * @brief Copies tracked PgSQL session variables to startup parameters + * + * This function synchronizes the current tracked session variables (in `variables` and `var_hash`) + * to the startup parameters arrays (`startup_parameters` and `startup_parameters_hash`). If `copy_only_critical_param` + * is true, only the critical parameters (indices 0 to PGSQL_NAME_LAST_LOW_WM-1) are copied. + * Otherwise, all tracked variables up to PGSQL_NAME_LAST_HIGH_WM are copied. + * + * @param copy_only_critical_param If true, only critical parameters are copied; otherwise, all tracked variables. + */ + void copy_pgsql_variables_to_startup_parameters(bool copy_only_critical_param); + + /** + * @brief Copies startup parameters to tracked PgSQL session variables. + * + * This function synchronizes the startup parameters arrays (`startup_parameters` and `startup_parameters_hash`) + * to the tracked session variables (`variables` and `var_hash`). If `copy_only_critical_param` is true, + * only the critical parameters (indices 0 to PGSQL_NAME_LAST_LOW_WM-1) are copied. Otherwise, all tracked + * variables up to PGSQL_NAME_LAST_HIGH_WM are copied. + * + * @param copy_only_critical_param If true, only critical parameters are copied; otherwise, all tracked variables. + */ + void copy_startup_parameters_to_pgsql_variables(bool copy_only_critical_param); + struct { unsigned long length; char* ptr; @@ -471,6 +507,9 @@ public: bool var_absent[PGSQL_NAME_LAST_HIGH_WM] = { false }; std::vector dynamic_variables_idx; + uint32_t startup_parameters_hash[PGSQL_NAME_LAST_HIGH_WM] = {}; + char* startup_parameters[PGSQL_NAME_LAST_HIGH_WM] = {}; + /** * @brief Keeps tracks of the 'server_status'. Do not confuse with the 'server_status' from the * 'MYSQL' connection itself. This flag keeps track of the configured server status from the @@ -499,7 +538,7 @@ public: bool reusable; bool processing_multi_statement; bool multiplex_delayed; - + bool is_client_connection; // true if this is a client connection, false if it is a server connection PgSQL_SrvC *parent; PgSQL_Connection_userinfo* userinfo; diff --git a/include/PgSQL_Session.h b/include/PgSQL_Session.h index 4b2ada944..de3436618 100644 --- a/include/PgSQL_Session.h +++ b/include/PgSQL_Session.h @@ -369,7 +369,6 @@ public: PtrSize_t pkt; std::string untracked_option_parameters; PgSQL_DateStyle_t current_datestyle = {}; - char* default_session_variables[PGSQL_NAME_LAST_HIGH_WM] = {}; #if 0 // uint64_t @@ -526,22 +525,6 @@ public: void detected_broken_connection(const char* file, unsigned int line, const char* func, const char* action, PgSQL_Connection* myconn, bool verbose = false); void generate_status_one_hostgroup(int hid, std::string& s); void set_previous_status_mode3(bool allow_execute = true); - - void set_default_session_variable(enum pgsql_variable_name idx, const char* value); - - /** - * @brief Retrieves default session variable - * - * This function tries to retrieve value of default session variable if present (provided in connection parameters). - * If value is not found, it falls back to the thread-specific default variables. - * - * @param idx The index of the session variable to retrieve. - * @return The value of the session variable - * - */ - const char* get_default_session_variable(enum pgsql_variable_name idx); - - void reset_default_session_variable(enum pgsql_variable_name idx); }; #define PgSQL_KILL_QUERY 1 diff --git a/lib/Base_Thread.cpp b/lib/Base_Thread.cpp index d6ee97fe7..c578cca01 100644 --- a/lib/Base_Thread.cpp +++ b/lib/Base_Thread.cpp @@ -132,7 +132,7 @@ S Base_Thread::create_new_session_and_client_data_stream(int _fd) { sess->client_myds->myprot.dump_pkt = true; #endif if constexpr (std::is_same_v) { - PgSQL_Connection* myconn = new PgSQL_Connection(); + PgSQL_Connection* myconn = new PgSQL_Connection(true); sess->client_myds->attach_connection(myconn); } else if constexpr (std::is_same_v) { MySQL_Connection* myconn = new MySQL_Connection(); diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index b5e668948..cac19a4af 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -147,8 +147,9 @@ void print_backtrace(void); #define NEXT_IMMEDIATE(new_st) do { async_state_machine = new_st; goto handler_again; } while (0) -PgSQL_Connection::PgSQL_Connection() { +PgSQL_Connection::PgSQL_Connection(bool is_client_conn) { proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "Creating new PgSQL_Connection %p\n", this); + is_client_connection = is_client_conn; pgsql_conn = NULL; result_type = 0; pgsql_result = NULL; @@ -215,13 +216,6 @@ PgSQL_Connection::~PgSQL_Connection() { delete query_result_reuse; query_result_reuse = NULL; } - for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) { - if (variables[i].value) { - free(variables[i].value); - variables[i].value = NULL; - var_hash[i] = 0; - } - } if (connected_host_details.hostname) { free(connected_host_details.hostname); @@ -233,6 +227,21 @@ PgSQL_Connection::~PgSQL_Connection() { } if (options.init_connect) free(options.init_connect); + + for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; ++i) { + if (variables[i].value) { + free(variables[i].value); + variables[i].value = NULL; + var_hash[i] = 0; + } + } + + for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; ++i) { + if (startup_parameters[i]) { + free(startup_parameters[i]); + startup_parameters_hash[i] = 0; + } + } } void PgSQL_Connection::next_event(PG_ASYNC_ST new_st) { @@ -756,44 +765,28 @@ void PgSQL_Connection::connect_start() { // charset validation is already done pgsql_variables.server_set_hash_and_value(myds->sess, PGSQL_CLIENT_ENCODING, client_charset, client_charset_hash); - std::vector client_options; - client_options.reserve(PGSQL_NAME_LAST_LOW_WM + myds->sess->client_myds->myconn->dynamic_variables_idx.size()); + // optimized way to set client parameters on backend connection when creating a new connection + conninfo << "options='"; + // excluding client_encoding, which is already set above + for (int idx = 1; idx < PGSQL_NAME_LAST_LOW_WM; idx++) { + const char* value = pgsql_variables.client_get_value(myds->sess, idx); + const char* escaped_str = escape_string_backslash_spaces(value); + conninfo << "-c " << pgsql_tracked_variables[idx].set_variable_name << "=" << escaped_str << " "; + if (escaped_str != value) + free((char*)escaped_str); - // excluding PGSQL_CLIENT_ENCODING - for (unsigned int idx = 1; idx < PGSQL_NAME_LAST_LOW_WM; idx++) { - if (pgsql_variables.client_get_hash(myds->sess, idx) == 0) continue; - client_options.push_back(idx); + const uint32_t hash = pgsql_variables.client_get_hash(myds->sess, idx); + pgsql_variables.server_set_hash_and_value(myds->sess, idx, value, hash); } - for (uint32_t idx : myds->sess->client_myds->myconn->dynamic_variables_idx) { - assert(pgsql_variables.client_get_hash(myds->sess, idx)); - client_options.push_back(idx); - } + myds->sess->mybe->server_myds->myconn->copy_pgsql_variables_to_startup_parameters(true); - if (client_options.empty() == false || - myds->sess->untracked_option_parameters.empty() == false) { - - // optimized way to set client parameters on backend connection when creating a new connection - conninfo << "options='"; - for (int idx : client_options) { - const char* value = pgsql_variables.client_get_value(myds->sess, idx); - const char* escaped_str = escape_string_backslash_spaces(value); - conninfo << "-c " << pgsql_tracked_variables[idx].set_variable_name << "=" << escaped_str << " "; - if (escaped_str != value) - free((char*)escaped_str); - - const uint32_t hash = pgsql_variables.client_get_hash(myds->sess, idx); - pgsql_variables.server_set_hash_and_value(myds->sess, idx, value, hash); - } - - myds->sess->mybe->server_myds->myconn->reorder_dynamic_variables_idx(); - - // if there are untracked parameters, the session should lock on the host group - if (myds->sess->untracked_option_parameters.empty() == false) { - conninfo << myds->sess->untracked_option_parameters; - } - conninfo << "'"; + // if there are untracked parameters, the session should lock on the host group + if (myds->sess->untracked_option_parameters.empty() == false) { + conninfo << myds->sess->untracked_option_parameters; } + conninfo << "'"; + } /*conninfo << "postgres://"; @@ -1881,16 +1874,19 @@ void PgSQL_Connection::reset() { reusable = true; creation_time = monotonic_time(); - for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) { + for (int i = (is_client_connection ? 0 : PGSQL_NAME_LAST_LOW_WM + 1); + i < PGSQL_NAME_LAST_HIGH_WM; + i++) { var_hash[i] = 0; if (variables[i].value) { free(variables[i].value); variables[i].value = NULL; - var_hash[i] = 0; } } dynamic_variables_idx.clear(); + if (!is_client_connection) copy_startup_parameters_to_pgsql_variables(/*copy_only_critical_param=*/true); + if (options.init_connect) { free(options.init_connect); options.init_connect = NULL; @@ -2202,3 +2198,68 @@ void PgSQL_Connection::set_error_from_PQerrorMessage() { const std::string_view& full_msg = !primary_msg.empty() ? primary_msg : lib_errmsg; PgSQL_Error_Helper::fill_error_info(error_info, sqlstate.data(), full_msg.data(), severity.data()); } + +std::pair PgSQL_Connection::get_startup_parameter_and_hash(enum pgsql_variable_name idx) { + // within valid range? + assert(idx >= 0 && idx < PGSQL_NAME_LAST_HIGH_WM); + + // Attempt to retrieve value from default startup parameters + if (startup_parameters_hash[idx] != 0) { + assert(startup_parameters[idx]); + return { startup_parameters[idx], startup_parameters_hash[idx] }; + } + // fall back to thread-specific default + return { pgsql_thread___default_variables[idx], 0 }; +} + +void PgSQL_Connection::copy_pgsql_variables_to_startup_parameters(bool copy_only_critical_param) { + + //memcpy(startup_parameters_hash, var_hash, sizeof(uint32_t) * PGSQL_NAME_LAST_LOW_WM); + for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; ++i) { + assert(var_hash[i]); + assert(variables[i].value); + startup_parameters_hash[i] = var_hash[i]; + free(startup_parameters[i]); + startup_parameters[i] = strdup(variables[i].value); + } + + if (copy_only_critical_param) return; + + for (int i = PGSQL_NAME_LAST_LOW_WM + 1; i < PGSQL_NAME_LAST_HIGH_WM; i++) { + if (var_hash[i] != 0) { + startup_parameters_hash[i] = var_hash[i]; + free(startup_parameters[i]); + startup_parameters[i] = strdup(variables[i].value); + } else { + startup_parameters_hash[i] = 0; + free(startup_parameters[i]); + startup_parameters[i] = nullptr; + } + } +} + +void PgSQL_Connection::copy_startup_parameters_to_pgsql_variables(bool copy_only_critical_param) { + + //memcpy(var_hash, startup_parameters_hash, sizeof(uint32_t) * PGSQL_NAME_LAST_LOW_WM); + for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) { + assert(startup_parameters_hash[i]); + assert(startup_parameters[i]); + var_hash[i] = startup_parameters_hash[i]; + free(variables[i].value); + variables[i].value = strdup(startup_parameters[i]); + } + + if (copy_only_critical_param) return; + + for (int i = PGSQL_NAME_LAST_LOW_WM + 1; i < PGSQL_NAME_LAST_HIGH_WM; i++) { + if (startup_parameters_hash[i]) { + var_hash[i] = startup_parameters_hash[i]; + free(variables[i].value); + variables[i].value = strdup(startup_parameters[i]); + } else { + var_hash[i] = 0; + free(variables[i].value); + variables[i].value = nullptr; + } + } +} diff --git a/lib/PgSQL_HostGroups_Manager.cpp b/lib/PgSQL_HostGroups_Manager.cpp index 5646170a4..f9b67fed5 100644 --- a/lib/PgSQL_HostGroups_Manager.cpp +++ b/lib/PgSQL_HostGroups_Manager.cpp @@ -2298,7 +2298,7 @@ PgSQL_Connection * PgSQL_SrvConnList::get_random_MyConn(PgSQL_Session *sess, boo } // we must create a new connection - conn = new PgSQL_Connection(); + conn = new PgSQL_Connection(false); conn->parent=mysrvc; // if attributes.multiplex == true , STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG is set to false. And vice-versa conn->set_status(!conn->parent->myhgc->attributes.multiplex, STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG); @@ -2312,7 +2312,7 @@ PgSQL_Connection * PgSQL_SrvConnList::get_random_MyConn(PgSQL_Session *sess, boo unsigned int conns_free = mysrvc->ConnectionsFree->conns_length(); unsigned int conns_used = mysrvc->ConnectionsUsed->conns_length(); if ((conns_used > conns_free) && (mysrvc->max_connections > (conns_free/2 + conns_used/2)) ) { - conn = new PgSQL_Connection(); + conn = new PgSQL_Connection(false); conn->parent=mysrvc; // if attributes.multiplex == true , STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG is set to false. And vice-versa conn->set_status(!conn->parent->myhgc->attributes.multiplex, STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG); @@ -2357,7 +2357,7 @@ PgSQL_Connection * PgSQL_SrvConnList::get_random_MyConn(PgSQL_Session *sess, boo __sync_fetch_and_add(&PgHGM->status.server_connections_delayed, 1); return NULL; } else { - conn = new PgSQL_Connection(); + conn = new PgSQL_Connection(false); conn->parent=mysrvc; // if attributes.multiplex == true , STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG is set to false. And vice-versa conn->set_status(!conn->parent->myhgc->attributes.multiplex, STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG); diff --git a/lib/PgSQL_Protocol.cpp b/lib/PgSQL_Protocol.cpp index 4b606f267..2b5047526 100644 --- a/lib/PgSQL_Protocol.cpp +++ b/lib/PgSQL_Protocol.cpp @@ -1211,11 +1211,9 @@ EXECUTION_STATE PgSQL_Protocol::process_handshake_response_packet(unsigned char* if (pgsql_variables.client_set_value(sess, PGSQL_DATESTYLE, datestyle.c_str(), false)) { // change current datestyle sess->current_datestyle = PgSQL_DateStyle_Util::parse_datestyle(datestyle); - sess->set_default_session_variable(PGSQL_DATESTYLE, datestyle.c_str()); } } else { pgsql_variables.client_set_value(sess, idx, value_copy.c_str(), false); - sess->set_default_session_variable((enum pgsql_variable_name)idx, value_copy.c_str()); } } else { // parameter provided is not part of the tracked variables. Will lock on hostgroup on next query. @@ -1234,10 +1232,10 @@ EXECUTION_STATE PgSQL_Protocol::process_handshake_response_packet(unsigned char* continue; const char* val = pgsql_thread___default_variables[i]; pgsql_variables.client_set_value(sess, i, val, false); - sess->set_default_session_variable((pgsql_variable_name)i, val); } sess->client_myds->myconn->reorder_dynamic_variables_idx(); + sess->client_myds->myconn->copy_pgsql_variables_to_startup_parameters(false); } else { // we always duplicate username and password, or crashes happen diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index a66cf63b1..3863d2045 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -617,16 +617,14 @@ void PgSQL_Session::reset() { } } } - if (client_myds) { - if (client_myds->myconn) { - client_myds->myconn->reset(); - } + if (client_myds && client_myds->myconn) { + client_myds->myconn->reset(); } } PgSQL_Session::~PgSQL_Session() { - reset(); // we moved this out to allow CHANGE_USER + reset(); if (locked_on_hostgroup >= 0) { thread->status_variables.stvar[st_var_hostgroup_locked]--; @@ -676,10 +674,6 @@ PgSQL_Session::~PgSQL_Session() { delete proxysql_node_address; proxysql_node_address = NULL; } - - for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) { - reset_default_session_variable((enum pgsql_variable_name)i); - } if (transaction_state_manager) delete transaction_state_manager; } @@ -1161,7 +1155,7 @@ void PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C newsess->thread_session_id = __sync_fetch_and_add(&glovars.thread_id, 1); } newsess->status = WAITING_CLIENT_DATA; - PgSQL_Connection* myconn = new PgSQL_Connection; + PgSQL_Connection* myconn = new PgSQL_Connection(true); newsess->client_myds->attach_connection(myconn); newsess->client_myds->myprot.init(&newsess->client_myds, newsess->client_myds->myconn->userinfo, newsess); newsess->mirror = true; @@ -4224,7 +4218,7 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (idx != PGSQL_NAME_LAST_HIGH_WM) { if ((value1.size() == sizeof("DEFAULT") - 1) && strncasecmp(value1.c_str(), (char*)"DEFAULT",sizeof("DEFAULT")-1) == 0) { - value1 = get_default_session_variable((enum pgsql_variable_name)idx); + std::tie(value1, std::ignore) = client_myds->myconn->get_startup_parameter_and_hash((enum pgsql_variable_name)idx); } char* transformed_value = nullptr; @@ -4278,7 +4272,7 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C // No need to set send_param_status to true, as the original DateStyle value may have been modified. // When send_param_status is true, it always sends the original value provided by the user in the SET statement. if (IS_PGTRACKED_VAR_OPTION_SET_PARAM_STATUS(pgsql_tracked_variables[idx])) { - param_status.push_back(std::make_pair(var, value1)); + param_status.emplace_back(var, value1); } } else { send_param_status = IS_PGTRACKED_VAR_OPTION_SET_PARAM_STATUS(pgsql_tracked_variables[idx]); @@ -4461,7 +4455,7 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C } if (send_param_status) - param_status.push_back(std::make_pair(var, *values)); + param_status.emplace_back(var, *values); } if (failed_to_parse_var) { @@ -4643,16 +4637,16 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C for (int idx = 0; idx < PGSQL_NAME_LAST_LOW_WM; idx++) { const char* name = pgsql_tracked_variables[idx].set_variable_name; - const char* value = get_default_session_variable((enum pgsql_variable_name)idx); + auto [value, hash] = client_myds->myconn->get_startup_parameter_and_hash((enum pgsql_variable_name)idx); proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection %s to %s\n", name, value); - uint32_t var_hash_int = SpookyHash::Hash32(value, strlen(value), 10); + uint32_t var_hash_int = ((hash != 0) ? hash : SpookyHash::Hash32(value, strlen(value), 10)); if (pgsql_variables.client_get_hash(this, idx) != var_hash_int) { if (!pgsql_variables.client_set_value(this, idx, value, false)) { return false; } if (IS_PGTRACKED_VAR_OPTION_SET_PARAM_STATUS(pgsql_tracked_variables[idx])) { - param_status.push_back(std::make_pair(name, value)); + param_status.emplace_back(name, value); } } } @@ -4660,15 +4654,15 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C for (int idx : client_myds->myconn->dynamic_variables_idx) { assert(idx < PGSQL_NAME_LAST_HIGH_WM); const char* name = pgsql_tracked_variables[idx].set_variable_name; - const char* value = get_default_session_variable((enum pgsql_variable_name)idx); + auto [value, hash] = client_myds->myconn->get_startup_parameter_and_hash((enum pgsql_variable_name)idx); proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection %s to %s\n", name, value); - uint32_t var_hash_int = SpookyHash::Hash32(value, strlen(value), 10); + uint32_t var_hash_int = ((hash != 0) ? hash : SpookyHash::Hash32(value, strlen(value), 10)); if (pgsql_variables.client_get_hash(this, idx) != var_hash_int) { if (!pgsql_variables.client_set_value(this, idx, value, false)) { return false; } if (IS_PGTRACKED_VAR_OPTION_SET_PARAM_STATUS(pgsql_tracked_variables[idx])) { - param_status.push_back(std::make_pair(name, value)); + param_status.emplace_back(name, value); } } } @@ -4696,16 +4690,16 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C if (idx != PGSQL_NAME_LAST_HIGH_WM) { const char* name = pgsql_tracked_variables[idx].set_variable_name; - const char* value = get_default_session_variable((enum pgsql_variable_name)idx); - - uint32_t var_hash_int = SpookyHash::Hash32(value, strlen(value), 10); + auto [value, hash] = client_myds->myconn->get_startup_parameter_and_hash((enum pgsql_variable_name)idx); + + uint32_t var_hash_int = ((hash != 0) ? hash : SpookyHash::Hash32(value, strlen(value), 10)); if (pgsql_variables.client_get_hash(this, idx) != var_hash_int) { if (!pgsql_variables.client_set_value(this, idx, value, true)) { return false; } if (IS_PGTRACKED_VAR_OPTION_SET_PARAM_STATUS(pgsql_tracked_variables[idx])) { proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection %s to %s\n", name, value); - param_status.emplace_back(std::make_pair(name, value)); + param_status.emplace_back(name, value); } } } else { @@ -5970,38 +5964,6 @@ void PgSQL_Session::switch_fast_forward_to_normal_mode() { } } -void PgSQL_Session::set_default_session_variable(enum pgsql_variable_name idx, const char* value) { - assert(value); - if (idx >= 0 && idx < PGSQL_NAME_LAST_HIGH_WM) { - if (default_session_variables[idx]) { - free(default_session_variables[idx]); - } - default_session_variables[idx] = strdup(value); - } -} - -const char* PgSQL_Session::get_default_session_variable(enum pgsql_variable_name idx) { - // Check if index is within valid range - if (idx >= 0 && idx < PGSQL_NAME_LAST_HIGH_WM) { - // Attempt to retrieve value from default session variables - const char* val = default_session_variables[idx]; - - // Return the found value, or fall back to thread-specific default if null - return (val) ? val : pgsql_thread___default_variables[idx]; - } - - return NULL; -} - -void PgSQL_Session::reset_default_session_variable(enum pgsql_variable_name idx) { - if (idx >= 0 && idx < PGSQL_NAME_LAST_HIGH_WM) { - if (default_session_variables[idx]) { - free(default_session_variables[idx]); - default_session_variables[idx] = NULL; - } - } -} - // Optimized single‐pass parser for PostgreSQL DateStyle strings. // It supports input in one of these forms: // - "ISO, MDY" (two tokens separated by a comma)