diff --git a/include/AI_Features_Manager.h b/include/AI_Features_Manager.h index 63532a7e3..01dc1c82e 100644 --- a/include/AI_Features_Manager.h +++ b/include/AI_Features_Manager.h @@ -71,7 +71,6 @@ private: // Helper methods int init_vector_db(); - int init_nl2sql(); int init_anomaly_detector(); void close_vector_db(); void close_nl2sql(); @@ -129,6 +128,16 @@ public: */ void shutdown(); + /** + * @brief Initialize NL2SQL converter + * + * Initializes the NL2SQL converter if not already initialized. + * This can be called at runtime after enabling nl2sql. + * + * @return 0 on success, non-zero on failure + */ + int init_nl2sql(); + /** * @brief Acquire write lock for thread-safe operations * diff --git a/include/GenAI_Thread.h b/include/GenAI_Thread.h index b4fa494e0..641713de6 100644 --- a/include/GenAI_Thread.h +++ b/include/GenAI_Thread.h @@ -301,6 +301,14 @@ public: */ char** get_variables_list(); + /** + * @brief Check if a variable exists + * + * @param name The name of the variable to check + * @return true if the variable exists, false otherwise + */ + bool has_variable(const char* name); + /** * @brief Print the version information */ diff --git a/lib/Admin_FlushVariables.cpp b/lib/Admin_FlushVariables.cpp index 4aced07a0..576b53e70 100644 --- a/lib/Admin_FlushVariables.cpp +++ b/lib/Admin_FlushVariables.cpp @@ -1079,6 +1079,14 @@ void ProxySQL_Admin::flush_genai_variables___database_to_runtime(SQLite3DB* db, pthread_mutex_unlock(&GloVars.checksum_mutex); } + // Check if NL2SQL needs to be initialized + if (GloAI && GloGATH->variables.genai_nl2sql_enabled && !GloAI->get_nl2sql()) { + proxy_info("NL2SQL enabled but not initialized, initializing now\n"); + if (GloAI->init_nl2sql() != 0) { + proxy_error("Failed to initialize NL2SQL converter\n"); + } + } + if (lock) wrunlock(); } if (resultset) delete resultset; diff --git a/lib/Admin_Handler.cpp b/lib/Admin_Handler.cpp index 0070d6ce9..c46cd797b 100644 --- a/lib/Admin_Handler.cpp +++ b/lib/Admin_Handler.cpp @@ -884,6 +884,40 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_ return true; } +// Creates a masked copy of the query string for logging, masking sensitive values like API keys +// Returns a newly allocated string that must be freed by the caller +static char* mask_sensitive_values_in_query(const char* query) { + if (!query || !strstr(query, "_key=")) + return strdup(query); + + char* masked = strdup(query); + char* key_pos = strstr(masked, "_key="); + if (key_pos) { + key_pos += 5; // Move past "_key=" + char* value_start = key_pos; + // Find the end of the value (either single quote, space, or end of string) + char* value_end = value_start; + if (*value_start == '\'') { + value_start++; // Skip opening quote + value_end = value_start; + while (*value_end && *value_end != '\'') + value_end++; + } else { + while (*value_end && *value_end != ' ' && *value_end != '\0') + value_end++; + } + + size_t value_len = value_end - value_start; + if (value_len > 2) { + // Keep first 2 chars, mask the rest + for (size_t i = 2; i < value_len; i++) { + value_start[i] = 'x'; + } + } + } + return masked; +} + // Returns true if the given name is either a know mysql or admin global variable. bool is_valid_global_variable(const char *var_name) { if (strlen(var_name) > 6 && !strncmp(var_name, "mysql-", 6) && GloMTH->has_variable(var_name + 6)) { @@ -902,6 +936,8 @@ bool is_valid_global_variable(const char *var_name) { #endif /* PROXYSQLCLICKHOUSE */ } else if (strlen(var_name) > 4 && !strncmp(var_name, "mcp-", 4) && GloMCPH && GloMCPH->has_variable(var_name + 4)) { return true; + } else if (strlen(var_name) > 6 && !strncmp(var_name, "genai-", 6) && GloGATH && GloGATH->has_variable(var_name + 6)) { + return true; } else { return false; } @@ -918,7 +954,9 @@ bool admin_handler_command_set(char *query_no_space, unsigned int query_no_space proxy_debug(PROXY_DEBUG_ADMIN, 4, "Received command %s\n", query_no_space); if (strncasecmp(query_no_space,(char *)"set autocommit",strlen((char *)"set autocommit"))) { if (strncasecmp(query_no_space,(char *)"SET @@session.autocommit",strlen((char *)"SET @@session.autocommit"))) { - proxy_info("Received command %s\n", query_no_space); + char* masked_query = mask_sensitive_values_in_query(query_no_space); + proxy_info("Received command %s\n", masked_query); + free(masked_query); } } } diff --git a/lib/GenAI_Thread.cpp b/lib/GenAI_Thread.cpp index bfecf7323..56d73bc77 100644 --- a/lib/GenAI_Thread.cpp +++ b/lib/GenAI_Thread.cpp @@ -673,6 +673,19 @@ char** GenAI_Threads_Handler::get_variables_list() { return list; } +bool GenAI_Threads_Handler::has_variable(const char* name) { + if (!name) + return false; + + // Check if name exists in genai_thread_variables_names + for (int i = 0; genai_thread_variables_names[i]; i++) { + if (!strcmp(name, genai_thread_variables_names[i])) + return true; + } + + return false; +} + void GenAI_Threads_Handler::print_version() { fprintf(stderr, "GenAI Threads Handler rev. %s -- %s -- %s\n", GENAI_THREAD_VERSION, __FILE__, __TIMESTAMP__); }