diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index 675cf090e2..c2df41d6da 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -64,7 +64,7 @@ using json = nlohmann::json; #define MYHGM_GEN_ADMIN_RUNTIME_SERVERS "SELECT hostgroup_id, hostname, port, gtid_port, CASE status WHEN 0 THEN \"ONLINE\" WHEN 1 THEN \"SHUNNED\" WHEN 2 THEN \"OFFLINE_SOFT\" WHEN 3 THEN \"OFFLINE_HARD\" WHEN 4 THEN \"SHUNNED\" END status, weight, compression, max_connections, max_replication_lag, use_ssl, max_latency_ms, comment FROM mysql_servers ORDER BY hostgroup_id, hostname, port" -#define MYHGM_MYSQL_HOSTGROUP_ATTRIBUTES "CREATE TABLE mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" +#define MYHGM_MYSQL_HOSTGROUP_ATTRIBUTES "CREATE TABLE mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , hostgroup_settings VARCHAR CHECK (JSON_VALID(hostgroup_settings) OR hostgroup_settings = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" typedef std::unordered_map umap_mysql_errors; diff --git a/include/ProxySQL_Cluster.hpp b/include/ProxySQL_Cluster.hpp index 4ca9cfd7ff..2eaf88650a 100644 --- a/include/ProxySQL_Cluster.hpp +++ b/include/ProxySQL_Cluster.hpp @@ -38,7 +38,7 @@ #define CLUSTER_QUERY_MYSQL_GROUP_REPLICATION_HOSTGROUPS "PROXY_SELECT writer_hostgroup, backup_writer_hostgroup, reader_hostgroup, offline_hostgroup, active, max_writers, writer_is_also_reader, max_transactions_behind, comment FROM runtime_mysql_group_replication_hostgroups ORDER BY writer_hostgroup" /* @brief Query to be intercepted by 'ProxySQL_Admin' for 'runtime_mysql_hostgroup_attributes'. See top comment for details. */ -#define CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES "PROXY_SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, comment FROM runtime_mysql_hostgroup_attributes ORDER BY hostgroup_id" +#define CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES "PROXY_SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment FROM runtime_mysql_hostgroup_attributes ORDER BY hostgroup_id" /* @brief Query to be intercepted by 'ProxySQL_Admin' for 'runtime_mysql_aws_aurora_hostgroups'. See top comment for details. */ #define CLUSTER_QUERY_MYSQL_AWS_AURORA "PROXY_SELECT writer_hostgroup, reader_hostgroup, active, aurora_port, domain_name, max_lag_ms, check_interval_ms, check_timeout_ms, writer_is_also_reader, new_reader_weight, add_lag_ms, min_lag_ms, lag_num_checks, comment FROM runtime_mysql_aws_aurora_hostgroups ORDER BY writer_hostgroup" diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 3627903140..7fb83388a1 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -2591,7 +2591,7 @@ SQLite3_result * MySQL_HostGroups_Manager::dump_table_mysql(const string& name) } else if (name == "mysql_replication_hostgroups") { query=(char *)"SELECT writer_hostgroup, reader_hostgroup, check_type, comment FROM mysql_replication_hostgroups"; } else if (name == "mysql_hostgroup_attributes") { - query=(char *)"SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, servers_defaults, comment FROM mysql_hostgroup_attributes ORDER BY hostgroup_id"; + query=(char *)"SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment FROM mysql_hostgroup_attributes ORDER BY hostgroup_id"; } else if (name == "mysql_servers") { query = (char *)MYHGM_GEN_ADMIN_RUNTIME_SERVERS; } else { @@ -6928,6 +6928,34 @@ T j_get_srv_default_int_val( return static_cast(-1); } +/** + * @brief Initializes the supplied 'MyHGC' with the specified 'hostgroup_settings'. + * @details Input verification is performed in the supplied 'hostgroup_settings'. It's expected to be a valid + * JSON. + * + * In case input verification fails for a field, supplied 'MyHGC' is NOT updated for that field. An error + * message is logged specifying the source of the error. + * + * @param hostgroup_settings String containing a JSON defined in 'mysql_hostgroup_attributes'. + * @param myhgc The 'MyHGC' of the target hostgroup of the supplied 'hostgroup_settings'. + */ +void init_myhgc_hostgroup_settings(const char* hostgroup_settings, MyHGC* myhgc) { + const uint32_t hid = myhgc->hid; + + if (hostgroup_settings[0] != '\0') { + try { + nlohmann::json j = nlohmann::json::parse(hostgroup_settings); + // fields to be populated + } + catch (const json::exception& e) { + proxy_error( + "JSON parsing for 'mysql_hostgroup_attributes.hostgroup_settings' for hostgroup %d failed with exception `%s`.\n", + hid, e.what() + ); + } + } +} + /** * @brief Initializes the supplied 'MyHGC' with the specified 'servers_defaults'. * @details Input verification is performed in the supplied 'server_defaults'. It's expected to be a valid @@ -6982,8 +7010,8 @@ void MySQL_HostGroups_Manager::generate_mysql_hostgroup_attributes_table() { const char * query=(const char *)"INSERT INTO mysql_hostgroup_attributes ( " "hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, " "init_connect, multiplex, connection_warming, throttle_connections_per_sec, " - "ignore_session_variables, servers_defaults, comment) VALUES " - "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)"; + "ignore_session_variables, hostgroup_settings, servers_defaults, comment) VALUES " + "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; //rc=(*proxy_sqlite3_prepare_v2)(mydb3, query, -1, &statement, 0); rc = mydb->prepare_v2(query, &statement); @@ -7019,12 +7047,13 @@ void MySQL_HostGroups_Manager::generate_mysql_hostgroup_attributes_table() { int connection_warming = atoi(r->fields[6]); int throttle_connections_per_sec = atoi(r->fields[7]); char * ignore_session_variables = r->fields[8]; - char * servers_defaults = r->fields[9]; - char * comment = r->fields[10]; - proxy_info("Loading MySQL Hostgroup Attributes info for (%d,%d,%d,%d,\"%s\",%d,%d,%d,\"%s\",'%s',\"%s\")\n", + char * hostgroup_settings = r->fields[9]; + char * servers_defaults = r->fields[10]; + char * comment = r->fields[11]; + proxy_info("Loading MySQL Hostgroup Attributes info for (%d,%d,%d,%d,\"%s\",%d,%d,%d,\"%s\",\"%s\",\"%s\",\"%s\")\n", hid, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, - ignore_session_variables, servers_defaults, comment + ignore_session_variables, hostgroup_settings, servers_defaults, comment ); rc=(*proxy_sqlite3_bind_int64)(statement, 1, hid); ASSERT_SQLITE_OK(rc, mydb); rc=(*proxy_sqlite3_bind_int64)(statement, 2, max_num_online_servers); ASSERT_SQLITE_OK(rc, mydb); @@ -7035,8 +7064,9 @@ void MySQL_HostGroups_Manager::generate_mysql_hostgroup_attributes_table() { rc=(*proxy_sqlite3_bind_int64)(statement, 7, connection_warming); ASSERT_SQLITE_OK(rc, mydb); rc=(*proxy_sqlite3_bind_int64)(statement, 8, throttle_connections_per_sec); ASSERT_SQLITE_OK(rc, mydb); rc=(*proxy_sqlite3_bind_text)(statement, 9, ignore_session_variables, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); - rc=(*proxy_sqlite3_bind_text)(statement, 10, servers_defaults, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); - rc=(*proxy_sqlite3_bind_text)(statement, 11, comment, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); + rc=(*proxy_sqlite3_bind_text)(statement, 10, hostgroup_settings, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); + rc=(*proxy_sqlite3_bind_text)(statement, 11, servers_defaults, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); + rc=(*proxy_sqlite3_bind_text)(statement, 12, comment, -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); SAFE_SQLITE3_STEP2(statement); rc=(*proxy_sqlite3_clear_bindings)(statement); ASSERT_SQLITE_OK(rc, mydb); rc=(*proxy_sqlite3_reset)(statement); ASSERT_SQLITE_OK(rc, mydb); @@ -7072,6 +7102,7 @@ void MySQL_HostGroups_Manager::generate_mysql_hostgroup_attributes_table() { // TODO: assign the variables } } + init_myhgc_hostgroup_settings(hostgroup_settings, myhgc); init_myhgc_servers_defaults(servers_defaults, myhgc); } for (unsigned int i=0; ilen; i++) { diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index a420b3e1e5..dcb0af0df7 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -594,11 +594,13 @@ MHD_Result http_handler(void *cls, struct MHD_Connection *connection, const char #define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_5_2 "CREATE TABLE mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" -#define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_5_2 +#define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_6_0 "CREATE TABLE mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , hostgroup_settings VARCHAR CHECK (JSON_VALID(hostgroup_settings) OR hostgroup_settings = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" -#define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_HOSTGROUP_ATTRIBUTES "CREATE TABLE runtime_mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" +//#define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_6_0 -#define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_5_2 +#define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_HOSTGROUP_ATTRIBUTES "CREATE TABLE runtime_mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , hostgroup_settings VARCHAR CHECK (JSON_VALID(hostgroup_settings) OR hostgroup_settings = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" + +#define ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_6_0 // Cluster solution @@ -12326,7 +12328,7 @@ void ProxySQL_Admin::save_mysql_servers_runtime_to_database(bool _runtime) { StrQuery = "INSERT INTO "; if (_runtime) StrQuery += "runtime_"; - StrQuery += "mysql_hostgroup_attributes (hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, servers_defaults, comment) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)"; + StrQuery += "mysql_hostgroup_attributes (hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; rc = admindb->prepare_v2(StrQuery.c_str(), &statement); ASSERT_SQLITE_OK(rc, admindb); //proxy_info("New mysql_aws_aurora_hostgroups table\n"); @@ -12336,13 +12338,14 @@ void ProxySQL_Admin::save_mysql_servers_runtime_to_database(bool _runtime) { rc=(*proxy_sqlite3_bind_int64)(statement, 2, atol(r->fields[1])); ASSERT_SQLITE_OK(rc, admindb); // max_num_online_servers rc=(*proxy_sqlite3_bind_int64)(statement, 3, atol(r->fields[2])); ASSERT_SQLITE_OK(rc, admindb); // autocommit rc=(*proxy_sqlite3_bind_int64)(statement, 4, atol(r->fields[3])); ASSERT_SQLITE_OK(rc, admindb); // free_connections_pct - rc=(*proxy_sqlite3_bind_text)(statement, 5, r->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // variable_name + rc=(*proxy_sqlite3_bind_text)(statement, 5, r->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // variable_name rc=(*proxy_sqlite3_bind_int64)(statement, 6, atol(r->fields[5])); ASSERT_SQLITE_OK(rc, admindb); // multiplex rc=(*proxy_sqlite3_bind_int64)(statement, 7, atol(r->fields[6])); ASSERT_SQLITE_OK(rc, admindb); // connection_warming rc=(*proxy_sqlite3_bind_int64)(statement, 8, atol(r->fields[7])); ASSERT_SQLITE_OK(rc, admindb); // throttle_connections_per_sec - rc=(*proxy_sqlite3_bind_text)(statement, 9, r->fields[8], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ignore_session_variables - rc=(*proxy_sqlite3_bind_text)(statement, 10, r->fields[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // servers_defaults - rc=(*proxy_sqlite3_bind_text)(statement, 11, r->fields[10], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // comment + rc=(*proxy_sqlite3_bind_text)(statement, 9, r->fields[8], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ignore_session_variables + rc=(*proxy_sqlite3_bind_text)(statement, 10, r->fields[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // hostgroup_settings + rc=(*proxy_sqlite3_bind_text)(statement, 11, r->fields[10], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // servers_defaults + rc=(*proxy_sqlite3_bind_text)(statement, 12, r->fields[11], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // comment SAFE_SQLITE3_STEP2(statement); rc=(*proxy_sqlite3_clear_bindings)(statement); ASSERT_SQLITE_OK(rc, admindb); @@ -13389,6 +13392,28 @@ void ProxySQL_Admin::disk_upgrade_mysql_servers() { " FROM mysql_hostgroup_attributes_v250" ); } + rci = configdb->check_table_structure((char*)"mysql_hostgroup_attributes", (char*)ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES_V2_5_2); + if (rci) { + // upgrade is required + proxy_warning("Detected version pre-v2.6.0 of mysql_hostgroup_attributes\n"); + proxy_warning("ONLINE UPGRADE of table mysql_hostgroup_attributes in progress\n"); + // drop mysql_hostgroup_attributes table with suffix _v252 + configdb->execute("DROP TABLE IF EXISTS mysql_hostgroup_attributes_v252"); + // rename current table to add suffix _v252 + configdb->execute("ALTER TABLE mysql_hostgroup_attributes RENAME TO mysql_hostgroup_attributes_v252"); + // create new table + configdb->build_table((char*)"mysql_hostgroup_attributes", (char*)ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES, false); + // copy fields from old table + configdb->execute( + "INSERT INTO mysql_hostgroup_attributes (" + " hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex," + " connection_warming, throttle_connections_per_sec, ignore_session_variables, servers_defaults, comment" + ") SELECT" + " hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex," + " connection_warming, throttle_connections_per_sec, ignore_session_variables, servers_defaults, comment" + " FROM mysql_hostgroup_attributes_v252" + ); + } configdb->execute("PRAGMA foreign_keys = ON"); } diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index 6d9d42f9f0..b60088f105 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -1926,8 +1926,8 @@ void ProxySQL_Cluster::pull_mysql_servers_from_peer(const std::string& checksum, const char * q=(const char *)"INSERT INTO mysql_hostgroup_attributes ( " "hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, " "init_connect, multiplex, connection_warming, throttle_connections_per_sec, " - "ignore_session_variables, comment) VALUES " - "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)"; + "ignore_session_variables, hostgroup_settings, servers_defaults, comment) VALUES " + "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; sqlite3_stmt *statement1 = NULL; int rc = GloAdmin->admindb->prepare_v2(q, &statement1); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); @@ -1942,7 +1942,9 @@ void ProxySQL_Cluster::pull_mysql_servers_from_peer(const std::string& checksum, rc=(*proxy_sqlite3_bind_int64)(statement1, 7, atol(row[6])); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // connection_warming rc=(*proxy_sqlite3_bind_int64)(statement1, 8, atol(row[7])); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // throttle_connections_per_sec rc=(*proxy_sqlite3_bind_text)(statement1, 9, row[8], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ignore_session_variables - rc=(*proxy_sqlite3_bind_text)(statement1, 10, row[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // comment + rc=(*proxy_sqlite3_bind_text)(statement1, 10,row[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // hostgroup_settings + rc=(*proxy_sqlite3_bind_text)(statement1, 11, row[10], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // servers_defaults + rc=(*proxy_sqlite3_bind_text)(statement1, 12, row[11], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // comment SAFE_SQLITE3_STEP2(statement1); rc=(*proxy_sqlite3_clear_bindings)(statement1); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); rc=(*proxy_sqlite3_reset)(statement1); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); diff --git a/test/tap/tests/test_cluster_sync-t.cpp b/test/tap/tests/test_cluster_sync-t.cpp index e5897061ec..f893297e0f 100644 --- a/test/tap/tests/test_cluster_sync-t.cpp +++ b/test/tap/tests/test_cluster_sync-t.cpp @@ -909,7 +909,7 @@ int main(int, char**) { const size_t num_payloads = module_sync_payloads.size(); plan( // Sync tests by values - 15 + + 16 + // All modules enabled sync checksum tests num_payloads * 3 + // Module with disabled sync checksum tests @@ -1053,6 +1053,133 @@ int main(int, char**) { check_mysql_servers_sync(cl, proxy_admin, r_proxy_admin, insert_mysql_servers_values_3); } + { + std::string print_master_hostgroup_attributes = ""; + string_format(t_debug_query, print_master_hostgroup_attributes, cl.admin_username, cl.admin_password, cl.host, cl.admin_port, "SELECT * FROM runtime_mysql_hostgroup_attributes"); + std::string print_replica_hostgroup_attributes = ""; + string_format(t_debug_query, print_replica_hostgroup_attributes, "radmin", "radmin", cl.host, R_PORT, "SELECT * FROM runtime_mysql_hostgroup_attributes"); + + // Configure 'runtime_mysql_hostgroup_attributes' and check sync + const char* t_insert_mysql_hostgroup_attributes = + "INSERT INTO mysql_hostgroup_attributes ( " + "hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, " + "multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, " + "hostgroup_settings, servers_defaults ) " + "VALUES (%d, %d, %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s')"; + std::vector> insert_hostgroup_attributes_values { + std::make_tuple(18, 2, -1, 20, "SET sql_mode = \"\"", 0, 0, 100, "", "", ""), + std::make_tuple(19, 2, -1, 20, "SET sql_mode = \"\"", 0, 0, 100, "{}", "{}", "{}"), + std::make_tuple(20, 0, 0, 30, "SET long_query_time = 0", 1, 0, 123, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "", ""), + std::make_tuple(21, 2, -1, 50, "SET sql_mode = \"\"", 1, 0, 125, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "{}", ""), + std::make_tuple(22, 3, -1, 40, "SET sql_mode = \"\"", 1, 0, 124, "{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}", "", "{\"weight\": 100, \"max_connections\": 1000}") + }; + std::vector insert_mysql_hostgroup_attributes_queries{}; + + for (auto const& values : insert_hostgroup_attributes_values) { + std::string insert_mysql_hostgroup_attributes_query = ""; + string_format( + t_insert_mysql_hostgroup_attributes, + insert_mysql_hostgroup_attributes_query, + std::get<0>(values), + std::get<1>(values), + std::get<2>(values), + std::get<3>(values), + std::get<4>(values), + std::get<5>(values), + std::get<6>(values), + std::get<7>(values), + std::get<8>(values), + std::get<9>(values), + std::get<10>(values) + ); + insert_mysql_hostgroup_attributes_queries.push_back(insert_mysql_hostgroup_attributes_query); + } + + const char* t_select_hostgroup_attributes_inserted_entries = + "SELECT COUNT(*) FROM mysql_hostgroup_attributes WHERE " + "hostgroup_id=%d AND max_num_online_servers=%d AND autocommit=%d AND free_connections_pct=%d AND init_connect='%s' AND " + "multiplex=%d AND connection_warming=%d AND throttle_connections_per_sec=%d AND ignore_session_variables='%s' AND " + "hostgroup_settings='%s' AND servers_defaults='%s'"; + std::vector select_mysql_hostgroup_attributes_queries{}; + + for (auto const& values : insert_hostgroup_attributes_values) { + std::string select_hostgroup_attributes_query = ""; + string_format( + t_select_hostgroup_attributes_inserted_entries, + select_hostgroup_attributes_query, + std::get<0>(values), + std::get<1>(values), + std::get<2>(values), + std::get<3>(values), + std::get<4>(values), + std::get<5>(values), + std::get<6>(values), + std::get<7>(values), + std::get<8>(values), + std::get<9>(values), + std::get<10>(values) + ); + select_mysql_hostgroup_attributes_queries.push_back(select_hostgroup_attributes_query); + } + + // SETUP CONFIG + + // Backup current table + MYSQL_QUERY__(proxy_admin, "CREATE TABLE mysql_hostgroup_attributes_sync_test_2687 AS SELECT * FROM mysql_hostgroup_attributes"); + MYSQL_QUERY__(proxy_admin, "DELETE FROM mysql_hostgroup_attributes"); + + // Insert the new hostgroup attributes values + for (const auto& query : insert_mysql_hostgroup_attributes_queries) { + MYSQL_QUERY__(proxy_admin, query.c_str()); + } + MYSQL_QUERY__(proxy_admin, "LOAD MYSQL SERVERS TO RUNTIME"); + + std::cout << "MASTER TABLE BEFORE SYNC:" << std::endl; + system(print_master_hostgroup_attributes.c_str()); + + // SYNCH CHECK + + // Sleep until timeout waiting for synchronization + uint waited = 0; + bool not_synced_query = false; + while (waited < SYNC_TIMEOUT) { + not_synced_query = false; + // Check that all the entries have been synced + for (const auto& query : select_mysql_hostgroup_attributes_queries) { + MYSQL_QUERY__(r_proxy_admin, query.c_str()); + MYSQL_RES* hostgroup_attributes_res = mysql_store_result(r_proxy_admin); + MYSQL_ROW row = mysql_fetch_row(hostgroup_attributes_res); + int row_value = atoi(row[0]); + mysql_free_result(hostgroup_attributes_res); + + if (row_value == 0) { + not_synced_query = true; + break; + } + } + + if (not_synced_query) { + waited += 1; + sleep(1); + } + else { + break; + } + } + + std::cout << "REPLICA TABLE AFTER SYNC:" << std::endl; + system(print_replica_hostgroup_attributes.c_str()); + ok(not_synced_query == false, "'mysql_hostgroup_attributes' should be synced."); + + // TEARDOWN CONFIG + MYSQL_QUERY__(proxy_admin, "DELETE FROM mysql_hostgroup_attributes"); + MYSQL_QUERY__(proxy_admin, "INSERT INTO mysql_hostgroup_attributes SELECT * FROM mysql_hostgroup_attributes_sync_test_2687"); + MYSQL_QUERY__(proxy_admin, "DROP TABLE mysql_hostgroup_attributes_sync_test_2687"); + MYSQL_QUERY__(proxy_admin, "LOAD MYSQL SERVERS TO RUNTIME"); + } + + sleep(2); + { std::string print_master_galera_hostgroups = ""; string_format(t_debug_query, print_master_galera_hostgroups, cl.admin_username, cl.admin_password, cl.host, cl.admin_port, "SELECT * FROM runtime_mysql_galera_hostgroups"); diff --git a/test/tap/tests/test_mysql_hostgroup_attributes-1-t.cpp b/test/tap/tests/test_mysql_hostgroup_attributes-1-t.cpp index 85ee8211f7..8f90fdf712 100644 --- a/test/tap/tests/test_mysql_hostgroup_attributes-1-t.cpp +++ b/test/tap/tests/test_mysql_hostgroup_attributes-1-t.cpp @@ -61,23 +61,31 @@ int main(int argc, char** argv) { std::unordered_map queries_and_checksums = { { "0x666CFBEEDB76EE9C", - "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','')" + "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','','')" }, { "0xE2FC2A5FEE8D18DC", - "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','',''),(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','hello world')", + "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','',''),(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','','hello world')", }, { "0xFACE1C64FF1C373E", - "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','',''),(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','hello world'),(17,0,0,30,'SET long_query_time=0',1,0,123,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','filtering variables')" + "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','',''),(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','','hello world'),(17,0,0,30,'SET long_query_time=0',1,0,123,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','','filtering variables')" }, { "0x161B2F2BB35BA05E", - "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','')," - "(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','hello world')," - "(17,0,0,30,'SET long_query_time=0',1,0,123,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','filtering variables')," - "(20,3,-1,40,'SET sql_mode=\"\"',1,0,124,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','{\"weight\": 100, \"max_connections\": 1000}','servers defaults')" + "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','','')," + "(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','','hello world')," + "(17,0,0,30,'SET long_query_time=0',1,0,123,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','','filtering variables')," + "(20,3,-1,40,'SET sql_mode=\"\"',1,0,124,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','{\"weight\": 100, \"max_connections\": 1000}','servers defaults')" }, + { + "0x1A6E38CBB2E44672", + "INSERT INTO mysql_hostgroup_attributes VALUES (19,1,1,10,'',1,1,10000,'','','','')," + "(18,2,-1,20,'SET sql_mode=\"\"',0,0,100,'','','','hello world')," + "(17,0,0,30,'SET long_query_time=0',1,0,123,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','','filtering variables')," + "(20,3,-1,40,'SET sql_mode=\"\"',1,0,124,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','','{\"weight\": 100, \"max_connections\": 1000}','servers defaults')," + "(21,2,-1,50,'SET sql_mode=\"\"',1,0,125,'{\"session_variables\":[\"tmp_table_size\",\"join_buffer_size\"]}','{}','{\"weight\": 100, \"max_connections\": 1000}','hostgroup settings')" + } }; plan(queries_and_checksums.size()*4);