@@ -114,9 +114,6 @@ extern struct MHD_Daemon *Admin_HTTP_Server;
114
114
115
115
extern ProxySQL_Statistics *GloProxyStats;
116
116
117
- template <enum SERVER_TYPE>
118
- int ProxySQL_Test___PurgeDigestTable (bool async_purge, bool parallel, char **msg);
119
-
120
117
extern char *ssl_key_fp;
121
118
extern char *ssl_cert_fp;
122
119
extern char *ssl_ca_fp;
@@ -276,6 +273,17 @@ const std::vector<std::string> LOAD_COREDUMP_FROM_MEMORY = {
276
273
" LOAD COREDUMP TO RUNTIME" ,
277
274
" LOAD COREDUMP TO RUN" };
278
275
276
+ const std::vector<std::string> CMD_PREFIX_PURGE_QUERY_DIGESTS = {
277
+ " PURGE TABLE stats.stats_mysql_query_digest TO " ,
278
+ " PURGE TABLE stats_mysql_query_digest TO " ,
279
+ " PURGE stats.stats_mysql_query_digest TO " ,
280
+ " PURGE stats_mysql_query_digest TO " ,
281
+ " PURGE TABLE stats.stats_pgsql_query_digest TO " ,
282
+ " PURGE TABLE stats_pgsql_query_digest TO " ,
283
+ " PURGE stats.stats_pgsql_query_digest TO " ,
284
+ " PURGE stats_pgsql_query_digest TO " ,
285
+ };
286
+
279
287
extern unordered_map<string,std::tuple<string, vector<string>, vector<string>>> load_save_disk_commands;
280
288
281
289
bool is_admin_command_or_alias (const std::vector<std::string>& cmds, char *query_no_space, int query_no_space_length) {
@@ -288,6 +296,17 @@ bool is_admin_command_or_alias(const std::vector<std::string>& cmds, char *query
288
296
return false ;
289
297
}
290
298
299
+ const char * match_command_prefix (const std::vector<std::string>& cmd_prefix, char *query, int query_len) {
300
+ for (auto &prefix : cmd_prefix) {
301
+ if ((unsigned int ) query_len >= prefix.length ()
302
+ && !strncasecmp (prefix.c_str (), query, prefix.length ()))
303
+ {
304
+ return prefix.c_str ();
305
+ }
306
+ }
307
+
308
+ return nullptr ;
309
+ }
291
310
292
311
template <typename S>
293
312
bool FlushCommandWrapper (S* sess, const std::vector<std::string>& cmds, char *query_no_space, int query_no_space_length, const string& name, const string& direction) {
@@ -322,6 +341,35 @@ bool FlushCommandWrapper(S* sess, const string& modname, char *query_no_space, i
322
341
return false ;
323
342
}
324
343
344
+ std::tuple<bool , enum SERVER_TYPE, time_t > parse_command_purge_query_digests (char *query, int query_len) {
345
+ bool match = false ;
346
+ enum SERVER_TYPE server_type = SERVER_TYPE_MYSQL;
347
+ time_t last_seen = 0 ;
348
+
349
+ const char *prefix = match_command_prefix (CMD_PREFIX_PURGE_QUERY_DIGESTS, query, query_len);
350
+ if (prefix) {
351
+ match = true ;
352
+
353
+ if (strstr (prefix, " _pgsql_" ) != nullptr ) {
354
+ server_type = SERVER_TYPE_PGSQL;
355
+ }
356
+
357
+ // parse timestamp
358
+ char *ts_str = strdup (query + strlen (prefix));
359
+ char *ts_end = nullptr ;
360
+ long long ts = strtoll (trim_spaces_in_place (ts_str), &ts_end, 10 );
361
+
362
+ // ts_str should only contain digits and respresent a valid timestamp
363
+ if ((*ts_end == 0 ) && (ts > 0 )) {
364
+ last_seen = realtime_to_monotonic_time (ts);
365
+ }
366
+
367
+ free (ts_str);
368
+ }
369
+
370
+ return std::make_tuple (match, server_type, last_seen);
371
+ }
372
+
325
373
template <typename S>
326
374
bool admin_handler_command_kill_connection (char *query_no_space, unsigned int query_no_space_length, S* sess, ProxySQL_Admin *pa) {
327
375
uint32_t id=atoi (query_no_space+16 );
@@ -2498,10 +2546,8 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) {
2498
2546
SPA->admindb ->execute (" DELETE FROM stats.stats_mysql_query_digest_reset" );
2499
2547
SPA->vacuum_stats (true );
2500
2548
// purge the digest map, asynchronously, in single thread
2501
- char *msg = NULL ;
2502
- int r1 = ProxySQL_Test___PurgeDigestTable<SERVER_TYPE_MYSQL>(true , false , &msg);
2503
- SPA->send_ok_msg_to_client (sess, msg, r1, query_no_space);
2504
- free (msg);
2549
+ int r1 = GloMyQPro->purge_query_digests (true , false );
2550
+ SPA->send_ok_msg_to_client (sess, NULL , r1, query_no_space);
2505
2551
run_query=false ;
2506
2552
goto __run_query;
2507
2553
}
@@ -2534,16 +2580,45 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) {
2534
2580
SPA->admindb ->execute (" DELETE FROM stats.stats_pgsql_query_digest_reset" );
2535
2581
SPA->vacuum_stats (true );
2536
2582
// purge the digest map, asynchronously, in single thread
2537
- char * msg = NULL ;
2538
- int r1 = ProxySQL_Test___PurgeDigestTable<SERVER_TYPE_PGSQL>(true , false , &msg);
2539
- SPA->send_ok_msg_to_client (sess, msg, r1, query_no_space);
2540
- free (msg);
2583
+ int r1 = GloPgQPro->purge_query_digests (true , false );
2584
+ SPA->send_ok_msg_to_client (sess, NULL , r1, query_no_space);
2541
2585
run_query = false ;
2542
2586
goto __run_query;
2543
2587
}
2544
2588
}
2545
2589
}
2546
2590
}
2591
+
2592
+ // handles 'PURGE stats_mysql_query_digest TO <value>'.
2593
+ // any entry in stats_mysql_query_digest where last_seen is less than <value> will be deleted.
2594
+ if (!strncasecmp (" PURGE " , query_no_space, strlen (" PURGE " ))
2595
+ && sess->session_type == PROXYSQL_SESSION_ADMIN
2596
+ ) {
2597
+ auto result = parse_command_purge_query_digests (query_no_space, query_no_space_length);
2598
+ bool match = std::get<0 >(result);
2599
+
2600
+ if (match == true ) {
2601
+ int ret = 0 ;
2602
+ enum SERVER_TYPE type = std::get<1 >(result);
2603
+ time_t last_seen = std::get<2 >(result);
2604
+
2605
+ if (last_seen > 0 ) {
2606
+ if (type == SERVER_TYPE_MYSQL) {
2607
+ ret = GloMyQPro->purge_query_digests (true , false , last_seen);
2608
+ } else if (type == SERVER_TYPE_PGSQL) {
2609
+ ret = GloPgQPro->purge_query_digests (true , false , last_seen);
2610
+ }
2611
+
2612
+ pa->send_ok_msg_to_client (sess, NULL , ret, query_no_space);
2613
+ } else {
2614
+ pa->send_error_msg_to_client (sess, " Invalid timestamp" );
2615
+ }
2616
+
2617
+ run_query = false ;
2618
+ goto __run_query;
2619
+ }
2620
+ }
2621
+
2547
2622
#ifdef DEBUG
2548
2623
/* *
2549
2624
* @brief Handles the 'PROXYSQL_SIMULATOR' command. Performing the operation specified in the payload
@@ -3837,4 +3912,3 @@ void admin_session_handler(S* sess, void *_pa, PtrSize_t *pkt) {
3837
3912
// Explicitly instantiate the required template class and member functions
3838
3913
template void admin_session_handler<MySQL_Session>(MySQL_Session* sess, void *_pa, PtrSize_t *pkt);
3839
3914
template void admin_session_handler<PgSQL_Session>(PgSQL_Session* sess, void *_pa, PtrSize_t *pkt);
3840
-
0 commit comments