Add CHECKSUM command

pull/493/head
ethanblackburn 10 years ago
parent d7b1d513ca
commit 26235f9c56

@ -65,7 +65,6 @@ class ProxySQL_Admin {
void flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool replace, bool del, bool onlyifempty);
void flush_mysql_variables___database_to_runtime(SQLite3DB *db, bool replace);
char **get_variables_list();
char *get_variable(char *name);
bool set_variable(char *name, char *value);
@ -120,7 +119,9 @@ class ProxySQL_Admin {
void load_mysql_variables_to_runtime() { flush_mysql_variables___database_to_runtime(admindb, true); }
void save_mysql_variables_from_runtime() { flush_mysql_variables___runtime_to_database(admindb, true, true, false); }
char *table_checksum(char *tablename, char *source, char **err);
void stats___mysql_query_rules();
void stats___mysql_query_digests();
void stats___mysql_query_digests_reset();

@ -1173,6 +1173,23 @@ SQLite3_result * ProxySQL_Admin::generate_show_table_status(const char *tablenam
return result;
}
char *parse_destination(char *query){
char *method=(char *)"TO";
char *pch=strstr(query, method);
if (pch){
return pch+3;
}
return NULL;
}
char *parse_source(char *query){
char *method=(char *)"FROM";
char *pch=strstr(query, method);
if (pch){
return pch+5;
}
return NULL;
}
void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *pkt) {
@ -1339,6 +1356,29 @@ void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *p
}
}
if(!strncasecmp("CHECKSUM TABLE ", query_no_space, 15)){
proxy_debug(PROXYSQL_DEBUG_ADMIN, 4, "Received CHECKSUM command\n");
char *source=parse_source(query_no_space);
char *tablename;
if (source){
int tablename_length=query_no_space_length-strlen(source)-20;
tablename=(char *)malloc(tablename_length);
strncpy(tablename, query_no_space+15, tablename_length);
} else {
tablename=query_no_space+15;
}
char *error=NULL;
char *checksum_result=SPA->table_checksum(tablename, source, &error);
if (error) {
SPA->send_MySQL_ERR(&sess->client_myds->myprot, error);
} else {
char *q=(char *)"SELECT '%s' AS 'table', '%s' AS 'checksum'";
query=(char *)malloc(strlen(q)+strlen(tablename)+strlen(checksum_result)+20);
sprintf(query,q,tablename,checksum_result);
goto __run_query;
}
}
if (strncasecmp("SHOW ", query_no_space, 5)) {
goto __end_show_commands; // in the next block there are only SHOW commands
}
@ -1547,6 +1587,7 @@ __run_query:
SPA->statsdb->execute_statement(query, &error , &cols , &affected_rows , &resultset);
SPA->statsdb->execute("PRAGMA query_only = OFF");
}
proxy_info("%s", query);
sess->SQLite3_to_MySQL(resultset, error, affected_rows, &sess->client_myds->myprot);
delete resultset;
}
@ -2072,6 +2113,9 @@ bool ProxySQL_Admin::is_command(std::string s) {
};
void ProxySQL_Admin::dump_mysql_collations() {
const CHARSET_INFO * c = compiled_charsets;
char buf[1024];
@ -2260,6 +2304,68 @@ void ProxySQL_Admin::flush_mysql_variables___runtime_to_database(SQLite3DB *db,
free(varnames);
}
char *ProxySQL_Admin::table_checksum(char *tablename, char *source, char **err){
char *error=NULL;
int cols=0;
int affected_rows=0;
char *q1=(char *)"SELECT * FROM %s ORDER BY rowid";
char *q2=(char *)malloc(strlen(q1)+strlen(tablename));
SQLite3_result *resultset=NULL;
sprintf(q2, q1, tablename);
if (source && !strncasecmp(source,"DISK", 4)){
configdb->execute_statement(q2, &error, &cols, &affected_rows, &resultset);
} else{
admindb->execute_statement(q2, &error, &cols, &affected_rows, &resultset);
}
if (error) {
*err=strdup(error);
proxy_error("Error on %s: %s\n", q2, error);
free(error);
return (char *)"NULL";
} else if (resultset->rows_count>0) {
int tot_l=0;
int tot_s=0;
char *large_buff[resultset->rows_count];
int column_length=resultset->columns;
for (std::vector<SQLite3_row *>::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) {
SQLite3_row *r=*it;
char *buffs[column_length];
int local_s=0;
for (int i=0; i<column_length;i++){
if (r->fields[i]){
int l=strlen(r->fields[i]);
local_s+=l;
buffs[i]=(char *)malloc(strlen(r->fields[i])+1);
strncpy(buffs[i], r->fields[i], strlen(r->fields[i]));
} else {
buffs[i]=(char *)"";
local_s+=1;
}
}
large_buff[tot_l]=(char *)malloc(local_s+1);
for (int i=0; i<column_length; i++){
strncat(large_buff[tot_l], buffs[i], strlen(buffs[i]));
}
tot_s+=local_s;
tot_l++;
}
char *result_str=(char *)malloc(tot_s+1);
for (int i=0; i<tot_l; i++){
strncat(result_str, large_buff[i], strlen(large_buff[i]));
}
if (resultset) delete resultset;
uint32 hash=SpookyHash::Hash32(result_str,strlen(result_str),0);
free(result_str);
char *checksum=(char *)malloc(16);
sprintf(checksum, "%x", hash);
return checksum;
} else {
free(error);
return (char *)"NULL";
}
}
char **ProxySQL_Admin::get_variables_list() {
size_t l=sizeof(admin_variables_names)/sizeof(char *);
unsigned int i;

@ -63,6 +63,7 @@ bool SQLite3DB::execute_statement(const char *str, char **error, int *cols, int
sqlite3_stmt *statement;
*error=NULL;
bool ret=false;
proxy_info("executing: %s\n", str);
if(sqlite3_prepare_v2(db, str, -1, &statement, 0) != SQLITE_OK) {
*error=strdup(sqlite3_errmsg(db));
goto __exit_execute_statement;

Loading…
Cancel
Save