diff --git a/include/sqlite3db.h b/include/sqlite3db.h index 7f82297a9..67a9f584b 100644 --- a/include/sqlite3db.h +++ b/include/sqlite3db.h @@ -85,6 +85,9 @@ class SQLite3_result { public: int columns; int rows_count; + char *checksum(); + int64_t raw_checksum(); + std::vector column_definition; std::vector rows; SQLite3_result() { diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index c1160a79a..83e7f95ed 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -1365,6 +1365,110 @@ void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *p sprintf(query,q,PROXYSQL_VERSION); goto __run_query; } + if(!strncasecmp("CHECKSUM ", query_no_space, 9)){ + proxy_debug(PROXYSQL_DEBUG_ADMIN, 4, "Received CHECKSUM command\n"); + ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa; + SQLite3_result *resultset=NULL; + char *tablename=NULL; + char *error=NULL; + int affected_rows=0; + int cols=0; + if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL SERVERS") && !strncasecmp("CHECKSUM DISK MYSQL SERVERS", query_no_space, strlen(query_no_space))){ + char *q=(char *)"SELECT * FROM mysql_servers ORDER BY hostgroup_id, hostname, port"; + tablename=(char *)"MYSQL SERVERS"; + SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL USERS") && !strncasecmp("CHECKSUM DISK MYSQL USERS", query_no_space, strlen(query_no_space))){ + char *q=(char *)"SELECT * FROM mysql_users ORDER BY username"; + tablename=(char *)"MYSQL USERS"; + SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL QUERY RULES") && !strncasecmp("CHECKSUM DISK MYSQL QUERY RULES", query_no_space, strlen(query_no_space))){ + char *q=(char *)"SELECT * FROM mysql_query_rules ORDER BY rule_id"; + tablename=(char *)"MYSQL QUERY RULES"; + SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL VARIABLES") && !strncasecmp("CHECKSUM DISK MYSQL VARIABLES", query_no_space, strlen(query_no_space))){ + char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-%' ORDER BY variable_name"; + tablename=(char *)"MYSQL VARIABLES"; + SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + + } + + if (strlen(query_no_space)==strlen("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM DISK MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))){ + char *q=(char *)"SELECT * FROM mysql_replication_hostgroups ORDER BY writer_hostgroup"; + tablename=(char *)"MYSQL REPLICATION HOSTGROUPS"; + SPA->configdb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + + } + + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL SERVERS") && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL SERVERS") && !strncasecmp("CHECKSUM MEM MYSQL SERVERS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL SERVERS") && !strncasecmp("CHECKSUM MYSQL SERVERS", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM mysql_servers ORDER BY hostgroup_id, hostname, port"; + tablename=(char *)"MYSQL SERVERS"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL USERS") && !strncasecmp("CHECKSUM MEMORY MYSQL USERS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL USERS") && !strncasecmp("CHECKSUM MEM MYSQL USERS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL USERS") && !strncasecmp("CHECKSUM MYSQL USERS", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM mysql_users ORDER BY username"; + tablename=(char *)"MYSQL USERS"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MEMORY MYSQL QUERY RULES", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MEM MYSQL QUERY RULES", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL QUERY RULES") && !strncasecmp("CHECKSUM MYSQL QUERY RULES", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM mysql_query_rules ORDER BY rule_id"; + tablename=(char *)"MYSQL QUERY RULES"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL VARIABLES") && !strncasecmp("CHECKSUM MEMORY MYSQL VARIABLES", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL VARIABLES") && !strncasecmp("CHECKSUM MEM MYSQL VARIABLES", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL VARIABLES") && !strncasecmp("CHECKSUM MYSQL VARIABLES", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-%' ORDER BY variable_name"; + tablename=(char *)"MYSQL VARIABLES"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEMORY MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MEM MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL REPLICATION HOSTGROUPS") && !strncasecmp("CHECKSUM MYSQL REPLICATION HOSTGROUPS", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM mysql_replication_hostgroups ORDER BY writer_hostgroup"; + tablename=(char *)"MYSQL REPLICATION HOSTGROUPS"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } + + if (error) { + proxy_error("Error: %s\n", error); + char buf[1024]; + sprintf(buf,"%s", error); + SPA->send_MySQL_ERR(&sess->client_myds->myprot, buf); + run_query=false; + } else if (resultset) { + char *q=(char *)"SELECT '%s' AS 'table', '%s' AS 'checksum'"; + char *checksum=(char *)resultset->checksum(); + query=(char *)malloc(strlen(q)+strlen(tablename)+strlen(checksum)+1); + sprintf(query,q,tablename,checksum); + } + goto __run_query; + } if (strncasecmp("SHOW ", query_no_space, 5)) { goto __end_show_commands; // in the next block there are only SHOW commands diff --git a/lib/sqlite3db.cpp b/lib/sqlite3db.cpp index 630c75d48..ee02412e3 100644 --- a/lib/sqlite3db.cpp +++ b/lib/sqlite3db.cpp @@ -1,5 +1,6 @@ #include "proxysql.h" #include "cpp.h" +#include "SpookyV2.h" #define USLEEP_SQLITE_LOCKED 100 @@ -177,3 +178,33 @@ void SQLite3DB::wrlock() { void SQLite3DB::wrunlock() { spin_wrunlock(&rwlock); } + +int64_t SQLite3_result::raw_checksum() { + if (this->rows_count==0) return 0; + uint64_t hash1, hash2; + SpookyHash myhash; + myhash.Init(19,3); + + for (std::vector::iterator it=rows.begin() ; it!=rows.end(); ++it) { + SQLite3_row *r=*it; + for (int i=0; ifields[i]) { + myhash.Update(r->fields[i],r->sizes[i]); + } else { + myhash.Update("",0); + } + } + } + myhash.Final(&hash1, &hash2); + return hash1; +} + + +char *SQLite3_result::checksum() { + uint64_t hash1=raw_checksum(); + char buf[128]; + uint32_t d32[2]; + memcpy(&d32,&hash1,sizeof(hash1)); + sprintf(buf,"0x%X%X", d32[0], d32[1]); + return strdup(buf); +}