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:
@ -17,6 +17,8 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include <maxscale/modinfo.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[] =
|
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" },
|
{ "now", "current_timestamp" },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: Duplicate the information from function_name_mappings_103 here.
|
|
||||||
static QC_NAME_MAPPING function_name_mappings_oracle[] =
|
static QC_NAME_MAPPING function_name_mappings_oracle[] =
|
||||||
{
|
{
|
||||||
{ "now", "current_timestamp" },
|
{ "now", "current_timestamp" },
|
||||||
@ -87,6 +89,26 @@ static QC_NAME_MAPPING function_name_mappings_oracle[] =
|
|||||||
{ NULL, NULL }
|
{ 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.
|
* The state of qc_sqlite.
|
||||||
*/
|
*/
|
||||||
@ -438,59 +460,53 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PUBLIC for now at least.
|
// 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)
|
if (strcasecmp(zTable, "DUAL") != 0)
|
||||||
{
|
{
|
||||||
size_t table_len = strlen(zTable);
|
|
||||||
char table[table_len + 1];
|
|
||||||
|
|
||||||
strcpy(table, zTable);
|
strcpy(table, zTable);
|
||||||
// TODO: Is this call really needed. Check also sqlite3Dequote.
|
|
||||||
exposed_sqlite3Dequote(table);
|
exposed_sqlite3Dequote(table);
|
||||||
|
|
||||||
if (!table_name_collected(table))
|
zCollected_table = update_table_names(database, nDatabase, table, nTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_collect_database)
|
||||||
{
|
{
|
||||||
char* zCopy = MXS_STRDUP_A(table);
|
zCollected_database = update_database_names(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t database_len = zDatabase ? strlen(zDatabase) : 0;
|
if (zCollected_table && zAlias)
|
||||||
char fullname[database_len + 1 + table_len + 1];
|
|
||||||
|
|
||||||
if (zDatabase)
|
|
||||||
{
|
{
|
||||||
strcpy(fullname, zDatabase);
|
QcAliasValue value(zCollected_database, zCollected_table);
|
||||||
// TODO: Is this call really needed. Check also sqlite3Dequote.
|
|
||||||
exposed_sqlite3Dequote(fullname);
|
|
||||||
strcat(fullname, ".");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fullname[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(fullname, table);
|
m_aliases.insert(Aliases::value_type(zAlias, value));
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
update_database_names(zDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QcSqliteInfo(uint32_t cllct)
|
QcSqliteInfo(uint32_t cllct)
|
||||||
@ -530,6 +546,11 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
static void free_field_infos(QC_FIELD_INFO* pInfos, size_t nInfos)
|
||||||
{
|
{
|
||||||
if (pInfos)
|
if (pInfos)
|
||||||
@ -601,7 +622,7 @@ private:
|
|||||||
return pz;
|
return pz;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool table_name_collected(const char* zTable)
|
const char* table_name_collected(const char* zTable)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
@ -610,10 +631,10 @@ private:
|
|||||||
++i;
|
++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;
|
size_t i = 0;
|
||||||
|
|
||||||
@ -622,10 +643,10 @@ private:
|
|||||||
++i;
|
++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;
|
size_t i = 0;
|
||||||
|
|
||||||
@ -634,33 +655,79 @@ private:
|
|||||||
++i;
|
++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);
|
||||||
{
|
|
||||||
if (zDatabase)
|
|
||||||
{
|
|
||||||
char database[strlen(zDatabase) + 1];
|
|
||||||
strcpy(database, zDatabase);
|
|
||||||
exposed_sqlite3Dequote(database);
|
|
||||||
|
|
||||||
if (!database_name_collected(database))
|
const char* zCollected_table = table_name_collected(zTable);
|
||||||
|
|
||||||
|
if (!zCollected_table)
|
||||||
{
|
{
|
||||||
char* zCopy = MXS_STRDUP_A(database);
|
char* zCopy = MXS_STRDUP_A(zTable);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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,
|
enlarge_string_array(1, m_database_names_len,
|
||||||
&m_pzDatabase_names, &m_database_names_capacity);
|
&m_pzDatabase_names, &m_database_names_capacity);
|
||||||
m_pzDatabase_names[m_database_names_len++] = zCopy;
|
m_pzDatabase_names[m_database_names_len++] = zCopy;
|
||||||
m_pzDatabase_names[m_database_names_len] = NULL;
|
m_pzDatabase_names[m_database_names_len] = NULL;
|
||||||
|
|
||||||
|
zCollected_database = zCopy;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return zCollected_database;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
||||||
@ -695,6 +762,7 @@ public:
|
|||||||
bool m_initializing; // Whether we are initializing sqlite3.
|
bool m_initializing; // Whether we are initializing sqlite3.
|
||||||
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"
|
||||||
@ -1772,7 +1840,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);
|
pInfo->update_names(pSrc->a[i].zDatabase, pSrc->a[i].zName, pSrc->a[i].zAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSrc->a[i].pSelect)
|
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)
|
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)
|
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)
|
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)
|
else if (pParse->pNewTable)
|
||||||
{
|
{
|
||||||
info->update_names(NULL, pParse->pNewTable->zName);
|
info->update_names(NULL, pParse->pNewTable->zName, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
exposed_sqlite3ExprDelete(pParse->db, pPIWhere);
|
exposed_sqlite3ExprDelete(pParse->db, pPIWhere);
|
||||||
@ -2023,11 +2091,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;
|
||||||
|
|
||||||
info->update_names(database, name);
|
info->update_names(database, name, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->update_names(NULL, name);
|
info->update_names(NULL, name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSelect)
|
if (pSelect)
|
||||||
@ -2062,7 +2130,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];
|
||||||
|
|
||||||
info->update_names(pItem->zDatabase, pItem->zName);
|
info->update_names(pItem->zDatabase, pItem->zName, pItem->zAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk through the tablenames while excluding alias
|
// Walk through the tablenames while excluding alias
|
||||||
@ -2092,7 +2160,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.
|
||||||
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);
|
strncpy(database, pDatabase->z, pDatabase->n);
|
||||||
database[pDatabase->n] = 0;
|
database[pDatabase->n] = 0;
|
||||||
|
|
||||||
info->update_names(database, name);
|
info->update_names(database, name, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->update_names(NULL, name);
|
info->update_names(NULL, name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->m_collect & QC_COLLECT_TABLES)
|
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);
|
strncpy(table, pTable->z, pTable->n);
|
||||||
table[pTable->n] = 0;
|
table[pTable->n] = 0;
|
||||||
|
|
||||||
info->update_names(zDatabase, table);
|
info->update_names(zDatabase, table, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maxscaleComment()
|
void maxscaleComment()
|
||||||
@ -2618,7 +2686,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;
|
||||||
|
|
||||||
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);
|
ss_dassert(pFullName->nSrc == 1);
|
||||||
const SrcList::SrcList_item* pItem = &pFullName->a[0];
|
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;
|
break;
|
||||||
|
|
||||||
@ -2797,7 +2865,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;
|
||||||
|
|
||||||
info->update_names("*any*", zName);
|
info->update_names("*any*", zName, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3137,8 +3205,8 @@ void maxscaleRenameTable(Parse* pParse, SrcList* pTables)
|
|||||||
ss_dassert(pItem->zName);
|
ss_dassert(pItem->zName);
|
||||||
ss_dassert(pItem->zAlias);
|
ss_dassert(pItem->zAlias);
|
||||||
|
|
||||||
info->update_names(pItem->zDatabase, pItem->zName);
|
info->update_names(pItem->zDatabase, pItem->zName, NULL);
|
||||||
info->update_names(NULL, pItem->zAlias); // The new name is passed in the alias field.
|
info->update_names(NULL, pItem->zAlias, NULL); // The new name is passed in the alias field.
|
||||||
}
|
}
|
||||||
|
|
||||||
exposed_sqlite3SrcListDelete(pParse->db, pTables);
|
exposed_sqlite3SrcListDelete(pParse->db, pTables);
|
||||||
@ -3593,7 +3661,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;
|
||||||
|
|
||||||
info->update_names(zDatabase, name);
|
info->update_names(zDatabase, name, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void maxscaleUse(Parse* pParse, Token* pToken)
|
void maxscaleUse(Parse* pParse, Token* pToken)
|
||||||
|
Reference in New Issue
Block a user