diff --git a/include/PgSQL_PreparedStatement.h b/include/PgSQL_PreparedStatement.h index 107c4fc08..13377f4da 100644 --- a/include/PgSQL_PreparedStatement.h +++ b/include/PgSQL_PreparedStatement.h @@ -22,22 +22,14 @@ public: uint64_t statement_id; char* first_comment; uint64_t total_mem_usage; - PgSQL_Describe_Prepared_Info* stmt_metadata; bool is_select_NOT_for_update; - Parse_Param_Types parse_param_types;// array of parameter types, used for prepared statements PgSQL_STMT_Global_info(uint64_t id, char* u, char* d, char* q, unsigned int ql, char* fc, Parse_Param_Types&& ppt, uint64_t _h); ~PgSQL_STMT_Global_info(); - - void update_stmt_metadata(PgSQL_Describe_Prepared_Info** new_stmt_metadata); void calculate_mem_usage(); - void unlock() { pthread_rwlock_unlock(&rwlock_); } - void wrlock() { pthread_rwlock_wrlock(&rwlock_); } - void rdlock() { pthread_rwlock_rdlock(&rwlock_); } private: - pthread_rwlock_t rwlock_; void compute_hash(); }; diff --git a/include/ProxySQL_Admin_Tables_Definitions.h b/include/ProxySQL_Admin_Tables_Definitions.h index ee8b500ae..4e86b8cda 100644 --- a/include/ProxySQL_Admin_Tables_Definitions.h +++ b/include/ProxySQL_Admin_Tables_Definitions.h @@ -306,7 +306,7 @@ #define STATS_SQLITE_TABLE_PGSQL_COMMANDS_COUNTERS "CREATE TABLE stats_pgsql_commands_counters (Command VARCHAR NOT NULL PRIMARY KEY , Total_Time_us INT NOT NULL , Total_cnt INT NOT NULL , cnt_100us INT NOT NULL , cnt_500us INT NOT NULL , cnt_1ms INT NOT NULL , cnt_5ms INT NOT NULL , cnt_10ms INT NOT NULL , cnt_50ms INT NOT NULL , cnt_100ms INT NOT NULL , cnt_500ms INT NOT NULL , cnt_1s INT NOT NULL , cnt_5s INT NOT NULL , cnt_10s INT NOT NULL , cnt_INFs)" #define STATS_SQLITE_TABLE_PGSQL_QUERY_DIGEST "CREATE TABLE stats_pgsql_query_digest (hostgroup INT , database VARCHAR NOT NULL , username VARCHAR NOT NULL , client_address VARCHAR NOT NULL , digest VARCHAR NOT NULL , digest_text VARCHAR NOT NULL , count_star INTEGER NOT NULL , first_seen INTEGER NOT NULL , last_seen INTEGER NOT NULL , sum_time INTEGER NOT NULL , min_time INTEGER NOT NULL , max_time INTEGER NOT NULL , sum_rows_affected INTEGER NOT NULL , sum_rows_sent INTEGER NOT NULL , PRIMARY KEY(hostgroup, database, username, client_address, digest))" #define STATS_SQLITE_TABLE_PGSQL_QUERY_DIGEST_RESET "CREATE TABLE stats_pgsql_query_digest_reset (hostgroup INT , database VARCHAR NOT NULL , username VARCHAR NOT NULL , client_address VARCHAR NOT NULL , digest VARCHAR NOT NULL , digest_text VARCHAR NOT NULL , count_star INTEGER NOT NULL , first_seen INTEGER NOT NULL , last_seen INTEGER NOT NULL , sum_time INTEGER NOT NULL , min_time INTEGER NOT NULL , max_time INTEGER NOT NULL , sum_rows_affected INTEGER NOT NULL , sum_rows_sent INTEGER NOT NULL , PRIMARY KEY(hostgroup, database, username, client_address, digest))" -#define STATS_SQLITE_TABLE_PGSQL_PREPARED_STATEMENTS_INFO "CREATE TABLE stats_pgsql_prepared_statements_info (global_stmt_id INT NOT NULL , database VARCHAR NOT NULL , username VARCHAR NOT NULL , digest VARCHAR NOT NULL , ref_count_client INT NOT NULL , ref_count_server INT NOT NULL , num_columns INT NOT NULL, num_params INT NOT NULL, query VARCHAR NOT NULL)" +#define STATS_SQLITE_TABLE_PGSQL_PREPARED_STATEMENTS_INFO "CREATE TABLE stats_pgsql_prepared_statements_info (global_stmt_id INT NOT NULL , database VARCHAR NOT NULL , username VARCHAR NOT NULL , digest VARCHAR NOT NULL , ref_count_client INT NOT NULL , ref_count_server INT NOT NULL , num_param_types INT NOT NULL , query VARCHAR NOT NULL)" //#define STATS_SQLITE_TABLE_MEMORY_METRICS "CREATE TABLE stats_memory_metrics (Variable_Name VARCHAR NOT NULL PRIMARY KEY , Variable_Value VARCHAR NOT NULL)" diff --git a/lib/PgSQL_PreparedStatement.cpp b/lib/PgSQL_PreparedStatement.cpp index 7f2e42e59..42f3f98a8 100644 --- a/lib/PgSQL_PreparedStatement.cpp +++ b/lib/PgSQL_PreparedStatement.cpp @@ -11,7 +11,7 @@ extern PgSQL_STMT_Manager_v14 *GloPgStmt; -const int PS_GLOBAL_STATUS_FIELD_NUM = 9; +const int PS_GLOBAL_STATUS_FIELD_NUM = 8; static uint64_t stmt_compute_hash(const char *user, const char *database, const char *query, unsigned int query_length, const Parse_Param_Types& param_types) { @@ -69,13 +69,11 @@ PgSQL_STMT_Global_info::PgSQL_STMT_Global_info(uint64_t id, char *fc, Parse_Param_Types&& ppt, uint64_t _h) { - pthread_rwlock_init(&rwlock_, NULL); total_mem_usage = 0; statement_id = id; ref_count_client = 0; ref_count_server = 0; digest_text = nullptr; - stmt_metadata = nullptr; username = strdup(u); dbname = strdup(d); query = (char *)malloc(ql + 1); @@ -162,81 +160,6 @@ __exit_PgSQL_STMT_Global_info___search_select: calculate_mem_usage(); } -void PgSQL_STMT_Global_info::calculate_mem_usage() { - total_mem_usage = sizeof(PgSQL_STMT_Global_info) + - query_length + 1; - - // NOSONAR: strlen is safe here - if (username) total_mem_usage += strlen(username) + 1; // NOSONAR - if (dbname) total_mem_usage += strlen(dbname) + 1; // NOSONAR - if (first_comment) total_mem_usage += strlen(first_comment) + 1; // NOSONAR - if (digest_text) total_mem_usage += strlen(digest_text) + 1; // NOSONAR - - if (stmt_metadata) { - total_mem_usage += sizeof(PgSQL_Describe_Prepared_Info); - total_mem_usage += stmt_metadata->parameter_types_count * sizeof(uint32_t) ; - total_mem_usage += stmt_metadata->columns_count * sizeof(ColumnMetadata); - for (uint16_t i = 0; i < stmt_metadata->columns_count; i++) { - if (stmt_metadata->columns[i].name) - // NOSONAR: strlen is safe here - total_mem_usage += strlen(stmt_metadata->columns[i].name) + 1; // NOSONAR - } - } -} - -void PgSQL_STMT_Global_info::update_stmt_metadata(PgSQL_Describe_Prepared_Info** new_stmt_metadata) { - - bool need_refresh = false; - pthread_rwlock_wrlock(&rwlock_); - - if (stmt_metadata == nullptr) { - stmt_metadata = *new_stmt_metadata; - *new_stmt_metadata = nullptr; - pthread_rwlock_unlock(&rwlock_); - return; - } - - if (stmt_metadata->parameter_types_count != (*new_stmt_metadata)->parameter_types_count) { - need_refresh = true; - } else { - for (size_t i = 0; i < (*new_stmt_metadata)->parameter_types_count; i++) { - if (stmt_metadata->parameter_types[i] != (*new_stmt_metadata)->parameter_types[i]) { - need_refresh = true; - break; - } - } - } - - if (need_refresh == false) { - if (stmt_metadata->columns_count != (*new_stmt_metadata)->columns_count) { - need_refresh = true; - } else { - for (size_t i = 0; i < (*new_stmt_metadata)->columns_count; ++i) { - const auto& current_col = stmt_metadata->columns[i]; - const auto& update_col = (*new_stmt_metadata)->columns[i]; - if (strcmp(current_col.name, update_col.name) || // NOSONAR: strcmp is safe here - current_col.table_oid != update_col.table_oid || - current_col.column_index != update_col.column_index || - current_col.type_oid != update_col.type_oid || - current_col.length != update_col.length || - current_col.type_modifier != update_col.type_modifier || - current_col.format != update_col.format) { - need_refresh = true; - break; - } - } - } - } - - if (need_refresh) { - delete stmt_metadata; - stmt_metadata = *new_stmt_metadata; - *new_stmt_metadata = nullptr; - calculate_mem_usage(); - } - pthread_rwlock_unlock(&rwlock_); -} - PgSQL_STMT_Global_info::~PgSQL_STMT_Global_info() { free(username); free(dbname); @@ -246,9 +169,17 @@ PgSQL_STMT_Global_info::~PgSQL_STMT_Global_info() { if (digest_text) free(digest_text); parse_param_types.clear(); // clear the parameter types vector - if (stmt_metadata) - delete stmt_metadata; - pthread_rwlock_destroy(&rwlock_); +} + +void PgSQL_STMT_Global_info::calculate_mem_usage() { + total_mem_usage = sizeof(PgSQL_STMT_Global_info) + + query_length + 1; + + // NOSONAR: strlen is safe here + if (username) total_mem_usage += strlen(username) + 1; // NOSONAR + if (dbname) total_mem_usage += strlen(dbname) + 1; // NOSONAR + if (first_comment) total_mem_usage += strlen(first_comment) + 1; // NOSONAR + if (digest_text) total_mem_usage += strlen(digest_text) + 1; // NOSONAR } void PgSQL_STMTs_local_v14::backend_insert(uint64_t global_stmt_id, uint32_t backend_stmt_id) { @@ -608,10 +539,9 @@ class PgSQL_PS_global_stats { unsigned long long ref_count_client; unsigned long long ref_count_server; char *query; - int num_columns; - int num_params; + int num_param_types; PgSQL_PS_global_stats(uint64_t stmt_id, const char *d, const char *u, uint64_t dig, const char *q, - unsigned long long ref_c, unsigned long long ref_s, int columns, int params) { + unsigned long long ref_c, unsigned long long ref_s, int params) { statement_id = stmt_id; digest = dig; query = strndup(q, pgsql_thread___query_digests_max_digest_length); @@ -619,8 +549,7 @@ class PgSQL_PS_global_stats { dbname = strdup(d); ref_count_client = ref_c; ref_count_server = ref_s; - num_columns = columns; - num_params = params; + num_param_types = params; } ~PgSQL_PS_global_stats() { if (query) @@ -647,10 +576,8 @@ class PgSQL_PS_global_stats { pta[5]=strdup(buf); snprintf(buf,sizeof(buf),"%llu",ref_count_server); pta[6]=strdup(buf); - snprintf(buf,sizeof(buf),"%d",num_columns); + snprintf(buf,sizeof(buf),"%d",num_param_types); pta[7]=strdup(buf); - snprintf(buf,sizeof(buf),"%d",num_params); - pta[8]=strdup(buf); return pta; } @@ -668,7 +595,6 @@ class PgSQL_PS_global_stats { SQLite3_result* PgSQL_STMT_Manager_v14::get_prepared_statements_global_infos() { proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Dumping current prepared statements global info\n"); auto result = std::make_unique(PS_GLOBAL_STATUS_FIELD_NUM); - rdlock(); result->add_column_definition(SQLITE_TEXT,"stmt_id"); result->add_column_definition(SQLITE_TEXT,"database"); result->add_column_definition(SQLITE_TEXT,"username"); @@ -676,25 +602,15 @@ SQLite3_result* PgSQL_STMT_Manager_v14::get_prepared_statements_global_infos() { result->add_column_definition(SQLITE_TEXT,"query"); result->add_column_definition(SQLITE_TEXT,"ref_count_client"); result->add_column_definition(SQLITE_TEXT,"ref_count_server"); - result->add_column_definition(SQLITE_TEXT,"num_columns"); - result->add_column_definition(SQLITE_TEXT,"num_params"); + result->add_column_definition(SQLITE_TEXT,"num_param_types"); + + rdlock(); for (auto it = map_stmt_id_to_info.begin(); it != map_stmt_id_to_info.end(); ++it) { - int columns_count = -1; - int parameter_types_count = -1; - PgSQL_STMT_Global_info *a = it->second; - - a->rdlock(); - if (const PgSQL_Describe_Prepared_Info* stmt_metadata = a->stmt_metadata; stmt_metadata != nullptr) { - columns_count = stmt_metadata->columns_count; - parameter_types_count = stmt_metadata->parameter_types_count; - } - a->unlock(); + PgSQL_STMT_Global_info *stmt_global_info = it->second; - auto pgs = std::make_unique(a->statement_id, - a->dbname, a->username, a->hash, a->query, - a->ref_count_client, a->ref_count_server, - columns_count, - parameter_types_count); + auto pgs = std::make_unique(stmt_global_info->statement_id, + stmt_global_info->dbname, stmt_global_info->username, stmt_global_info->hash, stmt_global_info->query, + stmt_global_info->ref_count_client, stmt_global_info->ref_count_server, stmt_global_info->parse_param_types.size()); char **pta = pgs->get_row(); result->add_row(pta); pgs->free_row(pta); diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index 85f197e4e..e0d9a1ebd 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -5769,25 +5769,6 @@ int PgSQL_Session::handle_post_sync_describe_message(PgSQL_Describe_Message* des (begint.tv_sec * 1000000000 + begint.tv_nsec); } } - // Use cached stmt_metadata only for statements; for portals, forward the describe request to backend. - if (extended_query_info.stmt_type == 'S') { - stmt_info->rdlock(); - if (stmt_info->stmt_metadata) { - // we have the metadata, so we can send it to the client - client_myds->setDSS_STATE_QUERY_SENT_NET(); - bool send_ready_packet = is_extended_query_ready_for_query(); - unsigned int nTxn = NumActiveTransactions(); - const char txn_state = (nTxn ? 'T' : 'I'); - client_myds->myprot.generate_describe_completion_packet(true, send_ready_packet, stmt_info->stmt_metadata, - extended_query_info.stmt_type, txn_state); - stmt_info->unlock(); - //LogQuery(NULL); - //CurrentQuery.end_time = thread->curtime; - RequestEnd(NULL, false); - return 0; - } - stmt_info->unlock(); - } // setting 'prepared' to prevent fetching results from the cache if the digest matches if (extended_query_exec_qp) { @@ -6361,26 +6342,12 @@ void PgSQL_Session::handler___rc0_PROCESSING_STMT_DESCRIBE_PREPARE(PgSQL_Data_St bool send_ready_packet = is_extended_query_ready_for_query(); char txn_state = myds->myconn->get_transaction_status_char(); - if (extended_query_info.stmt_type == 'S') { - GloPgStmt->wrlock(); - extended_query_info.stmt_info->update_stmt_metadata(&myds->myconn->stmt_metadata_result); - client_myds->myprot.generate_describe_completion_packet(true, send_ready_packet, extended_query_info.stmt_info->stmt_metadata, - extended_query_info.stmt_type, txn_state); - LogQuery(myds); - GloPgStmt->unlock(); - if (myds->myconn->stmt_metadata_result) { - delete myds->myconn->stmt_metadata_result; - myds->myconn->stmt_metadata_result = NULL; - } - } else { - // For portals, we don't cache metadata - client_myds->myprot.generate_describe_completion_packet(true, send_ready_packet, myds->myconn->stmt_metadata_result, - extended_query_info.stmt_type, txn_state); - LogQuery(myds); - if (myds->myconn->stmt_metadata_result) { - delete myds->myconn->stmt_metadata_result; - myds->myconn->stmt_metadata_result = NULL; - } + client_myds->myprot.generate_describe_completion_packet(true, send_ready_packet, myds->myconn->stmt_metadata_result, + extended_query_info.stmt_type, txn_state); + LogQuery(myds); + if (myds->myconn->stmt_metadata_result) { + delete myds->myconn->stmt_metadata_result; + myds->myconn->stmt_metadata_result = NULL; } } diff --git a/lib/ProxySQL_Admin_Stats.cpp b/lib/ProxySQL_Admin_Stats.cpp index 8be55be93..94d3ce03f 100644 --- a/lib/ProxySQL_Admin_Stats.cpp +++ b/lib/ProxySQL_Admin_Stats.cpp @@ -2324,8 +2324,8 @@ void ProxySQL_Admin::stats___pgsql_prepared_statements_info() { char* query32 = NULL; std::string query32s = ""; statsdb->execute("DELETE FROM stats_pgsql_prepared_statements_info"); - query1 = (char*)"INSERT INTO stats_pgsql_prepared_statements_info VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"; - query32s = "INSERT INTO stats_pgsql_prepared_statements_info VALUES " + generate_multi_rows_query(32, 9); + query1 = (char*)"INSERT INTO stats_pgsql_prepared_statements_info VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"; + query32s = "INSERT INTO stats_pgsql_prepared_statements_info VALUES " + generate_multi_rows_query(32, 8); query32 = (char*)query32s.c_str(); //rc=(*proxy_sqlite3_prepare_v2)(mydb3, query1, -1, &statement1, 0); //rc=sqlite3_prepare_v2(mydb3, query1, -1, &statement1, 0); @@ -2341,15 +2341,14 @@ void ProxySQL_Admin::stats___pgsql_prepared_statements_info() { SQLite3_row* r1 = *it; int idx = row_idx % 32; if (row_idx < max_bulk_row_idx) { // bulk - rc = sqlite3_bind_int64(statement32, (idx * 9) + 1, atoll(r1->fields[0])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_text(statement32, (idx * 9) + 2, r1->fields[1], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_text(statement32, (idx * 9) + 3, r1->fields[2], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_text(statement32, (idx * 9) + 4, r1->fields[3], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_int64(statement32, (idx * 9) + 5, atoll(r1->fields[5])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_int64(statement32, (idx * 9) + 6, atoll(r1->fields[6])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_int64(statement32, (idx * 9) + 7, atoll(r1->fields[7])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_int64(statement32, (idx * 9) + 8, atoll(r1->fields[8])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_text(statement32, (idx * 9) + 9, r1->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_int64(statement32, (idx * 8) + 1, atoll(r1->fields[0])); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_text(statement32, (idx * 8) + 2, r1->fields[1], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_text(statement32, (idx * 8) + 3, r1->fields[2], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_text(statement32, (idx * 8) + 4, r1->fields[3], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_int64(statement32, (idx * 8) + 5, atoll(r1->fields[5])); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_int64(statement32, (idx * 8) + 6, atoll(r1->fields[6])); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_int64(statement32, (idx * 8) + 7, atoll(r1->fields[7])); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_text(statement32, (idx * 8) + 8, r1->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); if (idx == 31) { SAFE_SQLITE3_STEP2(statement32); rc = (*proxy_sqlite3_clear_bindings)(statement32); ASSERT_SQLITE_OK(rc, statsdb); @@ -2363,8 +2362,7 @@ void ProxySQL_Admin::stats___pgsql_prepared_statements_info() { rc = sqlite3_bind_int64(statement1, 5, atoll(r1->fields[5])); ASSERT_SQLITE_OK(rc, statsdb); rc = sqlite3_bind_int64(statement1, 6, atoll(r1->fields[6])); ASSERT_SQLITE_OK(rc, statsdb); rc = sqlite3_bind_int64(statement1, 7, atoll(r1->fields[7])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_int64(statement1, 8, atoll(r1->fields[8])); ASSERT_SQLITE_OK(rc, statsdb); - rc = sqlite3_bind_text(statement1, 9, r1->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); + rc = sqlite3_bind_text(statement1, 8, r1->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, statsdb); SAFE_SQLITE3_STEP2(statement1); rc = (*proxy_sqlite3_clear_bindings)(statement1); ASSERT_SQLITE_OK(rc, statsdb); rc = (*proxy_sqlite3_reset)(statement1); ASSERT_SQLITE_OK(rc, statsdb);