diff --git a/include/maxscale/query_classifier.h b/include/maxscale/query_classifier.h index 9198c945f..d2bafe10f 100644 --- a/include/maxscale/query_classifier.h +++ b/include/maxscale/query_classifier.h @@ -185,12 +185,13 @@ typedef struct query_classifier /** * Called once to setup the query classifier * - * @param args The value of `query_classifier_args` in the configuration file. + * @param sql_mode The default sql mode. + * @param args The value of `query_classifier_args` in the configuration file. * * @return QC_RESULT_OK, if the query classifier could be setup, otherwise * some specific error code. */ - int32_t (*qc_setup)(const char* args); + int32_t (*qc_setup)(qc_sql_mode_t sql_mode, const char* args); /** * Called once at process startup, after @c qc_setup has successfully @@ -417,6 +418,7 @@ typedef struct query_classifier * * @param plugin_name The name of the plugin from which the query classifier * should be loaded. + * @param sql_mode The default sql mode. * @param plugin_args The arguments to be provided to the query classifier. * * @return True if the query classifier could be loaded and initialized, @@ -424,7 +426,7 @@ typedef struct query_classifier * * @see qc_end qc_thread_init */ -bool qc_setup(const char* plugin_name, const char* plugin_args); +bool qc_setup(const char* plugin_name, qc_sql_mode_t sql_mode, const char* plugin_args); /** * Intializes the query classifier. diff --git a/query_classifier/qc_dummy/qc_dummy.cc b/query_classifier/qc_dummy/qc_dummy.cc index 72e9573c3..739144822 100644 --- a/query_classifier/qc_dummy/qc_dummy.cc +++ b/query_classifier/qc_dummy/qc_dummy.cc @@ -86,7 +86,7 @@ int32_t qc_dummy_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** ppInfo return QC_RESULT_OK; } -int32_t qc_dummy_setup(const char* args) +int32_t qc_dummy_setup(qc_sql_mode_t sql_mode, const char* args) { return QC_RESULT_OK; } diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index 4fa202e91..ef086c5e6 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -2969,47 +2969,19 @@ void configure_options(const char* datadir, const char* langdir) } -int32_t qc_mysql_setup(const char* zArgs) +int32_t qc_mysql_setup(qc_sql_mode_t sql_mode, const char* zArgs) { + this_unit.sql_mode = sql_mode; + + if (sql_mode == QC_SQL_MODE_ORACLE) + { + this_unit.function_name_mappings = function_name_mappings_oracle; + } + if (zArgs) { -#if MYSQL_VERSION_MINOR >= 3 - char args[strlen(zArgs) + 1]; - strcpy(args, zArgs); - - char *p1; - char *token = strtok_r(args, ",", &p1); - - while (token) - { - char *p2; - char* key = trim(strtok_r(token, "=", &p2)); - - if (strcmp(key, "sql_mode") == 0) - { - char* value = trim(p2); - - if (strcmp(value, "MODE_ORACLE") == 0) - { - this_unit.sql_mode = QC_SQL_MODE_ORACLE; - this_unit.function_name_mappings = function_name_mappings_oracle; - } - else - { - MXS_WARNING("Unknown value \"%s\" for key \"%s\"", value, key); - } - } - else - { - MXS_WARNING("Unknown argument \"%s\".", key); - } - - token = strtok_r(NULL, ",", &p1); - } -#else MXS_WARNING("'%s' provided as arguments, " "even though no arguments are supported.", zArgs); -#endif } return QC_RESULT_OK; diff --git a/query_classifier/qc_sqlite/qc_sqlite.c b/query_classifier/qc_sqlite/qc_sqlite.c index 034ab5d40..88f28385f 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.c +++ b/query_classifier/qc_sqlite/qc_sqlite.c @@ -3294,7 +3294,7 @@ void maxscaleUse(Parse* pParse, Token* pToken) /** * API */ -static int32_t qc_sqlite_setup(const char* args); +static int32_t qc_sqlite_setup(qc_sql_mode_t sql_mode, const char* args); static int32_t qc_sqlite_process_init(void); static void qc_sqlite_process_end(void); static int32_t qc_sqlite_thread_init(void); @@ -3329,16 +3329,14 @@ static bool get_key_and_value(char* arg, const char** pkey, const char** pvalue) static const char ARG_LOG_UNRECOGNIZED_STATEMENTS[] = "log_unrecognized_statements"; static const char ARG_PARSE_AS[] = "parse_as"; -static const char ARG_SQL_MODE[] = "sql_mode"; -static int32_t qc_sqlite_setup(const char* cargs) +static int32_t qc_sqlite_setup(qc_sql_mode_t sql_mode, const char* cargs) { QC_TRACE(); assert(!this_unit.setup); qc_log_level_t log_level = QC_LOG_NOTHING; - qc_sql_mode_t sql_mode = QC_SQL_MODE_DEFAULT; - qc_parse_as_t parse_as = QC_PARSE_AS_DEFAULT; + qc_parse_as_t parse_as = (sql_mode == QC_SQL_MODE_ORACLE) ? QC_PARSE_AS_103 : QC_PARSE_AS_DEFAULT; QC_NAME_MAPPING* function_name_mappings = function_name_mappings_default; if (cargs) @@ -3385,21 +3383,6 @@ static int32_t qc_sqlite_setup(const char* cargs) "Parsing as pre-10.3.", value, key); } } - else if (strcmp(key, ARG_SQL_MODE) == 0) - { - if (strcmp(value, "MODE_ORACLE") == 0) - { - sql_mode = QC_SQL_MODE_ORACLE; - MXS_NOTICE("Expecting Oracle SQL."); - - parse_as = QC_PARSE_AS_103; - MXS_NOTICE("Parsing as 10.3."); - } - else - { - MXS_WARNING("Unknown value \"%s\" for key \"%s\"", value, key); - } - } else { MXS_WARNING("'%s' is not a recognized argument.", key); diff --git a/query_classifier/test/canonical_tests/canonizer.c b/query_classifier/test/canonical_tests/canonizer.c index ad8e5fcba..d619a4d61 100644 --- a/query_classifier/test/canonical_tests/canonizer.c +++ b/query_classifier/test/canonical_tests/canonizer.c @@ -46,7 +46,7 @@ int main(int argc, char** argv) set_langdir(strdup(".")); set_process_datadir(strdup("/tmp")); - qc_setup("qc_sqlite", NULL); + qc_setup("qc_sqlite", QC_SQL_MODE_DEFAULT, NULL); qc_process_init(QC_INIT_BOTH); infile = fopen(argv[1], "rb"); diff --git a/query_classifier/test/classify.c b/query_classifier/test/classify.c index 533f42b65..7e433ed42 100644 --- a/query_classifier/test/classify.c +++ b/query_classifier/test/classify.c @@ -313,7 +313,7 @@ int main(int argc, char** argv) if (mxs_log_init(NULL, ".", MXS_LOG_TARGET_DEFAULT)) { - if (qc_setup(lib, NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup(lib, QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { rc = run(input_name, expected_name); qc_process_end(QC_INIT_BOTH); diff --git a/query_classifier/test/compare.cc b/query_classifier/test/compare.cc index 8918b9336..18977843f 100644 --- a/query_classifier/test/compare.cc +++ b/query_classifier/test/compare.cc @@ -53,14 +53,15 @@ namespace char USAGE[] = "usage: compare [-r count] [-d] [-1 classfier1] [-2 classifier2] " - "[-A args] [-B args] [-v [0..2]] [-s statement]|[file]]\n\n" + "[-A args] [-B args] [-C args] [-m [default|oracle]] [-v [0..2]] [-s statement]|[file]]\n\n" "-r redo the test the specified number of times; 0 means forever, default is 1\n" "-d don't stop after first failed query\n" - "-1 the first classifier, default qc_mysqlembedded\n" - "-2 the second classifier, default qc_sqlite\n" + "-1 the first classifier, default 'qc_mysqlembedded'\n" + "-2 the second classifier, default 'qc_sqlite'\n" "-A arguments for the first classifier\n" "-B arguments for the second classifier\n" "-C arguments for both classifiers\n" + "-m initial sql mode, 'default' or 'oracle', default is 'default'\n" "-s compare single statement\n" "-S strict, also require that the parse result is identical\n" "-R strict reporting, report if parse result is different\n" @@ -173,13 +174,13 @@ QUERY_CLASSIFIER* load_classifier(const char* name) return pClassifier; } -QUERY_CLASSIFIER* get_classifier(const char* zName, const char* zArgs) +QUERY_CLASSIFIER* get_classifier(const char* zName, qc_sql_mode_t sql_mode, const char* zArgs) { QUERY_CLASSIFIER* pClassifier = load_classifier(zName); if (pClassifier) { - if ((pClassifier->qc_setup(zArgs) != QC_RESULT_OK) || + if ((pClassifier->qc_setup(sql_mode, zArgs) != QC_RESULT_OK) || ((pClassifier->qc_process_init() != QC_RESULT_OK))) { cerr << "error: Could not setup or init classifier " << zName << "." << endl; @@ -200,16 +201,17 @@ void put_classifier(QUERY_CLASSIFIER* pClassifier) } } -bool get_classifiers(const char* zName1, const char* zArgs1, QUERY_CLASSIFIER** ppClassifier1, +bool get_classifiers(qc_sql_mode_t sql_mode, + const char* zName1, const char* zArgs1, QUERY_CLASSIFIER** ppClassifier1, const char* zName2, const char* zArgs2, QUERY_CLASSIFIER** ppClassifier2) { bool rc = false; - QUERY_CLASSIFIER* pClassifier1 = get_classifier(zName1, zArgs1); + QUERY_CLASSIFIER* pClassifier1 = get_classifier(zName1, sql_mode, zArgs1); if (pClassifier1) { - QUERY_CLASSIFIER* pClassifier2 = get_classifier(zName2, zArgs2); + QUERY_CLASSIFIER* pClassifier2 = get_classifier(zName2, sql_mode, zArgs2); if (pClassifier2) { @@ -1369,11 +1371,12 @@ int main(int argc, char* argv[]) string classifier2Args("log_unrecognized_statements=1"); #endif const char* zStatement = NULL; + qc_sql_mode_t sql_mode = QC_SQL_MODE_DEFAULT; size_t rounds = 1; int v = VERBOSITY_NORMAL; int c; - while ((c = getopt(argc, argv, "r:d1:2:v:A:B:C:s:SR")) != -1) + while ((c = getopt(argc, argv, "r:d1:2:v:A:B:C:m:s:SR")) != -1) { switch (c) { @@ -1414,6 +1417,22 @@ int main(int argc, char* argv[]) zStatement = optarg; break; + case 'm': + if (strcasecmp(optarg, "default") == 0) + { + sql_mode = QC_SQL_MODE_DEFAULT; + } + else if (strcasecmp(optarg, "oracle") == 0) + { + sql_mode = QC_SQL_MODE_ORACLE; + } + else + { + rc = EXIT_FAILURE; + break; + } + break; + case 'S': global.strict = true; break; @@ -1449,7 +1468,8 @@ int main(int argc, char* argv[]) QUERY_CLASSIFIER* pClassifier1; QUERY_CLASSIFIER* pClassifier2; - if (get_classifiers(zClassifier1, zClassifier1Args, &pClassifier1, + if (get_classifiers(sql_mode, + zClassifier1, zClassifier1Args, &pClassifier1, zClassifier2, zClassifier2Args, &pClassifier2)) { size_t round = 0; diff --git a/query_classifier/test/crash_qc_sqlite.c b/query_classifier/test/crash_qc_sqlite.c index d4ac4e321..7c5892761 100644 --- a/query_classifier/test/crash_qc_sqlite.c +++ b/query_classifier/test/crash_qc_sqlite.c @@ -41,7 +41,7 @@ int main() set_libdir(strdup("../qc_sqlite")); - if (qc_setup("qc_sqlite", NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup("qc_sqlite", QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { const char s[] = "SELECT @@global.max_allowed_packet"; diff --git a/server/core/gateway.cc b/server/core/gateway.cc index b34196590..8333a6d6f 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -1897,7 +1897,7 @@ int main(int argc, char **argv) cnf = config_get_global_options(); ss_dassert(cnf); - if (!qc_setup(cnf->qc_name, cnf->qc_args)) + if (!qc_setup(cnf->qc_name, QC_SQL_MODE_DEFAULT, cnf->qc_args)) { const char* logerr = "Failed to initialise query classifier library."; print_log_n_stderr(true, true, logerr, logerr, eno); diff --git a/server/core/query_classifier.cc b/server/core/query_classifier.cc index 578923cb0..f263eeb32 100644 --- a/server/core/query_classifier.cc +++ b/server/core/query_classifier.cc @@ -45,7 +45,7 @@ static QUERY_CLASSIFIER* classifier; static qc_trx_parse_using_t qc_trx_parse_using = QC_TRX_PARSE_USING_PARSER; -bool qc_setup(const char* plugin_name, const char* plugin_args) +bool qc_setup(const char* plugin_name, qc_sql_mode_t sql_mode, const char* plugin_args) { QC_TRACE(); ss_dassert(!classifier); @@ -61,7 +61,7 @@ bool qc_setup(const char* plugin_name, const char* plugin_args) if (classifier) { - rv = classifier->qc_setup(plugin_args); + rv = classifier->qc_setup(sql_mode, plugin_args); if (rv != QC_RESULT_OK) { diff --git a/server/core/test/testtrxcompare.cc b/server/core/test/testtrxcompare.cc index ae85f91c5..956455a1d 100644 --- a/server/core/test/testtrxcompare.cc +++ b/server/core/test/testtrxcompare.cc @@ -184,7 +184,7 @@ int main(int argc, char* argv[]) if (mxs_log_init(NULL, ".", MXS_LOG_TARGET_DEFAULT)) { // We have to setup something in order for the regexes to be compiled. - if (qc_setup("qc_sqlite", NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup("qc_sqlite", QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { Tester tester(verbosity); diff --git a/server/core/test/testtrxtracking.cc b/server/core/test/testtrxtracking.cc index 9f0e67b7b..009e0ceab 100644 --- a/server/core/test/testtrxtracking.cc +++ b/server/core/test/testtrxtracking.cc @@ -421,7 +421,7 @@ int main(int argc, char* argv[]) if (mxs_log_init(NULL, ".", MXS_LOG_TARGET_DEFAULT)) { // We have to setup something in order for the regexes to be compiled. - if (qc_setup("qc_sqlite", NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup("qc_sqlite", QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { rc = EXIT_SUCCESS; diff --git a/server/modules/filter/cache/test/testkeygeneration.cc b/server/modules/filter/cache/test/testkeygeneration.cc index a17518505..0cbd6198e 100644 --- a/server/modules/filter/cache/test/testkeygeneration.cc +++ b/server/modules/filter/cache/test/testkeygeneration.cc @@ -128,7 +128,7 @@ int main(int argc, char* argv[]) { if (mxs_log_init(NULL, ".", MXS_LOG_TARGET_DEFAULT)) { - if (qc_setup(NULL, NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup(NULL, QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { const char* zModule = argv[1]; diff --git a/server/modules/filter/cache/test/testrules.cc b/server/modules/filter/cache/test/testrules.cc index 932b51870..cb64f4892 100644 --- a/server/modules/filter/cache/test/testrules.cc +++ b/server/modules/filter/cache/test/testrules.cc @@ -240,7 +240,7 @@ int main() pConfig->n_threads = 1; set_libdir(MXS_STRDUP_A("../../../../../query_classifier/qc_sqlite/")); - if (qc_setup("qc_sqlite", "") && qc_process_init(QC_INIT_BOTH)) + if (qc_setup("qc_sqlite", QC_SQL_MODE_DEFAULT, "") && qc_process_init(QC_INIT_BOTH)) { set_libdir(MXS_STRDUP_A("../")); rc = test(); diff --git a/server/modules/filter/cache/test/teststorage.cc b/server/modules/filter/cache/test/teststorage.cc index 8f243b85d..697ba2470 100644 --- a/server/modules/filter/cache/test/teststorage.cc +++ b/server/modules/filter/cache/test/teststorage.cc @@ -50,7 +50,7 @@ int TestStorage::run(int argc, char** argv) { if (mxs_log_init(NULL, ".", MXS_LOG_TARGET_DEFAULT)) { - if (qc_setup(NULL, NULL) && qc_process_init(QC_INIT_BOTH)) + if (qc_setup(NULL, QC_SQL_MODE_DEFAULT, NULL) && qc_process_init(QC_INIT_BOTH)) { const char* zModule = NULL; size_t threads = m_threads;