new object iteration logic including fix for crash reported in issue #31

pull/36/head
Guy Lichtman 2013-02-22 16:58:28 +02:00
parent f717564993
commit bc92825963
3 changed files with 157 additions and 83 deletions

View File

@ -79,14 +79,35 @@ public:
class ThdSesData {
public:
//enum indicating from where the object list came from
enum ObjectIterType {OBJ_NONE, OBJ_DB, OBJ_QUERY_CACHE, OBJ_TABLE_LIST};
ThdSesData(THD *pTHD);
THD* getTHD () { return m_pThd;}
const char * getCmdName () { return m_CmdName; }
const char * getUserName () { return m_UserName; }
/**
* Start fetching objects. Return true if there are objects available.
*/
bool startGetObjects();
/**
* Get next object. Return true if populated. False if there isn't an object available.
* Will point the passed pointers to point to db, name and type.
* obj_type is optional and may be null.
*/
bool getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type);
private:
THD *m_pThd;
const char *m_CmdName;
const char *m_UserName;
enum ObjectIterType m_objIterType;
//pointer for iterating tables
TABLE_LIST * m_tables;
//indicator if we are at the first table
bool m_firstTable;
//used for query cache iter
QueryTableInf * m_tableInf;
int m_index;
protected:
ThdSesData (const ThdSesData& );
ThdSesData &operator =(const ThdSesData& );

View File

