Skip to content

Commit

Permalink
Overriding some of the mariadb APIs to extract the warning count and …
Browse files Browse the repository at this point in the history
…print it in the log. This override will apply to all TAP tests, except when the TAP test is linked with the MySQL client library (LIBMYSQL_HELPER defined).
  • Loading branch information
rahim-kanji committed Nov 24, 2023
1 parent 581a095 commit 8bfdf16
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 0 deletions.
144 changes: 144 additions & 0 deletions test/tap/tap/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,150 @@ using std::vector;
using std::to_string;
using nlohmann::json;

thread_local std::vector<MYSQL*> mysql_conn;
thread_local std::vector<std::unique_ptr<char,decltype(&std::free)>> last_query_executed;

thread_local std::vector<MYSQL_STMT*> mysql_stmt;
thread_local std::vector<std::unique_ptr<char, decltype(&std::free)>> last_stmt_executed;

MYSQL* mysql_init_override(MYSQL* mysql, const char* file, int line) {
MYSQL* result = (*real_mysql_init)(mysql);
if (mysql_conn.capacity() == 0) {
fprintf(stdout, ">> [mysql_init] Override functions attached <<\n");
mysql_conn.reserve(64);
last_query_executed.reserve(64);
}
return result;
}

int mysql_query_override(MYSQL* mysql, const char* query, const char* file, int line) {
const int result = (*real_mysql_query)(mysql, query);
if (result == 0) {
mysql_conn.emplace_back(mysql);
last_query_executed.emplace_back(strdup(query),&std::free);
if (mysql_errno(mysql) == 0 && mysql_field_count(mysql) == 0 && mysql_warning_count(mysql) > 0) {
fprintf(stdout, "File %s, Line %d, [mysql_query] A warning was generated during the execution of the query:'%s', warning count:%d\n",
file, line, query, mysql_warning_count(mysql));
}
}
return result;
}

MYSQL_RES* mysql_store_result_override(MYSQL* mysql, const char* file, int line) {
MYSQL_RES* result = (*real_mysql_store_result)(mysql);
if (mysql_errno(mysql) == 0 && mysql_warning_count(mysql) > 0) {
size_t idx = -1;
for (size_t i = 0; i < mysql_conn.size(); i++) {
if (mysql_conn[i] == mysql) {
idx = i;
break;
}
}
fprintf(stdout, "File %s, Line %d, [mysql_store_result] A warning was generated during the execution of the query:'%s', warning count:%d\n",
file, line, (idx != -1 ? last_query_executed[idx].get() : ""), mysql_warning_count(mysql));
}
return result;
}

void mysql_close_override(MYSQL* mysql, const char* file, int line) {
size_t idx = -1;
for (size_t i = 0; i < mysql_conn.size(); i++) {
if (mysql_conn[i] == mysql)
idx = i;
break;
}
if (idx != -1) {
if (idx != mysql_conn.size() - 1) {
mysql_conn[idx] = mysql_conn.back();
last_query_executed[idx] = std::move(last_query_executed.back());
}
mysql_conn.pop_back();
last_query_executed.pop_back();
}
(*real_mysql_close)(mysql);
}

MYSQL_STMT* mysql_stmt_init_override(MYSQL* mysql, const char* file, int line) {
MYSQL_STMT* result = (*real_mysql_stmt_init)(mysql);
if (mysql_stmt.capacity() == 0) {
fprintf(stdout, ">> [mysql_stmt_init] Override functions attached << \n");
mysql_stmt.reserve(64);
last_stmt_executed.reserve(64);
}
return result;
}

int mysql_stmt_prepare_override(MYSQL_STMT* stmt, const char* stmt_str, unsigned long length, const char* file, int line) {
const int result = (*real_mysql_stmt_prepare)(stmt, stmt_str, length);
if (result == 0) {
mysql_stmt.emplace_back(stmt);
last_stmt_executed.emplace_back(strdup(stmt_str), &std::free);
// mysql_stmt_warning_count is not available in MySQL connector
if (mysql_stmt_errno(stmt) == 0 && /*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql) > 0) {
fprintf(stdout, "File %s, Line %d, [mysql_stmt_prepare] A warning was generated during the execution of the query:'%s', warning count:%d\n",
file, line, stmt_str, /*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql));
}
}
return result;
}

int mysql_stmt_execute_override(MYSQL_STMT* stmt, const char* file, int line) {
const int result = (*real_mysql_stmt_execute)(stmt);
if (result == 0) {
// mysql_stmt_warning_count is not available in MySQL connector
if (mysql_stmt_errno(stmt) == 0 && mysql_stmt_field_count(stmt) == 0 &&
/*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql) > 0) {
size_t idx = -1;
for (size_t i = 0; i < mysql_stmt.size(); i++) {
if (mysql_stmt[i] == stmt) {
idx = i;
break;
}
}
fprintf(stdout, "File %s, Line %d, [mysql_stmt_execute] A warning was generated during the execution of the query:'%s', warning count:%d\n",
file, line, (idx != -1 ? last_stmt_executed[idx].get() : ""), /*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql));
}
}
return result;
}

int mysql_stmt_store_result_override(MYSQL_STMT* stmt, const char* file, int line) {
const int result = (*real_mysql_stmt_store_result)(stmt);
if (result == 0) {
// mysql_stmt_warning_count is not available in MySQL connector
if (mysql_stmt_errno(stmt) == 0 && /*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql) > 0) {
size_t idx = -1;
for (size_t i = 0; i < mysql_stmt.size(); i++) {
if (mysql_stmt[i] == stmt) {
idx = i;
break;
}
}
fprintf(stdout, "File %s, Line %d, [mysql_stmt_store_result] A warning was generated during the execution of the query:'%s', warning count:%d\n",
file, line, (idx != -1 ? last_stmt_executed[idx].get() : ""), /*mysql_stmt_warning_count(stmt)*/mysql_warning_count(stmt->mysql));
}
}
return result;
}

