MXS-942: Don't return information_schema as the parsed database
When a DESCRIBE <table> or a SHOW COLUMNS IN <table> query is done, the actual query is performed on tables in the information_schema database. This might be what actually happens on the backend server but this information is not really useful when we need to know which database the query targets. By passing the actual table names instead of the underlying table names, the schemarouter is able to detect where these statements should be routed.
This commit is contained in:
@ -95,7 +95,7 @@ static parsing_info_t* parsing_info_init(void (*donefun)(void *));
|
||||
static void parsing_info_set_plain_str(void* ptr, char* str);
|
||||
/** Free THD context and close MYSQL */
|
||||
static void parsing_info_done(void* ptr);
|
||||
static void* skygw_get_affected_tables(void* lexptr);
|
||||
static TABLE_LIST* skygw_get_affected_tables(void* lexptr);
|
||||
static bool ensure_query_is_parsed(GWBUF* query);
|
||||
static bool parse_query(GWBUF* querybuf);
|
||||
static bool query_is_parsed(GWBUF* buf);
|
||||
@ -1063,7 +1063,7 @@ LEX* get_lex(GWBUF* querybuf)
|
||||
* @param thd Pointer to a valid THD
|
||||
* @return Pointer to the head of the TABLE_LIST chain or NULL in case of an error
|
||||
*/
|
||||
static void* skygw_get_affected_tables(void* lexptr)
|
||||
static TABLE_LIST* skygw_get_affected_tables(void* lexptr)
|
||||
{
|
||||
LEX* lex = (LEX*) lexptr;
|
||||
|
||||
@ -1073,7 +1073,23 @@ static void* skygw_get_affected_tables(void* lexptr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*) lex->current_select->table_list.first;
|
||||
TABLE_LIST *tbl = lex->current_select->table_list.first;
|
||||
|
||||
if (tbl && tbl->schema_select_lex && tbl->schema_select_lex->table_list.elements &&
|
||||
lex->sql_command != SQLCOM_SHOW_KEYS)
|
||||
{
|
||||
/**
|
||||
* Some statements e.g. EXPLAIN or SHOW COLUMNS give `information_schema`
|
||||
* as the underlying table and the table in the query is stored in
|
||||
* @c schema_select_lex.
|
||||
*
|
||||
* SHOW [KEYS | INDEX] does the reverse so we need to skip the
|
||||
* @c schema_select_lex when processing a SHOW [KEYS | INDEX] statement.
|
||||
*/
|
||||
tbl = tbl->schema_select_lex->table_list.first;
|
||||
}
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1111,7 +1127,7 @@ char** qc_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames)
|
||||
|
||||
while (lex->current_select)
|
||||
{
|
||||
tbl = (TABLE_LIST*) skygw_get_affected_tables(lex);
|
||||
tbl = skygw_get_affected_tables(lex);
|
||||
|
||||
while (tbl)
|
||||
{
|
||||
@ -1803,7 +1819,7 @@ char** qc_get_database_names(GWBUF* querybuf, int* size)
|
||||
|
||||
while (lex->current_select)
|
||||
{
|
||||
tbl = lex->current_select->table_list.first;
|
||||
tbl = skygw_get_affected_tables(lex);
|
||||
|
||||
while (tbl)
|
||||
{
|
||||
|
@ -1629,7 +1629,7 @@ void maxscaleExplain(Parse* pParse, SrcList* pName)
|
||||
|
||||
info->status = QC_QUERY_PARSED;
|
||||
info->types = QUERY_TYPE_READ;
|
||||
update_names(info, "information_schema", "COLUMNS");
|
||||
update_names(info, pName->a[0].zDatabase, pName->a[0].zName);
|
||||
append_affected_field(info,
|
||||
"COLUMN_DEFAULT COLUMN_KEY COLUMN_NAME "
|
||||
"COLUMN_TYPE EXTRA IS_NULLABLE");
|
||||
@ -2191,7 +2191,7 @@ extern void maxscaleShow(Parse* pParse, MxsShow* pShow)
|
||||
case MXS_SHOW_COLUMNS:
|
||||
{
|
||||
info->types = QUERY_TYPE_READ;
|
||||
update_names(info, "information_schema", "COLUMNS");
|
||||
update_names(info, zDatabase, zName);
|
||||
if (pShow->data == MXS_SHOW_COLUMNS_FULL)
|
||||
{
|
||||
append_affected_field(info,
|
||||
|
@ -3010,13 +3010,17 @@ like_or_where_opt ::= WHERE expr.
|
||||
|
||||
%type show {MxsShow}
|
||||
|
||||
show(A) ::= SHOW full_opt(X) COLUMNS from_or_in nm(Y) dbnm(Z) from_or_in_db_opt like_or_where_opt . {
|
||||
show(A) ::= SHOW full_opt(X) COLUMNS from_or_in nm(Y) dbnm(Z) from_or_in_db_opt(W) like_or_where_opt . {
|
||||
A.what = MXS_SHOW_COLUMNS;
|
||||
A.data = X;
|
||||
if (Z.z) {
|
||||
A.pName = &Z;
|
||||
A.pDatabase = &Y;
|
||||
}
|
||||
else if (W.z) {
|
||||
A.pName = &Y;
|
||||
A.pDatabase = &W;
|
||||
}
|
||||
else {
|
||||
A.pName = &Y;
|
||||
A.pDatabase = NULL;
|
||||
|
Reference in New Issue
Block a user