diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index 889940e00..184ed4f9d 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -412,7 +412,7 @@ static skygw_query_type_t resolve_query_type( ss_info_dassert(thd != NULL, ("thd is NULL\n")); - force_data_modify_op_replication = FALSE; + force_data_modify_op_replication = FALSE; lex = thd->lex; /** SELECT ..INTO variable|OUTFILE|DUMPFILE */ @@ -816,3 +816,45 @@ char* skygw_query_classifier_get_stmtname( return ((THD *)(mysql->thd))->lex->prepared_stmt_name.str; } + +char* skygw_get_canonical( + MYSQL* mysql, + char* querystr) +{ + THD* thd; + LEX* lex; + bool found = false; + char* newstr; + + thd = (THD *)mysql->thd; + lex = thd->lex; + Item* item; + + for (item=thd->free_list; item != NULL; item=item->next) + { + Item::Type itype; + + itype = item->type(); + + if (itype == Item::STRING_ITEM || itype == Item::INT_ITEM) + { + if (!found) + { + newstr = replace_str(querystr, + item->name, + "?"); + found = true; + } + else + { + char* prevstr = newstr; + + newstr = replace_str(prevstr, + item->name, + "?"); + free(prevstr); + } + } + } /*< for */ + return newstr; +} \ No newline at end of file diff --git a/query_classifier/query_classifier.h b/query_classifier/query_classifier.h index 31f9cf44e..fa7cefc78 100644 --- a/query_classifier/query_classifier.h +++ b/query_classifier/query_classifier.h @@ -60,6 +60,8 @@ skygw_query_type_t skygw_query_classifier_get_type( /** Free THD context and close MYSQL */ void skygw_query_classifier_free(MYSQL* mysql); char* skygw_query_classifier_get_stmtname(MYSQL* mysql); +char* skygw_get_canonical(MYSQL* mysql, char* querystr); + EXTERN_C_BLOCK_END diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 1ed569962..c7175c76f 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -23,7 +23,7 @@ #include #include #include - +#include #include "skygw_debug.h" #include "skygw_types.h" #include "skygw_utils.h" @@ -1863,3 +1863,69 @@ void skygw_file_done( free(file); } } + +/** + * Replaces in the string str all the occurrences of the source string old with + * the destination string new. The lengths of the strings old and new may differ. + * The string new may be of any length, but the string "old" must be of non-zero + * length - the penalty for providing an empty string for the "old" parameter is + * an infinite loop. In addition, none of the three parameters may be NULL. + * + * @param str String to be modified + * @param old Substring to be replaced + * @param new Replacement + * @return String with replacements in new memory area or NULL if memory + * allocation failed. + * Dependencies: For this function to compile, you will need to also #include + * the following files: , and . + * + * Thanks, to Laird Shaw who implemented most of this function. + */ +char* replace_str ( + const char *str, + const char *old, + const char *replacement) +{ + char* ret; + char* r; + const char* p; + const char* q; + size_t oldlen; + size_t count; + size_t retlen; + size_t newlen; + + oldlen = strlen(old); + newlen = strlen(replacement); + + if (oldlen != newlen) + { + for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) + { + count++; + } + /* this is undefined if p - str > PTRDIFF_MAX */ + retlen = p - str + strlen(p) + count * (newlen - oldlen); + } + else + { + retlen = strlen(str); + } + if ((ret = (char *)malloc(retlen + 1)) == NULL) + { + return NULL; + } + + for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) + { + /* this is undefined if q - p > PTRDIFF_MAX */ + ptrdiff_t l = q - p; + memcpy(r, p, l); + r += l; + memcpy(r, replacement, newlen); + r += newlen; + } + strcpy(r, p); + + return ret; +} \ No newline at end of file diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index 992f169d2..854c82541 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -191,5 +191,7 @@ int skygw_rwlock_unlock(skygw_rwlock_t* rwlock); int skygw_rwlock_init(skygw_rwlock_t** rwlock); int atomic_add(int *variable, int value); +char* replace_str(const char* str, const char* old, const char* replacement); + #endif /* SKYGW_UTILS_H */