From d880330c17d12c8b00088ea08cf45278089ea600 Mon Sep 17 00:00:00 2001 From: Rene Cannao Date: Thu, 9 Apr 2026 17:20:17 +0000 Subject: [PATCH] feat: add SAVE MYSQLX handlers and first-class LOAD/SAVE dispatch Replace the PLUGIN MYSQLX command namespace with canonical ProxySQL admin syntax matching the MYSQL/PGSQL convention. Plugin changes (mysqlx_admin_schema.cpp): - Add three SAVE handlers (save_users_from_runtime, save_routes_from_runtime, save_backend_endpoints_from_runtime) that copy runtime tables back to config tables (reverse of LOAD) - Register 6 commands with canonical names: LOAD MYSQLX USERS/ROUTES/BACKEND ENDPOINTS TO RUNTIME SAVE MYSQLX USERS/ROUTES/BACKEND ENDPOINTS TO MEMORY Admin handler changes (Admin_Handler.cpp): - Add 6 MYSQLX alias vector definitions following the existing LOAD_MYSQL_USERS_FROM_MEMORY pattern (4 aliases each: FROM MEMORY, FROM MEM, TO RUNTIME, TO RUN) - Replace the generic plugin fallback dispatch with MYSQLX-specific alias matching using is_admin_command_or_alias(), matching how MYSQL and PGSQL commands are dispatched - Use 'return false' pattern consistent with other admin commands --- lib/Admin_Handler.cpp | 51 ++++++++++++++++++++-- plugins/mysqlx/src/mysqlx_admin_schema.cpp | 51 ++++++++++++++++++++-- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/lib/Admin_Handler.cpp b/lib/Admin_Handler.cpp index d7dcafa5b..5eda1f2b9 100644 --- a/lib/Admin_Handler.cpp +++ b/lib/Admin_Handler.cpp @@ -313,6 +313,43 @@ const std::vector SAVE_TSDB_VARIABLES_TO_MEMORY = { "SAVE TSDB VARIABLES TO MEM" , "SAVE TSDB VARIABLES FROM RUNTIME" , "SAVE TSDB VARIABLES FROM RUN" }; + +// MySQLX plugin +const std::vector LOAD_MYSQLX_USERS_FROM_MEMORY = { + "LOAD MYSQLX USERS FROM MEMORY" , + "LOAD MYSQLX USERS FROM MEM" , + "LOAD MYSQLX USERS TO RUNTIME" , + "LOAD MYSQLX USERS TO RUN" }; + +const std::vector SAVE_MYSQLX_USERS_TO_MEMORY = { + "SAVE MYSQLX USERS TO MEMORY" , + "SAVE MYSQLX USERS TO MEM" , + "SAVE MYSQLX USERS FROM RUNTIME" , + "SAVE MYSQLX USERS FROM RUN" }; + +const std::vector LOAD_MYSQLX_ROUTES_FROM_MEMORY = { + "LOAD MYSQLX ROUTES FROM MEMORY" , + "LOAD MYSQLX ROUTES FROM MEM" , + "LOAD MYSQLX ROUTES TO RUNTIME" , + "LOAD MYSQLX ROUTES TO RUN" }; + +const std::vector SAVE_MYSQLX_ROUTES_TO_MEMORY = { + "SAVE MYSQLX ROUTES TO MEMORY" , + "SAVE MYSQLX ROUTES TO MEM" , + "SAVE MYSQLX ROUTES FROM RUNTIME" , + "SAVE MYSQLX ROUTES FROM RUN" }; + +const std::vector LOAD_MYSQLX_BACKEND_ENDPOINTS_FROM_MEMORY = { + "LOAD MYSQLX BACKEND ENDPOINTS FROM MEMORY" , + "LOAD MYSQLX BACKEND ENDPOINTS FROM MEM" , + "LOAD MYSQLX BACKEND ENDPOINTS TO RUNTIME" , + "LOAD MYSQLX BACKEND ENDPOINTS TO RUN" }; + +const std::vector SAVE_MYSQLX_BACKEND_ENDPOINTS_TO_MEMORY = { + "SAVE MYSQLX BACKEND ENDPOINTS TO MEMORY" , + "SAVE MYSQLX BACKEND ENDPOINTS TO MEM" , + "SAVE MYSQLX BACKEND ENDPOINTS FROM RUNTIME" , + "SAVE MYSQLX BACKEND ENDPOINTS FROM RUN" }; // const std::vector LOAD_COREDUMP_FROM_MEMORY = { "LOAD COREDUMP FROM MEMORY" , @@ -5298,9 +5335,17 @@ __end_show_commands: } if (run_query && sess->session_type == PROXYSQL_SESSION_ADMIN) { ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; - if (SPA->dispatch_plugin_admin_command(sess, query_no_space)) { - run_query=false; - goto __run_query; + if ( + is_admin_command_or_alias(LOAD_MYSQLX_USERS_FROM_MEMORY, query_no_space, query_no_space_length) || + is_admin_command_or_alias(SAVE_MYSQLX_USERS_TO_MEMORY, query_no_space, query_no_space_length) || + is_admin_command_or_alias(LOAD_MYSQLX_ROUTES_FROM_MEMORY, query_no_space, query_no_space_length) || + is_admin_command_or_alias(SAVE_MYSQLX_ROUTES_TO_MEMORY, query_no_space, query_no_space_length) || + is_admin_command_or_alias(LOAD_MYSQLX_BACKEND_ENDPOINTS_FROM_MEMORY, query_no_space, query_no_space_length) || + is_admin_command_or_alias(SAVE_MYSQLX_BACKEND_ENDPOINTS_TO_MEMORY, query_no_space, query_no_space_length) + ) { + if (SPA->dispatch_plugin_admin_command(sess, query_no_space)) { + return false; + } } } diff --git a/plugins/mysqlx/src/mysqlx_admin_schema.cpp b/plugins/mysqlx/src/mysqlx_admin_schema.cpp index fa900e2c1..c888c7a94 100644 --- a/plugins/mysqlx/src/mysqlx_admin_schema.cpp +++ b/plugins/mysqlx/src/mysqlx_admin_schema.cpp @@ -164,6 +164,48 @@ ProxySQL_PluginCommandResult load_backend_endpoints_to_runtime(const ProxySQL_Pl return result; } +ProxySQL_PluginCommandResult save_users_from_runtime(const ProxySQL_PluginCommandContext& ctx, const char*) { + if (ctx.admindb == nullptr) { + return command_failure("mysqlx users save requires admin db"); + } + if (!copy_table(*ctx.admindb, kRuntimeMysqlxUsersTable, kMysqlxUsersTable)) { + return command_failure("failed to copy mysqlx users from runtime"); + } + + ProxySQL_PluginCommandResult result {0, 0, ""}; + result.rows_affected = ctx.admindb->return_one_int("SELECT COUNT(*) FROM mysqlx_users"); + result.message = "mysqlx users saved from runtime"; + return result; +} + +ProxySQL_PluginCommandResult save_routes_from_runtime(const ProxySQL_PluginCommandContext& ctx, const char*) { + if (ctx.admindb == nullptr) { + return command_failure("mysqlx routes save requires admin db"); + } + if (!copy_table(*ctx.admindb, kRuntimeMysqlxRoutesTable, kMysqlxRoutesTable)) { + return command_failure("failed to copy mysqlx routes from runtime"); + } + + ProxySQL_PluginCommandResult result {0, 0, ""}; + result.rows_affected = ctx.admindb->return_one_int("SELECT COUNT(*) FROM mysqlx_routes"); + result.message = "mysqlx routes saved from runtime"; + return result; +} + +ProxySQL_PluginCommandResult save_backend_endpoints_from_runtime(const ProxySQL_PluginCommandContext& ctx, const char*) { + if (ctx.admindb == nullptr) { + return command_failure("mysqlx backend endpoints save requires admin db"); + } + if (!copy_table(*ctx.admindb, kRuntimeMysqlxBackendEndpointsTable, kMysqlxBackendEndpointsTable)) { + return command_failure("failed to copy mysqlx backend endpoints from runtime"); + } + + ProxySQL_PluginCommandResult result {0, 0, ""}; + result.rows_affected = ctx.admindb->return_one_int("SELECT COUNT(*) FROM mysqlx_backend_endpoints"); + result.message = "mysqlx backend endpoints saved from runtime"; + return result; +} + void register_table_pair( ProxySQL_PluginServices& services, const char* table_name, @@ -259,8 +301,11 @@ bool mysqlx_register_admin_schema(ProxySQL_PluginServices& services) { services.register_table(stats_processlist); } - services.register_command("PLUGIN MYSQLX LOAD USERS TO RUNTIME", &load_users_to_runtime); - services.register_command("PLUGIN MYSQLX LOAD ROUTES TO RUNTIME", &load_routes_to_runtime); - services.register_command("PLUGIN MYSQLX LOAD BACKEND ENDPOINTS TO RUNTIME", &load_backend_endpoints_to_runtime); + services.register_command("LOAD MYSQLX USERS TO RUNTIME", &load_users_to_runtime); + services.register_command("SAVE MYSQLX USERS TO MEMORY", &save_users_from_runtime); + services.register_command("LOAD MYSQLX ROUTES TO RUNTIME", &load_routes_to_runtime); + services.register_command("SAVE MYSQLX ROUTES TO MEMORY", &save_routes_from_runtime); + services.register_command("LOAD MYSQLX BACKEND ENDPOINTS TO RUNTIME", &load_backend_endpoints_to_runtime); + services.register_command("SAVE MYSQLX BACKEND ENDPOINTS TO MEMORY", &save_backend_endpoints_from_runtime); return true; }