From 2020b3f0bee98e72b9d59041892747290bd08010 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Wed, 21 Aug 2024 16:15:10 +0500 Subject: [PATCH 1/4] Handled 'PROXYSQL INTERNAL SESSION' command for PostgreSQL session --- include/PgSQL_Connection.h | 76 +++++++++++++++++++++++ include/PgSQL_Thread.h | 8 +++ lib/Base_Session.cpp | 61 +++++++++++------- lib/PgSQL_Session.cpp | 124 +++++++++++++++++-------------------- 4 files changed, 179 insertions(+), 90 deletions(-) diff --git a/include/PgSQL_Connection.h b/include/PgSQL_Connection.h index 531a9ed5f..b12468421 100644 --- a/include/PgSQL_Connection.h +++ b/include/PgSQL_Connection.h @@ -596,6 +596,82 @@ public: bool set_single_row_mode(); void optimize() {} + inline const PGconn* get_pg_connection() const { return pgsql_conn; } + inline int get_pg_server_version() { return PQserverVersion(pgsql_conn); } + inline const char* get_pg_server_version_str(char* buff, int buff_size) { + const int postgresql_version = get_pg_server_version(); + snprintf(buff, buff_size, "%d.%d.%d", postgresql_version / 10000, (postgresql_version / 100) % 100, postgresql_version % 100); + return buff; + } + inline int get_pg_protocol_version() { return PQprotocolVersion(pgsql_conn); } + inline const char* get_pg_host() { return PQhost(pgsql_conn); } + inline const char* get_pg_hostaddr() { return PQhostaddr(pgsql_conn); } + inline const char* get_pg_port() { return PQport(pgsql_conn); } + inline const char* get_pg_dbname() { return PQdb(pgsql_conn); } + inline const char* get_pg_user() { return PQuser(pgsql_conn); } + inline const char* get_pg_password() { return PQpass(pgsql_conn); } + inline const char* get_pg_options() { return PQoptions(pgsql_conn); } + inline int get_pg_socket_fd() { return PQsocket(pgsql_conn); } + inline int get_pg_backend_pid() { return PQbackendPID(pgsql_conn); } + inline int get_pg_connection_needs_password() { return PQconnectionNeedsPassword(pgsql_conn); } + inline int get_pg_connection_used_password() { return PQconnectionUsedPassword(pgsql_conn); } + inline int get_pg_connection_used_gssapi() { return PQconnectionUsedGSSAPI(pgsql_conn); } + inline int get_pg_client_encoding() { return PQclientEncoding(pgsql_conn); } + inline int get_pg_ssl_in_use() { return PQsslInUse(pgsql_conn); } + inline ConnStatusType get_pg_connection_status() { return PQstatus(pgsql_conn); } + inline const char* get_pg_connection_status_str() { + switch (get_pg_connection_status()) { + case CONNECTION_OK: + return "OK"; + case CONNECTION_BAD: + return "BAD"; + case CONNECTION_STARTED: + return "STARTED"; + case CONNECTION_MADE: + return "MADE"; + case CONNECTION_AWAITING_RESPONSE: + return "AWAITING_RESPONSE"; + case CONNECTION_AUTH_OK: + return "AUTH_OK"; + case CONNECTION_SETENV: + return "SETENV"; + case CONNECTION_SSL_STARTUP: + return "SSL_STARTUP"; + case CONNECTION_NEEDED: + return "NEEDED"; + case CONNECTION_CHECK_WRITABLE: + return "CHECK_WRITABLE"; + case CONNECTION_CONSUME: + return "CONSUME"; + case CONNECTION_GSS_STARTUP: + return "GSS_STARTUP"; + case CONNECTION_CHECK_TARGET: + return "CHECK_TARGET"; + case CONNECTION_CHECK_STANDBY: + return "CHECK_STANDBY"; + } + return "UNKNOWN"; + } + inline PGTransactionStatusType get_pg_transaction_status() { return PQtransactionStatus(pgsql_conn); } + inline const char* get_pg_transaction_status_str() { + switch (get_pg_transaction_status()) { + case PQTRANS_IDLE: + return "IDLE"; + case PQTRANS_ACTIVE: + return "ACTIVE"; + case PQTRANS_INTRANS: + return "IN-TRANSACTION"; + case PQTRANS_INERROR: + return "IN-ERROR-TRANSACTION"; + case PQTRANS_UNKNOWN: + return "UNKNOWN"; + } + return "INVALID"; + } + inline int get_pg_is_nonblocking() { return PQisnonblocking(pgsql_conn); } + inline int get_pg_is_threadsafe() { return PQisthreadsafe(); } + inline const char* get_pg_error_message() { return PQerrorMessage(pgsql_conn); } + //PgSQL_Conn_Param conn_params; PgSQL_ErrorInfo error_info; PGconn* pgsql_conn; diff --git a/include/PgSQL_Thread.h b/include/PgSQL_Thread.h index bacf60a88..105a2a06e 100644 --- a/include/PgSQL_Thread.h +++ b/include/PgSQL_Thread.h @@ -26,6 +26,14 @@ enum class AUTHENTICATION_METHOD { SASL_SCRAM_SHA_256_PLUS }; +constexpr const char* AUTHENTICATION_METHOD_STR[] = { + "NO_PASSWORD", + "CLEAR_TEXT_PASSWORD", + "MD5_PASSWORD", + "SASL_SCRAM_SHA_256", + "SASL_SCRAM_SHA_256_PLUS" +}; + /* #define MIN_POLL_LEN 8 #define MIN_POLL_DELETE_RATIO 8 diff --git a/lib/Base_Session.cpp b/lib/Base_Session.cpp index c32e5ccdb..50f87d8ab 100644 --- a/lib/Base_Session.cpp +++ b/lib/Base_Session.cpp @@ -292,31 +292,48 @@ void Base_Session::writeout() { } template -void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { +void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { unsigned int l = 0; l = strlen((char*)"PROXYSQL INTERNAL SESSION"); - if (pkt->size == (5 + l) && strncasecmp((char*)"PROXYSQL INTERNAL SESSION", (char*)pkt->ptr + 5, l) == 0) { - json j; - generate_proxysql_internal_session_json(j); - std::string s = j.dump(4, ' ', false, json::error_handler_t::replace); - SQLite3_result* resultset = new SQLite3_result(1); - resultset->add_column_definition(SQLITE_TEXT, "session_info"); - char* pta[1]; - pta[0] = (char*)s.c_str(); - resultset->add_row(pta); - bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; - SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active); - delete resultset; - l_free(pkt->size, pkt->ptr); - return; - } - // default - client_myds->DSS = STATE_QUERY_SENT_NET; if constexpr (std::is_same_v) { - client_myds->myprot.generate_pkt_ERR(true,NULL,NULL,1,1064,(char *)"42000",(char *)"Unknown PROXYSQL INTERNAL command",true); - } else if constexpr (std::is_same_v) { + if (pkt->size == (5 + l) && strncasecmp((char*)"PROXYSQL INTERNAL SESSION", (char*)pkt->ptr + 5, l) == 0) { + json j; + generate_proxysql_internal_session_json(j); + std::string s = j.dump(4, ' ', false, json::error_handler_t::replace); + SQLite3_result* resultset = new SQLite3_result(1); + resultset->add_column_definition(SQLITE_TEXT, "session_info"); + char* pta[1]; + pta[0] = (char*)s.c_str(); + resultset->add_row(pta); + bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; + SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active); + delete resultset; + l_free(pkt->size, pkt->ptr); + return; + } + // default + client_myds->DSS = STATE_QUERY_SENT_NET; + client_myds->myprot.generate_pkt_ERR(true, NULL, NULL, 1, 1064, (char*)"42000", (char*)"Unknown PROXYSQL INTERNAL command", true); + } + else if constexpr (std::is_same_v) { + if (pkt->size == (5 + 2 + l) && strncasecmp((char*)"PROXYSQL INTERNAL SESSION", (char*)pkt->ptr + 5, l) == 0) { + json j; + generate_proxysql_internal_session_json(j); + std::string s = j.dump(4, ' ', false, json::error_handler_t::replace); + SQLite3_result* resultset = new SQLite3_result(1); + resultset->add_column_definition(SQLITE_TEXT, "session_info"); + char* pta[1]; + pta[0] = (char*)s.c_str(); + resultset->add_row(pta); + SQLite3_to_Postgres(client_myds->PSarrayOUT, resultset, nullptr, 0, (const char*)pkt->ptr + 5); + delete resultset; + l_free(pkt->size, pkt->ptr); + return; + } + client_myds->DSS = STATE_QUERY_SENT_NET; client_myds->myprot.generate_error_packet(true, true, "Unknown PROXYSQL INTERNAL command", PGSQL_ERROR_CODES::ERRCODE_SYNTAX_ERROR, false, true); - } else { + } + else { assert(0); } if (mirror == false) { @@ -329,8 +346,6 @@ void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { l_free(pkt->size, pkt->ptr); } - - /** * @brief Check if any backend has an active MySQL connection. * diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index ed10188a0..3da7e9cb5 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -783,22 +783,15 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { sprintf(buff, "%p", thread); j["thread"] = buff; } - uint64_t age_ms = (thread->curtime - start_time) / 1000; + const uint64_t age_ms = (thread->curtime - start_time) / 1000; j["age_ms"] = age_ms; j["status"] = status; - j["autocommit"] = autocommit; j["thread_session_id"] = thread_session_id; j["current_hostgroup"] = current_hostgroup; j["default_hostgroup"] = default_hostgroup; j["locked_on_hostgroup"] = locked_on_hostgroup; - j["autocommit_on_hostgroup"] = autocommit_on_hostgroup; - j["last_insert_id"] = last_insert_id; - j["last_HG_affected_rows"] = last_HG_affected_rows; j["active_transactions"] = active_transactions; j["transaction_time_ms"] = thread->curtime - transaction_started_at; - j["warning_in_hg"] = warning_in_hg; - j["gtid"]["hid"] = gtid_hid; - j["gtid"]["last"] = (strlen(gtid_buf) ? gtid_buf : ""); j["qpo"]["create_new_connection"] = qpo->create_new_conn; j["qpo"]["reconnect"] = qpo->reconnect; j["qpo"]["sticky_conn"] = qpo->sticky_conn; @@ -811,7 +804,6 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { j["qpo"]["timeout"] = qpo->timeout; j["qpo"]["retries"] = qpo->retries; j["qpo"]["max_lag_ms"] = qpo->max_lag_ms; - j["default_schema"] = (default_schema ? default_schema : ""); j["user_attributes"] = (user_attributes ? user_attributes : ""); j["transaction_persistent"] = transaction_persistent; if (client_myds != NULL) { // only if client_myds is defined @@ -834,7 +826,7 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { } } j["client"]["DSS"] = client_myds->DSS; - j["client"]["switching_auth_type"] = client_myds->switching_auth_type; + j["client"]["auth_method"] = AUTHENTICATION_METHOD_STR[(int)client_myds->auth_method]; if (client_myds->myconn != NULL) { // only if myconn is defined if (client_myds->myconn->userinfo != NULL) { // only if userinfo is defined j["client"]["userinfo"]["username"] = (client_myds->myconn->userinfo->username ? client_myds->myconn->userinfo->username : ""); @@ -843,7 +835,6 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { j["client"]["userinfo"]["password"] = (client_myds->myconn->userinfo->password ? client_myds->myconn->userinfo->password : ""); #endif } - j["conn"]["session_track_gtids"] = (client_myds->myconn->options.session_track_gtids ? client_myds->myconn->options.session_track_gtids : ""); for (auto idx = 0; idx < SQL_NAME_LAST_LOW_WM; idx++) { client_myds->myconn->variables[idx].fill_client_internal_session(j, idx); } @@ -853,24 +844,32 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { c->variables[*it_c].fill_client_internal_session(j, *it_c); } } + //j["conn"]["autocommit"] = (client_myds->myconn->options.autocommit ? "ON" : "OFF"); + //j["conn"]["client_flag"]["value"] = client_myds->myconn->options.client_flag; + //j["conn"]["client_flag"]["client_found_rows"] = (client_myds->myconn->options.client_flag & CLIENT_FOUND_ROWS ? 1 : 0); + //j["conn"]["client_flag"]["client_multi_statements"] = (client_myds->myconn->options.client_flag & CLIENT_MULTI_STATEMENTS ? 1 : 0); + //j["conn"]["client_flag"]["client_multi_results"] = (client_myds->myconn->options.client_flag & CLIENT_MULTI_RESULTS ? 1 : 0); + //j["conn"]["client_flag"]["client_deprecate_eof"] = (client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF ? 1 : 0); + //j["conn"]["no_backslash_escapes"] = client_myds->myconn->options.no_backslash_escapes; + //j["conn"]["status"]["compression"] = client_myds->myconn->get_status(STATUS_MYSQL_CONNECTION_COMPRESSION); + //j["conn"]["ps"]["client_stmt_to_global_ids"] = client_myds->myconn->local_stmts->client_stmt_to_global_ids; + { + const PgSQL_Conn_Param& c = client_myds->myconn->conn_params; + + for (size_t i = 0; i < c.param_set.size(); i++) { - j["conn"]["autocommit"] = (client_myds->myconn->options.autocommit ? "ON" : "OFF"); - j["conn"]["client_flag"]["value"] = client_myds->myconn->options.client_flag; - j["conn"]["client_flag"]["client_found_rows"] = (client_myds->myconn->options.client_flag & CLIENT_FOUND_ROWS ? 1 : 0); - j["conn"]["client_flag"]["client_multi_statements"] = (client_myds->myconn->options.client_flag & CLIENT_MULTI_STATEMENTS ? 1 : 0); - j["conn"]["client_flag"]["client_multi_results"] = (client_myds->myconn->options.client_flag & CLIENT_MULTI_RESULTS ? 1 : 0); - j["conn"]["client_flag"]["client_deprecate_eof"] = (client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF ? 1 : 0); - j["conn"]["no_backslash_escapes"] = client_myds->myconn->options.no_backslash_escapes; - j["conn"]["status"]["compression"] = client_myds->myconn->get_status(STATUS_MYSQL_CONNECTION_COMPRESSION); - j["conn"]["ps"]["client_stmt_to_global_ids"] = client_myds->myconn->local_stmts->client_stmt_to_global_ids; + if (c.param_value[c.param_set[i]] != NULL) { + + j["client"]["conn"]["connection_options"][PgSQL_Param_Name_Str[c.param_set[i]]] = c.param_value[c.param_set[i]]; + } + } + } } } for (unsigned int i = 0; i < mybes->len; i++) { PgSQL_Backend* _mybe = NULL; _mybe = (PgSQL_Backend*)mybes->index(i); - //unsigned int i = _mybe->hostgroup_id; j["backends"][i]["hostgroup_id"] = _mybe->hostgroup_id; - j["backends"][i]["gtid"] = (strlen(_mybe->gtid_uuid) ? _mybe->gtid_uuid : ""); if (_mybe->server_myds) { PgSQL_Data_Stream* _myds = _mybe->server_myds; sprintf(buff, "%p", _myds); @@ -902,24 +901,20 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { j["backends"][i]["conn"]["myconnpoll_get"] = _myconn->statuses.myconnpoll_get; j["backends"][i]["conn"]["myconnpoll_put"] = _myconn->statuses.myconnpoll_put; //j["backend"][i]["conn"]["charset"] = _myds->myconn->options.charset; // not used for backend - j["backends"][i]["conn"]["session_track_gtids"] = (_myconn->options.session_track_gtids ? _myconn->options.session_track_gtids : ""); + //j["backends"][i]["conn"]["session_track_gtids"] = (_myconn->options.session_track_gtids ? _myconn->options.session_track_gtids : ""); j["backends"][i]["conn"]["init_connect"] = (_myconn->options.init_connect ? _myconn->options.init_connect : ""); j["backends"][i]["conn"]["init_connect_sent"] = _myds->myconn->options.init_connect_sent; - j["backends"][i]["conn"]["autocommit"] = (_myds->myconn->options.autocommit ? "ON" : "OFF"); - j["backends"][i]["conn"]["last_set_autocommit"] = _myds->myconn->options.last_set_autocommit; - j["backends"][i]["conn"]["no_backslash_escapes"] = _myconn->options.no_backslash_escapes; - j["backends"][i]["conn"]["status"]["get_lock"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_GET_LOCK); - j["backends"][i]["conn"]["status"]["lock_tables"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_LOCK_TABLES); - j["backends"][i]["conn"]["status"]["has_savepoint"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT); - j["backends"][i]["conn"]["status"]["temporary_table"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_TEMPORARY_TABLE); + //j["backends"][i]["conn"]["no_backslash_escapes"] = _myconn->options.no_backslash_escapes; + //j["backends"][i]["conn"]["status"]["get_lock"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_GET_LOCK); + //j["backends"][i]["conn"]["status"]["lock_tables"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_LOCK_TABLES); + //j["backends"][i]["conn"]["status"]["has_savepoint"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT); + //j["backends"][i]["conn"]["status"]["temporary_table"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_TEMPORARY_TABLE); j["backends"][i]["conn"]["status"]["user_variable"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_USER_VARIABLE); - j["backends"][i]["conn"]["status"]["found_rows"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_FOUND_ROWS); + //j["backends"][i]["conn"]["status"]["found_rows"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_FOUND_ROWS); j["backends"][i]["conn"]["status"]["no_multiplex"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_NO_MULTIPLEX); j["backends"][i]["conn"]["status"]["no_multiplex_HG"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_NO_MULTIPLEX_HG); - j["backends"][i]["conn"]["status"]["compression"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_COMPRESSION); - j["backends"][i]["conn"]["status"]["prepared_statement"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_PREPARED_STATEMENT); - j["backends"][i]["conn"]["status"]["has_warnings"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_HAS_WARNINGS); - j["backends"][i]["conn"]["warning_count"] = _myconn->warning_count; + //j["backends"][i]["conn"]["status"]["compression"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_COMPRESSION); + //j["backends"][i]["conn"]["status"]["prepared_statement"] = _myconn->get_status(STATUS_MYSQL_CONNECTION_PREPARED_STATEMENT); { // MultiplexDisabled : status returned by PgSQL_Connection::MultiplexDisabled(); // MultiplexDisabled_ext : status returned by PgSQL_Connection::MultiplexDisabled() || PgSQL_Connection::isActiveTransaction() @@ -932,39 +927,34 @@ void PgSQL_Session::generate_proxysql_internal_session_json(json& j) { } j["backends"][i]["conn"]["MultiplexDisabled_ext"] = multiplex_disabled; } - j["backends"][i]["conn"]["ps"]["backend_stmt_to_global_ids"] = _myconn->local_stmts->backend_stmt_to_global_ids; - j["backends"][i]["conn"]["ps"]["global_stmt_to_backend_ids"] = _myconn->local_stmts->global_stmt_to_backend_ids; - j["backends"][i]["conn"]["client_flag"]["value"] = _myconn->options.client_flag; - j["backends"][i]["conn"]["client_flag"]["client_found_rows"] = (_myconn->options.client_flag & CLIENT_FOUND_ROWS ? 1 : 0); - j["backends"][i]["conn"]["client_flag"]["client_multi_statements"] = (_myconn->options.client_flag & CLIENT_MULTI_STATEMENTS ? 1 : 0); - j["backends"][i]["conn"]["client_flag"]["client_deprecate_eof"] = (_myconn->options.client_flag & CLIENT_DEPRECATE_EOF ? 1 : 0); - if (_myconn->pgsql && _myconn->ret_mysql) { - MYSQL* _my = _myconn->pgsql; - sprintf(buff, "%p", _my); + //j["backends"][i]["conn"]["ps"]["backend_stmt_to_global_ids"] = _myconn->local_stmts->backend_stmt_to_global_ids; + //j["backends"][i]["conn"]["ps"]["global_stmt_to_backend_ids"] = _myconn->local_stmts->global_stmt_to_backend_ids; + //j["backends"][i]["conn"]["client_flag"]["value"] = _myconn->options.client_flag; + //j["backends"][i]["conn"]["client_flag"]["client_found_rows"] = (_myconn->options.client_flag & CLIENT_FOUND_ROWS ? 1 : 0); + //j["backends"][i]["conn"]["client_flag"]["client_multi_statements"] = (_myconn->options.client_flag & CLIENT_MULTI_STATEMENTS ? 1 : 0); + //j["backends"][i]["conn"]["client_flag"]["client_deprecate_eof"] = (_myconn->options.client_flag & CLIENT_DEPRECATE_EOF ? 1 : 0); + if (_myconn->is_connected()) { + sprintf(buff, "%p", _myconn->get_pg_connection()); j["backends"][i]["conn"]["pgsql"]["address"] = buff; - j["backends"][i]["conn"]["pgsql"]["host"] = (_my->host ? _my->host : ""); - j["backends"][i]["conn"]["pgsql"]["host_info"] = (_my->host_info ? _my->host_info : ""); - j["backends"][i]["conn"]["pgsql"]["port"] = _my->port; - j["backends"][i]["conn"]["pgsql"]["server_version"] = (_my->server_version ? _my->server_version : ""); - j["backends"][i]["conn"]["pgsql"]["user"] = (_my->user ? _my->user : ""); - j["backends"][i]["conn"]["pgsql"]["unix_socket"] = (_my->unix_socket ? _my->unix_socket : ""); - j["backends"][i]["conn"]["pgsql"]["db"] = (_my->db ? _my->db : ""); - j["backends"][i]["conn"]["pgsql"]["affected_rows"] = _my->affected_rows; - j["backends"][i]["conn"]["pgsql"]["insert_id"] = _my->insert_id; - j["backends"][i]["conn"]["pgsql"]["thread_id"] = _my->thread_id; - j["backends"][i]["conn"]["pgsql"]["server_status"] = _my->server_status; - j["backends"][i]["conn"]["pgsql"]["charset"] = _my->charset->nr; - j["backends"][i]["conn"]["pgsql"]["charset_name"] = _my->charset->csname; - //j["backends"][i]["conn"]["pgsql"][""] = _my->; - //j["backends"][i]["conn"]["pgsql"][""] = _my->; - j["backends"][i]["conn"]["pgsql"]["options"]["charset_name"] = (_my->options.charset_name ? _my->options.charset_name : ""); - j["backends"][i]["conn"]["pgsql"]["options"]["use_ssl"] = _my->options.use_ssl; - j["backends"][i]["conn"]["pgsql"]["net"]["last_errno"] = _my->net.last_errno; - j["backends"][i]["conn"]["pgsql"]["net"]["fd"] = _my->net.fd; - j["backends"][i]["conn"]["pgsql"]["net"]["max_packet_size"] = _my->net.max_packet_size; - j["backends"][i]["conn"]["pgsql"]["net"]["sqlstate"] = _my->net.sqlstate; - //j["backends"][i]["conn"]["pgsql"]["net"][""] = _my->net.; - //j["backends"][i]["conn"]["pgsql"]["net"][""] = _my->net.; + j["backends"][i]["conn"]["pgsql"]["host"] = _myconn->get_pg_host(); + j["backends"][i]["conn"]["pgsql"]["host_addr"] = _myconn->get_pg_hostaddr(); + j["backends"][i]["conn"]["pgsql"]["port"] = _myconn->get_pg_port(); + j["backends"][i]["conn"]["pgsql"]["user"] = _myconn->get_pg_user(); +#ifdef DEBUG + j["backends"][i]["conn"]["pgsql"]["password"] = _myconn->get_pg_password(); +#endif + j["backends"][i]["conn"]["pgsql"]["db"] = _myconn->get_pg_dbname(); + j["backends"][i]["conn"]["pgsql"]["backend_pid"] = _myconn->get_pg_backend_pid(); + j["backends"][i]["conn"]["pgsql"]["using_ssl"] = _myconn->get_pg_ssl_in_use() ? "YES" : "NO"; + j["backends"][i]["conn"]["pgsql"]["error_msg"] = _myconn->get_pg_error_message(); + j["backends"][i]["conn"]["pgsql"]["options"] = _myconn->get_pg_options(); + j["backends"][i]["conn"]["pgsql"]["fd"] = _myconn->get_pg_socket_fd(); + j["backends"][i]["conn"]["pgsql"]["protocol_version"] = _myconn->get_pg_protocol_version(); + j["backends"][i]["conn"]["pgsql"]["server_version"] = _myconn->get_pg_server_version_str(buff, sizeof(buff)); + j["backends"][i]["conn"]["pgsql"]["transaction_status"] = _myconn->get_pg_transaction_status_str(); + j["backends"][i]["conn"]["pgsql"]["connection_status"] = _myconn->get_pg_connection_status_str(); + j["backends"][i]["conn"]["pgsql"]["client_encoding"] = _myconn->get_pg_client_encoding(); + j["backends"][i]["conn"]["pgsql"]["is_nonblocking"] = _myconn->get_pg_is_nonblocking() ? "YES" : "NO"; } } } From f9ed50650fbcaf3015e33ae3708665e833732681 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Wed, 21 Aug 2024 16:29:45 +0500 Subject: [PATCH 2/4] Updated set_dbname implementation for PostgreSQL --- include/PgSQL_Connection.h | 2 +- lib/PgSQL_Connection.cpp | 31 +++++++++++-------------------- lib/PgSQL_Protocol.cpp | 6 +----- lib/PgSQL_Session.cpp | 8 +++++--- 4 files changed, 18 insertions(+), 29 deletions(-) diff --git a/include/PgSQL_Connection.h b/include/PgSQL_Connection.h index b12468421..34be4e3a7 100644 --- a/include/PgSQL_Connection.h +++ b/include/PgSQL_Connection.h @@ -291,7 +291,7 @@ class PgSQL_Connection_userinfo { ~PgSQL_Connection_userinfo(); void set(char *, char *, char *, char *); void set(PgSQL_Connection_userinfo *); - bool set_dbname(char *, int); + bool set_dbname(const char *); }; class PgSQL_Connection_Placeholder { diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index f9c998974..d93bd15c1 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -372,35 +372,26 @@ void PgSQL_Connection_userinfo::set(PgSQL_Connection_userinfo *ui) { set(ui->username, ui->password, ui->dbname, ui->sha1_pass); } - -bool PgSQL_Connection_userinfo::set_dbname(char *_new, int l) { - int _l=0; - if (dbname) { - _l=strlen(dbname); // bug fix for #609 - } - if ((dbname==NULL) || (l != _l) || (strncmp(_new, dbname, l ))) { +bool PgSQL_Connection_userinfo::set_dbname(const char* db) { + assert(db); + const int new_db_len = db ? strlen(db) : 0; + const int old_db_len = dbname ? strlen(dbname) : 0; + + if (old_db_len == 0 || + old_db_len != new_db_len || + strncmp(db, dbname, new_db_len)) { if (dbname) { free(dbname); - dbname =NULL; - } - if (l) { - dbname=(char *)malloc(l+1); - memcpy(dbname,_new,l); - dbname[l]=0; - } else { - int k=strlen(pgsql_thread___default_schema); - dbname =(char *)malloc(k+1); - memcpy(dbname,pgsql_thread___default_schema,k); - dbname[k]=0; } + dbname = (char*)malloc(new_db_len + 1); + memcpy(dbname, db, new_db_len); + dbname[new_db_len] = 0; compute_hash(); return true; } return false; } - - PgSQL_Connection_Placeholder::PgSQL_Connection_Placeholder() { pgsql=NULL; async_state_machine=ASYNC_CONNECT_START; diff --git a/lib/PgSQL_Protocol.cpp b/lib/PgSQL_Protocol.cpp index 0ff3f5f94..a57b6e1dd 100644 --- a/lib/PgSQL_Protocol.cpp +++ b/lib/PgSQL_Protocol.cpp @@ -946,11 +946,7 @@ EXECUTION_STATE PgSQL_Protocol::process_handshake_response_packet(unsigned char* userinfo->password = strdup((const char*)password); const char* db = (*myds)->myconn->conn_params.get_value(PG_DATABASE); - - if (db) - userinfo->set_dbname((char*)db, strlen(db)); - else - userinfo->set_dbname(userinfo->username, strlen(userinfo->username)); + userinfo->set_dbname(db ? db : userinfo->username); const char* charset = (*myds)->myconn->conn_params.get_value(PG_CLIENT_ENCODING); diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index 3da7e9cb5..b504061bf 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -5070,6 +5070,7 @@ void PgSQL_Session::handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE( l_free(pkt->size, pkt->ptr); //if (client_myds->encrypted==false) { if (client_myds->myconn->userinfo->dbname == NULL) { +#if 0 #ifdef PROXYSQLCLICKHOUSE if (session_type == PROXYSQL_SESSION_CLICKHOUSE) { if (strlen(default_schema) == 0) { @@ -5078,7 +5079,8 @@ void PgSQL_Session::handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE( } } #endif /* PROXYSQLCLICKHOUSE */ - client_myds->myconn->userinfo->set_dbname(default_schema, strlen(default_schema)); +#endif + client_myds->myconn->userinfo->set_dbname(default_schema); } int free_users = 0; int used_users = 0; @@ -5405,7 +5407,7 @@ void PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_INIT_DB packet\n"); if (session_type == PROXYSQL_SESSION_PGSQL) { __sync_fetch_and_add(&PgHGM->status.frontend_init_db, 1); - client_myds->myconn->userinfo->set_dbname((char*)pkt->ptr + sizeof(mysql_hdr) + 1, pkt->size - sizeof(mysql_hdr) - 1); + //client_myds->myconn->userinfo->set_dbname((char*)pkt->ptr + sizeof(mysql_hdr) + 1, pkt->size - sizeof(mysql_hdr) - 1); l_free(pkt->size, pkt->ptr); client_myds->setDSS_STATE_QUERY_SENT_NET(); unsigned int nTrx = NumActiveTransactions(); @@ -5446,7 +5448,7 @@ void PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___MYSQL_C schemanameptr[strlen(schemanameptr) - 1] = '\0'; schemanameptr++; } - client_myds->myconn->userinfo->set_dbname(schemanameptr, strlen(schemanameptr)); + //client_myds->myconn->userinfo->set_dbname(schemanameptr); free(schemaname); if (mirror == false) { RequestEnd(NULL); From e31dd5661f8090e572df46970f4f2c68e7dd300f Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Wed, 21 Aug 2024 22:49:17 +0500 Subject: [PATCH 3/4] Moved few methods from PgSQL_Connection.h to PgSQL_Connection.cpp --- include/PgSQL_Connection.h | 56 ++------------------------------------ lib/PgSQL_Connection.cpp | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/include/PgSQL_Connection.h b/include/PgSQL_Connection.h index 34be4e3a7..a6cfcdd21 100644 --- a/include/PgSQL_Connection.h +++ b/include/PgSQL_Connection.h @@ -598,11 +598,6 @@ public: inline const PGconn* get_pg_connection() const { return pgsql_conn; } inline int get_pg_server_version() { return PQserverVersion(pgsql_conn); } - inline const char* get_pg_server_version_str(char* buff, int buff_size) { - const int postgresql_version = get_pg_server_version(); - snprintf(buff, buff_size, "%d.%d.%d", postgresql_version / 10000, (postgresql_version / 100) % 100, postgresql_version % 100); - return buff; - } inline int get_pg_protocol_version() { return PQprotocolVersion(pgsql_conn); } inline const char* get_pg_host() { return PQhost(pgsql_conn); } inline const char* get_pg_hostaddr() { return PQhostaddr(pgsql_conn); } @@ -619,58 +614,13 @@ public: inline int get_pg_client_encoding() { return PQclientEncoding(pgsql_conn); } inline int get_pg_ssl_in_use() { return PQsslInUse(pgsql_conn); } inline ConnStatusType get_pg_connection_status() { return PQstatus(pgsql_conn); } - inline const char* get_pg_connection_status_str() { - switch (get_pg_connection_status()) { - case CONNECTION_OK: - return "OK"; - case CONNECTION_BAD: - return "BAD"; - case CONNECTION_STARTED: - return "STARTED"; - case CONNECTION_MADE: - return "MADE"; - case CONNECTION_AWAITING_RESPONSE: - return "AWAITING_RESPONSE"; - case CONNECTION_AUTH_OK: - return "AUTH_OK"; - case CONNECTION_SETENV: - return "SETENV"; - case CONNECTION_SSL_STARTUP: - return "SSL_STARTUP"; - case CONNECTION_NEEDED: - return "NEEDED"; - case CONNECTION_CHECK_WRITABLE: - return "CHECK_WRITABLE"; - case CONNECTION_CONSUME: - return "CONSUME"; - case CONNECTION_GSS_STARTUP: - return "GSS_STARTUP"; - case CONNECTION_CHECK_TARGET: - return "CHECK_TARGET"; - case CONNECTION_CHECK_STANDBY: - return "CHECK_STANDBY"; - } - return "UNKNOWN"; - } inline PGTransactionStatusType get_pg_transaction_status() { return PQtransactionStatus(pgsql_conn); } - inline const char* get_pg_transaction_status_str() { - switch (get_pg_transaction_status()) { - case PQTRANS_IDLE: - return "IDLE"; - case PQTRANS_ACTIVE: - return "ACTIVE"; - case PQTRANS_INTRANS: - return "IN-TRANSACTION"; - case PQTRANS_INERROR: - return "IN-ERROR-TRANSACTION"; - case PQTRANS_UNKNOWN: - return "UNKNOWN"; - } - return "INVALID"; - } inline int get_pg_is_nonblocking() { return PQisnonblocking(pgsql_conn); } inline int get_pg_is_threadsafe() { return PQisthreadsafe(); } inline const char* get_pg_error_message() { return PQerrorMessage(pgsql_conn); } + const char* get_pg_server_version_str(char* buff, int buff_size); + const char* get_pg_connection_status_str(); + const char* get_pg_transaction_status_str(); //PgSQL_Conn_Param conn_params; PgSQL_ErrorInfo error_info; diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index d93bd15c1..bf070dbb6 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -2817,3 +2817,59 @@ bool PgSQL_Connection::has_same_connection_options(const PgSQL_Connection* clien } return true; } + +const char* PgSQL_Connection::get_pg_server_version_str(char* buff, int buff_size) { + const int postgresql_version = get_pg_server_version(); + snprintf(buff, buff_size, "%d.%d.%d", postgresql_version / 10000, (postgresql_version / 100) % 100, postgresql_version % 100); + return buff; +} + +const char* PgSQL_Connection::get_pg_connection_status_str() { + switch (get_pg_connection_status()) { + case CONNECTION_OK: + return "OK"; + case CONNECTION_BAD: + return "BAD"; + case CONNECTION_STARTED: + return "STARTED"; + case CONNECTION_MADE: + return "MADE"; + case CONNECTION_AWAITING_RESPONSE: + return "AWAITING_RESPONSE"; + case CONNECTION_AUTH_OK: + return "AUTH_OK"; + case CONNECTION_SETENV: + return "SETENV"; + case CONNECTION_SSL_STARTUP: + return "SSL_STARTUP"; + case CONNECTION_NEEDED: + return "NEEDED"; + case CONNECTION_CHECK_WRITABLE: + return "CHECK_WRITABLE"; + case CONNECTION_CONSUME: + return "CONSUME"; + case CONNECTION_GSS_STARTUP: + return "GSS_STARTUP"; + case CONNECTION_CHECK_TARGET: + return "CHECK_TARGET"; + case CONNECTION_CHECK_STANDBY: + return "CHECK_STANDBY"; + } + return "UNKNOWN"; +} + +const char* PgSQL_Connection::get_pg_transaction_status_str() { + switch (get_pg_transaction_status()) { + case PQTRANS_IDLE: + return "IDLE"; + case PQTRANS_ACTIVE: + return "ACTIVE"; + case PQTRANS_INTRANS: + return "IN-TRANSACTION"; + case PQTRANS_INERROR: + return "IN-ERROR-TRANSACTION"; + case PQTRANS_UNKNOWN: + return "UNKNOWN"; + } + return "INVALID"; +} From 2fc58176f9c9ddadfb83a50476f412e32c8c1c4d Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Thu, 22 Aug 2024 13:30:04 +0500 Subject: [PATCH 4/4] Handle all cases of the 'PROXYSQL INTERNAL SESSION' command, with or without a semicolon --- lib/Base_Session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Base_Session.cpp b/lib/Base_Session.cpp index 50f87d8ab..81f942630 100644 --- a/lib/Base_Session.cpp +++ b/lib/Base_Session.cpp @@ -316,7 +316,7 @@ void Base_Session::return_proxysql_internal(PtrSize_t* pkt) { client_myds->myprot.generate_pkt_ERR(true, NULL, NULL, 1, 1064, (char*)"42000", (char*)"Unknown PROXYSQL INTERNAL command", true); } else if constexpr (std::is_same_v) { - if (pkt->size == (5 + 2 + l) && strncasecmp((char*)"PROXYSQL INTERNAL SESSION", (char*)pkt->ptr + 5, l) == 0) { + if (pkt->size >= (5 + 1 + l) && strncasecmp((char*)"PROXYSQL INTERNAL SESSION", (char*)pkt->ptr + 5, l) == 0) { json j; generate_proxysql_internal_session_json(j); std::string s = j.dump(4, ' ', false, json::error_handler_t::replace);