diff --git a/query_classifier/query_classifier.cc b/query_classifier/query_classifier.cc index 12f23988d..ab41845b4 100644 --- a/query_classifier/query_classifier.cc +++ b/query_classifier/query_classifier.cc @@ -1410,6 +1410,17 @@ char* skygw_get_canonical( querystr = replace_literal(querystr, item->name, "?"); } } /*< for */ + + /** Check for SET ... options with no Item classes */ + if (thd->free_list == NULL) + { + char *replaced = replace_quoted(querystr); + if (replaced) + { + free(querystr); + querystr = replaced; + } + } retblock: return querystr; } diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 2ae917712..10811abae 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,2 +1,2 @@ add_library(utils skygw_utils.cc ../server/core/atomic.c) -target_link_libraries(utils stdc++) +target_link_libraries(utils stdc++ ${PCRE2_LIBRARIES}) diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 235deed41..95391039e 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -16,6 +16,9 @@ * Copyright MariaDB Corporation Ab 2013-2014 */ +#ifndef PCRE2_CODE_UNIT_WIDTH +#define PCRE2_CODE_UNIT_WIDTH 8 +#endif #include #include @@ -30,6 +33,7 @@ #include #include "skygw_utils.h" #include +#include #if defined(MLIST) @@ -2117,6 +2121,63 @@ retblock: return newstr; } +/** + * Replace everything inside single or double quotes with question marks. + * @param str String to modify + * @return Pointer to new modified string or NULL if memory allocation failed + */ +char* replace_quoted(const char* str) +{ + PCRE2_SIZE erroffset; + int errcore; + static const PCRE2_SPTR pattern = (PCRE2_SPTR) "(['\"])[^'\"]+(['\"])"; + static const PCRE2_SPTR replace = (PCRE2_SPTR) "$1?$2"; + pcre2_code* re; + pcre2_match_data* mdata; + int orig_len = strlen(str); + size_t len = strlen(str); + char* output; + + if ((output = (char*) malloc(len * sizeof(char)))) + { + /** TODO: Consider moving pattern compilation to some init function. */ + if ((re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, + 0, &errcore, &erroffset, NULL))) + { + if ((mdata = pcre2_match_data_create_from_pattern(re, NULL))) + { + while (pcre2_substitute(re, (PCRE2_SPTR) str, orig_len, 0, + PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL, + replace, PCRE2_ZERO_TERMINATED, + (PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY) + { + char* tmp = (char*) realloc(output, len *= 2); + if (tmp == NULL) + { + free(output); + output = NULL; + break; + } + output = tmp; + } + pcre2_match_data_free(mdata); + } + else + { + free(output); + output = NULL; + } + pcre2_code_free(re); + } + else + { + free(output); + output = NULL; + } + } + return output; +} + /** * Calculate the number of decimal numbers from a size_t value. * diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index 1aca695d9..29d1d867e 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -277,6 +277,7 @@ size_t get_decimal_len(size_t s); char* replace_literal(char* haystack, const char* needle, const char* replacement); +char* replace_quoted(const char* str); bool is_valid_posix_path(char* path); bool strip_escape_chars(char*); int simple_str_hash(char* key);