From aa1b48119730e81c1214bbcb8e285c98d3d4f174 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Mon, 24 May 2021 10:54:00 +0300 Subject: [PATCH] MXS-3535 Collect information from ON clause In the case of qc_sqlite, it is done "precisely", while in the case of qc_mysqlembedded rather bluntly. Not time well spent to figure out exactly which pointer chains need to be walked. --- .../qc_mysqlembedded/qc_mysqlembedded.cc | 75 +++++++++++++++++++ query_classifier/qc_sqlite/qc_sqlite.cc | 10 +++ .../qc_sqlite/sqlite-src-3110100/src/parse.y | 10 ++- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index 5eab45dd1..0a27ee8b0 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -71,6 +71,9 @@ #include #include #include +#include + +using std::set; #if MYSQL_VERSION_MAJOR >= 10 && MYSQL_VERSION_MINOR >= 2 #define CTE_SUPPORTED @@ -3434,6 +3437,51 @@ static void update_field_infos(parsing_info_t* pi, } } +namespace +{ + +void collect_from_list(set& seen, parsing_info_t* pi, SELECT_LEX* select_lex, TABLE_LIST* pList) +{ + if (seen.find(pList) != seen.end()) + { + return; + } + + seen.insert(pList); + + if (pList->on_expr) + { + update_field_infos(pi, select_lex, COLLECT_SELECT, pList->on_expr, NULL); + } + + if (pList->next_global) + { + collect_from_list(seen, pi, select_lex, pList->next_global); + } + + if (pList->next_local) + { + collect_from_list(seen, pi, select_lex, pList->next_local); + } + + st_nested_join* pJoin = pList->nested_join; + + if (pJoin) + { + List_iterator it(pJoin->join_list); + + TABLE_LIST* pList2 = it++; + + while (pList2) + { + collect_from_list(seen, pi, select_lex, pList2); + pList2 = it++; + } + } +} + +} + int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_t* n_infos) { *infos = NULL; @@ -3474,6 +3522,33 @@ int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_ update_field_infos(pi, lex, select_lex, NULL); + set seen; + + if (lex->query_tables) + { + collect_from_list(seen, pi, select_lex, lex->query_tables); + } + + List_iterator it1(select_lex->top_join_list); + + TABLE_LIST* pList = it1++; + + while (pList) + { + collect_from_list(seen, pi, select_lex, pList); + pList = it1++; + } + + List_iterator it2(select_lex->sj_nests); + + /*TABLE_LIST**/ pList = it2++; + + while (pList) + { + collect_from_list(seen, pi, select_lex, pList); + pList = it2++; + } + QC_FUNCTION_INFO* fi = NULL; if ((lex->sql_command == SQLCOM_UPDATE) || (lex->sql_command == SQLCOM_UPDATE_MULTI)) diff --git a/query_classifier/qc_sqlite/qc_sqlite.cc b/query_classifier/qc_sqlite/qc_sqlite.cc index efaa3b482..0e9eb34fa 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.cc +++ b/query_classifier/qc_sqlite/qc_sqlite.cc @@ -1303,6 +1303,11 @@ public: pExclude); } + if (pSrc->a[i].pOn) + { + update_field_infos(&aliases, context, 0, pSrc->a[i].pOn, QC_TOKEN_MIDDLE, pExclude); + } + #ifdef QC_COLLECT_NAMES_FROM_USING // With this enabled, the affected fields of // select * from (t1 as t2 left join t1 as t3 using (a)), t1; @@ -1436,6 +1441,11 @@ public: { update_names_from_srclist(pAliases, pSrc->a[i].pSelect->pSrc); } + + if (pSrc->a[i].pOn) + { + update_field_infos(pAliases, 0, 0, pSrc->a[i].pOn, QC_TOKEN_MIDDLE, NULL); + } } } } diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y index bba08dc2e..a2b16eac4 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y @@ -1615,12 +1615,16 @@ table_reference(A) ::= join_table(X). { join_opt ::= . join_opt ::= JOIN_KW. -join_table(A) ::= table_reference(X) join_opt JOIN table_reference(Y) join_condition. { +%type join_condition {ExprSpan} +%destructor join_condition {sqlite3ExprDelete(pParse->db, $$.pExpr);} + +join_table(A) ::= table_reference(X) join_opt JOIN table_reference(Y) join_condition(Z). { + Y->a[Y->nSrc - 1].pOn = Z.pExpr; A = sqlite3SrcListCat(pParse->db, X, Y); } -join_condition ::= ON expr(X). { - sqlite3ExprDelete(pParse->db, X.pExpr); +join_condition(A) ::= ON expr(X). { + A = X; } %type escaped_table_reference {SrcList*}