my_bool mysql_stmt_close_override(MYSQL_STMT* stmt, const char* file, int line) {
size_t idx = -1;
for (size_t i = 0; i < mysql_stmt.size(); i++) {
if (mysql_stmt[i] == stmt)
idx = i;
break;
}
if (idx != -1) {
if (idx != mysql_stmt.size() - 1) {
mysql_stmt[idx] = mysql_stmt.back();
last_stmt_executed[idx] = std::move(last_stmt_executed.back());
}
mysql_stmt.pop_back();
last_stmt_executed.pop_back();
}
return (*real_mysql_stmt_close)(stmt);
}

std::size_t count_matches(const string& str, const string& substr) {
std::size_t result = 0;
std::size_t pos = 0;
Expand Down
35 changes: 35 additions & 0 deletions test/tap/tap/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@
#include "command_line.h"
#include "json.hpp"

#ifndef LIBMYSQL_HELPER
/* We are overriding some of the mariadb APIs to extract the warning count and print it in the log.
This override will apply to all TAP tests, except when the TAP test is linked with the MySQL client library (LIBMYSQL_HELPER defined).
*/
static MYSQL* (*real_mysql_init)(MYSQL* mysql) = &mysql_init;
static int (*real_mysql_query)(MYSQL* mysql, const char* query) = &mysql_query;
static MYSQL_RES* (*real_mysql_store_result)(MYSQL* mysql) = &mysql_store_result;
static void (*real_mysql_close)(MYSQL* mysql) = &mysql_close;
static MYSQL_STMT* (*real_mysql_stmt_init)(MYSQL* mysql) = &mysql_stmt_init;
static int (*real_mysql_stmt_prepare)(MYSQL_STMT* stmt, const char* stmt_str, unsigned long length) = &mysql_stmt_prepare;
static int (*real_mysql_stmt_execute)(MYSQL_STMT* stmt) = &mysql_stmt_execute;
static int (*real_mysql_stmt_store_result)(MYSQL_STMT* stmt) = &mysql_stmt_store_result;
static my_bool (*real_mysql_stmt_close)(MYSQL_STMT* stmt) = &mysql_stmt_close;

MYSQL* mysql_init_override(MYSQL* mysql, const char* file, int line);
int mysql_query_override(MYSQL* mysql, const char* query, const char* file, int line);
MYSQL_RES* mysql_store_result_override(MYSQL* mysql, const char* file, int line);
void mysql_close_override(MYSQL* mysql, const char* file, int line);
MYSQL_STMT* mysql_stmt_init_override(MYSQL* mysql, const char* file, int line);
int mysql_stmt_prepare_override(MYSQL_STMT* stmt, const char* stmt_str, unsigned long length, const char* file, int line);
int mysql_stmt_execute_override(MYSQL_STMT* stmt, const char* file, int line);
int mysql_stmt_store_result_override(MYSQL_STMT* stmt, const char* file, int line);
my_bool mysql_stmt_close_override(MYSQL_STMT* stmt, const char* file, int line);

#define mysql_init(mysql) mysql_init_override(mysql,__FILE__,__LINE__)
#define mysql_query(mysql,query) mysql_query_override(mysql,query,__FILE__,__LINE__)
#define mysql_store_result(mysql) mysql_store_result_override(mysql,__FILE__,__LINE__)
#define mysql_close(mysql) mysql_close_override(mysql,__FILE__,__LINE__)
#define mysql_stmt_init(mysql) mysql_stmt_init_override(mysql,__FILE__,__LINE__)
#define mysql_stmt_prepare(stmt,stmt_str,length) mysql_stmt_prepare_override(stmt,stmt_str,length,__FILE__,__LINE__)
#define mysql_stmt_execute(stmt) mysql_stmt_execute_override(stmt,__FILE__,__LINE__)
#define mysql_stmt_store_result(stmt) mysql_stmt_store_result_override(stmt,__FILE__,__LINE__)
#define mysql_stmt_close(stmt) mysql_stmt_close_override(stmt,__FILE__,__LINE__)
#endif

inline std::string get_formatted_time() {
time_t __timer;
char __buffer[30];
Expand Down

0 comments on commit 8bfdf16

Please sign in to comment.