From d060320b36f02d49303a0e9494b59be5555cfb7c Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Fri, 30 Jun 2017 12:47:46 +0200 Subject: [PATCH] MXS-1248: Further modifications for CTE - Fields in CTEs are marked as being used in subselects. - In qc_mysqlembedded all selects must be walked if CTE is present. - In qc_sqlite unions need special handling. --- .../qc_mysqlembedded/qc_mysqlembedded.cc | 42 ++++++++++++------- query_classifier/qc_sqlite/qc_sqlite.c | 7 +++- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index 2c850168d..acdaef6c1 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -2872,6 +2872,9 @@ int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_ #ifdef CTE_SUPPORTED if (lex->with_clauses_list) { + usage &= ~QC_USED_IN_SELECT; + usage |= QC_USED_IN_SUBSELECT; + With_clause* with_clause = lex->with_clauses_list; while (with_clause) @@ -2923,23 +2926,32 @@ int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_ } } +#ifdef CTE_SUPPORTED + if ((lex->sql_command == SQLCOM_SET_OPTION) || + (lex->with_clauses_list)) +#else if (lex->sql_command == SQLCOM_SET_OPTION) - { -#if defined(WAY_TO_DOWNCAST_SET_VAR_BASE_EXISTS) - // The list of set_var_base contains the value of variables. - // However, the actual type is a derived type of set_var_base - // and there is no information using which we could do the - // downcast... - List_iterator ilist(lex->var_list); - while (set_var_base* var = ilist++) - { - // Is set_var_base a set_var, set_var_user, set_var_password - // set_var_role - ... - } #endif - // ...so, we will simply assume that any nested selects are - // from statements like "set @a:=(SELECT a from t1)". + { + if (lex->sql_command == SQLCOM_SET_OPTION) + { +#if defined(WAY_TO_DOWNCAST_SET_VAR_BASE_EXISTS) + // The list of set_var_base contains the value of variables. + // However, the actual type is a derived type of set_var_base + // and there is no information using which we could do the + // downcast... + List_iterator ilist(lex->var_list); + while (set_var_base* var = ilist++) + { + // Is set_var_base a set_var, set_var_user, set_var_password + // set_var_role + ... + } +#endif + // ...so, we will simply assume that any nested selects are + // from statements like "set @a:=(SELECT a from t1)". The + // code after the closing }. + } usage &= ~QC_USED_IN_SELECT; usage |= QC_USED_IN_SUBSELECT; diff --git a/query_classifier/qc_sqlite/qc_sqlite.c b/query_classifier/qc_sqlite/qc_sqlite.c index 8eecb6b79..06ddeffd9 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.c +++ b/query_classifier/qc_sqlite/qc_sqlite.c @@ -1081,7 +1081,7 @@ static void update_field_infos_from_with(QC_SQLITE_INFO* info, if (pCte->pSelect) { - update_field_infos_from_select(info, pCte->pSelect, QC_USED_IN_SELECT, NULL); + update_field_infos_from_select(info, pCte->pSelect, QC_USED_IN_SUBSELECT, NULL); } } } @@ -1487,6 +1487,11 @@ static void update_field_infos_from_select(QC_SQLITE_INFO* info, { update_field_infos_from_with(info, pSelect->pWith); } + + if ((pSelect->op == TK_UNION) && pSelect->pPrior) + { + update_field_infos_from_select(info, pSelect->pPrior, usage, pExclude); + } } static void update_database_names(QC_SQLITE_INFO* info, const char* zDatabase)