From cae71e0eb3d0dc4aea1562442412235b1a2a875c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sun, 27 Sep 2015 09:19:39 +0000 Subject: [PATCH] Implemented new column in myql_query_rules : match_digest (#390) --- include/query_processor.h | 6 ++- lib/ProxySQL_Admin.cpp | 65 +++++++++++++++++++++--------- lib/Query_Processor.cpp | 84 +++++++++++++++++++++++++++------------ 3 files changed, 109 insertions(+), 46 deletions(-) diff --git a/include/query_processor.h b/include/query_processor.h index ee2cc2550..926be3be9 100644 --- a/include/query_processor.h +++ b/include/query_processor.h @@ -61,6 +61,7 @@ struct _Query_Processor_rule_t { char *username; char *schemaname; int flagIN; + char *match_digest; char *match_pattern; bool negate_match_pattern; int flagOUT; @@ -71,7 +72,8 @@ struct _Query_Processor_rule_t { int timeout; int delay; bool apply; - void *regex_engine; + void *regex_engine1; + void *regex_engine2; int hits; struct _Query_Processor_rule_t *parent; // pointer to parent, to speed up parent update }; @@ -195,7 +197,7 @@ class Query_Processor { void wrunlock(); // explicit write unlock bool insert(QP_rule_t *qr, bool lock=true); // insert a new rule. Uses a generic void pointer to a structure that may vary depending from the Query Processor // virtual bool insert_locked(QP_rule_t *qr) {return false;}; // call this instead of insert() in case lock was already acquired via wrlock() - QP_rule_t * new_query_rule(int rule_id, bool active, char *username, char *schemaname, int flagIN, char *match_pattern, bool negate_match_pattern, int flagOUT, char *replace_pattern, int destination_hostgroup, int cache_ttl, int reconnect, int timeout, int delay, bool apply); // to use a generic query rule struct, this is generated by this function and returned as generic void pointer + QP_rule_t * new_query_rule(int rule_id, bool active, char *username, char *schemaname, int flagIN, char *match_digest, char *match_pattern, bool negate_match_pattern, int flagOUT, char *replace_pattern, int destination_hostgroup, int cache_ttl, int reconnect, int timeout, int delay, bool apply); // to use a generic query rule struct, this is generated by this function and returned as generic void pointer void delete_query_rule(QP_rule_t *qr); // destructor //virtual bool remove(int rule_id, bool lock=true) {return false;}; // FIXME: not implemented yet, should be implemented at all ? // virtual bool remove_locked(int rule_id) {return false;}; // call this instead of remove() in case lock was already acquired via wrlock() diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index 72353d8f4..6f7057641 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -54,7 +54,7 @@ pthread_mutex_t admin_mutex = PTHREAD_MUTEX_INITIALIZER; #define ADMIN_SQLITE_TABLE_MYSQL_SERVERS "CREATE TABLE mysql_servers (hostgroup_id INT NOT NULL DEFAULT 0 , hostname VARCHAR NOT NULL , port INT NOT NULL DEFAULT 3306 , status VARCHAR CHECK (UPPER(status) IN ('ONLINE','SHUNNED','OFFLINE_SOFT', 'OFFLINE_HARD')) NOT NULL DEFAULT 'ONLINE' , weight INT CHECK (weight >= 0) NOT NULL DEFAULT 1 , compression INT CHECK (compression >=0 AND compression <= 102400) NOT NULL DEFAULT 0 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000 , max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0 , PRIMARY KEY (hostgroup_id, hostname, port) )" #define ADMIN_SQLITE_TABLE_MYSQL_USERS "CREATE TABLE mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 0 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" -#define ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES "CREATE TABLE mysql_query_rules (rule_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 0 , username VARCHAR , schemaname VARCHAR , flagIN INT NOT NULL DEFAULT 0 , match_pattern VARCHAR , negate_match_pattern INT CHECK (negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0 , flagOUT INT , replace_pattern VARCHAR , destination_hostgroup INT DEFAULT NULL , cache_ttl INT CHECK(cache_ttl > 0) , reconnect INT CHECK (reconnect IN (0,1)) DEFAULT NULL , timeout INT UNSIGNED , delay INT UNSIGNED , apply INT CHECK(apply IN (0,1)) NOT NULL DEFAULT 0)" +#define ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES "CREATE TABLE mysql_query_rules (rule_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 0 , username VARCHAR , schemaname VARCHAR , flagIN INT NOT NULL DEFAULT 0 , match_digest VARCHAR , match_pattern VARCHAR , negate_match_pattern INT CHECK (negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0 , flagOUT INT , replace_pattern VARCHAR , destination_hostgroup INT DEFAULT NULL , cache_ttl INT CHECK(cache_ttl > 0) , reconnect INT CHECK (reconnect IN (0,1)) DEFAULT NULL , timeout INT UNSIGNED , delay INT UNSIGNED , apply INT CHECK(apply IN (0,1)) NOT NULL DEFAULT 0)" #define ADMIN_SQLITE_TABLE_GLOBAL_VARIABLES "CREATE TABLE global_variables (variable_name VARCHAR NOT NULL PRIMARY KEY , variable_value VARCHAR NOT NULL)" #define ADMIN_SQLITE_TABLE_MYSQL_COLLATIONS "CREATE TABLE mysql_collations (Id INTEGER NOT NULL PRIMARY KEY , Collation VARCHAR NOT NULL , Charset VARCHAR NOT NULL , `Default` VARCHAR NOT NULL)" @@ -2330,12 +2330,12 @@ void ProxySQL_Admin::save_mysql_query_rules_from_runtime() { if (resultset==NULL) return; admindb->execute("DELETE FROM mysql_query_rules"); //char *a=(char *)"INSERT INTO mysql_query_rules VALUES (\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")"; - char *a=(char *)"INSERT INTO mysql_query_rules (rule_id, active, username, schemaname, flagIN, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply) VALUES (%s, %s, %s, %s, %s, \"%s\", %s, %s, %s, %s, %s, %s, %s, %s, %s)"; + char *a=(char *)"INSERT INTO mysql_query_rules (rule_id, active, username, schemaname, flagIN, match_digest, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"; for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; int arg_len=0; - char *buffs[15]; - for (int i=0; i<15; i++) { + char *buffs[16]; + for (int i=0; i<16; i++) { if (r->fields[i]) { int l=strlen(r->fields[i])+4; arg_len+=l; @@ -2356,20 +2356,21 @@ void ProxySQL_Admin::save_mysql_query_rules_from_runtime() { buffs[2], buffs[3], ( strcmp(r->fields[4],"-1")==0 ? "NULL" : r->fields[4] ), // flagIN - buffs[5], // match_pattern - r->fields[6], // negate - ( strcmp(r->fields[7],"-1")==0 ? "NULL" : r->fields[7] ), // flagOUT - buffs[8], // replace_pattern - ( strcmp(r->fields[9],"-1")==0 ? "NULL" : r->fields[9] ), // destination_hostgroup - ( strcmp(r->fields[10],"-1")==0 ? "NULL" : r->fields[10] ), // cache_ttl - ( strcmp(r->fields[11],"-1")==0 ? "NULL" : r->fields[11] ), // reconnect - ( strcmp(r->fields[12],"-1")==0 ? "NULL" : r->fields[12] ), // timeout - ( strcmp(r->fields[13],"-1")==0 ? "NULL" : r->fields[13] ), // delay - ( strcmp(r->fields[14],"-1")==0 ? "NULL" : r->fields[14] ) // apply + buffs[5], // match_digest + buffs[6], // match_pattern + r->fields[7], // negate + ( strcmp(r->fields[8],"-1")==0 ? "NULL" : r->fields[8] ), // flagOUT + buffs[9], // replace_pattern + ( strcmp(r->fields[10],"-1")==0 ? "NULL" : r->fields[10] ), // destination_hostgroup + ( strcmp(r->fields[11],"-1")==0 ? "NULL" : r->fields[11] ), // cache_ttl + ( strcmp(r->fields[12],"-1")==0 ? "NULL" : r->fields[12] ), // reconnect + ( strcmp(r->fields[13],"-1")==0 ? "NULL" : r->fields[13] ), // timeout + ( strcmp(r->fields[14],"-1")==0 ? "NULL" : r->fields[14] ), // delay + ( strcmp(r->fields[15],"-1")==0 ? "NULL" : r->fields[15] ) // apply ); //fprintf(stderr,"%s\n",query); admindb->execute(query); - for (int i=0; i<15; i++) { + for (int i=0; i<16; i++) { free(buffs[i]); } free(query); @@ -2810,7 +2811,7 @@ char * ProxySQL_Admin::load_mysql_query_rules_to_runtime() { int affected_rows=0; if (GloQPro==NULL) return (char *)"Global Query Processor not started: command impossible to run"; SQLite3_result *resultset=NULL; - char *query=(char *)"SELECT rule_id, username, schemaname, flagIN, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply FROM main.mysql_query_rules WHERE active=1"; + char *query=(char *)"SELECT rule_id, username, schemaname, flagIN, match_digest, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply FROM main.mysql_query_rules WHERE active=1"; admindb->execute_statement(query, &error , &cols , &affected_rows , &resultset); if (error) { proxy_error("Error on %s : %s\n", query, error); @@ -2819,8 +2820,25 @@ char * ProxySQL_Admin::load_mysql_query_rules_to_runtime() { GloQPro->reset_all(false); QP_rule_t * nqpr; for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { - SQLite3_row *r=*it; - nqpr=GloQPro->new_query_rule(atoi(r->fields[0]), true, r->fields[1], r->fields[2], atoi(r->fields[3]), r->fields[4], (atoi(r->fields[5])==1 ? true : false), (r->fields[6]==NULL ? -1 : atol(r->fields[6])), r->fields[7], (r->fields[8]==NULL ? -1 : atoi(r->fields[8])), (r->fields[9]==NULL ? -1 : atol(r->fields[9])), (r->fields[10]==NULL ? -1 : atol(r->fields[10])), (r->fields[11]==NULL ? -1 : atol(r->fields[11])), (r->fields[12]==NULL ? -1 : atol(r->fields[12])), (atoi(r->fields[13])==1 ? true : false)); + SQLite3_row *r=*it; + nqpr=GloQPro->new_query_rule( + atoi(r->fields[0]), + true, + r->fields[1], + r->fields[2], + atoi(r->fields[3]), + r->fields[4], + r->fields[5], + (atoi(r->fields[6])==1 ? true : false), + (r->fields[7]==NULL ? -1 : atol(r->fields[7])), + r->fields[8], + (r->fields[9]==NULL ? -1 : atoi(r->fields[9])), + (r->fields[10]==NULL ? -1 : atol(r->fields[10])), + (r->fields[11]==NULL ? -1 : atol(r->fields[11])), + (r->fields[12]==NULL ? -1 : atol(r->fields[12])), + (r->fields[13]==NULL ? -1 : atol(r->fields[13])), + (atoi(r->fields[14])==1 ? true : false) + ); GloQPro->insert(nqpr, false); } GloQPro->sort(false); @@ -2923,7 +2941,7 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { int i; int rows=0; admindb->execute("PRAGMA foreign_keys = OFF"); - char *q=(char *)"INSERT OR REPLACE INTO mysql_query_rules (rule_id, active, username, schemaname, flagIN, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply) VALUES (%d, %d, %s, %s, %s, %s, %d, %s, %s, %s, %s, %s, %s, %s, %d)"; + char *q=(char *)"INSERT OR REPLACE INTO mysql_query_rules (rule_id, active, username, schemaname, flagIN, march_digest, match_pattern, negate_match_pattern, flagOUT, replace_pattern, destination_hostgroup, cache_ttl, reconnect, timeout, delay, apply) VALUES (%d, %d, %s, %s, %s, %s, %s, %d, %s, %s, %s, %s, %s, %s, %s, %d)"; for (i=0; i< count; i++) { const Setting &rule = mysql_query_rules[i]; int rule_id; @@ -2933,6 +2951,8 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { bool schemaname_exists=false; std::string schemaname; int flagIN=0; + bool match_digest_exists=false; + std::string match_digest; bool match_pattern_exists=false; std::string match_pattern; int negate_match_pattern=0; @@ -2950,6 +2970,7 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { if (rule.lookupValue("username", username)) username_exists=true; if (rule.lookupValue("schemaname", schemaname)) schemaname_exists=true; rule.lookupValue("flagIN", flagIN); + if (rule.lookupValue("match_digest", match_digest)) match_digest_exists=true; if (rule.lookupValue("match_pattern", match_pattern)) match_pattern_exists=true; rule.lookupValue("negate_match_pattern", negate_match_pattern); rule.lookupValue("flagOUT", flagOUT); @@ -2968,6 +2989,7 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { ( username_exists ? strlen(username.c_str()) : 0 ) + 4 + ( schemaname_exists ? strlen(schemaname.c_str()) : 0 ) + 4 + strlen(std::to_string(flagIN).c_str()) + 4 + + ( match_digest_exists ? strlen(match_digest.c_str()) : 0 ) + 4 + ( match_pattern_exists ? strlen(match_pattern.c_str()) : 0 ) + 4 + strlen(std::to_string(negate_match_pattern).c_str()) + 4 + strlen(std::to_string(flagOUT).c_str()) + 4 + @@ -2988,6 +3010,10 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { schemaname="\"" + schemaname + "\""; else schemaname = "NULL"; + if (match_digest_exists) + match_digest="\"" + match_digest + "\""; + else + match_digest = "NULL"; if (match_pattern_exists) match_pattern="\"" + match_pattern + "\""; else @@ -3001,6 +3027,7 @@ int ProxySQL_Admin::Read_MySQL_Query_Rules_from_configfile() { username.c_str(), schemaname.c_str(), ( flagIN >= 0 ? std::to_string(flagIN).c_str() : "NULL") , + match_digest.c_str(), match_pattern.c_str(), ( negate_match_pattern == 0 ? 0 : 1) , ( flagOUT >= 0 ? std::to_string(flagOUT).c_str() : "NULL") , diff --git a/lib/Query_Processor.cpp b/lib/Query_Processor.cpp index eb098008e..8a4336cba 100644 --- a/lib/Query_Processor.cpp +++ b/lib/Query_Processor.cpp @@ -37,28 +37,30 @@ class QP_rule_text_hitsonly { class QP_rule_text { public: char **pta; + const int num_fields=17; QP_rule_text(QP_rule_t *QPr) { pta=NULL; - pta=(char **)malloc(sizeof(char *)*16); + pta=(char **)malloc(sizeof(char *)*num_fields); itostr(pta[0], (long long)QPr->rule_id); itostr(pta[1], (long long)QPr->active); pta[2]=strdup_null(QPr->username); pta[3]=strdup_null(QPr->schemaname); itostr(pta[4], (long long)QPr->flagIN); - pta[5]=strdup_null(QPr->match_pattern); - itostr(pta[6], (long long)QPr->negate_match_pattern); - itostr(pta[7], (long long)QPr->flagOUT); - pta[8]=strdup_null(QPr->replace_pattern); - itostr(pta[9], (long long)QPr->destination_hostgroup); - itostr(pta[10], (long long)QPr->cache_ttl); - itostr(pta[11], (long long)QPr->reconnect); - itostr(pta[12], (long long)QPr->timeout); - itostr(pta[13], (long long)QPr->delay); - itostr(pta[14], (long long)QPr->apply); - itostr(pta[15], (long long)QPr->hits); + pta[5]=strdup_null(QPr->match_digest); + pta[6]=strdup_null(QPr->match_pattern); + itostr(pta[7], (long long)QPr->negate_match_pattern); + itostr(pta[8], (long long)QPr->flagOUT); + pta[9]=strdup_null(QPr->replace_pattern); + itostr(pta[10], (long long)QPr->destination_hostgroup); + itostr(pta[11], (long long)QPr->cache_ttl); + itostr(pta[12], (long long)QPr->reconnect); + itostr(pta[13], (long long)QPr->timeout); + itostr(pta[14], (long long)QPr->delay); + itostr(pta[15], (long long)QPr->apply); + itostr(pta[16], (long long)QPr->hits); } ~QP_rule_text() { - for(int i=0; i<16; i++) { + for(int i=0; irule_id < b->rule_id); } -static re2_t * compile_query_rule(QP_rule_t *qr) { +static re2_t * compile_query_rule(QP_rule_t *qr, int i) { re2_t *r=(re2_t *)malloc(sizeof(re2_t)); r->opt=new re2::RE2::Options(RE2::Quiet); r->opt->set_case_sensitive(false); - r->re=new RE2(qr->match_pattern, *r->opt); + if (i==1) { + r->re=new RE2(qr->match_digest, *r->opt); + } else if (i==2) { + r->re=new RE2(qr->match_pattern, *r->opt); + } return r; }; @@ -216,11 +222,17 @@ static void __delete_query_rule(QP_rule_t *qr) { free(qr->match_pattern); if (qr->replace_pattern) free(qr->replace_pattern); - if (qr->regex_engine) { - re2_t *r=(re2_t *)qr->regex_engine; + if (qr->regex_engine1) { + re2_t *r=(re2_t *)qr->regex_engine1; delete r->opt; delete r->re; - free(qr->regex_engine); + free(qr->regex_engine1); + } + if (qr->regex_engine2) { + re2_t *r=(re2_t *)qr->regex_engine2; + delete r->opt; + delete r->re; + free(qr->regex_engine2); } free(qr); }; @@ -404,13 +416,14 @@ void Query_Processor::wrunlock() { -QP_rule_t * Query_Processor::new_query_rule(int rule_id, bool active, char *username, char *schemaname, int flagIN, char *match_pattern, bool negate_match_pattern, int flagOUT, char *replace_pattern, int destination_hostgroup, int cache_ttl, int reconnect, int timeout, int delay, bool apply) { +QP_rule_t * Query_Processor::new_query_rule(int rule_id, bool active, char *username, char *schemaname, int flagIN, char *match_digest, char *match_pattern, bool negate_match_pattern, int flagOUT, char *replace_pattern, int destination_hostgroup, int cache_ttl, int reconnect, int timeout, int delay, bool apply) { QP_rule_t * newQR=(QP_rule_t *)malloc(sizeof(QP_rule_t)); newQR->rule_id=rule_id; newQR->active=active; newQR->username=(username ? strdup(username) : NULL); newQR->schemaname=(schemaname ? strdup(schemaname) : NULL); newQR->flagIN=flagIN; + newQR->match_digest=(match_digest ? strdup(match_digest) : NULL); newQR->match_pattern=(match_pattern ? strdup(match_pattern) : NULL); newQR->negate_match_pattern=negate_match_pattern; newQR->flagOUT=flagOUT; @@ -421,9 +434,10 @@ QP_rule_t * Query_Processor::new_query_rule(int rule_id, bool active, char *user newQR->timeout=timeout; newQR->delay=delay; newQR->apply=apply; - newQR->regex_engine=NULL; + newQR->regex_engine1=NULL; + newQR->regex_engine2=NULL; newQR->hits=0; - proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "Creating new rule in %p : rule_id:%d, active:%d, username=%s, schemaname=%s, flagIN:%d, %smatch_pattern=\"%s\", flagOUT:%d replace_pattern=\"%s\", destination_hostgroup:%d, apply:%d\n", newQR, newQR->rule_id, newQR->active, newQR->username, newQR->schemaname, newQR->flagIN, (newQR->negate_match_pattern ? "(!)" : "") , newQR->match_pattern, newQR->flagOUT, newQR->replace_pattern, newQR->destination_hostgroup, newQR->apply); + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "Creating new rule in %p : rule_id:%d, active:%d, username=%s, schemaname=%s, flagIN:%d, %smatch_digest=\"%s\", %smatch_pattern=\"%s\", flagOUT:%d replace_pattern=\"%s\", destination_hostgroup:%d, apply:%d\n", newQR, newQR->rule_id, newQR->active, newQR->username, newQR->schemaname, newQR->flagIN, (newQR->negate_match_pattern ? "(!)" : "") , newQR->match_digest, (newQR->negate_match_pattern ? "(!)" : "") , newQR->match_pattern, newQR->flagOUT, newQR->replace_pattern, newQR->destination_hostgroup, newQR->apply); return newQR; }; @@ -511,7 +525,7 @@ SQLite3_result * Query_Processor::get_stats_query_rules() { SQLite3_result * Query_Processor::get_current_query_rules() { proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Dumping current query rules, using Global version %d\n", version); - SQLite3_result *result=new SQLite3_result(16); + SQLite3_result *result=new SQLite3_result(17); spin_rdlock(&rwlock); QP_rule_t *qr1; result->add_column_definition(SQLITE_TEXT,"rule_id"); @@ -519,6 +533,7 @@ SQLite3_result * Query_Processor::get_current_query_rules() { result->add_column_definition(SQLITE_TEXT,"username"); result->add_column_definition(SQLITE_TEXT,"schemaname"); result->add_column_definition(SQLITE_TEXT,"flagIN"); + result->add_column_definition(SQLITE_TEXT,"match_digest"); result->add_column_definition(SQLITE_TEXT,"match_pattern"); result->add_column_definition(SQLITE_TEXT,"negate_match_pattern"); result->add_column_definition(SQLITE_TEXT,"flagOUT"); @@ -615,11 +630,15 @@ Query_Processor_Output * Query_Processor::process_mysql_query(MySQL_Session *ses qr1=*it; if (qr1->active) { proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Copying Query Rule id: %d\n", qr1->rule_id); - qr2=new_query_rule(qr1->rule_id, qr1->active, qr1->username, qr1->schemaname, qr1->flagIN, qr1->match_pattern, qr1->negate_match_pattern, qr1->flagOUT, qr1->replace_pattern, qr1->destination_hostgroup, qr1->cache_ttl, qr1->reconnect, qr1->timeout, qr1->delay, qr1->apply); + qr2=new_query_rule(qr1->rule_id, qr1->active, qr1->username, qr1->schemaname, qr1->flagIN, qr1->match_digest, qr1->match_pattern, qr1->negate_match_pattern, qr1->flagOUT, qr1->replace_pattern, qr1->destination_hostgroup, qr1->cache_ttl, qr1->reconnect, qr1->timeout, qr1->delay, qr1->apply); qr2->parent=qr1; // pointer to parent to speed up parent update (hits) + if (qr2->match_digest) { + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Compiling regex for rule_id: %d, match_digest: \n", qr2->rule_id, qr2->match_digest); + qr2->regex_engine1=(void *)compile_query_rule(qr2,1); + } if (qr2->match_pattern) { proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 4, "Compiling regex for rule_id: %d, match_pattern: \n", qr2->rule_id, qr2->match_pattern); - qr2->regex_engine=(void *)compile_query_rule(qr2); + qr2->regex_engine2=(void *)compile_query_rule(qr2,2); } _thr_SQP_rules->push_back(qr2); } @@ -648,7 +667,21 @@ Query_Processor_Output * Query_Processor::process_mysql_query(MySQL_Session *ses } } - re2p=(re2_t *)qr->regex_engine; + // match on digest + if (qp && qp->digest_text ) { // we call this only if we have a query digest + re2p=(re2_t *)qr->regex_engine1; + if (qr->match_digest) { + bool rc; + // we always match on original query + rc=RE2::PartialMatch(qp->digest_text,*re2p->re); + if ((rc==true && qr->negate_match_pattern==true) || ( rc==false && qr->negate_match_pattern==false )) { + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching pattern\n", qr->rule_id); + continue; + } + } + } + // match on query + re2p=(re2_t *)qr->regex_engine2; if (qr->match_pattern) { bool rc; if (ret && ret->new_query) { @@ -664,6 +697,7 @@ Query_Processor_Output * Query_Processor::process_mysql_query(MySQL_Session *ses continue; } } + // if we arrived here, we have a match qr->hits++; // this is done without atomic function because it updates only the local variables