MXS-1340 Collect alias names

Alias names for tables are now collected, so that the true
table name of a referred to field can be reported. That modification
will be made in a subsequent commit.
This commit is contained in:
Johan Wikman 2017-08-03 10:54:03 +03:00
parent 5933062666
commit eecd7a03c5

View File

@ -17,6 +17,8 @@
#include <signal.h>
#include <string.h>
#include <new>
#include <string>
#include <map>
#include <maxscale/alloc.h>
#include <maxscale/log_manager.h>
#include <maxscale/modinfo.h>
@ -75,11 +77,11 @@ static QC_NAME_MAPPING function_name_mappings_default[] =
static QC_NAME_MAPPING function_name_mappings_103[] =
{
// NOTE: If something is added here, add it to function_name_mappings_oracle as well.
{ "now", "current_timestamp" },
{ NULL, NULL }
};
// NOTE: Duplicate the information from function_name_mappings_103 here.
static QC_NAME_MAPPING function_name_mappings_oracle[] =
{
{ "now", "current_timestamp" },
@ -87,6 +89,26 @@ static QC_NAME_MAPPING function_name_mappings_oracle[] =
{ NULL, NULL }
};
/**
* Stores alias information. The key in the mapping is the alias name,
* and an instance of this struct contains the actual table/database.
*
* zDatabase and zTable point to memory that belongs to QcSqliteInfo
* so they can be simply copied in all contexts.
*/
struct QcAliasValue
{
QcAliasValue(const char* zD, const char* zT)
: zDatabase(zD)
, zTable(zT)
{
}
const char* zDatabase;
const char* zTable;
};
/**
* The state of qc_sqlite.
*/
@ -438,58 +460,52 @@ public:
}
// PUBLIC for now at least.
void update_names(const char* zDatabase, const char* zTable)
void update_names(const char* zDatabase, const char* zTable, const char* zAlias)
{
if ((m_collect & QC_COLLECT_TABLES) && !(m_collected & QC_COLLECT_TABLES))
ss_dassert(zTable);
bool should_collect_alias = zAlias && should_collect(QC_COLLECT_FIELDS);
bool should_collect_table = should_collect_alias || should_collect(QC_COLLECT_TABLES);
bool should_collect_database = zDatabase &&
(should_collect_alias || should_collect(QC_COLLECT_DATABASES));
const char* zCollected_database = NULL;
const char* zCollected_table = NULL;
size_t nDatabase = zDatabase ? strlen(zDatabase) : 0;
size_t nTable = zTable ? strlen(zTable) : 0;
char database[nDatabase + 1];
char table[nTable + 1];
if (should_collect_database)
{
strcpy(database, zDatabase);
exposed_sqlite3Dequote(database);
}
if (should_collect_table)
{
if (strcasecmp(zTable, "DUAL") != 0)
{
size_t table_len = strlen(zTable);
char table[table_len + 1];
strcpy(table, zTable);
// TODO: Is this call really needed. Check also sqlite3Dequote.
exposed_sqlite3Dequote(table);
if (!table_name_collected(table))
{
char* zCopy = MXS_STRDUP_A(table);
enlarge_string_array(1, m_table_names_len, &m_pzTable_names, &m_table_names_capacity);
m_pzTable_names[m_table_names_len++] = zCopy;
m_pzTable_names[m_table_names_len] = NULL;
}
size_t database_len = zDatabase ? strlen(zDatabase) : 0;
char fullname[database_len + 1 + table_len + 1];
if (zDatabase)
{
strcpy(fullname, zDatabase);
// TODO: Is this call really needed. Check also sqlite3Dequote.
exposed_sqlite3Dequote(fullname);
strcat(fullname, ".");
}
else
{
fullname[0] = 0;
}
strcat(fullname, table);
if (!table_fullname_collected(fullname))
{
char* zCopy = MXS_STRDUP_A(fullname);
enlarge_string_array(1, m_table_fullnames_len,
&m_pzTable_fullnames, &m_table_fullnames_capacity);
m_pzTable_fullnames[m_table_fullnames_len++] = zCopy;
m_pzTable_fullnames[m_table_fullnames_len] = NULL;
}
zCollected_table = update_table_names(database, nDatabase, table, nTable);
}
}
update_database_names(zDatabase);
if (should_collect_database)
{
zCollected_database = update_database_names(database);
}
if (zCollected_table && zAlias)
{
QcAliasValue value(zCollected_database, zCollected_table);
m_aliases.insert(Aliases::value_type(zAlias, value));
}
}
private:
@ -530,6 +546,11 @@ private:
}
private:
bool should_collect(qc_collect_info_t collect) const
{
return ((m_collect & collect) && !(m_collected & collect));
}
static void free_field_infos(QC_FIELD_INFO* pInfos, size_t nInfos)
{
if (pInfos)
@ -601,7 +622,7 @@ private:
return pz;
}
bool table_name_collected(const char* zTable)
const char* table_name_collected(const char* zTable)
{
size_t i = 0;
@ -610,10 +631,10 @@ private:
++i;
}
return i != m_table_names_len;
return (i != m_table_names_len) ? m_pzTable_names[i] : NULL;
}
bool table_fullname_collected(const char* zTable)
const char* table_fullname_collected(const char* zTable)
{
size_t i = 0;
@ -622,10 +643,10 @@ private:
++i;
}
return i != m_table_fullnames_len;
return (i != m_table_fullnames_len) ? m_pzTable_fullnames[i] : NULL;
}
bool database_name_collected(const char* zDatabase)
const char* database_name_collected(const char* zDatabase)
{
size_t i = 0;
@ -634,33 +655,79 @@ private:
++i;
}
return i != m_database_names_len;
return (i != m_database_names_len) ? m_pzDatabase_names[i] : NULL;
}
void update_database_names(const char* zDatabase)
const char* update_table_names(const char* zDatabase, size_t nDatabase,
const char* zTable, size_t nTable)
{
if ((m_collect & QC_COLLECT_DATABASES) && !(m_collected & QC_COLLECT_DATABASES))
ss_dassert(zTable && nTable);
const char* zCollected_table = table_name_collected(zTable);
if (!zCollected_table)
{
if (zDatabase)
{
char database[strlen(zDatabase) + 1];
strcpy(database, zDatabase);
exposed_sqlite3Dequote(database);
char* zCopy = MXS_STRDUP_A(zTable);
if (!database_name_collected(database))
{
char* zCopy = MXS_STRDUP_A(database);
enlarge_string_array(1, m_table_names_len, &m_pzTable_names, &m_table_names_capacity);
m_pzTable_names[m_table_names_len++] = zCopy;
m_pzTable_names[m_table_names_len] = NULL;
enlarge_string_array(1, m_database_names_len,
&m_pzDatabase_names, &m_database_names_capacity);
m_pzDatabase_names[m_database_names_len++] = zCopy;
m_pzDatabase_names[m_database_names_len] = NULL;
}
}
zCollected_table = zCopy;
}
char fullname[nDatabase + 1 + nTable + 1];
if (nDatabase)
{
strcpy(fullname, zDatabase);
strcat(fullname, ".");
}
else
{
fullname[0] = 0;
}
strcat(fullname, zTable);
if (!table_fullname_collected(fullname))
{
char* zCopy = MXS_STRDUP_A(fullname);
enlarge_string_array(1, m_table_fullnames_len,
&m_pzTable_fullnames, &m_table_fullnames_capacity);
m_pzTable_fullnames[m_table_fullnames_len++] = zCopy;
m_pzTable_fullnames[m_table_fullnames_len] = NULL;
}
return zCollected_table;
}
const char* update_database_names(const char* zDatabase)
{
ss_dassert(zDatabase);
ss_dassert(strlen(zDatabase) != 0);
const char* zCollected_database = database_name_collected(zDatabase);
if (!zCollected_database)
{
char* zCopy = MXS_STRDUP_A(zDatabase);
enlarge_string_array(1, m_database_names_len,
&m_pzDatabase_names, &m_database_names_capacity);
m_pzDatabase_names[m_database_names_len++] = zCopy;
m_pzDatabase_names[m_database_names_len] = NULL;
zCollected_database = zCopy;
}
return zCollected_database;
}
public:
typedef std::map<std::string, QcAliasValue> Aliases;
// TODO: Make these private once everything's been updated.
qc_parse_result_t m_status; // The validity of the information in this structure.
uint32_t m_collect; // What information should be collected.
@ -695,6 +762,7 @@ public:
bool m_initializing; // Whether we are initializing sqlite3.
qc_sql_mode_t m_sql_mode; // The current sql_mode.
QC_NAME_MAPPING* m_pFunction_name_mappings; // How function names should be mapped.
Aliases m_aliases; // Alias names for tables
};
extern "C"
@ -1772,7 +1840,7 @@ static void update_field_infos_from_select(QcSqliteInfo* pInfo,
{
if (pSrc->a[i].zName)
{
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName);
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias);
}
if (pSrc->a[i].pSelect)
@ -1841,7 +1909,7 @@ static void update_names_from_srclist(QcSqliteInfo* pInfo, const SrcList* pSrc)
{
if (pSrc->a[i].zName)
{
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName);
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias);
}
if (pSrc->a[i].pSelect && pSrc->a[i].pSelect->pSrc)
@ -1938,7 +2006,7 @@ void mxs_sqlite3BeginTrigger(Parse *pParse, /* The parse context of the CRE
if (pItem->zName)
{
info->update_names(pItem->zDatabase, pItem->zName);
info->update_names(pItem->zDatabase, pItem->zName, pItem->zAlias);
}
}
}
@ -1985,7 +2053,7 @@ void mxs_sqlite3CreateIndex(Parse *pParse, /* All information about this par
}
else if (pParse->pNewTable)
{
info->update_names(NULL, pParse->pNewTable->zName);
info->update_names(NULL, pParse->pNewTable->zName, NULL);
}
exposed_sqlite3ExprDelete(pParse->db, pPIWhere);
@ -2023,11 +2091,11 @@ void mxs_sqlite3CreateView(Parse *pParse, /* The parsing context */
strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0;
info->update_names(database, name);
info->update_names(database, name, NULL);
}
else
{
info->update_names(NULL, name);
info->update_names(NULL, name, NULL);
}
if (pSelect)
@ -2062,7 +2130,7 @@ void mxs_sqlite3DeleteFrom(Parse* pParse, SrcList* pTabList, Expr* pWhere, SrcLi
{
const SrcList::SrcList_item* pItem = &pUsing->a[i];
info->update_names(pItem->zDatabase, pItem->zName);
info->update_names(pItem->zDatabase, pItem->zName, pItem->zAlias);
}
// Walk through the tablenames while excluding alias
@ -2092,7 +2160,7 @@ void mxs_sqlite3DeleteFrom(Parse* pParse, SrcList* pTabList, Expr* pWhere, SrcLi
if (!isSame)
{
// No alias name, update the table name.
info->update_names(pTable->zDatabase, pTable->zName);
info->update_names(pTable->zDatabase, pTable->zName, NULL);
}
}
}
@ -2326,11 +2394,11 @@ void mxs_sqlite3StartTable(Parse *pParse, /* Parser context */
strncpy(database, pDatabase->z, pDatabase->n);
database[pDatabase->n] = 0;
info->update_names(database, name);
info->update_names(database, name, NULL);
}
else
{
info->update_names(NULL, name);
info->update_names(NULL, name, NULL);
}
if (info->m_collect & QC_COLLECT_TABLES)
@ -2519,7 +2587,7 @@ void maxscaleCreateSequence(Parse* pParse, Token* pDatabase, Token* pTable)
strncpy(table, pTable->z, pTable->n);
table[pTable->n] = 0;
info->update_names(zDatabase, table);
info->update_names(zDatabase, table, NULL);
}
void maxscaleComment()
@ -2618,7 +2686,7 @@ void maxscaleDrop(Parse* pParse, int what, Token* pDatabase, Token* pName)
strncpy(table, pName->z, pName->n);
table[pName->n] = 0;
info->update_names(zDatabase, table);
info->update_names(zDatabase, table, NULL);
}
}
@ -2785,7 +2853,7 @@ void maxscaleHandler(Parse* pParse, mxs_handler_t type, SrcList* pFullName, Toke
ss_dassert(pFullName->nSrc == 1);
const SrcList::SrcList_item* pItem = &pFullName->a[0];
info->update_names(pItem->zDatabase, pItem->zName);
info->update_names(pItem->zDatabase, pItem->zName, pItem->zAlias);
}
break;
@ -2797,7 +2865,7 @@ void maxscaleHandler(Parse* pParse, mxs_handler_t type, SrcList* pFullName, Toke
strncpy(zName, pName->z, pName->n);
zName[pName->n] = 0;
info->update_names("*any*", zName);
info->update_names("*any*", zName, NULL);
}
break;
@ -3137,8 +3205,8 @@ void maxscaleRenameTable(Parse* pParse, SrcList* pTables)
ss_dassert(pItem->zName);
ss_dassert(pItem->zAlias);
info->update_names(pItem->zDatabase, pItem->zName);
info->update_names(NULL, pItem->zAlias); // The new name is passed in the alias field.
info->update_names(pItem->zDatabase, pItem->zName, NULL);
info->update_names(NULL, pItem->zAlias, NULL); // The new name is passed in the alias field.
}
exposed_sqlite3SrcListDelete(pParse->db, pTables);
@ -3593,7 +3661,7 @@ void maxscaleTruncate(Parse* pParse, Token* pDatabase, Token* pName)
strncpy(name, pName->z, pName->n);
name[pName->n] = 0;
info->update_names(zDatabase, name);
info->update_names(zDatabase, name, NULL);
}
void maxscaleUse(Parse* pParse, Token* pToken)