@ -414,71 +414,25 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
yajl_add_string_val(gen, "host", sctx->host);
yajl_add_string_val(gen, "ip", sctx->ip);
const char *cmd = pThdData->getCmdName();
//only print tables if lex is not null and it is not a quit command
LEX * pLex = Audit_formatter::thd_lex(pThdData->getTHD());
QueryTableInf *pQuery_cache_table_list = getQueryCacheTableList1 (pThdData->getTHD());
if (pLex && command != COM_QUIT && pLex->query_tables == NULL && pQuery_cache_table_list)
{
yajl_add_string_val(gen, "cmd", "select");
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
for (int i=0;i<pQuery_cache_table_list->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && pQuery_cache_table_list->num_of_elem >=0;i++)
{
yajl_gen_map_open(gen);
yajl_add_obj (gen, pQuery_cache_table_list->db[i],pQuery_cache_table_list->object_type[i],pQuery_cache_table_list->table_name[i] );
yajl_gen_map_close(gen);
}
yajl_gen_array_close(gen);
}
else
{
yajl_add_string_val(gen, "cmd", cmd);
}
if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0)
{
if ((pThdData->getTHD())->db !=0)
{
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
yajl_add_obj (gen,(pThdData->getTHD())->db,"database", NULL);
yajl_gen_array_close(gen);
}
}
if (pLex && command != COM_QUIT && pLex->query_tables)
yajl_add_string_val(gen, "cmd", cmd);
//get objects
if(pThdData->startGetObjects())
{
yajl_add_string(gen, "objects");
yajl_gen_array_open(gen);
TABLE_LIST * table = pLex->query_tables;
bool isFirstElementInView = true;
while (table)
const char * db_name = NULL;
const char * obj_name = NULL;
const char * obj_type = NULL;
while(pThdData->getNextObject(&db_name, &obj_name, &obj_type))
{
yajl_gen_map_open(gen);
if (isFirstElementInView && strstr (cmd,"_view")!=NULL )
{
yajl_add_obj (gen,table->get_db_name(), "view",table->get_table_name());
isFirstElementInView = false;
}
else
{
yajl_add_obj (gen,table->get_db_name(), retrive_object_type(table),table->get_table_name());
}
yajl_add_obj (gen, db_name, obj_type, obj_name );
yajl_gen_map_close(gen);
table = table->next_global;
}
yajl_gen_array_close(gen);
}
size_t qlen = 0;
const char * query = thd_query_str(pThdData->getTHD(), &qlen);
if (query && qlen > 0)
{
@ -527,9 +481,116 @@ ssize_t Audit_json_formatter::event_format(ThdSesData* pThdData, IWriter * write
ThdSesData::ThdSesData (THD *pTHD) : m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL)
ThdSesData::ThdSesData (THD *pTHD) :
m_pThd (pTHD), m_CmdName(NULL), m_UserName(NULL),
m_objIterType(OBJ_NONE), m_tables(NULL), m_firstTable(true),
m_tableInf(NULL), m_index(0)
{
m_CmdName = retrieve_command (m_pThd);
m_UserName = retrieve_user (m_pThd);
}
bool ThdSesData::startGetObjects()
{
//reset vars as this may be called multiple times
m_objIterType = OBJ_NONE;
m_tables = NULL;
m_firstTable = true;
m_index = 0;
m_tableInf = Audit_formatter::getQueryCacheTableList1(getTHD());
int command = Audit_formatter::thd_inst_command(getTHD());
LEX * pLex = Audit_formatter::thd_lex(getTHD());
//query cache case
if(pLex && command == COM_QUERY && m_tableInf && m_tableInf->num_of_elem > 0)
{
m_objIterType = OBJ_QUERY_CACHE;
return true;
}
const char *cmd = getCmdName();
//commands which have single database object
if (strcmp (cmd,"Init DB") ==0 || strcmp (cmd, "SHOW TABLES")== 0 || strcmp (cmd, "SHOW TABLE")==0)
{
if(getTHD()->db)
{
m_objIterType = OBJ_DB;
return true;
}
return false;
}
//only return query tabls if command is COM_QUERY
//TODO: check if other commands can also generate query tables such as "show fields"
if (pLex && command == COM_QUERY && pLex->query_tables)
{
m_tables = pLex->query_tables;
m_objIterType = OBJ_TABLE_LIST;
return true;
}
//no objects
return false;
}
bool ThdSesData::getNextObject(const char ** db_name, const char ** obj_name, const char ** obj_type)
{
switch(m_objIterType)
{
case OBJ_DB:
{
if(m_firstTable)
{
*db_name = getTHD()->db;
*obj_name = NULL;
if(obj_type)
{
*obj_type = "DATABASE";
}
m_firstTable = false;
return true;
}
return false;
}
case OBJ_QUERY_CACHE:
{
if(m_index < m_tableInf->num_of_elem &&
m_index< MAX_NUM_QUERY_TABLE_ELEM)
{
*db_name = m_tableInf->db[m_index];
*obj_name = m_tableInf->table_name[m_index];
if(obj_type)
{
*obj_type = m_tableInf->object_type[m_index];
}
m_index++;
return true;
}
return false;
}
case OBJ_TABLE_LIST:
{
if(m_tables)
{
*db_name = m_tables->get_db_name();
*obj_name = m_tables->get_table_name();
if(obj_type)
{
//object is a view if it view command (alter_view, drop_view ..)
//and first object or view field is populated
if((m_firstTable && strstr(getCmdName(), "_view") != NULL) ||
m_tables->view)
{
*obj_type = "VIEW";
m_firstTable = false;
}
else
{
*obj_type = "TABLE";
}
}
m_tables = m_tables->next_global;
return true;
}
return false;
}
default :
return false;
}
}

View File

@ -680,35 +680,22 @@ static void audit(ThdSesData *pThdData)
}
}
if (num_record_objs > 0) {
LEX *pLex = Audit_formatter::thd_lex(pThdData->getTHD());
TABLE_LIST * table = pLex->query_tables;
//when statement is returned from query cache, objects will be included in pQueryTableInf
QueryTableInf * pQueryTableInf = (QueryTableInf*)THDVAR(pThdData->getTHD(), query_cache_table_list);
int matched = 0;
if(strcmp(pThdData->getCmdName(),"Quit") == 0 || (!table && (!pQueryTableInf || pQueryTableInf->num_of_elem <= 0))) //empty list of objects
bool matched = false;
if(pThdData->startGetObjects())
{
matched = record_empty_objs_set;
}
else
{
if(pQueryTableInf) //query cache case
const char * db_name = NULL;
const char * obj_name = NULL;
while(!matched && pThdData->getNextObject(&db_name, &obj_name, NULL))
{
for (int i=0; i < pQueryTableInf->num_of_elem && i < MAX_NUM_QUERY_TABLE_ELEM && !matched ; i++)
{
matched = check_db_obj(pQueryTableInf->db[i], pQueryTableInf->table_name[i]);
}
}
else
{
while (table && !matched)
{
matched = check_db_obj(table->get_db_name(), table->get_table_name());
table = table->next_global;
}
matched = check_db_obj(db_name, obj_name);
}
}
else //no objects
{
matched = record_empty_objs_set;
}
if (!matched) {
return;
return;
}
}
if (pThdPrintedList && pThdPrintedList->cur_index < MAX_NUM_QUEUE_ELEM)
@ -1327,6 +1314,11 @@ const char * retrieve_command (THD * thd)
{
command = COM_END;
}
//check if from query cache. If so set to select and return
if(THDVAR(thd, query_cache_table_list) != 0)
{
return "select";
}
const int sql_command = thd_sql_command(thd);
if (sql_command >=0 && sql_command <= (MAX_COM_STATUS_VARS_RECORDS -1) )
{
@ -1337,7 +1329,7 @@ const char * retrieve_command (THD * thd)
cmd = command_name[command].str;
}
Security_context * sctx = Audit_formatter::thd_inst_main_security_ctx(thd);
if (strcmp (cmd, "Connect") ==0 && (sctx->priv_user == NULL || *sctx->priv_user == 0x0))
if (strcmp (cmd, "Connect") ==0 && ((sctx->user && strcmp(sctx->user, "event_scheduler") != 0) && (sctx->priv_user == NULL || *sctx->priv_user == 0x0)))
{
cmd = "Failed Login";
}