diff --git a/include/MySQL_Session.h b/include/MySQL_Session.h index afcee079b..44cb5c8ae 100644 --- a/include/MySQL_Session.h +++ b/include/MySQL_Session.h @@ -232,7 +232,7 @@ class MySQL_Session: public Base_Sessionget_client_myds_info_json(j); } @@ -2785,7 +2784,9 @@ bool MySQL_Session::handler_again___status_CHANGING_SCHEMA(int *_rc) { return false; } + bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) { + //fprintf(stderr,"CONNECTING_SERVER\n"); unsigned long long curtime=monotonic_time(); thread->atomic_curtime=curtime; if (mirror) { @@ -2894,68 +2895,7 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) { st=previous_status.top(); previous_status.pop(); myds->wait_until=0; - - if ( - (mysql_thread___connpool_match_client_deprecate_eof || session_fast_forward) - && !client_myds->myconn->match_tracked_options(mybe->server_myds->myconn) - ) { - if (myds->connect_retries_on_failure > 0) { - proxy_info( - "Failed to obtain suitable connection for fast-forward; server lacks the required capabilities" - " hostgroup=%d client_flags=%u server_capabilities=%lu\n", - current_hostgroup, - client_myds->myconn->options.client_flag, - mybe->server_myds->myconn->mysql->server_capabilities - ); - - const MySrvC* parent { myconn->parent }; - MyHGM->p_update_mysql_error_counter( - p_mysql_error_type::proxysql, parent->myhgc->hid, parent->address, parent->port, - ER_PROXYSQL_FAST_FORWARD_CONN_CREATE - ); - myds->connect_retries_on_failure--; - myds->destroy_MySQL_Connection_From_Pool(false); - - // We are still in 'FAST_FORWARD' and we require a new connection, since we are - // moving to 'CONNECTING_SERVER' the previous status shouldn't be consumed. - previous_status.push(st); - - // NOTE-connect_retries_delay: In case of failure to connect, if - // 'mysql_thread___connect_retries_delay' is set, we impose a delay in the session - // processing via 'pause_until'. Complementary NOTE above. - if (mysql_thread___connect_retries_delay) { - pause_until = thread->curtime + mysql_thread___connect_retries_delay*1000; - set_status(CONNECTING_SERVER); - - return false; - } - - NEXT_IMMEDIATE_NEW(CONNECTING_SERVER); - } else { - char buf[256] = { 0 }; - cstr_format(buf, - "Fast-forward connection attempt failed; server lacks the required capabilities" - " hostgroup=%d client_flags=%u server_capabilities=%lu\n", - current_hostgroup, - client_myds->myconn->options.client_flag, - mybe->server_myds->myconn->mysql->server_capabilities - ); - - client_myds->myprot.generate_pkt_ERR(true, NULL, NULL, 1, 1815, (char *)"HY000", buf, true); - - while (previous_status.size()) { - st=previous_status.top(); - previous_status.pop(); - } - - myds->destroy_MySQL_Connection_From_Pool(true); - myds->max_connect_time=0; - - NEXT_IMMEDIATE_NEW(WAITING_CLIENT_DATA); - } - } - - if (session_fast_forward==true) { + if (session_fast_forward) { // we have a successful connection and session_fast_forward enabled // set DSS=STATE_SLEEP or it will believe it have to use MARIADB client library myds->DSS=STATE_SLEEP; @@ -3858,7 +3798,7 @@ void MySQL_Session::GPFC_PreparedStatements(PtrSize_t& pkt, unsigned char c) { } } -int MySQL_Session::GPFC_Replication_SwitchToFastForward(PtrSize_t& pkt, unsigned char c) { +void MySQL_Session::GPFC_Replication_SwitchToFastForward(PtrSize_t& pkt, unsigned char c) { // In this switch we handle commands that download binlog events from MySQL // servers. For these commands a lot of the features provided by ProxySQL // aren't useful, like multiplexing, query parsing, etc. For this reason, @@ -3904,7 +3844,6 @@ int MySQL_Session::GPFC_Replication_SwitchToFastForward(PtrSize_t& pkt, unsigned // We reinitialize the 'wait_until' since this session shouldn't wait for processing as // we are now transitioning to 'FAST_FORWARD'. mybe->server_myds->wait_until = 0; - if (mybe->server_myds->DSS==STATE_NOT_INITIALIZED) { // NOTE: This section is entirely borrowed from 'STATE_SLEEP' for 'session_fast_forward'. // Check comments there for extra information. @@ -3923,32 +3862,6 @@ int MySQL_Session::GPFC_Replication_SwitchToFastForward(PtrSize_t& pkt, unsigned previous_status.push(FAST_FORWARD); // next status will be FAST_FORWARD set_status(CONNECTING_SERVER); // now we need a connection } else { - bool match_tracked { - // If DSS **IS** initialized, we **MUST** have a connection - mybe->server_myds->DSS != STATE_NOT_INITIALIZED - // Due to the first condition it's safe check the conn tracked options. Matching capabilities are - // mandatory for fast-forward transitions, otherwise session should be terminated. - && client_myds->myconn->match_tracked_options(mybe->server_myds->myconn) - }; - - // If a connection has been already acquired, but it doesn't match the required capabilities, the - // mismatch should be reported, and session should be killed. Flagging the session as 'killed' is - // important, since this is already a 'fast_forward' session, and handling will be different as for - // regular sessions. - if (!match_tracked) { - proxy_info( - "Failed to switch to fast-forward; session connection lacks the required capabilities" - " hostgroup=%d client_flags=%u server_capabilities=%lu\n", - current_hostgroup, - client_myds->myconn->options.client_flag, - mybe->server_myds->myconn->mysql->server_capabilities - ); - mybe->server_myds->destroy_MySQL_Connection_From_Pool(false); - mybe->server_myds->fd=0; - this->killed = true; - return -1; - } - // In case of having a connection, we need to make user to reset the state machine // for current server 'MySQL_Data_Stream', setting it outside of any state handled // by 'mariadb' library. Otherwise 'MySQL_Thread' will threat this @@ -3983,8 +3896,6 @@ int MySQL_Session::GPFC_Replication_SwitchToFastForward(PtrSize_t& pkt, unsigned } set_status(FAST_FORWARD); // we can set status to FAST_FORWARD } - - return 0; } bool MySQL_Session::GPFC_QueryUSE(PtrSize_t& pkt, int& handler_ret) { @@ -4290,7 +4201,7 @@ __get_pkts_from_client: case _MYSQL_COM_BINLOG_DUMP: case _MYSQL_COM_BINLOG_DUMP_GTID: case _MYSQL_COM_REGISTER_SLAVE: - handler_ret = GPFC_Replication_SwitchToFastForward(pkt, c); + GPFC_Replication_SwitchToFastForward(pkt, c); break; case _MYSQL_COM_QUIT: proxy_debug(PROXY_DEBUG_MYSQL_COM, 5, "Got COM_QUIT packet\n"); @@ -5257,6 +5168,8 @@ handler_again: int rc=0; if (handler_again___status_CONNECTING_SERVER(&rc)) goto handler_again; // we changed status + //if (rc==1) //handler_again___status_CONNECTING_SERVER returns 1 + // goto __exit_DSS__STATE_NOT_INITIALIZED; } break; case session_status___NONE: diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index bd6f0f9dc..d7ba8de43 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -361,7 +361,6 @@ static char * mysql_thread_variables_names[]= { (char *)"handle_unknown_charset", (char *)"free_connections_pct", (char *)"connection_warming", - (char *)"connpool_match_client_deprecate_eof", #ifdef IDLE_THREADS (char *)"session_idle_ms", #endif // IDLE_THREADS @@ -983,7 +982,6 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() { variables.connect_timeout_client=10000; variables.connect_timeout_server=1000; variables.connect_timeout_server_max=10000; - variables.connpool_match_client_deprecate_eof=true; variables.free_connections_pct=10; variables.connect_retries_delay=1; variables.monitor_enabled=true; @@ -2134,7 +2132,6 @@ char ** MySQL_Threads_Handler::get_variables_list() { VariablesPointers_bool["client_session_track_gtid"] = make_tuple(&variables.client_session_track_gtid, false); VariablesPointers_bool["commands_stats"] = make_tuple(&variables.commands_stats, false); VariablesPointers_bool["connection_warming"] = make_tuple(&variables.connection_warming, false); - VariablesPointers_bool["connpool_match_client_deprecate_eof"] = make_tuple(&variables.connpool_match_client_deprecate_eof, false); VariablesPointers_bool["default_reconnect"] = make_tuple(&variables.default_reconnect, false); VariablesPointers_bool["enable_client_deprecate_eof"] = make_tuple(&variables.enable_client_deprecate_eof, false); VariablesPointers_bool["enable_server_deprecate_eof"] = make_tuple(&variables.enable_server_deprecate_eof, false); @@ -4001,7 +3998,7 @@ void MySQL_Thread::process_all_sessions() { if (sess->to_process==1) { if (sess->pause_until <= curtime) { rc=sess->handler(); - + //total_active_transactions_+=sess->active_transactions; if (rc==-1 || sess->killed==true) { char _buf[1024]; if (sess->client_myds && sess->killed) @@ -4199,7 +4196,6 @@ void MySQL_Thread::refresh_variables() { REFRESH_VARIABLE_BOOL(multiplexing); REFRESH_VARIABLE_BOOL(log_unhealthy_connections); REFRESH_VARIABLE_BOOL(connection_warming); - REFRESH_VARIABLE_BOOL(connpool_match_client_deprecate_eof); REFRESH_VARIABLE_BOOL(enforce_autocommit_on_reads); REFRESH_VARIABLE_BOOL(autocommit_false_not_reusable); REFRESH_VARIABLE_BOOL(autocommit_false_is_transaction); diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 21a370a02..c889c380d 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -456,8 +456,6 @@ MySQL_Connection::MySQL_Connection() { options.ldap_user_variable_value=NULL; options.ldap_user_variable_sent=false; options.session_track_gtids_int=0; - options.server_capabilities=0; - compression_pkt_id=0; mysql_result=NULL; query.ptr=NULL; @@ -731,6 +729,7 @@ unsigned int MySQL_Connection::number_of_matching_session_variables(const MySQL_ return ret; } + bool MySQL_Connection::match_tracked_options(const MySQL_Connection *c) { uint32_t cf1 = options.client_flag; // own client flags uint32_t cf2 = c->options.client_flag; // other client flags @@ -738,17 +737,7 @@ bool MySQL_Connection::match_tracked_options(const MySQL_Connection *c) { if ((cf1 & CLIENT_MULTI_STATEMENTS) == (cf2 & CLIENT_MULTI_STATEMENTS)) { if ((cf1 & CLIENT_MULTI_RESULTS) == (cf2 & CLIENT_MULTI_RESULTS)) { if ((cf1 & CLIENT_IGNORE_SPACE) == (cf2 & CLIENT_IGNORE_SPACE)) { - // 'server_capabilities' is empty for backend connections - const MySQL_Connection* backend { !c->options.server_capabilities ? c : this }; - const MySQL_Connection* frontend { c->options.server_capabilities ? c : this }; - const bool ff { frontend->myds && frontend->myds->sess->session_fast_forward }; - - if (mysql_thread___connpool_match_client_deprecate_eof || ff) { - return (frontend->options.client_flag & CLIENT_DEPRECATE_EOF) == - (backend->mysql->server_capabilities & CLIENT_DEPRECATE_EOF); - } else { - return true; - } + return true; } } } diff --git a/src/SQLite3_Server.cpp b/src/SQLite3_Server.cpp index 2bb7bc70a..da0949520 100644 --- a/src/SQLite3_Server.cpp +++ b/src/SQLite3_Server.cpp @@ -962,8 +962,7 @@ __run_query: if ((*proxy_sqlite3_get_autocommit)(db)==0) { in_trans = true; } - bool deprecate_eof = sess->client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF; - sess->SQLite3_to_MySQL(resultset, error, affected_rows, &sess->client_myds->myprot, in_trans, deprecate_eof); + sess->SQLite3_to_MySQL(resultset, error, affected_rows, &sess->client_myds->myprot, in_trans); delete resultset; #ifdef TEST_READONLY if (strncasecmp("SELECT",query_no_space,6)) { @@ -1055,7 +1054,7 @@ static void *child_mysql(void *arg) { fds[0].revents=0; fds[0].events=POLLIN|POLLOUT; free(arg); - sess->client_myds->myprot.generate_pkt_initial_handshake(true,NULL,NULL, &sess->thread_session_id, true); + sess->client_myds->myprot.generate_pkt_initial_handshake(true,NULL,NULL, &sess->thread_session_id, false); while (__sync_fetch_and_add(&glovars.shutdown,0)==0) { if (myds->available_data_out()) { diff --git a/test/tap/tap/utils.cpp b/test/tap/tap/utils.cpp index a4d8e74af..a15411033 100644 --- a/test/tap/tap/utils.cpp +++ b/test/tap/tap/utils.cpp @@ -239,7 +239,7 @@ std::size_t count_matches(const string& str, const string& substr) { } int mysql_query_t__(MYSQL* mysql, const char* query, const char* f, int ln, const char* fn) { - diag("%s:%d:%s(): Issuing query \"%s\" to ('%s':%d)", f, ln, fn, query, mysql->host, mysql->port); + diag("%s:%d:%s(): Issuing query '%s' to ('%s':%d)", f, ln, fn, query, mysql->host, mysql->port); return mysql_query(mysql, query); } @@ -582,9 +582,9 @@ ext_val_t ext_single_row_val(const mysql_res_row& row, const int32_t& d if (row.empty() || row.front().empty()) { return { -1, def_val, {} }; } else { - errno = 0; - char* p_end {}; - const int32_t val = std::strtol(row.front().c_str(), &p_end, 10); + errno = 0; + char* p_end {}; + const int32_t val = std::strtol(row.front().c_str(), &p_end, 10); if (row[0] == p_end || errno == ERANGE) { return { -2, def_val, string { row[0] } }; @@ -598,9 +598,9 @@ ext_val_t ext_single_row_val(const mysql_res_row& row, const uint32_t& if (row.empty() || row.front().empty()) { return { -1, def_val, {} }; } else { - errno = 0; - char* p_end {}; - const uint32_t val = std::strtoul(row.front().c_str(), &p_end, 10); + errno = 0; + char* p_end {}; + const uint32_t val = std::strtoul(row.front().c_str(), &p_end, 10); if (row[0] == p_end || errno == ERANGE) { return { -2, def_val, string { row[0] } }; @@ -615,9 +615,9 @@ ext_val_t ext_single_row_val(const mysql_res_row& row, const int64_t& d if (row.empty() || row.front().empty()) { return { -1, def_val, {} }; } else { - errno = 0; - char* p_end {}; - const int64_t val = std::strtoll(row.front().c_str(), &p_end, 10); + errno = 0; + char* p_end {}; + const int64_t val = std::strtoll(row.front().c_str(), &p_end, 10); if (row[0] == p_end || errno == ERANGE) { return { -2, def_val, string { row[0] } }; @@ -631,9 +631,9 @@ ext_val_t ext_single_row_val(const mysql_res_row& row, const uint64_t& if (row.empty() || row.front().empty()) { return { -1, def_val, {} }; } else { - errno = 0; - char* p_end {}; - const uint64_t val = std::strtoull(row.front().c_str(), &p_end, 10); + errno = 0; + char* p_end {}; + const uint64_t val = std::strtoull(row.front().c_str(), &p_end, 10); if (row[0] == p_end || errno == ERANGE) { return { -2, def_val, string { row[0] } }; @@ -1789,61 +1789,6 @@ int dump_conn_stats(MYSQL* admin, const vector hgs) { return EXIT_SUCCESS; } -string row_to_str(const mysql_res_row& row) { - string res { "[" }; - - for (const auto& e : row) { - res += "\"" + e + "\""; - - if (&e != &row.back()) { - res += ","; - } - } - - res += "]"; - - return res; -} - -ext_val_t ext_single_row_val(const mysql_res_row& row, const hg_pool_st_t& def_val) { - if (row.empty() || row.size() != sizeof(hg_pool_st_t)/sizeof(uint32_t)) { - return { -1, def_val, {} }; - } else { - for (int i = 0; i < sizeof(hg_pool_st_t)/sizeof(uint32_t); i++) { - if (row[i].empty()) { - return { -1, def_val, {} }; - } - } - - errno = 0; - char* p_end { nullptr }; - hg_pool_st_t res {}; - const string row_str { row_to_str(row) }; - - res.hostgroup = std::strtoull(row.front().c_str(), &p_end, 10); - if (row[0].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.conn_used = std::strtoull(row[1].c_str(), &p_end, 10); - if (row[1].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.conn_free = std::strtoull(row[2].c_str(), &p_end, 10); - if (row[2].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.conn_ok = std::strtoull(row[3].c_str(), &p_end, 10); - if (row[3].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.conn_err = std::strtoull(row[4].c_str(), &p_end, 10); - if (row[4].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.max_conn_used = std::strtoull(row[5].c_str(), &p_end, 10); - if (row[5].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - res.max_conn_used = std::strtoull(row[6].c_str(), &p_end, 10); - if (row[6].c_str() == p_end || errno == ERANGE) { return { -2, def_val, row_str }; } - - return { EXIT_SUCCESS, res, row_str }; - } -} - -ext_val_t get_conn_pool_hg_stats(MYSQL* admin, uint32_t hg) { - const string HG_STATS_QUERY { gen_conn_stats_query({ hg }) }; - return mysql_query_ext_val(admin, HG_STATS_QUERY, hg_pool_st_t {}); -} - pair fetch_conn_stats(MYSQL* admin, const vector hgs) { const string stats_query { gen_conn_stats_query(hgs) }; const pair> conn_pool_stats { exec_dql_query(admin, stats_query, true) }; @@ -1896,8 +1841,6 @@ int check_cond(MYSQL* mysql, const string& q) { res = 0; } } - - mysql_free_result(myres); } } else { diag("Check failed with error '%s'", mysql_error(mysql)); diff --git a/test/tap/tap/utils.h b/test/tap/tap/utils.h index 16b85efdb..29eeb4c73 100644 --- a/test/tap/tap/utils.h +++ b/test/tap/tap/utils.h @@ -54,14 +54,6 @@ my_bool mysql_stmt_close_override(MYSQL_STMT* stmt, const char* file, int line); } -static inline int mysql_query_override(MYSQL* mysql, const std::string& query, const char* file, int line) { - return mysql_query_override(mysql, query.c_str(), file, line); -} - -#else -static inline int mysql_query(MYSQL* mysql, const std::string& query) { - return mysql_query(mysql, query.c_str()); -} #endif /** @@ -94,9 +86,6 @@ inline std::string get_formatted_time() { * @return Result of calling 'mysql_query'. */ int mysql_query_t__(MYSQL* mysql, const char* query, const char* f, int ln, const char* fn); -inline static int mysql_query_t__(MYSQL* mysql, const std::string& query, const char* f, int ln, const char* fn) { - return mysql_query_t__(mysql, query.c_str(), f, ln, fn); -} /** * @brief Convenience macro with query logging. @@ -123,7 +112,8 @@ inline static int mysql_query_t__(MYSQL* mysql, const std::string& query, const #define MYSQL_QUERY_T(mysql, query) \ do { \ - if (mysql_query_t(mysql, query)) { \ + diag("Issuing query '%s' to ('%s':%d)", query, mysql->host, mysql->port); \ + if (mysql_query(mysql, query)) { \ fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); \ return EXIT_FAILURE; \ } \ @@ -192,7 +182,7 @@ struct ext_val_t { }; /** - * @brief Specializations of function 'ext_single_row_val' for different types. + * @brief Specifications of function 'ext_single_row_val' for different types. * @details These functions serve as the extension point for `mysql_query_ext_val`. A new specialization of * the function is required for each type that `mysql_query_ext_val` should support for the default value. * @param row The row from which the first value is going to be extracted and parsed. @@ -735,31 +725,6 @@ struct POOL_STATS_IDX { }; }; -struct hg_pool_st_t { - uint32_t hostgroup; - uint32_t conn_used; - uint32_t conn_free; - uint32_t conn_ok; - uint32_t conn_err; - uint32_t max_conn_used; - uint32_t queries; -}; - -/** - * @brief A more complex type specialization of 'ext_single_row_val'. - * @details For internal use of function 'get_conn_pool_hg_stats'. - * @param row The row from which the first value is going to be extracted and parsed. - * @param def_val The default value to use in case of failure to extract. - * @return An `ext_val_t` where T is the type of the provided default value. - */ -ext_val_t ext_single_row_val(const mysql_res_row& row, const hg_pool_st_t& def_val); -/** - * @brief Fetches the stats from a particular hostgroup. - * @param admin An already opened connection to MySQL admin. - * @return An `ext_val_t` wrapping the extracted values. - */ -ext_val_t get_conn_pool_hg_stats(MYSQL* admin, uint32_t hg); - /** * @brief Dumps a resultset with fields from the supplied hgs from 'stats_mysql_connection_pool'. * @details The fetched fields are 'hostgroup,ConnUsed,ConnFree,ConnOk,ConnERR,MaxConnUsed,Queries'. @@ -776,7 +741,6 @@ using pool_state_t = std::map; * @return A pair of the shape {err_code, pool_state_t}. */ std::pair fetch_conn_stats(MYSQL* admin, const std::vector hgs); - /** * @brief Waits until the condition specified by the 'query' holds, or 'timeout' is reached. * @details Several details about the function impl: diff --git a/test/tap/tests/Makefile b/test/tap/tests/Makefile index 9d970dc75..4e99576cf 100644 --- a/test/tap/tests/Makefile +++ b/test/tap/tests/Makefile @@ -213,14 +213,6 @@ tests: tests-cpp \ reg_test_3504-change_user_libmysql_helper \ mysql_reconnect_libmariadb-t \ mysql_reconnect_libmysql-t \ - test_match_eof_conn_cap_libmysql-t \ - test_match_eof_conn_cap_libmariadb-t \ - test_sqlite3_special_queries_libmariadb-t \ - test_sqlite3_special_queries_libmysql-t \ - test_ssl_fast_forward-2_libmariadb-t \ - test_ssl_fast_forward-2_libmysql-t \ - test_ssl_fast_forward-3_libmariadb-t \ - test_ssl_fast_forward-3_libmysql-t \ setparser_test2 setparser_test2-t \ setparser_test3 setparser_test3-t \ set_testing-240.csv \ @@ -339,24 +331,6 @@ test_match_eof_conn_cap_libmysql-t: test_match_eof_conn_cap.cpp $(TAP_LDIR)/libt test_match_eof_conn_cap_libmariadb-t: test_match_eof_conn_cap.cpp $(TAP_LDIR)/libtap_mysql8.a $(CXX) -DDISABLE_WARNING_COUNT_LOGGING $< $(IDIRS) $(LDIRS) $(OPT) $(MYLIBS) $(STATIC_LIBS) -o $@ -test_sqlite3_special_queries_libmariadb-t: test_sqlite3_special_queries.cpp $(TAP_LDIR)/libtap.so - $(CXX) -DDISABLE_WARNING_COUNT_LOGGING $< $(IDIRS) $(LDIRS) $(OPT) $(MYLIBS) $(STATIC_LIBS) -o $@ - -test_sqlite3_special_queries_libmysql-t: test_sqlite3_special_queries.cpp $(TAP_LDIR)/libtap_mysql8.a - $(CXX) -DLIBMYSQL_HELPER8 -DDISABLE_WARNING_COUNT_LOGGING $< -I$(TEST_MYSQL8_IDIR) -I$(TEST_MYSQL8_EDIR) -L$(TEST_MYSQL8_LDIR) -lmysqlclient -ltap_mysql8 -lresolv $(CUSTOMARGS) -o $@ - -test_ssl_fast_forward-2_libmariadb-t: test_ssl_fast_forward-2.cpp $(TAP_LDIR)/libtap.so - $(CXX) -DDISABLE_WARNING_COUNT_LOGGING $< $(IDIRS) $(LDIRS) $(OPT) $(MYLIBS) $(STATIC_LIBS) -o $@ - -test_ssl_fast_forward-2_libmysql-t: test_ssl_fast_forward-2.cpp $(TAP_LDIR)/libtap_mysql8.a - $(CXX) -DLIBMYSQL_HELPER8 -DDISABLE_WARNING_COUNT_LOGGING $< -I$(TEST_MYSQL8_IDIR) -I$(TEST_MYSQL8_EDIR) -L$(TEST_MYSQL8_LDIR) -lmysqlclient -ltap_mysql8 -lresolv $(CUSTOMARGS) -o $@ - -test_ssl_fast_forward-3_libmariadb-t: test_ssl_fast_forward-3.cpp $(TAP_LDIR)/libtap.so - $(CXX) -DDISABLE_WARNING_COUNT_LOGGING $< $(IDIRS) $(LDIRS) $(OPT) $(MYLIBS) $(STATIC_LIBS) -o $@ - -test_ssl_fast_forward-3_libmysql-t: test_ssl_fast_forward-3.cpp $(TAP_LDIR)/libtap_mysql8.a - $(CXX) -DLIBMYSQL_HELPER8 -DDISABLE_WARNING_COUNT_LOGGING $< -I$(TEST_MYSQL8_IDIR) -I$(TEST_MYSQL8_EDIR) -L$(TEST_MYSQL8_LDIR) -lmysqlclient -ltap_mysql8 -lresolv $(CUSTOMARGS) -o $@ - test_clickhouse_server_libmysql-t: test_clickhouse_server-t.cpp $(TAP_LDIR)/libtap.so $(CXX) -DLIBMYSQL_HELPER -DDISABLE_WARNING_COUNT_LOGGING $< -I$(TEST_MYSQL_IDIR) -I$(TEST_MYSQL_EDIR) -L$(TEST_MYSQL_LDIR) -lmysqlclient -ltap_mysql57 $(CUSTOMARGS) -o $@ diff --git a/test/tap/tests/test_match_eof_conn_cap.cpp b/test/tap/tests/test_match_eof_conn_cap.cpp deleted file mode 100644 index 10c64f956..000000000 --- a/test/tap/tests/test_match_eof_conn_cap.cpp +++ /dev/null @@ -1,1094 +0,0 @@ -/** - * @file test_match_eof_conn_cap.cpp - * @brief Checks that ProxySQL correctly matches capabilities when matching client and backend conns. - * @details When a client session requires a backend connection, it requests it to the connection pool. - * A filtering (via `MySQL_Connection::match_tracked_options`) takes place for conn selection, if no - * suitable conn is found, it should be created with the requested session options. This test checks this - * logic correctness and exercises it for all possible combinations of client and backend conns capabilities - * (`CLIENT_DEPRECATE_EOF`) and ProxySQL config regarding enforced matching - * (`mysql-connpool_match_client_deprecate_eof`). For doing this, the test: - * 1. Configs ProxySQL as MySQL backend of itself, via the `SQLite3` interface. This way, support for - * all frontend-backend capabilities combinations can be tested with a single instance. - * 2. Configs a client user with 'fast_forward'. Since fast-forward is relevant for conn-matching, the - * config for the user will be switched (on/off) for each test, to exercise different combinations. - * Then, the test performs the following checks for conn creation: - * 1. Creates a conn to ProxySQL with one of the possible caps combination. - * 1. Switches (or not) the capability support for client/backend conns. - * 2. Attempts to perform a query, forcing the creation of a backend conn. - * 3. Performs multiple checks over the query and ProxySQL error log metrics: - * - Checks if the query was expected to fail/succeed (conn creation). - * - Checks error log for conn creation failures (caps mismatch). - * - Checks audit log for number of conn received (SQLite3 backend ProxySQL-ProxySQL). - * - Checks stats on connection creation to be increased by the expected amount. - * A similar flow is exercised for conn matching, with the difference that the previous steps are performed - * against an already warm-up conn-pool. - * - * For being able to test `CLIENT_DEPRECATE_EOF` disabled, and ensuring the correct handling of sessions by - * ProxySQL the test is compiled against both `libmaridb` and `libmysql`. Executing both binaries **is - * required** as right now it's the only way to exercise all the possibilities. - * - * NOTE: The checks on this test are oriented for the capability `CLIENT_DEPRECATE_EOF` and the config - * option `mysql-connpool_match_client_deprecate_eof`. Still, the flow present in this test is more - * generic, as it should match the one for any other client capability that requires to be matched between - * frontend and backend conns. This is even more relevant if the match is required for an smooth transition - * between regular and `fast-forward` sessions, as it's the case for `CLIENT_DEPRECATE_EOF`. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mysql.h" - -#include "tap.h" -#include "command_line.h" -#include "utils.h" - -using std::fstream; -using std::string; -using std::vector; - -#define _S(s) ( std::string {s} ) -#define _TO_S(s) ( std::to_string(s) ) - -#define CHECK_EXT_VAL(val)\ - do {\ - if (val.err) {\ - diag("%s:%d: Query failed err=\"%s\"", __func__, __LINE__, val.str.c_str());\ - return EXIT_FAILURE;\ - }\ - } while(0) - -MYSQL* create_mysql_conn(const conn_opts_t& opts) { - const char* host { opts.host.c_str() }; - const char* user { opts.user.c_str() }; - const char* pass { opts.pass.c_str() }; - - MYSQL* conn = mysql_init(NULL); - -#ifndef LIBMYSQL_HELPER8 - conn->options.client_flag &= ~CLIENT_DEPRECATE_EOF; -#endif - -#ifdef LIBMYSQL_HELPER8 - { - enum mysql_ssl_mode ssl_mode = SSL_MODE_DISABLED; - mysql_options(conn, MYSQL_OPT_SSL_MODE, &ssl_mode); - } -#endif - - if (!mysql_real_connect(conn, host, user, pass, NULL, opts.port, NULL, 0)) { - fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(conn)); - return NULL; - } - - return conn; -} - -#define SELECT_RUNTIME_VAR "SELECT variable_value FROM runtime_global_variables WHERE variable_name=" -#define TAP_NAME "TAP_FAST_FORWARD_CONNS_MATCHING_FLAGS___" - -// Test specific ENV variables -const int HG_ID = get_env_int(TAP_NAME"MYSQL_SERVER_HOSTGROUP", 0); -const int SQLITE3_HG = get_env_int(TAP_NAME"SQLITE3_HOSTGROUP", 1459); -const int SQLITE3_PORT = get_env_int(TAP_NAME"SQLITE3_HOSTGROUP", 6030); -const int CONN_POOL_WARNMUP = get_env_int(TAP_NAME"CONN_POOL_WARNMUP", 10); -const char* FF_USER = get_env_str(TAP_NAME"FF_USER", "sbtest2"); -const char* FF_PASS = get_env_str(TAP_NAME"FF_PASS", "sbtest2"); -const int RETRIES_DELAY = get_env_int(TAP_NAME"CONNECT_RETRIES_DELAY", 500); -const int TO_SERVER_MAX = get_env_int(TAP_NAME"CONNECT_TIMEOUT_SERVER_MAX", 2000); - -// Not specific ENV variables -const string PROXYSQL_LOG_PATH { get_env_str("REGULAR_INFRA_DATADIR", "/tmp/") + _S("/proxysql.log") }; -const string PROXYSQL_AUDIT_DIR { get_env_str("REGULAR_INFRA_DATADIR", "/tmp/datadir") }; - -void dump_as_table(MYSQL* conn, const string& msg, const std::string& query) { - int rc = mysql_query_t(conn, query.c_str()); - if (rc) { - fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(conn)); - exit(1); - } - - MYSQL_RES* myres { mysql_store_result(conn) }; - diag("%s\n%s", msg.c_str(), dump_as_table(myres).c_str()); - mysql_free_result(myres); -} - -void run_setup_query(MYSQL* conn, const string& query) { - int rc = mysql_query_t(conn, query.c_str()); - if (rc) { - fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(conn)); - exit(1); - } -} - -const vector& mysql_variables_setup { - "SET mysql-have_ssl='false'", - "LOAD MYSQL VARIABLES TO RUNTIME", -}; - -const vector& sqlite3_server_setup { - "DELETE FROM mysql_servers WHERE hostgroup_id = " + _TO_S(SQLITE3_HG), - "INSERT INTO mysql_servers (hostgroup_id, hostname, port, use_ssl)" - " VALUES (" + _TO_S(SQLITE3_HG) + ", '127.0.0.1', " + _TO_S(SQLITE3_PORT) + ", 0)", - "LOAD MYSQL SERVERS TO RUNTIME", - - "DELETE FROM mysql_users WHERE username = '" + _S(FF_USER) + "'", - "INSERT INTO mysql_users (username,password,fast_forward,default_hostgroup)" - " VALUES ('" + _S(FF_USER) + "','" + _S(FF_PASS) + "',1," + _TO_S(SQLITE3_HG) + ")", - "LOAD MYSQL USERS TO RUNTIME", -}; - -int wait_for_conn_pool_st(MYSQL* admin, int32_t tg_hg, int32_t count) { - int to = wait_for_cond(admin, - "SELECT IIF(" - "(SELECT SUM(ConnUsed) + SUM(ConnFree)" - " FROM stats_mysql_connection_pool" - " WHERE hostgroup=" + _TO_S(tg_hg) + ")=" + _TO_S(count) + "," - " TRUE, FALSE" - ")", - 10 - ); - - if (to == EXIT_FAILURE) { - diag("Waiting for conn_pool status failed tg_hg=%d conn_count=%d", tg_hg, count); - dump_as_table(admin, "'stats_mysql_connection_pool' status after wait:", - "SELECT hostgroup, srv_host, srv_port, ConnFree, ConnUsed, ConnOK, ConnERR" - " FROM stats_mysql_connection_pool" - ); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - -const string SELECT_CONN_SUM { - "SELECT SUM(ConnUsed) + SUM(ConnFree) FROM stats_mysql_connection_pool" - " WHERE hostgroup='" + std::to_string(SQLITE3_HG) + "'" -}; - -const string CONN_POOL_HG_STATUS { - "SELECT hostgroup, srv_host, srv_port, ConnFree, ConnUsed, ConnOK, ConnERR" - " FROM stats_mysql_connection_pool WHERE hostgroup='" + std::to_string(SQLITE3_HG) + "'" -}; - -int conn_pool_cleanup(MYSQL* admin, int tg_hg, int count) { - ext_val_t hg_conn_sum { mysql_query_ext_val(admin, SELECT_CONN_SUM, -1) }; - - if (hg_conn_sum.err != EXIT_SUCCESS) { - const string err { get_ext_val_err(admin, hg_conn_sum) }; - diag("Fetching conn_pool status failed err:`%s`", err.c_str()); - return EXIT_FAILURE; - } - - diag("Checking conn_pool status ConnUsed+ConnFree=%d tg=%d", hg_conn_sum.val, count); - - if (hg_conn_sum.val >= 1) { - MYSQL_QUERY_T(admin, - "UPDATE mysql_servers SET max_connections=" + _TO_S(count) - + " WHERE hostgroup_id=" + _TO_S(SQLITE3_HG) - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL SERVERS TO RUNTIME"); - - int rc = wait_for_conn_pool_st(admin, tg_hg, count); - - if (rc == EXIT_SUCCESS) { - MYSQL_QUERY_T(admin, - "UPDATE mysql_servers SET max_connections=" + _TO_S(1000) - + " WHERE hostgroup_id=" + _TO_S(SQLITE3_HG) - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL SERVERS TO RUNTIME"); - } - - return rc; - } - - return EXIT_SUCCESS; -} - -const vector test_conn_creation___mysql_config { - "SET mysql-connect_retries_delay=" + _TO_S(RETRIES_DELAY), - "SET mysql-connect_timeout_server=" + _TO_S(100), - "SET mysql-connect_timeout_server_max=" + _TO_S(TO_SERVER_MAX), - "LOAD MYSQL VARIABLES TO RUNTIME" -}; - -const char* get_ext (const char *fspec) { - const char* e { strrchr (fspec, '.') }; - - if (e == NULL) { - return ""; - } else { - return e; - } -} - -string find_latest_split(const std::string &dir_path, const string& prefix) { - DIR *dir = opendir(dir_path.c_str()); - if (!dir) { - printf("Failed to open directory path=\"%s\"", dir_path.c_str()); - return {}; - } - - struct dirent* entry { nullptr }; - string latest_split_fname {}; - uint64_t latest_split_ext { 0 }; - - while ((entry = readdir(dir)) != nullptr) { - const string fname { entry->d_name }; - - if (fname == "." || fname == "..") { - continue; - } - - if (fname.rfind(prefix) == 0) { - const string ext { get_ext(fname.c_str()) }; - const string e_ext { ext.size() > 1 ? ext.substr(1) : "" }; - - errno = 0; - char* p_end { nullptr }; - const uint64_t ext_val { std::strtoull(e_ext.c_str(), &p_end, 10) }; - - if (ext.c_str() == p_end) { - continue; - } else if (latest_split_ext < ext_val) { - latest_split_ext = ext_val; - latest_split_fname = fname; - } - } - } - - closedir(dir); - - return latest_split_fname; -} - -struct pool_cnf_t { - bool warmup { false }; - uint32_t conn_caps { 0 }; -}; - -struct conn_conf_t { - const CommandLine& cl; - bool fast_forward { false }; - uint32_t conn_caps { 0 }; -}; - -/** - * @details - * Scenario 1 -> 0: - * Should be tested through simple config and dynamic (on-the-fly) switch. When demanding the scenario, no - * conn should be found for either case (backend doesn't support either ProxySQL supports the creation). We - * need to test conn creation and conn_pool warmup here. - * - * Scenario 0 -> 1: - * ProxySQL won't allow a mismatch **for conn creation**, since the backend connection support is - * automatically disabled based on client requirements. This scenario can still be tested with a warmup - * connection pool. Dynamic switch shouldn't make a difference here as it's only relevant for connection - * creation. - */ -struct proxy_cnf_t { - bool cli_depr_eof { false }; - bool srv_depr_eof { false }; - bool match_depr_eof { false }; - bool force_mismatch { false }; -}; - -struct test_cnf_t { - pool_cnf_t pool_status; - conn_conf_t conn_conf; - proxy_cnf_t proxy_conf; -}; - -vector gen_all_proxy_cnfs() { - vector> all_bin_vec { get_all_bin_vec(4) }; - std::sort(all_bin_vec.begin(), all_bin_vec.end()); - - vector all_proxy_cnfs {}; - for (const vector& bin_vec : all_bin_vec) { - all_proxy_cnfs.push_back({ bin_vec[3], bin_vec[2], bin_vec[1], bin_vec[0] }); - } - - return all_proxy_cnfs; -} - -string to_string(const pool_cnf_t& st) { - return "{" - "\"is_warmup\": " + _TO_S(st.warmup) + ",\"conn_caps\":" + _TO_S(st.conn_caps) + - "}"; -} - -string to_string(const conn_conf_t& cnf) { - return "{" - "\"fast_forward\": " + _TO_S(cnf.fast_forward) + ",\"conn_caps\":" + _TO_S(cnf.conn_caps) + - "}"; -} - -string to_string(const proxy_cnf_t& cnf) { - return "{" - "\"client_deprecate_eof\": " + _TO_S(cnf.cli_depr_eof) + - ",\"server_deprecate_eof\":" + _TO_S(cnf.srv_depr_eof) + - ",\"connpool_match_deprecate_eof\":" + _TO_S(cnf.match_depr_eof) + - ",\"force_mismatch\":" + _TO_S(cnf.force_mismatch) + - "}"; -} - -int apply_proxy_conf(MYSQL* admin, const proxy_cnf_t& cnf) { - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(cnf.cli_depr_eof)); - MYSQL_QUERY_T(admin, "SET mysql-enable_server_deprecate_eof=" + _TO_S(cnf.srv_depr_eof)); - MYSQL_QUERY_T(admin, "SET mysql-connpool_match_client_deprecate_eof=" + _TO_S(cnf.match_depr_eof)); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - return EXIT_SUCCESS; -} - -string to_string(const test_cnf_t& test_conf) { - return "{" - "\"pool_status\":" + to_string(test_conf.pool_status) + - ",\"conn_conf\":" + to_string(test_conf.conn_conf) + - ",\"proxy_conf\":" + to_string(test_conf.proxy_conf) + - "}"; -} - -int test_conn_acquisition(MYSQL* admin, const test_cnf_t& test_conf) { - const conn_conf_t& conn_cnf { test_conf.conn_conf }; - const pool_cnf_t& pool_st { test_conf.pool_status }; - const proxy_cnf_t& proxy_cnf { test_conf.proxy_conf }; - - diag("Started '%s' %s", __func__, to_string(test_conf).c_str()); - - diag("Setting test global 'mysql-variables' test='%s'", __func__); - std::for_each(test_conn_creation___mysql_config.begin(), test_conn_creation___mysql_config.end(), - [&admin] (const string& q) { return run_setup_query(admin, q); } - ); - - // UPDATE GENERIC TEST CONFIG - /////////////////////////////////////////////////////////////////////////// - const ext_val_t retries_delay { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-connect_retries_delay'", -1) - }; - CHECK_EXT_VAL(retries_delay); - const ext_val_t to_server_max { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-connect_timeout_server_max'", -1) - }; - CHECK_EXT_VAL(to_server_max); - /////////////////////////////////////////////////////////////////////////// - - diag( - "Update 'fast-forward' for testing user user=\"%s\" fast_forward=%d", - FF_USER, conn_cnf.fast_forward - ); - MYSQL_QUERY_T(admin, - "UPDATE mysql_users SET fast_forward=" + _TO_S(conn_cnf.fast_forward) + - " WHERE username='" + _S(FF_USER) + "'" - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - - diag("Using %s 'mysql-enable_client/server_deprecate_eof'", proxy_cnf.force_mismatch ? "DYNAMIC" : "STATIC"); - int rc = apply_proxy_conf(admin, proxy_cnf); - if (rc) { return EXIT_FAILURE; } - - diag("Create client MySQL conn user=\"%s\" port=\"%d\"", FF_USER, conn_cnf.cl.port); - MYSQL* proxy { create_mysql_conn({ conn_cnf.cl.host, FF_USER, FF_PASS, conn_cnf.cl.port }) }; - if (proxy == NULL) { return EXIT_FAILURE; } - dump_as_table(admin, "'connection_pool' status after client conn:", CONN_POOL_HG_STATUS); - - if (proxy_cnf.force_mismatch) { - diag("Revert 'client_deprecate_eof' client_deprecate_eof=%d", !proxy_cnf.cli_depr_eof); - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(!proxy_cnf.cli_depr_eof)); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - } - - diag("Get pre-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t pre_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(pre_hg_st); - const ext_val_t pre_srv_conns { mysql_query_ext_val(admin, - "SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='Server_Connections_created'", - int64_t(-1) - )}; - CHECK_EXT_VAL(pre_srv_conns); - - fstream logfile_fs {}; - - { - diag("Open General log to check for errors path=\"%s\"", PROXYSQL_LOG_PATH.c_str()); - int of_err = open_file_and_seek_end(PROXYSQL_LOG_PATH, logfile_fs); - if (of_err != EXIT_SUCCESS) { return of_err; } - } - - diag("Open ProxySQL audit log to check the connections attempts path=\"%s\"", PROXYSQL_LOG_PATH.c_str()); - const ext_val_t audit_fname { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-auditlog_filename'", _S("audit.log")) - }; - CHECK_EXT_VAL(audit_fname); - - const string latest_split { find_latest_split(PROXYSQL_AUDIT_DIR, audit_fname.val) }; - const string audit_path { PROXYSQL_AUDIT_DIR + "/" + latest_split }; - fstream auditlog_fs {}; - - { - diag("Open Audit log to check for conns path=\"%s\"", audit_path.c_str()); - int of_err = open_file_and_seek_end(audit_path, auditlog_fs); - if (of_err != EXIT_SUCCESS) { return of_err; } - } - - diag("Issuing query (trx) creating new backend conn"); - rc = mysql_query_t(proxy, "BEGIN"); - if (rc == 0) { - diag("Previous query successful; closing trx is required"); - mysql_query_t(proxy, "COMMIT"); - } - - // Sanity check; query should **NEVER** fail if mismatch is allowed (no fast-forward). - if (rc != 0 && !(proxy_cnf.match_depr_eof || conn_cnf.fast_forward)) { - diag( - "Config should allow capabilities mismatch, but query failed. Aborting test error=\"%s\"", - mysql_error(proxy) - ); - return EXIT_FAILURE; - } - - if ( - // * -> (* *) -> *: - // No match required or fast-forward should allow any conn combination - (!proxy_cnf.match_depr_eof && !conn_cnf.fast_forward) - || - // * -> (* *) -> *: - // ConnPool warmup scenarios: - ( - // For pool to serve the query, warmup conns caps need to match config on client-side. Client - // conn caps must be checked (not only config) as disabled always win negotiation. - proxy_cnf.match_depr_eof && pool_st.warmup && !conn_cnf.fast_forward && ( - (bool(pool_st.conn_caps & CLIENT_DEPRECATE_EOF) == - (proxy_cnf.cli_depr_eof && (conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF))) - ) - ) - || - // * -> (X *) -> X - ( - !proxy_cnf.force_mismatch && ( - // * -> (1 1) -> 1 || * -> (0 0) -> 0: - // Client config matches backend; conn should be possible - (proxy_cnf.cli_depr_eof == proxy_cnf.srv_depr_eof) - // * -> (0 1) -> 0: - // Both servers (backend and ProxySQL) lack the capability - || proxy_cnf.cli_depr_eof == 0 - // * -> (X *) -> X: - // Caps forwarded for fast-forward; backend config ignored - || conn_cnf.fast_forward - // 0 -> (1 0) -> 1: - // Both clients; frontend and ProxySQL have the cap disabled - || !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) - && proxy_cnf.cli_depr_eof && !proxy_cnf.srv_depr_eof - ) - && - // 0 -> (1 1) -> *: - // TODO: This scenario could be improved if ProxySQL forwarded client caps to backend conns. - !( - !conn_cnf.fast_forward - && !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) - && proxy_cnf.cli_depr_eof && proxy_cnf.srv_depr_eof - ) - ) - || - // * -> (X *) -> !X - ( - proxy_cnf.force_mismatch && ( - // * -> (0 *) -> 1: - // Disabled client caps forwarded for fast-forward (configured or implied by client) - ( - conn_cnf.fast_forward && ( - (proxy_cnf.cli_depr_eof == 0) || !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) - ) - ) - || - // * -> (0 0) -> *: - // Both ends controlled by config; conn should by possible - (proxy_cnf.cli_depr_eof == 0 && proxy_cnf.srv_depr_eof == 0) - || - // 0 -> (1 *) -> 0: - // Only case of "* ->(1 *) -> 0" for which ProxySQL can create the backend conn, when client - // doesn't support it and wins frontend negotiation. - ( - !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) && proxy_cnf.cli_depr_eof - ) - ) - ) - - ) { - ok( - rc == 0, - "Query should SUCCEED (backend-conn match) conn_conf='%s' proxy_conf='%s' pool_st='%s'", - to_string(conn_cnf).c_str(), to_string(proxy_cnf).c_str(), to_string(pool_st).c_str() - ); - } else { - ok( - rc != 0, - "Query should FAIL (no backend-conn match) conn_conf='%s' proxy_conf='%s' pool_st='%s'", - to_string(conn_cnf).c_str(), to_string(proxy_cnf).c_str(), to_string(pool_st).c_str() - ); - } - - uint32_t exp_conns { 0 }; - - // * -> (* *) -> *: - // If conn_pool is warm-up with conns using 'proxy_cnf.cli_depr_eof' and client conn caps matches - // 'proxy_cnf.cli_depr_eof'. Conns should be reused from the pool. - if ( - // fast-forward avoids the connection pool - pool_st.warmup && !conn_cnf.fast_forward - && ( - // If matching is enforced, capability present in pool should match client conn - (proxy_cnf.match_depr_eof && - bool(pool_st.conn_caps & CLIENT_DEPRECATE_EOF) == - (proxy_cnf.cli_depr_eof && (conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF))) - || - // For no matching shouldn't matter - !proxy_cnf.match_depr_eof - ) - ) { - exp_conns = 0; - } - // Conn creation is required; no warmup pool - else { - // A match is required between client and backend conns: - if ( - // No match enforced, and no fast-forward should always work - (!proxy_cnf.match_depr_eof && !conn_cnf.fast_forward) - || - // Match is enforced, either by config or fast-forward - ( - (proxy_cnf.match_depr_eof || conn_cnf.fast_forward) - && - ( - // 1 -> (0 X) -> 1: - // Disabled wins negotiation; ProxySQL forwards clients caps for fast-forward - ( - conn_cnf.fast_forward - && (!proxy_cnf.cli_depr_eof || !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF)) - // && proxy_cnf.srv_depr_eof - ) - || - // 0 -> (1 *) -> 0: - ( - proxy_cnf.force_mismatch && - !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) && proxy_cnf.cli_depr_eof - ) - // 0 -> (1 0) -> 1: - || - ( - !proxy_cnf.force_mismatch && - !(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) - && proxy_cnf.cli_depr_eof && !proxy_cnf.srv_depr_eof - ) - ) - ) - || - // X -> (0 0) -> X: Client caps should always match backend - (!proxy_cnf.cli_depr_eof && !proxy_cnf.srv_depr_eof) - || - // No requirements on the conn; ProxySQL forwards disabled caps - ( - (!proxy_cnf.match_depr_eof && conn_cnf.fast_forward) - && - // 1 -> (1 1) -> 0: - !(proxy_cnf.cli_depr_eof && proxy_cnf.force_mismatch) - ) - || - // Backend matches ProxySQL advertised caps - (!proxy_cnf.force_mismatch - // 0 -> (1 X) -> 1: ProxySQL doesn't try to create the backend conn without support. - // NOTE: This could be avoided if ProxySQL forwards client preferences for disabled caps. - && !(!(conn_cnf.conn_caps & CLIENT_DEPRECATE_EOF) && proxy_cnf.cli_depr_eof) - // X -> (1 0) -> 1: - && !(!conn_cnf.fast_forward && (proxy_cnf.cli_depr_eof && !proxy_cnf.srv_depr_eof)) - ) - ) { - exp_conns = 1; - } else { - exp_conns = TO_SERVER_MAX / RETRIES_DELAY; - } - } - - const string conn_match_regex { - "Failed to obtain suitable connection for fast-forward; server lacks the required capabilities" - " hostgroup=" + _TO_S(SQLITE3_HG) + " client_flags=\\d+ server_capabilities=\\d+" - }; - - diag("Check ProxySQL log for connection mismatches regex=\"%s\"", conn_match_regex.c_str()); - vector match_lines { get_matching_lines(logfile_fs, conn_match_regex)}; - diag("Found General log matching lines count=%ld", match_lines.size()); - - uint32_t exp_lines { exp_conns == 1 || exp_conns == 0 ? 0 : exp_conns }; - ok( - match_lines.size() == exp_lines, - "Error log should hold conn match failures lines=%ld exp_lines=%d", - match_lines.size(), exp_lines - ); - - diag("Check Audit log for connections attempts on SQLite3"); - vector audit_lines { get_matching_lines(auditlog_fs, - "SQLite3_Connect_OK.*" + _S(FF_USER) - )}; - diag("Found Audit log matching lines count=%ld", audit_lines.size()); - - ok( - audit_lines.size() == exp_conns, - "Audit log should contain SQLite3 created conns lines=%ld exp_conns=%d", - audit_lines.size(), exp_conns - ); - - diag("Get post-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t post_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(post_hg_st); - - ok( - pre_hg_st.val.conn_ok + exp_conns == post_hg_st.val.conn_ok, - "Conn created should have increased by query attempt pre-ConnOK=%d post-ConnOK=%d", - pre_hg_st.val.conn_ok, post_hg_st.val.conn_ok - ); - - const ext_val_t post_srv_conns { - mysql_query_ext_val( - admin, - "SELECT variable_value FROM stats.stats_mysql_global" - " WHERE variable_name='Server_Connections_created'", - int64_t(-1) - ) - }; - CHECK_EXT_VAL(post_srv_conns); - - ok( - pre_srv_conns.val + exp_conns == post_srv_conns.val, - "Conn created should have increased by query attempt" - " pre-Server_Connections_created=%ld post-Server_Connections_created=%ld", - pre_srv_conns.val, post_srv_conns.val - ); - - dump_as_table(admin, "'connection_pool' status after client conn:", CONN_POOL_HG_STATUS); - - mysql_close(proxy); - - return EXIT_SUCCESS; -} - -int test_conn_acquisition( - MYSQL* admin, const CommandLine& cl, bool ff, bool client_eof, bool force_match, bool warmup_pool -) { - diag("Started '%s' ff=%d client_eof=%d force_match=%d", __func__, ff, client_eof, force_match); - - diag("Setting test global 'mysql-variables' test='%s'", __func__); - std::for_each(test_conn_creation___mysql_config.begin(), test_conn_creation___mysql_config.end(), - [&admin] (const string& q) { return run_setup_query(admin, q); } - ); - - ////// - const ext_val_t retries_delay { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-connect_retries_delay'", -1) - }; - CHECK_EXT_VAL(retries_delay); - const ext_val_t to_server_max { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-connect_timeout_server_max'", -1) - }; - CHECK_EXT_VAL(to_server_max); - ////// - - diag("Update 'fast-forward' for testing user user=\"%s\" fast_forward=%d", FF_USER, ff); - MYSQL_QUERY_T(admin, - "UPDATE mysql_users SET fast_forward=" + _TO_S(ff) + " WHERE username='" + _S(FF_USER) + "'" - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - - diag("Update 'mysql-enable_client_deprecate_eof' enable_client_deprecate_eof=%d", client_eof); - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(client_eof)); - MYSQL_QUERY_T(admin, "SET mysql-connpool_match_client_deprecate_eof=" + _TO_S(force_match)); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - diag("Create client MySQL conn user=\"%s\" port=\"%d\"", FF_USER, cl.port); - MYSQL* proxy { create_mysql_conn({ cl.host, FF_USER, FF_PASS, cl.port }) }; - if (proxy == NULL) { return EXIT_FAILURE; } - dump_as_table(admin, "'connection_pool' status after client conn:", CONN_POOL_HG_STATUS); - - diag("Revert support for 'enable_client_deprecate_eof' client_eof=%d", client_eof); - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(!client_eof)); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - diag("Get pre-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t pre_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(pre_hg_st); - const ext_val_t pre_srv_conns { mysql_query_ext_val(admin, - "SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='Server_Connections_created'", - int64_t(-1) - )}; - CHECK_EXT_VAL(pre_srv_conns); - - fstream logfile_fs {}; - - { - diag("Open General log to check for errors path=\"%s\"", PROXYSQL_LOG_PATH.c_str()); - int of_err = open_file_and_seek_end(PROXYSQL_LOG_PATH, logfile_fs); - if (of_err != EXIT_SUCCESS) { return of_err; } - } - - diag("Open ProxySQL audit log to check the connections attempts path=\"%s\"", PROXYSQL_LOG_PATH.c_str()); - const ext_val_t audit_fname { - mysql_query_ext_val(admin, SELECT_RUNTIME_VAR"'mysql-auditlog_filename'", _S("audit.log")) - }; - CHECK_EXT_VAL(audit_fname); - - const string latest_split { find_latest_split(PROXYSQL_AUDIT_DIR, audit_fname.val) }; - const string audit_path { PROXYSQL_AUDIT_DIR + "/" + latest_split }; - fstream auditlog_fs {}; - - { - diag("Open Audit log to check for conns path=\"%s\"", audit_path.c_str()); - int of_err = open_file_and_seek_end(audit_path, auditlog_fs); - if (of_err != EXIT_SUCCESS) { return of_err; } - } - - diag("Issue query (start trx) to create new backend conn query=\"%s\"", "BEGIN"); - int rc = mysql_query_t(proxy, "BEGIN"); - if (rc == 0) { - diag("Previous query successful; closing trx is required"); - mysql_query_t(proxy, "COMMIT"); - } else if (rc != 0 && !(force_match || ff)) { - diag("Query failed. Aborting test error=\"%s\"", mysql_error(proxy)); - return EXIT_FAILURE; - } - - if ((force_match || ff) && client_eof) { - ok( - rc != 0, - "Query should FAIL (no backend-conn match) ff=%d client_eof=%d force_match=%d", - ff, client_eof, force_match - ); - } else { - ok( - rc == 0, - "Query should SUCCEED (backend-conn match) ff=%d client_eof=%d force_match=%d", - ff, client_eof, force_match - ); - } - - const int32_t exp_conns { - !(force_match || ff) && warmup_pool ? 0 : - (force_match || ff || client_eof) ? TO_SERVER_MAX/RETRIES_DELAY : 1 - }; - const string conn_match_regex { - "Failed to obtain suitable connection for fast-forward; server lacks the required capabilities" - " hostgroup=" + _TO_S(SQLITE3_HG) + " client_flags=\\d+ server_capabilities=\\d+" - }; - - diag("Check ProxySQL log for connection mismatches regex=\"%s\"", conn_match_regex.c_str()); - vector match_lines { get_matching_lines(logfile_fs, conn_match_regex)}; - diag("Found General log matching lines count=%ld", match_lines.size()); - - bool exp_lines {}; - ok( - force_match || ff ? match_lines.size() == exp_conns : match_lines.size() == 0, - "Error log should hold conn match failures lines=%ld exp_lines=%d", - match_lines.size(), exp_conns - ); - - diag("Check Audit log for connections attempts on SQLite3"); - vector audit_lines { get_matching_lines(auditlog_fs, - "SQLite3_Connect_OK.*" + _S(FF_USER) - )}; - diag("Found Audit log matching lines count=%ld", audit_lines.size()); - - ok( - audit_lines.size() == exp_conns, - "Audit log should contain SQLite3 created conns lines=%ld exp_lines=%d", - audit_lines.size(), exp_conns - ); - - diag("Get post-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t post_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(post_hg_st); - - ok( - pre_hg_st.val.conn_ok + exp_conns == post_hg_st.val.conn_ok, - "Conn created should have increased by query attempt pre-ConnOK=%d post-ConnOK=%d", - pre_hg_st.val.conn_ok, post_hg_st.val.conn_ok - ); - - const ext_val_t post_srv_conns { - mysql_query_ext_val( - admin, - "SELECT variable_value FROM stats.stats_mysql_global" - " WHERE variable_name='Server_Connections_created'", - int64_t(-1) - ) - }; - CHECK_EXT_VAL(post_srv_conns); - - ok( - pre_srv_conns.val + exp_conns == post_srv_conns.val, - "Conn created should have increased by query attempt" - " pre-Server_Connections_created=%ld post-Server_Connections_created=%ld", - pre_srv_conns.val, post_srv_conns.val - ); - - dump_as_table(admin, "'connection_pool' status after client conn:", CONN_POOL_HG_STATUS); - - mysql_close(proxy); - - return EXIT_SUCCESS; -} - -int test_conn_creation( - MYSQL* admin, const CommandLine& cl, bool ff, bool client_eof, bool force_match -) { - diag("Started '%s' ff=%d client_eof=%d force_match=%d", __func__, ff, client_eof, force_match); - - diag("Initial connpool cleanup on hg hg=%d conn_tg=%d", SQLITE3_HG, 0); - int rc = conn_pool_cleanup(admin, SQLITE3_HG, 0); - if (rc) { return EXIT_FAILURE; } - - dump_as_table(admin, "'stats_mysql_connection_pool' status:", CONN_POOL_HG_STATUS); - - return test_conn_acquisition(admin, cl, ff, client_eof, force_match, false); -} - -int test_conn_creation(MYSQL* admin, const conn_conf_t& conn_cnf, const proxy_cnf_t& proxy_cnf) { - const test_cnf_t test_cnf { pool_cnf_t { false, 0 }, conn_cnf, proxy_cnf }; - diag("Started '%s' %s", __func__, to_string(test_cnf).c_str()); - - diag("Initial connpool cleanup on hg hg=%d conn_tg=%d", SQLITE3_HG, 0); - int rc = conn_pool_cleanup(admin, SQLITE3_HG, 0); - if (rc) { return EXIT_FAILURE; } - - dump_as_table(admin, "'stats_mysql_connection_pool' status:", CONN_POOL_HG_STATUS); - - return test_conn_acquisition(admin, test_cnf); -} - -// CONN_POOL_WARMUP: Check backend conns created... Support vs Not-Supported -int test_conn_matching(MYSQL* admin, const test_cnf_t& test_cnf) { - const conn_conf_t& conn_cnf { test_cnf.conn_conf }; - const proxy_cnf_t& proxy_cnf { test_cnf.proxy_conf }; - - diag("Started '%s' %s", __func__, to_string(test_cnf).c_str()); - - diag("Initial connpool cleanup on hg hg=%d conn_tg=%d", SQLITE3_HG, 0); - int rc = conn_pool_cleanup(admin, SQLITE3_HG, 0); - if (rc) { return EXIT_FAILURE; } - - dump_as_table(admin, "'stats_mysql_connection_pool' status:", CONN_POOL_HG_STATUS); - - bool pool_depr_eof { bool(test_cnf.pool_status.conn_caps & CLIENT_DEPRECATE_EOF) }; - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(pool_depr_eof)); - MYSQL_QUERY_T(admin, "SET mysql-enable_server_deprecate_eof=" + _TO_S(pool_depr_eof)); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - diag( - "Warming-up conn-pool with conns conns=%d eof_support=%d", - CONN_POOL_WARNMUP, !proxy_cnf.cli_depr_eof - ); - - { - diag("Update 'fast-forward' for testing user user=\"%s\" ff=%d", FF_USER, conn_cnf.fast_forward); - MYSQL_QUERY_T(admin, - "UPDATE mysql_users SET fast_forward=" + _TO_S(0) + " WHERE username='" + _S(FF_USER) + "'" - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - - diag("Create client MySQL conn user=\"%s\" port=\"%d\"", FF_USER, conn_cnf.cl.port); - MYSQL* proxy_warmup { create_mysql_conn({ conn_cnf.cl.host, FF_USER, FF_PASS, conn_cnf.cl.port }) }; - // MYSQL* proxy_warmup { create_mysql_conn({ cl.host, cl.username, cl.password, cl.port }) }; - if (proxy_warmup == NULL) { return EXIT_FAILURE; } - - for (int i = 0; i < CONN_POOL_WARNMUP; i++) { - MYSQL_QUERY_T(proxy_warmup, - "/* create_new_connection=1 */ BEGIN" - // "/* create_new_connection=1;hostgroup=" + std::to_string(SQLITE3_HG) + " */ BEGIN" - ); - MYSQL_QUERY_T(proxy_warmup, "COMMIT"); - } - - mysql_close(proxy_warmup); - - diag("Update 'fast-forward' for testing user user=\"%s\" ff=%d", FF_USER, conn_cnf.fast_forward); - MYSQL_QUERY_T(admin, - "UPDATE mysql_users SET fast_forward=" + _TO_S(1) + " WHERE username='" + _S(FF_USER) + "'" - ); - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - } - - dump_as_table(admin, "'stats_mysql_connection_pool' status:", CONN_POOL_HG_STATUS); - - return test_conn_acquisition(admin, test_cnf); -} - -#ifdef LIBMYSQL_HELPER8 - -/** - * @brief Checks that client is disconnected when a conn is trying converted to 'fast-forward' and the - * currently locked backend connection doesn't match the correct capabilities. - * @param admin An already oppened MySQL connection to the admin interface. - * @return EXIT_SUCCESS if test was able to be performed, EXIT_FAILURE otherwise. - */ -int test_conn_ff_conv(MYSQL* admin, const CommandLine& cl, bool client_eof) { - diag("Started '%s' client_eof=%d", __func__, client_eof); - - diag("Initial connpool cleanup on hg hg=%d conn_tg=%d", SQLITE3_HG, 0); - int rc = conn_pool_cleanup(admin, SQLITE3_HG, 0); - if (rc) { return EXIT_FAILURE; } - - diag("Update 'mysql-enable_client_deprecate_eof' enable_client_deprecate_eof=%d", client_eof); - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(client_eof)); - diag("Allowing capabilities mismatch when selecting backend connections"); - MYSQL_QUERY_T(admin, "SET mysql-connpool_match_client_deprecate_eof=0"); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - diag("Pairing frontend conn with backend one with mismatching capabilities"); - diag("Create client MySQL conn user=\"%s\" port=\"%d\"", cl.username, cl.port); - MYSQL* proxy { create_mysql_conn({ cl.host, cl.username, cl.password, cl.port }) }; - if (proxy == NULL) { return EXIT_FAILURE; } - dump_as_table(admin, "'connection_pool' status after client conn:", CONN_POOL_HG_STATUS); - - diag("Revert support for 'enable_client_deprecate_eof' client_eof=%d", !client_eof); - MYSQL_QUERY_T(admin, "SET mysql-enable_client_deprecate_eof=" + _TO_S(!client_eof)); - MYSQL_QUERY_T(admin, "SET mysql-enable_server_deprecate_eof=1"); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - diag("Get pre-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t pre_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(pre_hg_st); - const ext_val_t pre_srv_conns { mysql_query_ext_val(admin, - "SELECT variable_value FROM stats.stats_mysql_global WHERE variable_name='Server_Connections_created'", - int64_t(-1) - )}; - CHECK_EXT_VAL(pre_srv_conns); - - diag("Issue query (start trx) to create new backend conn query=\"%s\"", "BEGIN"); - rc = mysql_query_t(proxy, "/* hostgroup=" + std::to_string(SQLITE3_HG) + " */ BEGIN"); - if (rc) { - diag("Query failed. Aborting test error=\"%s\"", mysql_error(proxy)); - return EXIT_FAILURE; - } - - diag("Get post-conn attempt stats from target hostgroup tg=%d", SQLITE3_HG); - const ext_val_t post_hg_st { get_conn_pool_hg_stats(admin, SQLITE3_HG) }; - CHECK_EXT_VAL(post_hg_st); - - ok( - pre_hg_st.val.conn_used + 1 == post_hg_st.val.conn_used, - "Conn created should have increased by query attempt pre-ConnUsed=%d post-ConnUsed=%d", - pre_hg_st.val.conn_used, post_hg_st.val.conn_used - ); - - diag("Switching now the session to FAST-FORWARD (opening binlog); DISCONNECT should be enforced"); - MYSQL_RPL rpl {}; - rc = mysql_binlog_open(proxy, &rpl); - - diag( - "Error after starting replication rc=%d errno=%d error=\"%s\"", - rc, mysql_errno(proxy), mysql_error(proxy) - ); - - rc = mysql_binlog_fetch(proxy, &rpl); - - diag( - "Error when trying to fetch replication data rc=%d errno=%d error=\"%s\"", - rc, mysql_errno(proxy), mysql_error(proxy) - ); - - mysql_close(proxy); - - return EXIT_SUCCESS; -} - -#endif - -int main(int argc, char** argv) { - CommandLine cl; - - if (cl.getEnv()) { - diag("Failed to get the required environmental variables."); - return EXIT_FAILURE; - } - - plan( - 5 * gen_all_proxy_cnfs().size() -#ifdef LIBMYSQL_HELPER8 - * 4 + 2 -#else - * 2 -#endif - ); - - MYSQL* admin { create_mysql_conn({ cl.admin_host, cl.admin_username, cl.admin_password, cl.admin_port }) }; - if (admin == NULL) { return EXIT_FAILURE; } - - diag("Setting up global 'mysql-variables' config for the all tests..."); - std::for_each(mysql_variables_setup.begin(), mysql_variables_setup.end(), - [&admin] (const string& q) { return run_setup_query(admin, q); } - ); - diag("Setting up global 'SQLite3 server' config for the test"); - std::for_each(sqlite3_server_setup.begin(), sqlite3_server_setup.end(), - [&admin] (const string& q) { return run_setup_query(admin, q); } - ); - - int rc = 0; - uint32_t conn_caps { -#ifdef LIBMYSQL_HELPER8 - CLIENT_DEPRECATE_EOF -#else - 0 -#endif - }; - - for (const proxy_cnf_t& proxy_cnf : gen_all_proxy_cnfs()) { - rc = test_conn_creation(admin, { cl, true, conn_caps }, proxy_cnf ); - if (rc) { goto cleanup; } - } - for (const proxy_cnf_t& proxy_cnf : gen_all_proxy_cnfs()) { - rc = test_conn_creation(admin, { cl, false, conn_caps }, proxy_cnf ); - if (rc) { goto cleanup; } - } - -#ifdef LIBMYSQL_HELPER8 - - for (const proxy_cnf_t& proxy_cnf : gen_all_proxy_cnfs()) { - rc = test_conn_matching(admin, { - { true, CLIENT_DEPRECATE_EOF }, { cl, true, conn_caps }, proxy_cnf - }); - if (rc) { goto cleanup; } - } - for (const proxy_cnf_t& proxy_cnf : gen_all_proxy_cnfs()) { - rc = test_conn_matching(admin, { - { true, CLIENT_DEPRECATE_EOF }, { cl, false, conn_caps }, proxy_cnf - }); - if (rc) { goto cleanup; } - } - - rc = test_conn_ff_conv(admin, cl, true); - if (rc) { goto cleanup; } - - rc = test_conn_ff_conv(admin, cl, false); - if (rc) { goto cleanup; } - -#endif - -cleanup: - - diag("Recover DISK 'mysql_servers' config"); - MYSQL_QUERY_T(admin, "LOAD MYSQL SERVERS FROM DISK"); - MYSQL_QUERY_T(admin, "LOAD MYSQL SERVERS TO RUNTIME"); - - diag("Recover DISK 'mysql_variables' config"); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES FROM DISK"); - MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME"); - - mysql_close(admin); - - return exit_status(); -} diff --git a/test/tap/tests/test_sqlite3_special_queries.cpp b/test/tap/tests/test_sqlite3_special_queries.cpp deleted file mode 100644 index b35e8dbda..000000000 --- a/test/tap/tests/test_sqlite3_special_queries.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file test_sqlite3_special_queries.cpp - * @brief Execute all the special queries intercepted by SQLite3 sessions. - * @details The test should be compiled against 'libmariadb' and 'libmysql' to ensure compatibility in the - * response of the intercepted queries. - */ - -#include -#include - -#include "mysql.h" - -#include "command_line.h" -#include "utils.h" -#include "tap.h" - -using std::string; -using std::vector; - -struct test_opts_t { - unsigned long cflags; - enum enum_mysql_set_option set_opt; -}; - -string to_string(const test_opts_t& opts) { - return string { "{" } - + "cflags:" + std::to_string(opts.cflags) + ", " - + "set_opt:" + std::to_string(opts.set_opt) - + "}"; -} - -test_opts_t get_opt(vector bin_vec) { - return test_opts_t { - bin_vec[0] ? CLIENT_DEPRECATE_EOF : 0, - bin_vec[1] ? MYSQL_OPTION_MULTI_STATEMENTS_ON : MYSQL_OPTION_MULTI_STATEMENTS_OFF - }; -} - -vector gen_tests() { - vector tests {}; - const auto opts { get_all_bin_vec(2) }; - - std::transform(opts.begin(), opts.end(), std::back_inserter(tests), get_opt); - - return tests; -} - -const vector set_queries { - "SET character_set_results='latin1'", - "SET SQL_AUTO_IS_NULL=1", - "SET NAMES 'utf8'", - "/*!40100 SET @@SQL_MODE='' */", - "/*!40103 SET TIME_ZONE='UTC' */", - "/*!80000 SET SESSION transaction_isolation = 'READ-COMMITTED' */", - "SET SESSION transaction_isolation = 'READ-COMMITTED'", - "SET wait_timeout=86400" -}; - -int main(int argc, char** argv) { - CommandLine cl; - - if (cl.getEnv()) { - diag("Failed to get the required environmental variables."); - return EXIT_FAILURE; - } - - const vector tests { gen_tests() }; - plan(tests.size()*(3 + set_queries.size())); - - for (const test_opts_t& opts : tests) { - diag("Executing test test_opts=%s", to_string(opts).c_str()); - MYSQL* proxy = mysql_init(NULL); - mysql_options(proxy, MYSQL_DEFAULT_AUTH, "mysql_native_password"); - - int cflags = opts.cflags; - -#ifdef LIBMYSQL_HELPER8 - { - enum mysql_ssl_mode ssl_mode = SSL_MODE_DISABLED; - mysql_options(proxy, MYSQL_OPT_SSL_MODE, &ssl_mode); - } -#endif - - if (!mysql_real_connect(proxy, cl.host, cl.username, cl.password, NULL, cl.port, NULL, cflags)) { - fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy)); - return EXIT_FAILURE; - } - - int set_rc = mysql_set_server_option(proxy, opts.set_opt); - - ok( - set_rc == 0, - "Setting server option should succeed rc=%d test_opts=%s", - set_rc, to_string(opts).c_str() - ); - - int ping_rc = mysql_ping(proxy); - ok(ping_rc == 0, "Pinging the server succeed rc=%d", ping_rc); - - int initdb_rc = mysql_select_db(proxy, "information_schema"); - ok(initdb_rc == 0, "COM_INIT_DB should succeed rc=%d", initdb_rc); - - for (const auto& q : set_queries) { - diag("Executing 'special SET' query q='%s'", q.c_str()); - int rc = mysql_query(proxy, q.c_str()); - ok(rc == 0, "Query should execute without error q='%s'", q.c_str()); - } - - mysql_close(proxy); - } - - return exit_status(); -} diff --git a/test/tap/tests/test_ssl_fast_forward-2.cpp b/test/tap/tests/test_ssl_fast_forward-2-t.cpp similarity index 100% rename from test/tap/tests/test_ssl_fast_forward-2.cpp rename to test/tap/tests/test_ssl_fast_forward-2-t.cpp diff --git a/test/tap/tests/test_ssl_fast_forward-3.cpp b/test/tap/tests/test_ssl_fast_forward-3-t.cpp similarity index 100% rename from test/tap/tests/test_ssl_fast_forward-3.cpp rename to test/tap/tests/test_ssl_fast_forward-3-t.cpp