MXS-1337 update_names(...) moved to QcSqliteInfo

The update_names() will have to be updated to take a possible alias
name as well. That needs to be tracked inside QcSqliteInfo, so that
when there is a statement like "select t2.a from t1 t2" we report
the field as t1.a and not as t2.a.
This commit is contained in:
Johan Wikman
2017-08-01 12:40:27 +03:00
parent cfb5a315cf
commit 542f3b69db

View File

@ -175,10 +175,43 @@ static void update_field_infos_from_with(QcSqliteInfo* info,
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_database_names(QcSqliteInfo* info, const char* name);
static void update_names(QcSqliteInfo* info, const char* zDatabase, const char* zTable);
static void update_names_from_srclist(QcSqliteInfo* info, const SrcList* pSrc); static void update_names_from_srclist(QcSqliteInfo* info, const SrcList* pSrc);
// Defined in parse.y
extern "C"
{
extern void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr);
extern void exposed_sqlite3ExprListDelete(sqlite3 *db, ExprList *pList);
extern void exposed_sqlite3IdListDelete(sqlite3 *db, IdList *pList);
extern void exposed_sqlite3SrcListDelete(sqlite3 *db, SrcList *pList);
extern void exposed_sqlite3SelectDelete(sqlite3 *db, Select *p);
extern void exposed_sqlite3BeginTrigger(Parse *pParse,
Token *pName1,
Token *pName2,
int tr_tm,
int op,
IdList *pColumns,
SrcList *pTableName,
Expr *pWhen,
int isTemp,
int noErr);
extern void exposed_sqlite3FinishTrigger(Parse *pParse,
TriggerStep *pStepList,
Token *pAll);
extern int exposed_sqlite3Dequote(char *z);
extern int exposed_sqlite3EndTable(Parse*, Token*, Token*, u8, Select*);
extern int exposed_sqlite3Select(Parse* pParse, Select* p, SelectDest* pDest);
extern void exposed_sqlite3StartTable(Parse *pParse, /* Parser context */
Token *pName1, /* First part of the name of the table or view */
Token *pName2, /* Second part of the name of the table or view */
int isTemp, /* True if this is a TEMP table */
int isView, /* True if this is a VIEW */
int isVirtual, /* True if this is a VIRTUAL table */
int noErr); /* Do nothing if table already exists */
}
/** /**
* Contains information about a particular query. * Contains information about a particular query.
@ -404,6 +437,66 @@ public:
return rv; return rv;
} }
// PUBLIC for now at least.
void update_names(const char* zDatabase, const char* zTable)
{
if ((collect & QC_COLLECT_TABLES) && !(collected & QC_COLLECT_TABLES))
{
if (strcasecmp(zTable, "DUAL") != 0)
{
char* zCopy = MXS_STRDUP(zTable);
MXS_ABORT_IF_NULL(zCopy);
// TODO: Is this call really needed. Check also sqlite3Dequote.
exposed_sqlite3Dequote(zCopy);
enlarge_string_array(1, table_names_len, &table_names, &table_names_capacity);
table_names[table_names_len++] = zCopy;
table_names[table_names_len] = NULL;
if (zDatabase)
{
zCopy = (char*)MXS_MALLOC(strlen(zDatabase) + 1 + strlen(zTable) + 1);
MXS_ABORT_IF_NULL(zCopy);
strcpy(zCopy, zDatabase);
strcat(zCopy, ".");
strcat(zCopy, zTable);
exposed_sqlite3Dequote(zCopy);
}
else
{
zCopy = MXS_STRDUP(zCopy);
MXS_ABORT_IF_NULL(zCopy);
}
enlarge_string_array(1, table_fullnames_len,
&table_fullnames, &table_fullnames_capacity);
table_fullnames[table_fullnames_len++] = zCopy;
table_fullnames[table_fullnames_len] = NULL;
}
}
if ((collect & QC_COLLECT_DATABASES) && !(collected & QC_COLLECT_DATABASES))
{
if (zDatabase)
{
update_database_names(zDatabase);
}
}
}
void update_database_names(const char* zDatabase)
{
char* zCopy = MXS_STRDUP(zDatabase);
MXS_ABORT_IF_NULL(zCopy);
exposed_sqlite3Dequote(zCopy);
enlarge_string_array(1, database_names_len,
&database_names, &database_names_capacity);
database_names[database_names_len++] = zCopy;
database_names[database_names_len] = NULL;
}
private: private:
QcSqliteInfo(uint32_t cllct) QcSqliteInfo(uint32_t cllct)
: status(QC_QUERY_INVALID) : status(QC_QUERY_INVALID)
@ -550,43 +643,6 @@ public:
QC_NAME_MAPPING* function_name_mappings; // How function names should be mapped. QC_NAME_MAPPING* function_name_mappings; // How function names should be mapped.
}; };
// Defined in parse.y
extern "C"
{
extern void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr);
extern void exposed_sqlite3ExprListDelete(sqlite3 *db, ExprList *pList);
extern void exposed_sqlite3IdListDelete(sqlite3 *db, IdList *pList);
extern void exposed_sqlite3SrcListDelete(sqlite3 *db, SrcList *pList);
extern void exposed_sqlite3SelectDelete(sqlite3 *db, Select *p);
extern void exposed_sqlite3BeginTrigger(Parse *pParse,
Token *pName1,
Token *pName2,
int tr_tm,
int op,
IdList *pColumns,
SrcList *pTableName,
Expr *pWhen,
int isTemp,
int noErr);
extern void exposed_sqlite3FinishTrigger(Parse *pParse,
TriggerStep *pStepList,
Token *pAll);
extern int exposed_sqlite3Dequote(char *z);
extern int exposed_sqlite3EndTable(Parse*, Token*, Token*, u8, Select*);
extern int exposed_sqlite3Select(Parse* pParse, Select* p, SelectDest* pDest);
extern void exposed_sqlite3StartTable(Parse *pParse, /* Parser context */
Token *pName1, /* First part of the name of the table or view */
Token *pName2, /* Second part of the name of the table or view */
int isTemp, /* True if this is a TEMP table */
int isView, /* True if this is a VIEW */
int isVirtual, /* True if this is a VIRTUAL table */
int noErr); /* Do nothing if table already exists */
}
extern "C" extern "C"
{ {
@ -1649,7 +1705,7 @@ static void update_field_infos_from_idlist(QcSqliteInfo* info,
} }
} }
static void update_field_infos_from_select(QcSqliteInfo* info, static void update_field_infos_from_select(QcSqliteInfo* pInfo,
const Select* pSelect, const Select* pSelect,
uint32_t usage, uint32_t usage,
const ExprList* pExclude) const ExprList* pExclude)
@ -1662,7 +1718,7 @@ static void update_field_infos_from_select(QcSqliteInfo* info,
{ {
if (pSrc->a[i].zName) if (pSrc->a[i].zName)
{ {
update_names(info, pSrc->a[i].zDatabase, pSrc->a[i].zName); pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName);
} }
if (pSrc->a[i].pSelect) if (pSrc->a[i].pSelect)
@ -1672,7 +1728,7 @@ static void update_field_infos_from_select(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, pSrc->a[i].pSelect, sub_usage, pExclude); update_field_infos_from_select(pInfo, pSrc->a[i].pSelect, sub_usage, pExclude);
} }
#ifdef QC_COLLECT_NAMES_FROM_USING #ifdef QC_COLLECT_NAMES_FROM_USING
@ -1682,7 +1738,7 @@ static void update_field_infos_from_select(QcSqliteInfo* info,
// 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(info, pSrc->a[i].pUsing, 0, pSelect->pEList); update_field_infos_from_idlist(pInfo, pSrc->a[i].pUsing, 0, pSelect->pEList);
} }
#endif #endif
} }
@ -1690,112 +1746,53 @@ static void update_field_infos_from_select(QcSqliteInfo* info,
if (pSelect->pEList) if (pSelect->pEList)
{ {
update_field_infos_from_exprlist(info, pSelect->pEList, usage, NULL); update_field_infos_from_exprlist(pInfo, pSelect->pEList, usage, NULL);
} }
if (pSelect->pWhere) if (pSelect->pWhere)
{ {
info->has_clause = true; pInfo->has_clause = true;
update_field_infos(info, 0, pSelect->pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pSelect->pEList); update_field_infos(pInfo, 0, pSelect->pWhere, QC_USED_IN_WHERE, QC_TOKEN_MIDDLE, pSelect->pEList);
} }
if (pSelect->pGroupBy) if (pSelect->pGroupBy)
{ {
update_field_infos_from_exprlist(info, pSelect->pGroupBy, QC_USED_IN_GROUP_BY, pSelect->pEList); update_field_infos_from_exprlist(pInfo, pSelect->pGroupBy, QC_USED_IN_GROUP_BY, pSelect->pEList);
} }
if (pSelect->pHaving) if (pSelect->pHaving)
{ {
info->has_clause = true; pInfo->has_clause = true;
#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(info, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList); update_field_infos(pInfo, 0, pSelect->pHaving, 0, QC_TOKEN_MIDDLE, pSelect->pEList);
#endif #endif
} }
if (pSelect->pWith) if (pSelect->pWith)
{ {
update_field_infos_from_with(info, pSelect->pWith); update_field_infos_from_with(pInfo, pSelect->pWith);
} }
if ((pSelect->op == TK_UNION) && pSelect->pPrior) if ((pSelect->op == TK_UNION) && pSelect->pPrior)
{ {
update_field_infos_from_select(info, pSelect->pPrior, usage, pExclude); update_field_infos_from_select(pInfo, pSelect->pPrior, usage, pExclude);
} }
} }
static void update_database_names(QcSqliteInfo* info, const char* zDatabase) static void update_names_from_srclist(QcSqliteInfo* pInfo, const SrcList* pSrc)
{
char* zCopy = MXS_STRDUP(zDatabase);
MXS_ABORT_IF_NULL(zCopy);
exposed_sqlite3Dequote(zCopy);
enlarge_string_array(1, info->database_names_len,
&info->database_names, &info->database_names_capacity);
info->database_names[info->database_names_len++] = zCopy;
info->database_names[info->database_names_len] = NULL;
}
static void update_names(QcSqliteInfo* info, const char* zDatabase, const char* zTable)
{
if ((info->collect & QC_COLLECT_TABLES) && !(info->collected & QC_COLLECT_TABLES))
{
if (strcasecmp(zTable, "DUAL") != 0)
{
char* zCopy = MXS_STRDUP(zTable);
MXS_ABORT_IF_NULL(zCopy);
// TODO: Is this call really needed. Check also sqlite3Dequote.
exposed_sqlite3Dequote(zCopy);
enlarge_string_array(1, info->table_names_len, &info->table_names, &info->table_names_capacity);
info->table_names[info->table_names_len++] = zCopy;
info->table_names[info->table_names_len] = NULL;
if (zDatabase)
{
zCopy = (char*)MXS_MALLOC(strlen(zDatabase) + 1 + strlen(zTable) + 1);
MXS_ABORT_IF_NULL(zCopy);
strcpy(zCopy, zDatabase);
strcat(zCopy, ".");
strcat(zCopy, zTable);
exposed_sqlite3Dequote(zCopy);
}
else
{
zCopy = MXS_STRDUP(zCopy);
MXS_ABORT_IF_NULL(zCopy);
}
enlarge_string_array(1, info->table_fullnames_len,
&info->table_fullnames, &info->table_fullnames_capacity);
info->table_fullnames[info->table_fullnames_len++] = zCopy;
info->table_fullnames[info->table_fullnames_len] = NULL;
}
}
if ((info->collect & QC_COLLECT_DATABASES) && !(info->collected & QC_COLLECT_DATABASES))
{
if (zDatabase)
{
update_database_names(info, zDatabase);
}
}
}
static void update_names_from_srclist(QcSqliteInfo* info, 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)
{ {
update_names(info, pSrc->a[i].zDatabase, pSrc->a[i].zName); pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName);
} }
if (pSrc->a[i].pSelect && pSrc->a[i].pSelect->pSrc) if (pSrc->a[i].pSelect && pSrc->a[i].pSelect->pSrc)
{ {
update_names_from_srclist(info, pSrc->a[i].pSelect->pSrc); update_names_from_srclist(pInfo, pSrc->a[i].pSelect->pSrc);
} }
} }
} }
@ -1887,7 +1884,7 @@ void mxs_sqlite3BeginTrigger(Parse *pParse, /* The parse context of the CRE
if (pItem->zName) if (pItem->zName)
{ {
update_names(info, pItem->zDatabase, pItem->zName); info->update_names(pItem->zDatabase, pItem->zName);
} }
} }
} }
@ -1934,7 +1931,7 @@ void mxs_sqlite3CreateIndex(Parse *pParse, /* All information about this par
} }
else if (pParse->pNewTable) else if (pParse->pNewTable)
{ {
update_names(info, NULL, pParse->pNewTable->zName); info->update_names(NULL, pParse->pNewTable->zName);
} }
exposed_sqlite3ExprDelete(pParse->db, pPIWhere); exposed_sqlite3ExprDelete(pParse->db, pPIWhere);
@ -1972,11 +1969,11 @@ void mxs_sqlite3CreateView(Parse *pParse, /* The parsing context */
strncpy(database, pDatabase->z, pDatabase->n); strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0; database[pDatabase->n] = 0;
update_names(info, database, name); info->update_names(database, name);
} }
else else
{ {
update_names(info, NULL, name); info->update_names(NULL, name);
} }
if (pSelect) if (pSelect)
@ -2011,7 +2008,7 @@ void mxs_sqlite3DeleteFrom(Parse* pParse, SrcList* pTabList, Expr* pWhere, SrcLi
{ {
const SrcList::SrcList_item* pItem = &pUsing->a[i]; const SrcList::SrcList_item* pItem = &pUsing->a[i];
update_names(info, pItem->zDatabase, pItem->zName); info->update_names(pItem->zDatabase, pItem->zName);
} }
// Walk through the tablenames while excluding alias // Walk through the tablenames while excluding alias
@ -2041,7 +2038,7 @@ void mxs_sqlite3DeleteFrom(Parse* pParse, SrcList* pTabList, Expr* pWhere, SrcLi
if (!isSame) if (!isSame)
{ {
// No alias name, update the table name. // No alias name, update the table name.
update_names(info, pTable->zDatabase, pTable->zName); info->update_names(pTable->zDatabase, pTable->zName);
} }
} }
} }
@ -2275,11 +2272,11 @@ void mxs_sqlite3StartTable(Parse *pParse, /* Parser context */
strncpy(database, pDatabase->z, pDatabase->n); strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0; database[pDatabase->n] = 0;
update_names(info, database, name); info->update_names(database, name);
} }
else else
{ {
update_names(info, NULL, name); info->update_names(NULL, name);
} }
if (info->collect & QC_COLLECT_TABLES) if (info->collect & QC_COLLECT_TABLES)
@ -2468,7 +2465,7 @@ void maxscaleCreateSequence(Parse* pParse, Token* pDatabase, Token* pTable)
strncpy(table, pTable->z, pTable->n); strncpy(table, pTable->z, pTable->n);
table[pTable->n] = 0; table[pTable->n] = 0;
update_names(info, zDatabase, table); info->update_names(zDatabase, table);
} }
void maxscaleComment() void maxscaleComment()
@ -2567,7 +2564,7 @@ void maxscaleDrop(Parse* pParse, int what, Token* pDatabase, Token* pName)
strncpy(table, pName->z, pName->n); strncpy(table, pName->z, pName->n);
table[pName->n] = 0; table[pName->n] = 0;
update_names(info, zDatabase, table); info->update_names(zDatabase, table);
} }
} }
@ -2734,7 +2731,7 @@ void maxscaleHandler(Parse* pParse, mxs_handler_t type, SrcList* pFullName, Toke
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(info, pItem->zDatabase, pItem->zName); info->update_names(pItem->zDatabase, pItem->zName);
} }
break; break;
@ -2746,7 +2743,7 @@ void maxscaleHandler(Parse* pParse, mxs_handler_t type, SrcList* pFullName, Toke
strncpy(zName, pName->z, pName->n); strncpy(zName, pName->z, pName->n);
zName[pName->n] = 0; zName[pName->n] = 0;
update_names(info, "*any*", zName); info->update_names("*any*", zName);
} }
break; break;
@ -3086,8 +3083,8 @@ void maxscaleRenameTable(Parse* pParse, SrcList* pTables)
ss_dassert(pItem->zName); ss_dassert(pItem->zName);
ss_dassert(pItem->zAlias); ss_dassert(pItem->zAlias);
update_names(info, pItem->zDatabase, pItem->zName); info->update_names(pItem->zDatabase, pItem->zName);
update_names(info, NULL, pItem->zAlias); // The new name is passed in the alias field. info->update_names(NULL, pItem->zAlias); // The new name is passed in the alias field.
} }
exposed_sqlite3SrcListDelete(pParse->db, pTables); exposed_sqlite3SrcListDelete(pParse->db, pTables);
@ -3542,7 +3539,7 @@ void maxscaleTruncate(Parse* pParse, Token* pDatabase, Token* pName)
strncpy(name, pName->z, pName->n); strncpy(name, pName->z, pName->n);
name[pName->n] = 0; name[pName->n] = 0;
update_names(info, zDatabase, name); info->update_names(zDatabase, name);
} }
void maxscaleUse(Parse* pParse, Token* pToken) void maxscaleUse(Parse* pParse, Token* pToken)