MXS-1307 Aliases must be stored hierarchically

Alias handling must be made so that in a subselect, aliases created
in an outer select are available, but aliases created in another
subselect are not.
This commit is contained in:
Johan Wikman
2017-08-09 15:31:05 +03:00
parent ebe9596966
commit 878bbe4a98

View File

@ -123,6 +123,8 @@ struct QcAliasValue
const char* zTable; const char* zTable;
}; };
typedef std::map<std::string, QcAliasValue> QcAliases;
/** /**
* The state of qc_sqlite. * The state of qc_sqlite.
*/ */
@ -174,33 +176,44 @@ static void parse_query_string(const char* query, int len, bool suppress_logging
static bool query_is_parsed(GWBUF* query, uint32_t collect); static bool query_is_parsed(GWBUF* query, uint32_t collect);
static bool should_exclude(const char* zName, const ExprList* pExclude); static bool should_exclude(const char* zName, const ExprList* pExclude);
static void update_field_infos_from_expr(QcSqliteInfo* info, static void update_field_infos_from_expr(QcSqliteInfo* info,
QcAliases* pAliases,
const Expr* pExpr, const Expr* pExpr,
uint32_t usage, uint32_t usage,
const ExprList* pExclude); const ExprList* pExclude);
static void update_field_infos(QcSqliteInfo* info, static void update_field_infos(QcSqliteInfo* info,
QcAliases* pAliases,
int prev_token, int prev_token,
const Expr* pExpr, const Expr* pExpr,
uint32_t usage, uint32_t usage,
qc_token_position_t pos, qc_token_position_t pos,
const ExprList* pExclude); const ExprList* pExclude);
static void update_field_infos_from_exprlist(QcSqliteInfo* info, static void update_field_infos_from_exprlist(QcSqliteInfo* info,
QcAliases* pAliases,
const ExprList* pEList, const ExprList* pEList,
uint32_t usage, uint32_t usage,
const ExprList* pExclude); const ExprList* pExclude);
static void update_field_infos_from_idlist(QcSqliteInfo* info, static void update_field_infos_from_idlist(QcSqliteInfo* info,
QcAliases* pAliases,
const IdList* pIds, const IdList* pIds,
uint32_t usage, uint32_t usage,
const ExprList* pExclude); const ExprList* pExclude);
static void update_field_infos_from_select(QcSqliteInfo* info, static void update_field_infos_from_select(QcSqliteInfo* info,
QcAliases& aliases,
const Select* pSelect,
uint32_t usage,
const ExprList* pExclude);
static void update_field_infos_from_subselect(QcSqliteInfo* info,
QcAliases* pAliases,
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(QcSqliteInfo* info, static void update_field_infos_from_with(QcSqliteInfo* info,
QcAliases* pAliases,
const With* pWith); const With* pWith);
static void update_function_info(QcSqliteInfo* info, static void update_function_info(QcSqliteInfo* info,
const char* name, const char* name,
uint32_t usage); uint32_t usage);
static void update_names_from_srclist(QcSqliteInfo* info, const SrcList* pSrc); static void update_names_from_srclist(QcSqliteInfo* info, QcAliases* pAliases, const SrcList* pSrc);
// Defined in parse.y // Defined in parse.y
extern "C" extern "C"
@ -525,7 +538,8 @@ public:
return rv; return rv;
} }
void update_field_info(const char* zDatabase, void update_field_info(const QcAliases* pAliases,
const char* zDatabase,
const char* zTable, const char* zTable,
const char* zColumn, const char* zColumn,
uint32_t usage, uint32_t usage,
@ -548,11 +562,11 @@ public:
return; return;
} }
if (!zDatabase && zTable) if (!zDatabase && zTable && pAliases)
{ {
Aliases::const_iterator i = m_aliases.find(zTable); QcAliases::const_iterator i = pAliases->find(zTable);
if (i != m_aliases.end()) if (i != pAliases->end())
{ {
const QcAliasValue& value = i->second; const QcAliasValue& value = i->second;
@ -641,11 +655,11 @@ public:
} }
} }
void update_names(const char* zDatabase, const char* zTable, const char* zAlias) void update_names(const char* zDatabase, const char* zTable, const char* zAlias, QcAliases* pAliases)
{ {
ss_dassert(zTable); ss_dassert(zTable);
bool should_collect_alias = zAlias && should_collect(QC_COLLECT_FIELDS); bool should_collect_alias = pAliases && zAlias && should_collect(QC_COLLECT_FIELDS);
bool should_collect_table = should_collect_alias || should_collect(QC_COLLECT_TABLES); bool should_collect_table = should_collect_alias || should_collect(QC_COLLECT_TABLES);
bool should_collect_database = zDatabase && bool should_collect_database = zDatabase &&
(should_collect_alias || should_collect(QC_COLLECT_DATABASES)); (should_collect_alias || should_collect(QC_COLLECT_DATABASES));
@ -681,11 +695,11 @@ public:
zCollected_database = update_database_names(database); zCollected_database = update_database_names(database);
} }
if (zCollected_table && zAlias) if (pAliases && zCollected_table && zAlias)
{ {
QcAliasValue value(zCollected_database, zCollected_table); QcAliasValue value(zCollected_database, zCollected_table);
m_aliases.insert(Aliases::value_type(zAlias, value)); pAliases->insert(QcAliases::value_type(zAlias, value));
} }
} }
@ -791,7 +805,7 @@ public:
{ {
ss_dassert(this_thread.initialized); ss_dassert(this_thread.initialized);
update_names_from_srclist(this, pSrcList); update_names_from_srclist(this, NULL, pSrcList);
exposed_sqlite3SrcListDelete(pParse->db, pSrcList); exposed_sqlite3SrcListDelete(pParse->db, pSrcList);
} }
@ -803,7 +817,7 @@ public:
m_status = QC_QUERY_PARSED; m_status = QC_QUERY_PARSED;
m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT); m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT);
update_names_from_srclist(this, pSrcList); update_names_from_srclist(this, NULL, pSrcList);
exposed_sqlite3SrcListDelete(pParse->db, pSrcList); exposed_sqlite3SrcListDelete(pParse->db, pSrcList);
} }
@ -843,7 +857,7 @@ public:
if (pItem->zName) if (pItem->zName)
{ {
update_names(pItem->zDatabase, pItem->zName, pItem->zAlias); update_names(pItem->zDatabase, pItem->zName, pItem->zAlias, NULL);
} }
} }
} }
@ -880,11 +894,11 @@ public:
if (pTblName) if (pTblName)
{ {
update_names_from_srclist(this, pTblName); update_names_from_srclist(this, NULL, pTblName);
} }
else if (pParse->pNewTable) else if (pParse->pNewTable)
{ {
update_names(NULL, pParse->pNewTable->zName, NULL); update_names(NULL, pParse->pNewTable->zName, NULL, NULL);
} }
exposed_sqlite3ExprDelete(pParse->db, pPIWhere); exposed_sqlite3ExprDelete(pParse->db, pPIWhere);
@ -914,22 +928,24 @@ public:
strncpy(name, pName->z, pName->n); strncpy(name, pName->z, pName->n);
name[pName->n] = 0; name[pName->n] = 0;
QcAliases aliases;
if (pDatabase) if (pDatabase)
{ {
char database[pDatabase->n + 1]; char database[pDatabase->n + 1];
strncpy(database, pDatabase->z, pDatabase->n); strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0; database[pDatabase->n] = 0;
update_names(database, name, NULL); update_names(database, name, NULL, &aliases);
} }
else else
{ {
update_names(NULL, name, NULL); update_names(NULL, name, NULL, &aliases);
} }
if (pSelect) if (pSelect)
{ {
update_field_infos_from_select(this, pSelect, QC_USED_IN_SELECT, NULL); update_field_infos_from_select(this, aliases, pSelect, QC_USED_IN_SELECT, NULL);
} }
exposed_sqlite3ExprListDelete(pParse->db, pCNames); exposed_sqlite3ExprListDelete(pParse->db, pCNames);
@ -948,6 +964,8 @@ public:
m_operation = QUERY_OP_DELETE; m_operation = QUERY_OP_DELETE;
m_has_clause = pWhere ? true : false; m_has_clause = pWhere ? true : false;
QcAliases aliases;
if (pUsing) if (pUsing)
{ {
// Walk through the using declaration and update // Walk through the using declaration and update
@ -956,7 +974,7 @@ public:
{ {
const SrcList::SrcList_item* pItem = &pUsing->a[i]; const SrcList::SrcList_item* pItem = &pUsing->a[i];
update_names(pItem->zDatabase, pItem->zName, pItem->zAlias); update_names(pItem->zDatabase, pItem->zName, pItem->zAlias, &aliases);
} }
// Walk through the tablenames while excluding alias // Walk through the tablenames while excluding alias
@ -986,18 +1004,18 @@ public:
if (!isSame) if (!isSame)
{ {
// No alias name, update the table name. // No alias name, update the table name.
update_names(pTable->zDatabase, pTable->zName, NULL); update_names(pTable->zDatabase, pTable->zName, NULL, &aliases);
} }
} }
} }
else else
{ {
update_names_from_srclist(this, pTabList); update_names_from_srclist(this, &aliases, pTabList);
} }
if (pWhere) if (pWhere)
{ {
update_field_infos(this, 0, pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, 0); update_field_infos(this, &aliases, 0, pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, 0);
} }
} }
@ -1014,7 +1032,7 @@ public:
m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT); m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT);
m_operation = QUERY_OP_DROP; m_operation = QUERY_OP_DROP;
update_names_from_srclist(this, pTable); update_names_from_srclist(this, NULL, pTable);
exposed_sqlite3SrcListDelete(pParse->db, pName); exposed_sqlite3SrcListDelete(pParse->db, pName);
exposed_sqlite3SrcListDelete(pParse->db, pTable); exposed_sqlite3SrcListDelete(pParse->db, pTable);
@ -1035,7 +1053,7 @@ public:
{ {
m_is_drop_table = true; m_is_drop_table = true;
} }
update_names_from_srclist(this, pName); update_names_from_srclist(this, NULL, pName);
exposed_sqlite3SrcListDelete(pParse->db, pName); exposed_sqlite3SrcListDelete(pParse->db, pName);
} }
@ -1051,11 +1069,12 @@ public:
if (pSelect) if (pSelect)
{ {
update_field_infos_from_select(this, pSelect, QC_USED_IN_SELECT, NULL); QcAliases aliases;
update_field_infos_from_select(this, aliases, pSelect, QC_USED_IN_SELECT, NULL);
} }
else if (pOldTable) else if (pOldTable)
{ {
update_names_from_srclist(this, pOldTable); update_names_from_srclist(this, NULL, pOldTable);
exposed_sqlite3SrcListDelete(pParse->db, pOldTable); exposed_sqlite3SrcListDelete(pParse->db, pOldTable);
} }
} }
@ -1077,11 +1096,14 @@ public:
m_operation = QUERY_OP_INSERT; m_operation = QUERY_OP_INSERT;
ss_dassert(pTabList); ss_dassert(pTabList);
ss_dassert(pTabList->nSrc >= 1); ss_dassert(pTabList->nSrc >= 1);
update_names_from_srclist(this, pTabList);
QcAliases aliases;
update_names_from_srclist(this, &aliases, pTabList);
if (pColumns) if (pColumns)
{ {
update_field_infos_from_idlist(this, pColumns, 0, NULL); update_field_infos_from_idlist(this, &aliases, pColumns, 0, NULL);
} }
if (pSelect) if (pSelect)
@ -1097,12 +1119,12 @@ public:
usage = QC_USED_IN_SELECT; usage = QC_USED_IN_SELECT;
} }
update_field_infos_from_select(this, pSelect, usage, NULL); update_field_infos_from_select(this, aliases, pSelect, usage, NULL);
} }
if (pSet) if (pSet)
{ {
update_field_infos_from_exprlist(this, pSet, 0, NULL); update_field_infos_from_exprlist(this, &aliases, pSet, 0, NULL);
} }
} }
@ -1171,11 +1193,11 @@ public:
strncpy(database, pDatabase->z, pDatabase->n); strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0; database[pDatabase->n] = 0;
update_names(database, name, NULL); update_names(database, name, NULL, NULL);
} }
else else
{ {
update_names(NULL, name, NULL); update_names(NULL, name, NULL, NULL);
} }
if (m_collect & QC_COLLECT_TABLES) if (m_collect & QC_COLLECT_TABLES)
@ -1203,9 +1225,11 @@ public:
if (m_operation != QUERY_OP_EXPLAIN) if (m_operation != QUERY_OP_EXPLAIN)
{ {
QcAliases aliases;
m_type_mask = QUERY_TYPE_WRITE; m_type_mask = QUERY_TYPE_WRITE;
m_operation = QUERY_OP_UPDATE; m_operation = QUERY_OP_UPDATE;
update_names_from_srclist(this, pTabList); update_names_from_srclist(this, &aliases, pTabList);
m_has_clause = (pWhere ? true : false); m_has_clause = (pWhere ? true : false);
if (pChanges) if (pChanges)
@ -1214,13 +1238,14 @@ public:
{ {
ExprList::ExprList_item* pItem = &pChanges->a[i]; ExprList::ExprList_item* pItem = &pChanges->a[i];
update_field_infos(this, 0, pItem->pExpr, QC_USED_IN_SET, QC_TOKEN_MIDDLE, NULL); update_field_infos(this, &aliases,
0, pItem->pExpr, QC_USED_IN_SET, QC_TOKEN_MIDDLE, NULL);
} }
} }
if (pWhere) if (pWhere)
{ {
update_field_infos(this, 0, pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pChanges); update_field_infos(this, &aliases, 0, pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pChanges);
} }
} }
@ -1256,7 +1281,8 @@ public:
uint32_t usage = sub_select ? QC_USED_IN_SUBSELECT : QC_USED_IN_SELECT; uint32_t usage = sub_select ? QC_USED_IN_SUBSELECT : QC_USED_IN_SELECT;
update_field_infos_from_select(this, pSelect, usage, NULL); QcAliases aliases;
update_field_infos_from_select(this, aliases, pSelect, usage, NULL);
} }
void maxscaleAlterTable(Parse *pParse, /* Parser context. */ void maxscaleAlterTable(Parse *pParse, /* Parser context. */
@ -1273,15 +1299,15 @@ public:
switch (command) switch (command)
{ {
case MXS_ALTER_DISABLE_KEYS: case MXS_ALTER_DISABLE_KEYS:
update_names_from_srclist(this, pSrc); update_names_from_srclist(this, NULL, pSrc);
break; break;
case MXS_ALTER_ENABLE_KEYS: case MXS_ALTER_ENABLE_KEYS:
update_names_from_srclist(this, pSrc); update_names_from_srclist(this, NULL, pSrc);
break; break;
case MXS_ALTER_RENAME: case MXS_ALTER_RENAME:
update_names_from_srclist(this, pSrc); update_names_from_srclist(this, NULL, pSrc);
break; break;
default: default:
@ -1300,7 +1326,7 @@ public:
if (pExprList) if (pExprList)
{ {
update_field_infos_from_exprlist(this, pExprList, 0, NULL); update_field_infos_from_exprlist(this, NULL, pExprList, 0, NULL);
} }
exposed_sqlite3SrcListDelete(pParse->db, pName); exposed_sqlite3SrcListDelete(pParse->db, pName);
@ -1314,7 +1340,7 @@ public:
m_status = QC_QUERY_PARSED; m_status = QC_QUERY_PARSED;
m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT); m_type_mask = (QUERY_TYPE_WRITE | QUERY_TYPE_COMMIT);
update_names_from_srclist(this, pTables); update_names_from_srclist(this, NULL, pTables);
exposed_sqlite3SrcListDelete(pParse->db, pTables); exposed_sqlite3SrcListDelete(pParse->db, pTables);
} }
@ -1340,7 +1366,7 @@ public:
strncpy(table, pTable->z, pTable->n); strncpy(table, pTable->z, pTable->n);
table[pTable->n] = 0; table[pTable->n] = 0;
update_names(zDatabase, table, NULL); update_names(zDatabase, table, NULL, NULL);
} }
void maxscaleComment() void maxscaleComment()
@ -1424,7 +1450,7 @@ public:
strncpy(table, pName->z, pName->n); strncpy(table, pName->z, pName->n);
table[pName->n] = 0; table[pName->n] = 0;
update_names(zDatabase, table, NULL); update_names(zDatabase, table, NULL, NULL);
} }
} }
@ -1537,7 +1563,7 @@ public:
ss_dassert(pFullName->nSrc == 1); ss_dassert(pFullName->nSrc == 1);
const SrcList::SrcList_item* pItem = &pFullName->a[0]; const SrcList::SrcList_item* pItem = &pFullName->a[0];
update_names(pItem->zDatabase, pItem->zName, pItem->zAlias); update_names(pItem->zDatabase, pItem->zName, pItem->zAlias, NULL);
} }
break; break;
@ -1549,7 +1575,7 @@ public:
strncpy(zName, pName->z, pName->n); strncpy(zName, pName->z, pName->n);
zName[pName->n] = 0; zName[pName->n] = 0;
update_names("*any*", zName, NULL); update_names("*any*", zName, NULL, NULL);
} }
break; break;
@ -1570,7 +1596,7 @@ public:
if (pFullName) if (pFullName)
{ {
update_names_from_srclist(this, pFullName); update_names_from_srclist(this, NULL, pFullName);
exposed_sqlite3SrcListDelete(pParse->db, pFullName); exposed_sqlite3SrcListDelete(pParse->db, pFullName);
} }
@ -1585,7 +1611,7 @@ public:
if (pTables) if (pTables)
{ {
update_names_from_srclist(this, pTables); update_names_from_srclist(this, NULL, pTables);
exposed_sqlite3SrcListDelete(pParse->db, pTables); exposed_sqlite3SrcListDelete(pParse->db, pTables);
} }
@ -1872,8 +1898,8 @@ public:
ss_dassert(pItem->zName); ss_dassert(pItem->zName);
ss_dassert(pItem->zAlias); ss_dassert(pItem->zAlias);
update_names(pItem->zDatabase, pItem->zName, NULL); update_names(pItem->zDatabase, pItem->zName, NULL, NULL);
update_names(NULL, pItem->zAlias, NULL); // The new name is passed in the alias field. update_names(NULL, pItem->zAlias, NULL, NULL); // The new name is passed in the alias field.
} }
exposed_sqlite3SrcListDelete(pParse->db, pTables); exposed_sqlite3SrcListDelete(pParse->db, pTables);
@ -2128,7 +2154,8 @@ public:
if (pValue->op == TK_SELECT) if (pValue->op == TK_SELECT)
{ {
update_field_infos_from_select(this, pValue->x.pSelect, QcAliases aliases;
update_field_infos_from_select(this, aliases, pValue->x.pSelect,
QC_USED_IN_SUBSELECT, NULL); QC_USED_IN_SUBSELECT, NULL);
} }
} }
@ -2267,7 +2294,7 @@ public:
strncpy(name, pName->z, pName->n); strncpy(name, pName->z, pName->n);
name[pName->n] = 0; name[pName->n] = 0;
update_names(zDatabase, name, NULL); update_names(zDatabase, name, NULL, NULL);
} }
void maxscaleUse(Parse* pParse, Token* pToken) void maxscaleUse(Parse* pParse, Token* pToken)
@ -2496,8 +2523,6 @@ private:
} }
public: public:
typedef std::map<std::string, QcAliasValue> Aliases;
// TODO: Make these private once everything's been updated. // TODO: Make these private once everything's been updated.
qc_parse_result_t m_status; // The validity of the information in this structure. qc_parse_result_t m_status; // The validity of the information in this structure.
uint32_t m_collect; // What information should be collected. uint32_t m_collect; // What information should be collected.
@ -2531,7 +2556,6 @@ public:
size_t m_function_infos_capacity; // The capacity of the function_infos array. size_t m_function_infos_capacity; // The capacity of the function_infos array.
qc_sql_mode_t m_sql_mode; // The current sql_mode. qc_sql_mode_t m_sql_mode; // The current sql_mode.
QC_NAME_MAPPING* m_pFunction_name_mappings; // How function names should be mapped. QC_NAME_MAPPING* m_pFunction_name_mappings; // How function names should be mapped.
Aliases m_aliases; // Alias names for tables
}; };
extern "C" extern "C"
@ -3034,6 +3058,7 @@ extern void maxscale_update_function_info(const char* name, uint32_t usage)
} }
static void update_field_infos_from_expr(QcSqliteInfo* info, static void update_field_infos_from_expr(QcSqliteInfo* info,
QcAliases* pAliases,
const Expr* pExpr, const Expr* pExpr,
uint32_t usage, uint32_t usage,
const ExprList* pExclude) const ExprList* pExclude)
@ -3098,12 +3123,13 @@ static void update_field_infos_from_expr(QcSqliteInfo* info,
if (should_update) if (should_update)
{ {
info->update_field_info(item.database, item.table, item.column, usage, pExclude); info->update_field_info(pAliases, item.database, item.table, item.column, usage, pExclude);
} }
} }
} }
static void update_field_infos_from_with(QcSqliteInfo* info, static void update_field_infos_from_with(QcSqliteInfo* pInfo,
QcAliases* pAliases,
const With* pWith) const With* pWith)
{ {
for (int i = 0; i < pWith->nCte; ++i) for (int i = 0; i < pWith->nCte; ++i)
@ -3112,7 +3138,7 @@ static void update_field_infos_from_with(QcSqliteInfo* info,
if (pCte->pSelect) if (pCte->pSelect)
{ {
update_field_infos_from_select(info, pCte->pSelect, QC_USED_IN_SUBSELECT, NULL); update_field_infos_from_subselect(pInfo, pAliases, pCte->pSelect, QC_USED_IN_SUBSELECT, NULL);
} }
} }
} }
@ -3186,6 +3212,7 @@ static const char* get_token_symbol(int token)
} }
static void update_field_infos(QcSqliteInfo* info, static void update_field_infos(QcSqliteInfo* info,
QcAliases* pAliases,
int prev_token, int prev_token,
const Expr* pExpr, const Expr* pExpr,
uint32_t usage, uint32_t usage,
@ -3201,15 +3228,15 @@ static void update_field_infos(QcSqliteInfo* info,
switch (pExpr->op) switch (pExpr->op)
{ {
case TK_ASTERISK: // select * case TK_ASTERISK: // select *
update_field_infos_from_expr(info, pExpr, usage, pExclude); update_field_infos_from_expr(info, pAliases, pExpr, usage, pExclude);
break; break;
case TK_DOT: // select a.b ... select a.b.c case TK_DOT: // select a.b ... select a.b.c
update_field_infos_from_expr(info, pExpr, usage, pExclude); update_field_infos_from_expr(info, pAliases, pExpr, usage, pExclude);
break; break;
case TK_ID: // select a case TK_ID: // select a
update_field_infos_from_expr(info, pExpr, usage, pExclude); update_field_infos_from_expr(info, pAliases, pExpr, usage, pExclude);
break; break;
case TK_VARIABLE: case TK_VARIABLE:
@ -3375,7 +3402,7 @@ static void update_field_infos(QcSqliteInfo* info,
if (pLeft) if (pLeft)
{ {
update_field_infos(info, pExpr->op, pExpr->pLeft, usage, QC_TOKEN_LEFT, pExclude); update_field_infos(info, pAliases, pExpr->op, pExpr->pLeft, usage, QC_TOKEN_LEFT, pExclude);
} }
if (pRight) if (pRight)
@ -3385,7 +3412,7 @@ static void update_field_infos(QcSqliteInfo* info,
usage &= ~QC_USED_IN_SET; usage &= ~QC_USED_IN_SET;
} }
update_field_infos(info, pExpr->op, pExpr->pRight, usage, QC_TOKEN_RIGHT, pExclude); update_field_infos(info, pAliases, pExpr->op, pExpr->pRight, usage, QC_TOKEN_RIGHT, pExclude);
} }
if (pExpr->x.pList) if (pExpr->x.pList)
@ -3397,7 +3424,7 @@ static void update_field_infos(QcSqliteInfo* info,
case TK_FUNCTION: case TK_FUNCTION:
if (!ignore_exprlist) if (!ignore_exprlist)
{ {
update_field_infos_from_exprlist(info, pExpr->x.pList, usage, pExclude); update_field_infos_from_exprlist(info, pAliases, pExpr->x.pList, usage, pExclude);
} }
break; break;
@ -3410,11 +3437,11 @@ static void update_field_infos(QcSqliteInfo* info,
sub_usage &= ~QC_USED_IN_SELECT; sub_usage &= ~QC_USED_IN_SELECT;
sub_usage |= QC_USED_IN_SUBSELECT; sub_usage |= QC_USED_IN_SUBSELECT;
update_field_infos_from_select(info, pExpr->x.pSelect, sub_usage, pExclude); update_field_infos_from_subselect(info, pAliases, pExpr->x.pSelect, sub_usage, pExclude);
} }
else else
{ {
update_field_infos_from_exprlist(info, pExpr->x.pList, usage, pExclude); update_field_infos_from_exprlist(info, pAliases, pExpr->x.pList, usage, pExclude);
} }
break; break;
} }
@ -3424,6 +3451,7 @@ static void update_field_infos(QcSqliteInfo* info,
} }
static void update_field_infos_from_exprlist(QcSqliteInfo* info, static void update_field_infos_from_exprlist(QcSqliteInfo* info,
QcAliases* pAliases,
const ExprList* pEList, const ExprList* pEList,
uint32_t usage, uint32_t usage,
const ExprList* pExclude) const ExprList* pExclude)
@ -3432,11 +3460,12 @@ static void update_field_infos_from_exprlist(QcSqliteInfo* info,
{ {
ExprList::ExprList_item* pItem = &pEList->a[i]; ExprList::ExprList_item* pItem = &pEList->a[i];
update_field_infos(info, 0, pItem->pExpr, usage, QC_TOKEN_MIDDLE, pExclude); update_field_infos(info, pAliases, 0, pItem->pExpr, usage, QC_TOKEN_MIDDLE, pExclude);
} }
} }
static void update_field_infos_from_idlist(QcSqliteInfo* info, static void update_field_infos_from_idlist(QcSqliteInfo* info,
QcAliases* pAliases,
const IdList* pIds, const IdList* pIds,
uint32_t usage, uint32_t usage,
const ExprList* pExclude) const ExprList* pExclude)
@ -3445,11 +3474,12 @@ static void update_field_infos_from_idlist(QcSqliteInfo* info,
{ {
IdList::IdList_item* pItem = &pIds->a[i]; IdList::IdList_item* pItem = &pIds->a[i];
info->update_field_info(NULL, NULL, pItem->zName, usage, pExclude); info->update_field_info(pAliases, NULL, NULL, pItem->zName, usage, pExclude);
} }
} }
static void update_field_infos_from_select(QcSqliteInfo* pInfo, static void update_field_infos_from_select(QcSqliteInfo* pInfo,
QcAliases& aliases,
const Select* pSelect, const Select* pSelect,
uint32_t usage, uint32_t usage,
const ExprList* pExclude) const ExprList* pExclude)
@ -3462,7 +3492,7 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
{ {
if (pSrc->a[i].zName) if (pSrc->a[i].zName)
{ {
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias); pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias, &aliases);
} }
if (pSrc->a[i].pSelect) if (pSrc->a[i].pSelect)
@ -3472,7 +3502,7 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
sub_usage &= ~QC_USED_IN_SELECT; sub_usage &= ~QC_USED_IN_SELECT;
sub_usage |= QC_USED_IN_SUBSELECT; sub_usage |= QC_USED_IN_SUBSELECT;
update_field_infos_from_select(pInfo, pSrc->a[i].pSelect, sub_usage, pExclude); update_field_infos_from_select(pInfo, aliases, pSrc->a[i].pSelect, sub_usage, pExclude);
} }
#ifdef QC_COLLECT_NAMES_FROM_USING #ifdef QC_COLLECT_NAMES_FROM_USING
@ -3482,7 +3512,7 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
// does not reveal its value, right? // does not reveal its value, right?
if (pSrc->a[i].pUsing) if (pSrc->a[i].pUsing)
{ {
update_field_infos_from_idlist(pInfo, pSrc->a[i].pUsing, 0, pSelect->pEList); update_field_infos_from_idlist(pInfo, aliases, pSrc->a[i].pUsing, 0, pSelect->pEList);
} }
#endif #endif
} }
@ -3490,18 +3520,20 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
if (pSelect->pEList) if (pSelect->pEList)
{ {
update_field_infos_from_exprlist(pInfo, pSelect->pEList, usage, NULL); update_field_infos_from_exprlist(pInfo, &aliases, pSelect->pEList, usage, NULL);
} }
if (pSelect->pWhere) if (pSelect->pWhere)
{ {
pInfo->m_has_clause = true; pInfo->m_has_clause = true;
update_field_infos(pInfo, 0, pSelect->pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pSelect->pEList); update_field_infos(pInfo, &aliases,
0, pSelect->pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pSelect->pEList);
} }
if (pSelect->pGroupBy) if (pSelect->pGroupBy)
{ {
update_field_infos_from_exprlist(pInfo, pSelect->pGroupBy, QC_USED_IN_GROUP_BY, pSelect->pEList); update_field_infos_from_exprlist(pInfo, &aliases,
pSelect->pGroupBy, QC_USED_IN_GROUP_BY, pSelect->pEList);
} }
if (pSelect->pHaving) if (pSelect->pHaving)
@ -3510,33 +3542,46 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
#if defined(COLLECT_HAVING_AS_WELL) #if defined(COLLECT_HAVING_AS_WELL)
// A HAVING clause can only refer to fields that already have been // A HAVING clause can only refer to fields that already have been
// mentioned. Consequently, they need not be collected. // mentioned. Consequently, they need not be collected.
update_field_infos(pInfo, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList); update_field_infos(pInfo, aliases, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList);
#endif #endif
} }
if (pSelect->pWith) if (pSelect->pWith)
{ {
update_field_infos_from_with(pInfo, pSelect->pWith); update_field_infos_from_with(pInfo, &aliases, pSelect->pWith);
} }
if ((pSelect->op == TK_UNION) && pSelect->pPrior) if ((pSelect->op == TK_UNION) && pSelect->pPrior)
{ {
update_field_infos_from_select(pInfo, pSelect->pPrior, usage, pExclude); update_field_infos_from_subselect(pInfo, &aliases, pSelect->pPrior, usage, pExclude);
} }
} }
static void update_names_from_srclist(QcSqliteInfo* pInfo, const SrcList* pSrc) static void update_field_infos_from_subselect(QcSqliteInfo* pInfo,
QcAliases* pAliases,
const Select* pSelect,
uint32_t usage,
const ExprList* pExclude)
{
QcAliases aliases(*pAliases);
update_field_infos_from_select(pInfo, aliases, pSelect, usage, pExclude);
}
static void update_names_from_srclist(QcSqliteInfo* pInfo,
QcAliases* pAliases,
const SrcList* pSrc)
{ {
for (int i = 0; i < pSrc->nSrc; ++i) for (int i = 0; i < pSrc->nSrc; ++i)
{ {
if (pSrc->a[i].zName) if (pSrc->a[i].zName)
{ {
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias); pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias, pAliases);
} }
if (pSrc->a[i].pSelect && pSrc->a[i].pSelect->pSrc) if (pSrc->a[i].pSelect && pSrc->a[i].pSelect->pSrc)
{ {
update_names_from_srclist(pInfo, pSrc->a[i].pSelect->pSrc); update_names_from_srclist(pInfo, pAliases, pSrc->a[i].pSelect->pSrc);
} }
} }
} }