Added support for mysqldump

Added 2 new functions to answer some of queries from mysqldump:
ProxySQL_Admin::generate_show_fields_from()
ProxySQL_Admin::generate_show_table_status()

ProxySQL_Admin() replies with an OK or an artificial resultset to most of the queries from mysqldump
pull/393/head
René Cannaò 11 years ago
parent e551213bf7
commit dccc5b7f43

@ -136,5 +136,7 @@ class ProxySQL_Admin {
void flush_error_log();
void GenericRefreshStatistics(const char *query_no_space, unsigned int query_no_space_length, bool admin);
SQLite3_result * generate_show_table_status(const char *, char **err);
SQLite3_result * generate_show_fields_from(const char *tablename, char **err);
};
#endif /* __CLASS_PROXYSQL_ADMIN_H */

@ -984,6 +984,190 @@ void ProxySQL_Admin::GenericRefreshStatistics(const char *query_no_space, unsign
}
SQLite3_result * ProxySQL_Admin::generate_show_fields_from(const char *tablename, char **err) {
char *tn=NULL; // tablename
// note that tablename is passed with a trailing '
tn=(char *)malloc(strlen(tablename));
unsigned int i=0, j=0;
while (i<strlen(tablename)) {
if (tablename[i]!='\\' && tablename[i]!='`' && tablename[i]!='\'') {
tn[j]=tablename[i];
j++;
}
i++;
}
tn[j]=0;
/*
if (!strcmp(tablename,"global_variables`") || !strcmp(tablename,"global\\_variables`")) tn=(char *)"global_variables";
else if (!strcmp(tablename,"debug_levels`") || !strcmp(tablename,"debug_levels`")) tn=(char *)"debug_levels";
else if (!strcmp(tablename,"mysql_collations`") || !strcmp(tablename,"mysql\\_collations`")) tn=(char *)"mysql_collations";
else if (!strcmp(tablename,"mysql_query_rules`") || !strcmp(tablename,"mysql\\_query\\_rules`")) tn=(char *)"mysql_query_rules";
else if (!strcmp(tablename,"mysql_servers`") || !strcmp(tablename,"mysql\\_servers`")) tn=(char *)"mysql_servers";
else if (!strcmp(tablename,"mysql_users`") || !strcmp(tablename,"mysql\\_users`")) tn=(char *)"mysql_users";
*/
/*
if (tn==NULL) {
*err=strdup((char *)"Table does not exist");
free(tn);
return NULL;
}
*/
SQLite3_result *resultset=NULL;
char *q1=(char *)"PRAGMA table_info(%s)";
char *q2=(char *)malloc(strlen(q1)+strlen(tn));
sprintf(q2,q1,tn);
int affected_rows;
int cols;
char *error=NULL;
admindb->execute_statement(q2, &error , &cols , &affected_rows , &resultset);
if (error) {
proxy_error("Error on %s : %s\n", q2, error);
free(q2);
*err=strdup(error);
free(error);
if (resultset) delete resultset;
free(tn);
return NULL;
}
if (resultset==NULL) {
free(tn);
return NULL;
}
if (resultset->rows_count==0) {
free(tn);
delete resultset;
*err=strdup((char *)"Table does not exist");
return NULL;
}
SQLite3_result *result=new SQLite3_result(6);
result->add_column_definition(SQLITE_TEXT,"Field");
result->add_column_definition(SQLITE_TEXT,"Type");
result->add_column_definition(SQLITE_TEXT,"Null");
result->add_column_definition(SQLITE_TEXT,"Key");
result->add_column_definition(SQLITE_TEXT,"Default");
result->add_column_definition(SQLITE_TEXT,"Extra");
char *pta[6];
pta[1]=(char *)"varchar(255)";
pta[2]=(char *)"NO";
pta[3]=(char *)"";
pta[4]=(char *)"";
pta[5]=(char *)"";
free(q2);
for (std::vector<SQLite3_row *>::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) {
SQLite3_row *r=*it;
pta[0]=r->fields[0];
result->add_row(pta);
}
delete resultset;
free(tn);
return result;
}
SQLite3_result * ProxySQL_Admin::generate_show_table_status(const char *tablename, char **err) {
char *pta[18];
pta[0]=NULL;
char *tn=NULL; // tablename
// note that tablename is passed with a trailing '
tn=(char *)malloc(strlen(tablename));
unsigned int i=0, j=0;
while (i<strlen(tablename)) {
if (tablename[i]!='\\' && tablename[i]!='`' && tablename[i]!='\'') {
tn[j]=tablename[i];
j++;
}
i++;
}
tn[j]=0;
/*
if (!strcmp(tablename,"global_variables'") || !strcmp(tablename,"global\\_variables'")) pta[0]=(char *)"global_variables";
else if (!strcmp(tablename,"debug_levels'") || !strcmp(tablename,"debug\\_levels'")) pta[0]=(char *)"debug_levels";
else if (!strcmp(tablename,"mysql_collations'") || !strcmp(tablename,"mysql\\_collations'")) pta[0]=(char *)"mysql_collations";
else if (!strcmp(tablename,"mysql_query_rules'") || !strcmp(tablename,"mysql\\_query\\_rules'")) pta[0]=(char *)"mysql_query_rules";
else if (!strcmp(tablename,"mysql_servers'") || !strcmp(tablename,"mysql\\_servers'")) pta[0]=(char *)"mysql_servers";
else if (!strcmp(tablename,"mysql_users'") || !strcmp(tablename,"mysql\\_users'")) pta[0]=(char *)"mysql_users";
*/
/*
if (tn==NULL) {
*err=strdup((char *)"Table does not exist");
free(tn);
return NULL;
}
*/
SQLite3_result *resultset=NULL;
char *q1=(char *)"PRAGMA table_info(%s)";
char *q2=(char *)malloc(strlen(q1)+strlen(tn));
sprintf(q2,q1,tn);
int affected_rows;
int cols;
char *error=NULL;
admindb->execute_statement(q2, &error , &cols , &affected_rows , &resultset);
if (error) {
proxy_error("Error on %s : %s\n", q2, error);
free(q2);
*err=strdup(error);
free(error);
if (resultset) delete resultset;
free(tn);
return NULL;
}
if (resultset==NULL) {
free(tn);
return NULL;
}
if (resultset->rows_count==0) {
free(tn);
delete resultset;
*err=strdup((char *)"Table does not exist");
return NULL;
}
SQLite3_result *result=new SQLite3_result(18);
result->add_column_definition(SQLITE_TEXT,"Name");
result->add_column_definition(SQLITE_TEXT,"Engine");
result->add_column_definition(SQLITE_TEXT,"Version");
result->add_column_definition(SQLITE_TEXT,"Row_format");
result->add_column_definition(SQLITE_TEXT,"Rows");
result->add_column_definition(SQLITE_TEXT,"Avg_row_length");
result->add_column_definition(SQLITE_TEXT,"Data_length");
result->add_column_definition(SQLITE_TEXT,"Max_data_length");
result->add_column_definition(SQLITE_TEXT,"Index_length");
result->add_column_definition(SQLITE_TEXT,"Data_free");
result->add_column_definition(SQLITE_TEXT,"Auto_increment");
result->add_column_definition(SQLITE_TEXT,"Create_time");
result->add_column_definition(SQLITE_TEXT,"Update_time");
result->add_column_definition(SQLITE_TEXT,"Check_time");
result->add_column_definition(SQLITE_TEXT,"Collation");
result->add_column_definition(SQLITE_TEXT,"Checksum");
result->add_column_definition(SQLITE_TEXT,"Create_options");
result->add_column_definition(SQLITE_TEXT,"Comment");
pta[0]=tn;
pta[1]=(char *)"SQLite";
pta[2]=(char *)"10";
pta[3]=(char *)"Dynamic";
pta[4]=(char *)"10";
pta[5]=(char *)"0";
pta[6]=(char *)"0";
pta[7]=(char *)"0";
pta[8]=(char *)"0";
pta[9]=(char *)"0";
pta[10]=(char *)"NULL";
pta[11]=(char *)"0000-00-00 00:00:00";
pta[12]=(char *)"0000-00-00 00:00:00";
pta[13]=(char *)"0000-00-00 00:00:00";
pta[14]=(char *)"utf8_bin";
pta[15]=(char *)"NULL";
pta[16]=(char *)"";
pta[17]=(char *)"";
result->add_row(pta);
free(tn);
return result;
}
void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *pkt) {
char *error=NULL;
@ -1032,6 +1216,80 @@ void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *p
goto __run_query;
}
// queries generated by mysqldump
ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa;
if (
!strncmp("/*!40014 SET ", query_no_space, 13) ||
!strncmp("/*!40101 SET ", query_no_space, 13) ||
!strncmp("/*!40103 SET ", query_no_space, 13) ||
!strncmp("/*!40111 SET ", query_no_space, 13) ||
!strncmp("/*!40000 ALTER TABLE", query_no_space, strlen("/*!40000 ALTER TABLE"))
||
!strncmp("/*!40100 SET @@SQL_MODE='' */", query_no_space, strlen("/*!40100 SET @@SQL_MODE='' */"))
||
!strncmp("/*!40103 SET TIME_ZONE=", query_no_space, strlen("/*!40103 SET TIME_ZONE="))
||
!strncmp("LOCK TABLES", query_no_space, strlen("LOCK TABLES"))
||
!strncmp("UNLOCK TABLES", query_no_space, strlen("UNLOCK TABLES"))
||
!strncmp("SET SQL_QUOTE_SHOW_CREATE=1", query_no_space, strlen("SET SQL_QUOTE_SHOW_CREATE=1"))
||
!strncmp("SET SESSION character_set_results", query_no_space, strlen("SET SESSION character_set_results"))
||
!strncasecmp("USE ", query_no_space, strlen("USE ")) // this applies to all clients, not only mysqldump
) {
SPA->send_MySQL_OK(&sess->client_myds->myprot, NULL);
run_query=false;
goto __run_query;
}
if (!strncmp("SHOW VARIABLES LIKE 'gtid\\_mode'", query_no_space, strlen("SHOW VARIABLES LIKE 'gtid\\_mode'"))) {
l_free(query_length,query);
query=l_strdup("SELECT variable_name Variable_name, Variable_value Value FROM global_variables WHERE Variable_name='gtid_mode'");
query_length=strlen(query)+1;
goto __run_query;
}
if (!strncmp("select @@collation_database", query_no_space, strlen("select @@collation_database"))) {
l_free(query_length,query);
query=l_strdup("SELECT Collation '@@collation_database' FROM mysql_collations WHERE Collation='utf8_general_ci' LIMIT 1");
query_length=strlen(query)+1;
goto __run_query;
}
if (!strncmp("SHOW VARIABLES LIKE 'ndbinfo\\_version'", query_no_space, strlen("SHOW VARIABLES LIKE 'ndbinfo\\_version'"))) {
l_free(query_length,query);
query=l_strdup("SELECT variable_name Variable_name, Variable_value Value FROM global_variables WHERE Variable_name='ndbinfo_version'");
query_length=strlen(query)+1;
goto __run_query;
}
if (!strncmp("show table status like '", query_no_space, strlen("show table status like '"))) {
char *strA=query_no_space+24;
int strAl=strlen(strA);
if (strAl<2) { // error
goto __run_query;
}
char *err=NULL;
SQLite3_result *resultset=SPA->generate_show_table_status(strA, &err);
sess->SQLite3_to_MySQL(resultset, err, 0, &sess->client_myds->myprot);
if (resultset) delete resultset;
if (err) free(err);
run_query=false;
goto __run_query;
}
if (!strncmp("show fields from `", query_no_space, strlen("show fields from `"))) {
char *strA=query_no_space+18;
int strAl=strlen(strA);
if (strAl<2) { // error
goto __run_query;
}
char *err=NULL;
SQLite3_result *resultset=SPA->generate_show_fields_from(strA, &err);
sess->SQLite3_to_MySQL(resultset, err, 0, &sess->client_myds->myprot);
if (resultset) delete resultset;
if (err) free(err);
run_query=false;
goto __run_query;
}
}
// FIXME: this should be removed, it is just a POC for issue #253 . What is important is the call to GloMTH->signal_all_threads();
@ -1123,6 +1381,33 @@ void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *p
goto __run_query;
}
if ((query_no_space_length>17) && (!strncasecmp("SHOW TABLES LIKE ", query_no_space, 17))) {
strA=query_no_space+17;
strAl=strlen(strA);
strB=(char *)"SELECT name AS tables FROM sqlite_master WHERE type='table' AND name LIKE '%s'";
strBl=strlen(strB);
char *tn=NULL; // tablename
tn=(char *)malloc(strlen(strA));
unsigned int i=0, j=0;
while (i<strlen(strA)) {
if (strA[i]!='\\' && strA[i]!='`' && strA[i]!='\'') {
tn[j]=strA[i];
j++;
}
i++;
}
tn[j]=0;
int l=strBl+strlen(tn)-2;
char *b=(char *)l_alloc(l+1);
snprintf(b,l+1,strB,tn);
b[l]=0;
free(tn);
l_free(query_length,query);
query=b;
query_length=l+1;
goto __run_query;
}
if (query_no_space_length==strlen("SHOW MYSQL USERS") && !strncasecmp("SHOW MYSQL USERS",query_no_space, query_no_space_length)) {
l_free(query_length,query);
query=l_strdup("SELECT * FROM mysql_users ORDER BY username, active DESC, username ASC");
@ -1187,6 +1472,13 @@ void admin_session_handler(MySQL_Session *sess, ProxySQL_Admin *pa, PtrSize_t *p
tbh=dbh;
dbh=strdup("main");
}
if (strlen(tbh)>=3 && tbh[0]=='`' && tbh[strlen(tbh)-1]=='`') { // tablename is quoted
char *tbh_tmp=(char *)malloc(strlen(tbh)-1);
strncpy(tbh_tmp,tbh+1,strlen(tbh)-2);
tbh_tmp[strlen(tbh)-2]=0;
free(tbh);
tbh=tbh_tmp;
}
int l=strBl+strlen(tbh)*3+strlen(dbh)-8;
char *buff=(char *)l_alloc(l+1);
snprintf(buff,l+1,strB,tbh,tbh,dbh,tbh);

Loading…
Cancel
Save