From c6b579619a5a2de50c43ed7675e6ecc16dfca73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 4 Jul 2017 23:04:27 +0300 Subject: [PATCH] MXS-1310: Route implicit table queries to the current shard When a query that implicitly uses the current database is detected, it will be routed to the shard which has the current database. --- .../schemarouter/schemaroutersession.cc | 47 ++++++++++++++----- .../modules/routing/schemarouter/shard_map.cc | 4 ++ 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/server/modules/routing/schemarouter/schemaroutersession.cc b/server/modules/routing/schemarouter/schemaroutersession.cc index 00a4c5b69..cf904b181 100644 --- a/server/modules/routing/schemarouter/schemaroutersession.cc +++ b/server/modules/routing/schemarouter/schemaroutersession.cc @@ -663,7 +663,8 @@ bool extract_database(GWBUF* buf, char* str) plen = gw_mysql_get_byte3(packet) - 1; /** Copy database name from MySQL packet to session */ - if (qc_get_operation(buf) == QUERY_OP_CHANGE_DB) + if (mxs_mysql_get_command(buf) == MYSQL_COM_QUERY && + qc_get_operation(buf) == QUERY_OP_CHANGE_DB) { const char *delim = "` \n\t;"; @@ -1405,22 +1406,43 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype) { SERVER *rval = NULL; bool has_dbs = false; /**If the query targets any database other than the current one*/ - const QC_FIELD_INFO* info; - size_t n_info; - qc_get_field_info(buffer, &info, &n_info); - - for (size_t i = 0; i < n_info; i++) + if (mxs_mysql_get_command(buffer) == MYSQL_COM_QUERY) { - if (info[i].database) + bool uses_current_database = false; + int n_tables = 0; + char** tables = qc_get_table_names(buffer, &n_tables, true); + + for (int i = 0; i < n_tables; i++) { - if (strcmp(info[i].database, "information_schema") == 0 && rval == NULL) + if (strchr(tables[i], '.') == NULL) + { + uses_current_database = true; + } + + MXS_FREE(tables[i]); + } + + MXS_FREE(tables); + + if (uses_current_database) + { + MXS_INFO("Query uses current database"); + return m_shard.get_location(m_current_db); + } + + int n_databases = 0; + char** databases = qc_get_database_names(buffer, &n_databases); + + for (int i = 0; i < n_databases; i++) + { + if (strcasecmp(databases[i], "information_schema") == 0 && rval == NULL) { has_dbs = false; } else { - SERVER* target = m_shard.get_location(info[i].database); + SERVER* target = m_shard.get_location(databases[i]); if (target) { @@ -1435,15 +1457,18 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype) rval = target; has_dbs = true; MXS_INFO("Query targets database '%s' on server '%s'", - info[i].database, rval->unique_name); + databases[i], rval->unique_name); } } } + + MXS_FREE(databases[i]); } + + MXS_FREE(databases); } /* Check if the query is a show tables query with a specific database */ - if (qc_query_is_type(qtype, QUERY_TYPE_SHOW_TABLES)) { char *query = modutil_get_SQL(buffer); diff --git a/server/modules/routing/schemarouter/shard_map.cc b/server/modules/routing/schemarouter/shard_map.cc index 6a4ebcc11..f26acd6b8 100644 --- a/server/modules/routing/schemarouter/shard_map.cc +++ b/server/modules/routing/schemarouter/shard_map.cc @@ -13,6 +13,8 @@ #include "shard_map.hh" +#include + #include Shard::Shard(): @@ -26,12 +28,14 @@ Shard::~Shard() bool Shard::add_location(std::string db, SERVER* target) { + std::transform(db.begin(), db.end(), db.begin(), ::tolower); return m_map.insert(std::make_pair(db, target)).second; } SERVER* Shard::get_location(std::string db) { SERVER* rval = NULL; + std::transform(db.begin(), db.end(), db.begin(), ::tolower); ServerMap::iterator iter = m_map.find(db); if (iter != m_map.end())