Now, default variables are set for all tracked variables

Improved error handling
v3.0_4799_4827
Rahim Kanji 1 year ago
parent 5fb518dc90
commit e6ddae643b

@ -957,7 +957,7 @@ public:
char* ldap_user_variable;
char* add_ldap_user_comment;
char* default_session_track_gtids;
char* default_variables[PGSQL_NAME_LAST_LOW_WM];
char* default_variables[PGSQL_NAME_LAST_HIGH_WM];
char* firewall_whitelist_errormsg;
#ifdef DEBUG
bool session_debug;

@ -1182,7 +1182,7 @@ __thread int pgsql_thread___query_cache_soft_ttl_pct;
__thread int pgsql_thread___query_cache_handle_warnings;
__thread bool pgsql_thread___session_idle_show_processlist;
__thread char* pgsql_thread___default_variables[PGSQL_NAME_LAST_LOW_WM];
__thread char* pgsql_thread___default_variables[PGSQL_NAME_LAST_HIGH_WM];
__thread int pgsql_thread___handle_unknown_charset;
//---------------------------
@ -1482,7 +1482,7 @@ extern __thread int pgsql_thread___query_cache_soft_ttl_pct;
extern __thread int pgsql_thread___query_cache_handle_warnings;
extern __thread bool pgsql_thread___session_idle_show_processlist;
extern __thread char* pgsql_thread___default_variables[PGSQL_NAME_LAST_LOW_WM];
extern __thread char* pgsql_thread___default_variables[PGSQL_NAME_LAST_HIGH_WM];
extern __thread int pgsql_thread___handle_unknown_charset;
//---------------------------
@ -1769,13 +1769,13 @@ pgsql_variable_st pgsql_tracked_variables[] {
{ PGSQL_STANDARD_CONFORMING_STRINGS, SETTING_VARIABLE, "standard_conforming_strings", "standard_conforming_strings", "on", (PGTRACKED_VAR_OPT_BOOL | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE | PGTRACKED_VAR_OPT_PARAM_STATUS), nullptr },
{ PGSQL_TIMEZONE, SETTING_VARIABLE, "timezone", "timezone", "GMT" , (PGTRACKED_VAR_OPT_QUOTE | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE | PGTRACKED_VAR_OPT_PARAM_STATUS), { "TIME ZONE", nullptr } },
{ PGSQL_NAME_LAST_LOW_WM, session_status___NONE, "placeholder", "placeholder", "0" , 0, nullptr }, // this is just a placeholder to separate the previous index from the next block
{ PGSQL_BYTEA_OUTPUT, SETTING_VARIABLE, "bytea_output", "bytea_output", "hex", (PGTRACKED_VAR_OPT_QUOTE), nullptr },
{ PGSQL_CLIENT_MIN_MESSAGES, SETTING_VARIABLE, "client_min_messages", "client_min_messages", "NOTICE", (PGTRACKED_VAR_OPT_QUOTE), nullptr },
{ PGSQL_ENABLE_BITMAPSCAN, SETTING_VARIABLE, "enable_bitmapscan", "enable_bitmapscan", "on", (PGTRACKED_VAR_OPT_BOOL), nullptr },
{ PGSQL_ENABLE_INDEXSCAN, SETTING_VARIABLE, "enable_indexscan", "enable_indexscan", "on", (PGTRACKED_VAR_OPT_BOOL), nullptr },
{ PGSQL_ENABLE_SEQSCAN, SETTING_VARIABLE, "enable_seqscan", "enable_seqscan", "on", (PGTRACKED_VAR_OPT_BOOL), nullptr },
{ PGSQL_ESCAPE_STRING_WARNING, SETTING_VARIABLE, "escape_string_warning", "escape_string_warning", "on", (PGTRACKED_VAR_OPT_BOOL), nullptr },
{ PGSQL_MAINTENANCE_WORK_MEM, SETTING_VARIABLE, "maintenance_work_mem", "maintenance_work_mem", "64MB", (PGTRACKED_VAR_OPT_QUOTE), nullptr },
{ PGSQL_BYTEA_OUTPUT, SETTING_VARIABLE, "bytea_output", "bytea_output", "hex", (PGTRACKED_VAR_OPT_QUOTE | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_CLIENT_MIN_MESSAGES, SETTING_VARIABLE, "client_min_messages", "client_min_messages", "NOTICE", (PGTRACKED_VAR_OPT_QUOTE | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_ENABLE_BITMAPSCAN, SETTING_VARIABLE, "enable_bitmapscan", "enable_bitmapscan", "on", (PGTRACKED_VAR_OPT_BOOL | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_ENABLE_INDEXSCAN, SETTING_VARIABLE, "enable_indexscan", "enable_indexscan", "on", (PGTRACKED_VAR_OPT_BOOL | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_ENABLE_SEQSCAN, SETTING_VARIABLE, "enable_seqscan", "enable_seqscan", "on", (PGTRACKED_VAR_OPT_BOOL | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_ESCAPE_STRING_WARNING, SETTING_VARIABLE, "escape_string_warning", "escape_string_warning", "on", (PGTRACKED_VAR_OPT_BOOL | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
{ PGSQL_MAINTENANCE_WORK_MEM, SETTING_VARIABLE, "maintenance_work_mem", "maintenance_work_mem", "64MB", (PGTRACKED_VAR_OPT_QUOTE | PGTRACKED_VAR_OPT_GLOBAL_VARIABLE), nullptr },
};
#else

@ -1123,7 +1123,7 @@ EXECUTION_STATE PgSQL_Protocol::process_handshake_response_packet(unsigned char*
for (auto& option : options_list) {
int idx = PGSQL_NAME_LAST_HIGH_WM;
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (i == PGSQL_NAME_LAST_LOW_WM)
if (i == PGSQL_NAME_LAST_LOW_WM)
continue;
if (variable_name_exists(pgsql_tracked_variables[i], option.first.c_str()) == true) {
idx = i;

@ -4896,20 +4896,46 @@ 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) {
const char* value_tmp = get_default_session_variable((enum pgsql_variable_name)idx);
value1 = value_tmp ? value_tmp : ((idx < PGSQL_NAME_LAST_LOW_WM) ? pgsql_thread___default_variables[idx] : pgsql_tracked_variables[idx].default_value);
value1 = get_default_session_variable((enum pgsql_variable_name)idx);
}
if (idx == PGSQL_DATESTYLE) {
assert(current_datestyle.format != DATESTYLE_FORMAT_NONE);
assert(current_datestyle.order != DATESTYLE_ORDER_NONE);
// PostgreSQL strangely accepts an empty value for datestyle, but it does not alter previously set vaclue.
if (value1.empty()) {
client_myds->DSS = STATE_QUERY_SENT_NET;
unsigned int nTrx = NumActiveTransactions();
const char trx_state = (nTrx ? 'T' : 'I');
client_myds->myprot.generate_ok_packet(true, true, NULL, 0, dig, trx_state, NULL, param_status);
RequestEnd(NULL);
l_free(pkt->size, pkt->ptr);
return true;
}
// Convert DateStyle to a string. Any missing parts will be filled using the current DateStyle value.
// For example:
// If current DateStyle is 'ISO, MDY' and the user sets 'DMY' the resulting DateStyle will be 'ISO, DMY'
value1 = PgSQL_DateStyle_Util::datestyle_to_string(value1, current_datestyle);
const std::string& value_tmp = PgSQL_DateStyle_Util::datestyle_to_string(value1, current_datestyle);
// if something goes wrong, the value will be empty
if (value1.empty()) return false;
if (value_tmp.empty()) {
char* m = NULL;
char* errmsg = NULL;
proxy_error("invalid value for parameter \"DateStyle\": \"%s\"\n", value1.c_str());
m = (char*)"invalid value for parameter \"DateStyle\": \"%s\"";
errmsg = (char*)malloc(value1.length() + strlen(m));
sprintf(errmsg, m, value1.c_str());
client_myds->DSS = STATE_QUERY_SENT_NET;
client_myds->myprot.generate_error_packet(true, true, errmsg,
PGSQL_ERROR_CODES::ERRCODE_INVALID_PARAMETER_VALUE, false, true);
client_myds->DSS = STATE_SLEEP;
status = WAITING_CLIENT_DATA;
free(errmsg);
return true;
}
value1 = value_tmp;
}
proxy_debug(PROXY_DEBUG_MYSQL_COM, 8, "Changing connection %s to %s\n", var.c_str(), value1.c_str());
@ -5233,8 +5259,8 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (!charset.empty()) {
if ((charset.size() == sizeof("DEFAULT") - 1) && strncasecmp(charset.c_str(), (char*)"DEFAULT", sizeof("DEFAULT") - 1) == 0) {
const char* charset_tmp = get_default_session_variable(PGSQL_CLIENT_ENCODING);
charset = charset_tmp ? charset_tmp : pgsql_thread___default_variables[PGSQL_CLIENT_ENCODING];
charset = get_default_session_variable(PGSQL_CLIENT_ENCODING);
assert(charset.empty() == false);
}
proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Processing SET CLIENT_ENCODING %s\n", charset.c_str());
@ -5246,14 +5272,14 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
if (charset_encoding == -1) {
char* m = NULL;
char* errmsg = NULL;
proxy_error("Cannot find charset [%s]\n", charset.c_str());
m = (char*)"Unknown character set: '%s'";
proxy_error("invalid value for parameter \"Client_Encoding\": \"%s\"\n", charset.c_str());
m = (char*)"invalid value for parameter \"Client_Encoding\": \"%s\"";
errmsg = (char*)malloc(charset.length() + strlen(m));
sprintf(errmsg, m, charset.c_str());
client_myds->DSS = STATE_QUERY_SENT_NET;
client_myds->myprot.generate_error_packet(true, true, errmsg,
PGSQL_ERROR_CODES::ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION, false, true);
PGSQL_ERROR_CODES::ERRCODE_INVALID_PARAMETER_VALUE, false, true);
client_myds->DSS = STATE_SLEEP;
status = WAITING_CLIENT_DATA;
free(errmsg);
@ -5318,7 +5344,8 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (i == PGSQL_NAME_LAST_LOW_WM) continue;
if (i == PGSQL_NAME_LAST_LOW_WM)
continue;
const char* name = pgsql_tracked_variables[i].set_variable_name;
const char* value = get_default_session_variable((enum pgsql_variable_name)i);
@ -5349,7 +5376,8 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C
int idx = PGSQL_NAME_LAST_HIGH_WM;
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (i == PGSQL_NAME_LAST_LOW_WM) continue;
if (i == PGSQL_NAME_LAST_LOW_WM)
continue;
if (variable_name_exists(pgsql_tracked_variables[i], nq.c_str()) == true) {
idx = i;
@ -6754,6 +6782,10 @@ void PgSQL_Session::reset_default_session_variable(enum pgsql_variable_name idx)
// - "ISO" (a single token; the second string will be empty)
// Leading and trailing whitespace is removed from each token.
std::vector<std::string> PgSQL_DateStyle_Util::split_datestyle(std::string_view input) {
if (input.empty())
return {};
std::string token1, token2;
// Reserve capacity in case the input is large (typically not needed for DateStyle)
token1.reserve(input.size());
@ -6897,7 +6929,6 @@ PgSQL_DateStyle_t PgSQL_DateStyle_Util::parse_datestyle(std::string_view input)
std::string PgSQL_DateStyle_Util::datestyle_to_string(PgSQL_DateStyle_t datestyle, const PgSQL_DateStyle_t& default_datestyle) {
if (datestyle.format == DATESTYLE_FORMAT_NONE && datestyle.order == DATESTYLE_ORDER_NONE) {
assert(0);
return {};
}

@ -1020,7 +1020,7 @@ PgSQL_Threads_Handler::PgSQL_Threads_Handler() {
variables.init_connect = NULL;
variables.ldap_user_variable = NULL;
variables.add_ldap_user_comment = NULL;
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
variables.default_variables[i] = strdup(pgsql_tracked_variables[i].default_value);
}
variables.default_session_track_gtids = strdup((char*)MYSQL_DEFAULT_SESSION_TRACK_GTIDS);
@ -1289,7 +1289,7 @@ char* PgSQL_Threads_Handler::get_variable_string(char* name) {
}
}
if (!strncmp(name, "default_", 8)) {
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i]) == false)
continue;
char buf[128];
@ -1422,7 +1422,7 @@ char* PgSQL_Threads_Handler::get_variable(char* name) { // this is the public fu
}
if (strlen(name) > 8) {
if (strncmp(name, "default_", 8) == 0) {
for (unsigned int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (unsigned int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i])) {
size_t var_len = strlen(pgsql_tracked_variables[i].internal_variable_name);
if (strlen(name) == (var_len + 8)) {
@ -1802,7 +1802,11 @@ bool PgSQL_Threads_Handler::set_variable(char* name, const char* value) { // thi
}
if (!strncmp(name, "default_", 8)) {
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (i == PGSQL_NAME_LAST_LOW_WM)
continue;
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i]) == false)
continue;
char buf[128];
@ -1810,13 +1814,11 @@ bool PgSQL_Threads_Handler::set_variable(char* name, const char* value) { // thi
if (!strcmp(name, buf)) {
if (i == PGSQL_DATESTYLE) {
if (vallen) {
// Ensure a complete DateStyle value is provided by validating both format and order.
PgSQL_DateStyle_t datestyle = PgSQL_DateStyle_Util::parse_datestyle(value);
if (datestyle.format == DATESTYLE_FORMAT_NONE || datestyle.order == DATESTYLE_ORDER_NONE) {
proxy_error("Invalid DateStyle value. Please provide both format and order (e.g., 'ISO, DMY'). %s\n", value);
return false;
}
// Ensure a complete DateStyle value is provided by validating both format and order.
PgSQL_DateStyle_t datestyle = PgSQL_DateStyle_Util::parse_datestyle(value);
if (datestyle.format == DATESTYLE_FORMAT_NONE || datestyle.order == DATESTYLE_ORDER_NONE) {
proxy_error("Invalid DateStyle value. Please provide both format and order (e.g., 'ISO, DMY'). %s\n", value);
return false;
}
}
@ -2241,13 +2243,13 @@ char** PgSQL_Threads_Handler::get_variables_list() {
const size_t l = sizeof(pgsql_thread_variables_names) / sizeof(char*);
unsigned int i;
size_t ltv = 0;
for (i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i]))
ltv++;
}
char** ret = (char**)malloc(sizeof(char*) * (l + ltv)); // not adding + 1 because pgsql_thread_variables_names is already NULL terminated
size_t fv = 0;
for (i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i])) {
char* m = (char*)malloc(strlen(pgsql_tracked_variables[i].internal_variable_name) + 1 + strlen((char*)"default_"));
sprintf(m, "default_%s", pgsql_tracked_variables[i].internal_variable_name);
@ -2269,7 +2271,7 @@ char** PgSQL_Threads_Handler::get_variables_list() {
bool PgSQL_Threads_Handler::has_variable(const char* name) {
if (strlen(name) > 8) {
if (strncmp(name, "default_", 8) == 0) {
for (unsigned int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (unsigned int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (IS_PGTRACKED_VAR_OPTION_SET_GLOBAL_VARIABLE(pgsql_tracked_variables[i])) {
size_t var_len = strlen(pgsql_tracked_variables[i].internal_variable_name);
if (strlen(name) == (var_len + 8)) {
@ -2648,7 +2650,7 @@ PgSQL_Threads_Handler::~PgSQL_Threads_Handler() {
if (variables.ssl_p2s_crl) free(variables.ssl_p2s_crl);
if (variables.ssl_p2s_crlpath) free(variables.ssl_p2s_crlpath);
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (variables.default_variables[i]) {
free(variables.default_variables[i]);
variables.default_variables[i] = NULL;
@ -2777,7 +2779,7 @@ PgSQL_Thread::~PgSQL_Thread() {
if (pgsql_thread___server_version) { free(pgsql_thread___server_version); pgsql_thread___server_version = NULL; }
if (pgsql_thread___server_encoding) { free(pgsql_thread___server_encoding); pgsql_thread___server_encoding = NULL; }
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (pgsql_thread___default_variables[i]) {
free(pgsql_thread___default_variables[i]);
pgsql_thread___default_variables[i] = NULL;
@ -3902,7 +3904,7 @@ void PgSQL_Thread::refresh_variables() {
mysql_thread___default_session_track_gtids = GloPTH->get_variable_string((char*)"default_session_track_gtids");
*/
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
if (pgsql_thread___default_variables[i]) {
free(pgsql_thread___default_variables[i]);
pgsql_thread___default_variables[i] = NULL;
@ -4067,7 +4069,7 @@ PgSQL_Thread::PgSQL_Thread() {
variables.stats_time_query_processor = false;
variables.query_cache_stores_empty_result = true;
for (int i = 0; i < PGSQL_NAME_LAST_LOW_WM; i++) {
for (int i = 0; i < PGSQL_NAME_LAST_HIGH_WM; i++) {
pgsql_thread___default_variables[i] = NULL;
}
shutdown = 0;

Loading…
Cancel
Save