MXS-1248: Report fields from CTE expressions
Now field and function information of CTE expressions are collected.
This commit is contained in:
@ -74,6 +74,20 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#if MYSQL_VERSION_MAJOR >= 10 && MYSQL_VERSION_MINOR >= 2
|
||||||
|
#define CTE_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CTE_SUPPORTED)
|
||||||
|
// We need to be able to access private data of With_element that has no
|
||||||
|
// public access methods. So, we use this very questionable method of
|
||||||
|
// making the private parts public. Ok, as qc_myselembedded is only
|
||||||
|
// used for verifying the output of qc_sqlite.
|
||||||
|
#define private public
|
||||||
|
#include <sql_cte.h>
|
||||||
|
#undef private
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines what a particular name should be mapped to.
|
* Defines what a particular name should be mapped to.
|
||||||
*/
|
*/
|
||||||
@ -159,7 +173,6 @@ static bool parse_query(GWBUF* querybuf);
|
|||||||
static bool query_is_parsed(GWBUF* buf);
|
static bool query_is_parsed(GWBUF* buf);
|
||||||
int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_t* n_infos);
|
int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_t* n_infos);
|
||||||
|
|
||||||
|
|
||||||
#if MYSQL_VERSION_MAJOR >= 10 && MYSQL_VERSION_MINOR >= 3
|
#if MYSQL_VERSION_MAJOR >= 10 && MYSQL_VERSION_MINOR >= 3
|
||||||
inline void get_string_and_length(const LEX_CSTRING& ls, const char** s, size_t* length)
|
inline void get_string_and_length(const LEX_CSTRING& ls, const char** s, size_t* length)
|
||||||
{
|
{
|
||||||
@ -2725,6 +2738,22 @@ static void update_field_infos(parsing_info_t* pi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CTE_SUPPORTED
|
||||||
|
static void update_field_infos(parsing_info_t* pi,
|
||||||
|
LEX* lex,
|
||||||
|
st_select_lex_unit* select,
|
||||||
|
uint32_t usage,
|
||||||
|
List<Item>* excludep)
|
||||||
|
{
|
||||||
|
st_select_lex* s = select->first_select();
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
update_field_infos(pi, lex, s, usage, excludep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void update_field_infos(parsing_info_t* pi,
|
static void update_field_infos(parsing_info_t* pi,
|
||||||
LEX* lex,
|
LEX* lex,
|
||||||
st_select_lex* select,
|
st_select_lex* select,
|
||||||
@ -2840,6 +2869,33 @@ int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_
|
|||||||
|
|
||||||
update_field_infos(pi, lex, &lex->select_lex, usage, NULL);
|
update_field_infos(pi, lex, &lex->select_lex, usage, NULL);
|
||||||
|
|
||||||
|
#ifdef CTE_SUPPORTED
|
||||||
|
if (lex->with_clauses_list)
|
||||||
|
{
|
||||||
|
With_clause* with_clause = lex->with_clauses_list;
|
||||||
|
|
||||||
|
while (with_clause)
|
||||||
|
{
|
||||||
|
SQL_I_List<With_element>& with_list = with_clause->with_list;
|
||||||
|
With_element* element = with_list.first;
|
||||||
|
|
||||||
|
while (element)
|
||||||
|
{
|
||||||
|
update_field_infos(pi, lex, element->spec, usage, NULL);
|
||||||
|
|
||||||
|
if (element->first_recursive)
|
||||||
|
{
|
||||||
|
update_field_infos(pi, lex, element->first_recursive, usage, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
with_clause = with_clause->next_with_clause;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
List_iterator<Item> ilist(lex->value_list);
|
List_iterator<Item> ilist(lex->value_list);
|
||||||
while (Item* item = ilist++)
|
while (Item* item = ilist++)
|
||||||
{
|
{
|
||||||
|
@ -220,6 +220,8 @@ static void update_field_infos_from_select(QC_SQLITE_INFO* info,
|
|||||||
const Select* pSelect,
|
const Select* pSelect,
|
||||||
uint32_t usage,
|
uint32_t usage,
|
||||||
const ExprList* pExclude);
|
const ExprList* pExclude);
|
||||||
|
static void update_field_infos_from_with(QC_SQLITE_INFO* info,
|
||||||
|
const With* pWith);
|
||||||
static void update_function_info(QC_SQLITE_INFO* info,
|
static void update_function_info(QC_SQLITE_INFO* info,
|
||||||
const char* name,
|
const char* name,
|
||||||
uint32_t usage);
|
uint32_t usage);
|
||||||
@ -1070,6 +1072,20 @@ static void update_field_infos_from_expr(QC_SQLITE_INFO* info,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_field_infos_from_with(QC_SQLITE_INFO* info,
|
||||||
|
const With* pWith)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pWith->nCte; ++i)
|
||||||
|
{
|
||||||
|
const struct Cte* pCte = &pWith->a[i];
|
||||||
|
|
||||||
|
if (pCte->pSelect)
|
||||||
|
{
|
||||||
|
update_field_infos_from_select(info, pCte->pSelect, QC_USED_IN_SELECT, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const char* get_token_symbol(int token)
|
static const char* get_token_symbol(int token)
|
||||||
{
|
{
|
||||||
switch (token)
|
switch (token)
|
||||||
@ -1466,6 +1482,11 @@ static void update_field_infos_from_select(QC_SQLITE_INFO* info,
|
|||||||
update_field_infos(info, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList);
|
update_field_infos(info, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pSelect->pWith)
|
||||||
|
{
|
||||||
|
update_field_infos_from_with(info, pSelect->pWith);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_database_names(QC_SQLITE_INFO* info, const char* zDatabase)
|
static void update_database_names(QC_SQLITE_INFO* info, const char* zDatabase)
|
||||||
|
Reference in New Issue
Block a user