Added parameter NULL checks to query_classifier.cc
This commit is contained in:
@ -67,28 +67,18 @@ extern __thread log_info_t tls_log_info;
|
|||||||
|
|
||||||
#define QTYPE_LESS_RESTRICTIVE_THAN_WRITE(t) (t<QUERY_TYPE_WRITE ? true : false)
|
#define QTYPE_LESS_RESTRICTIVE_THAN_WRITE(t) (t<QUERY_TYPE_WRITE ? true : false)
|
||||||
|
|
||||||
static THD* get_or_create_thd_for_parsing(
|
static THD* get_or_create_thd_for_parsing(MYSQL* mysql, char* query_str);
|
||||||
MYSQL* mysql,
|
static unsigned long set_client_flags(MYSQL* mysql);
|
||||||
char* query_str);
|
static bool create_parse_tree(THD* thd);
|
||||||
|
static skygw_query_type_t resolve_query_type(THD* thd);
|
||||||
static unsigned long set_client_flags(
|
|
||||||
MYSQL* mysql);
|
|
||||||
|
|
||||||
static bool create_parse_tree(
|
|
||||||
THD* thd);
|
|
||||||
|
|
||||||
static skygw_query_type_t resolve_query_type(
|
|
||||||
THD* thd);
|
|
||||||
|
|
||||||
static bool skygw_stmt_causes_implicit_commit(
|
static bool skygw_stmt_causes_implicit_commit(
|
||||||
LEX* lex,
|
LEX* lex,
|
||||||
int* autocommit_stmt);
|
int* autocommit_stmt);
|
||||||
|
|
||||||
static int is_autocommit_stmt(
|
static int is_autocommit_stmt(LEX* lex);
|
||||||
LEX* lex);
|
static void parsing_info_set_plain_str(void* ptr, char* str);
|
||||||
|
static void* skygw_get_affected_tables(void* lexptr);
|
||||||
|
|
||||||
static void parsing_info_set_plain_str(void* ptr,
|
|
||||||
char* str);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls parser for the query includede in the buffer. Creates and adds parsing
|
* Calls parser for the query includede in the buffer. Creates and adds parsing
|
||||||
@ -107,6 +97,11 @@ skygw_query_type_t query_classifier_get_type(
|
|||||||
|
|
||||||
ss_info_dassert(querybuf != NULL, ("querybuf is NULL"));
|
ss_info_dassert(querybuf != NULL, ("querybuf is NULL"));
|
||||||
|
|
||||||
|
if (querybuf == NULL)
|
||||||
|
{
|
||||||
|
succp = false;
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
/** Create parsing info for the query and store it to buffer */
|
/** Create parsing info for the query and store it to buffer */
|
||||||
succp = query_is_parsed(querybuf);
|
succp = query_is_parsed(querybuf);
|
||||||
|
|
||||||
@ -133,6 +128,7 @@ skygw_query_type_t query_classifier_get_type(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
retblock:
|
||||||
return qtype;
|
return qtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +154,7 @@ bool parse_query (
|
|||||||
/** Do not parse without releasing previous parse info first */
|
/** Do not parse without releasing previous parse info first */
|
||||||
ss_dassert(!query_is_parsed(querybuf));
|
ss_dassert(!query_is_parsed(querybuf));
|
||||||
|
|
||||||
if (query_is_parsed(querybuf))
|
if (querybuf == NULL || query_is_parsed(querybuf))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -225,7 +221,7 @@ bool query_is_parsed(
|
|||||||
GWBUF* buf)
|
GWBUF* buf)
|
||||||
{
|
{
|
||||||
CHK_GWBUF(buf);
|
CHK_GWBUF(buf);
|
||||||
return GWBUF_IS_PARSED(buf);
|
return (buf != NULL && GWBUF_IS_PARSED(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -957,13 +953,25 @@ return_rc:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(NOT_USED)
|
||||||
char* skygw_query_classifier_get_stmtname(
|
char* skygw_query_classifier_get_stmtname(
|
||||||
MYSQL* mysql)
|
GWBUF* buf)
|
||||||
{
|
{
|
||||||
|
MYSQL* mysql;
|
||||||
|
|
||||||
|
if (buf == NULL ||
|
||||||
|
buf->gwbuf_bufobj == NULL ||
|
||||||
|
buf->gwbuf_bufobj->bo_data == NULL ||
|
||||||
|
(mysql = (MYSQL *)((parsing_info_t *)buf->gwbuf_bufobj->bo_data)->pi_handle) == NULL ||
|
||||||
|
mysql->thd == NULL ||
|
||||||
|
(THD *)(mysql->thd))->lex == NULL ||
|
||||||
|
(THD *)(mysql->thd))->lex->prepared_stmt_name == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return ((THD *)(mysql->thd))->lex->prepared_stmt_name.str;
|
return ((THD *)(mysql->thd))->lex->prepared_stmt_name.str;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parse tree from parsed querybuf.
|
* Get the parse tree from parsed querybuf.
|
||||||
@ -975,31 +983,29 @@ char* skygw_query_classifier_get_stmtname(
|
|||||||
LEX* get_lex(GWBUF* querybuf)
|
LEX* get_lex(GWBUF* querybuf)
|
||||||
{
|
{
|
||||||
|
|
||||||
parsing_info_t* pi;
|
parsing_info_t* pi;
|
||||||
MYSQL* mysql;
|
MYSQL* mysql;
|
||||||
THD* thd;
|
THD* thd;
|
||||||
|
|
||||||
if (!GWBUF_IS_PARSED(querybuf))
|
if (querybuf == NULL || !GWBUF_IS_PARSED(querybuf))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf,
|
pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf,
|
||||||
GWBUF_PARSING_INFO);
|
GWBUF_PARSING_INFO);
|
||||||
|
|
||||||
if (pi == NULL)
|
if (pi == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mysql = (MYSQL *)pi->pi_handle) == NULL ||
|
if ((mysql = (MYSQL *)pi->pi_handle) == NULL ||
|
||||||
(thd = (THD *)mysql->thd) == NULL)
|
(thd = (THD *)mysql->thd) == NULL)
|
||||||
{
|
{
|
||||||
ss_dassert(mysql != NULL &&
|
ss_dassert(mysql != NULL && thd != NULL);
|
||||||
thd != NULL);
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
}
|
return thd->lex;
|
||||||
|
|
||||||
return thd->lex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1009,7 +1015,7 @@ LEX* get_lex(GWBUF* querybuf)
|
|||||||
* @param thd Pointer to a valid THD
|
* @param thd Pointer to a valid THD
|
||||||
* @return Pointer to the head of the TABLE_LIST chain or NULL in case of an error
|
* @return Pointer to the head of the TABLE_LIST chain or NULL in case of an error
|
||||||
*/
|
*/
|
||||||
void* skygw_get_affected_tables(void* lexptr)
|
static void* skygw_get_affected_tables(void* lexptr)
|
||||||
{
|
{
|
||||||
LEX* lex = (LEX*)lexptr;
|
LEX* lex = (LEX*)lexptr;
|
||||||
|
|
||||||
@ -1027,87 +1033,93 @@ void* skygw_get_affected_tables(void* lexptr)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the parsetree and lists all the affected tables and views in the query.
|
* Reads the parsetree and lists all the affected tables and views in the query.
|
||||||
* In the case of an error, the size of the table is set to zero and no memory is allocated.
|
* In the case of an error, the size of the table is set to zero and no memory
|
||||||
* The caller must free the allocated memory.
|
* is allocated. The caller must free the allocated memory.
|
||||||
*
|
*
|
||||||
* @param querybuf GWBUF where the table names are extracted from
|
* @param querybuf GWBUF where the table names are extracted from
|
||||||
* @param tblsize Pointer where the number of tables is written
|
* @param tblsize Pointer where the number of tables is written
|
||||||
* @return Array of null-terminated strings with the table names
|
* @return Array of null-terminated strings with the table names
|
||||||
*/
|
*/
|
||||||
char** skygw_get_table_names(GWBUF* querybuf,int* tblsize, bool fullnames)
|
char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames)
|
||||||
{
|
{
|
||||||
LEX* lex;
|
LEX* lex;
|
||||||
TABLE_LIST* tbl;
|
TABLE_LIST* tbl;
|
||||||
int i = 0,
|
int i = 0,
|
||||||
currtblsz = 0;
|
currtblsz = 0;
|
||||||
char **tables = NULL,
|
char **tables = NULL,
|
||||||
**tmp = NULL;
|
**tmp = NULL;
|
||||||
|
|
||||||
if( (lex = get_lex(querybuf)) == NULL ||
|
if(querybuf == NULL ||
|
||||||
lex->current_select == NULL )
|
tblsize == NULL ||
|
||||||
|
(lex = get_lex(querybuf)) == NULL ||
|
||||||
|
lex->current_select == NULL)
|
||||||
{
|
{
|
||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
lex->current_select = lex->all_selects_list;
|
lex->current_select = lex->all_selects_list;
|
||||||
|
|
||||||
while(lex->current_select){
|
while(lex->current_select)
|
||||||
|
{
|
||||||
tbl = (TABLE_LIST*)skygw_get_affected_tables(lex);
|
tbl = (TABLE_LIST*)skygw_get_affected_tables(lex);
|
||||||
|
|
||||||
while (tbl)
|
while (tbl)
|
||||||
{
|
{
|
||||||
if(i >= currtblsz){
|
if (i >= currtblsz)
|
||||||
|
|
||||||
tmp = (char**)malloc(sizeof(char*)*(currtblsz*2+1));
|
|
||||||
|
|
||||||
if(tmp){
|
|
||||||
if(currtblsz > 0){
|
|
||||||
int x;
|
|
||||||
for(x = 0;x<currtblsz;x++){
|
|
||||||
tmp[x] = tables[x];
|
|
||||||
}
|
|
||||||
free(tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
tables = tmp;
|
|
||||||
currtblsz = currtblsz*2 + 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if(tmp != NULL){
|
|
||||||
char *catnm = NULL;
|
|
||||||
|
|
||||||
if(fullnames)
|
|
||||||
{
|
{
|
||||||
if(tbl->db && strcmp(tbl->db,"skygw_virtual") != 0)
|
tmp = (char**)malloc(sizeof(char*)*(currtblsz*2+1));
|
||||||
|
|
||||||
|
if(tmp)
|
||||||
|
{
|
||||||
|
if(currtblsz > 0)
|
||||||
{
|
{
|
||||||
catnm = (char*)calloc(strlen(tbl->db) + strlen(tbl->table_name) + 2,sizeof(char));
|
int x;
|
||||||
|
for(x = 0; x<currtblsz; x++)
|
||||||
|
{
|
||||||
|
tmp[x] = tables[x];
|
||||||
|
}
|
||||||
|
free(tables);
|
||||||
|
}
|
||||||
|
tables = tmp;
|
||||||
|
currtblsz = currtblsz*2 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tmp != NULL)
|
||||||
|
{
|
||||||
|
char *catnm = NULL;
|
||||||
|
|
||||||
|
if(fullnames)
|
||||||
|
{
|
||||||
|
if (tbl->db &&
|
||||||
|
strcmp(tbl->db,"skygw_virtual") != 0)
|
||||||
|
{
|
||||||
|
catnm = (char*)calloc(strlen(tbl->db) +
|
||||||
|
strlen(tbl->table_name) +
|
||||||
|
2,
|
||||||
|
sizeof(char));
|
||||||
strcpy(catnm,tbl->db);
|
strcpy(catnm,tbl->db);
|
||||||
strcat(catnm,".");
|
strcat(catnm,".");
|
||||||
strcat(catnm,tbl->table_name);
|
strcat(catnm,tbl->table_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(catnm)
|
||||||
|
{
|
||||||
|
tables[i++] = catnm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tables[i++] = strdup(tbl->table_name);
|
||||||
|
}
|
||||||
|
tbl=tbl->next_local;
|
||||||
}
|
}
|
||||||
|
} /*< while (tbl) */
|
||||||
if(catnm)
|
lex->current_select = lex->current_select->next_select_in_list();
|
||||||
{
|
} /*< while(lex->current_select) */
|
||||||
tables[i++] = catnm;
|
retblock:
|
||||||
}
|
*tblsize = i;
|
||||||
else
|
return tables;
|
||||||
{
|
|
||||||
tables[i++] = strdup(tbl->table_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbl=tbl->next_local;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lex->current_select = lex->current_select->next_select_in_list();
|
|
||||||
}
|
|
||||||
|
|
||||||
retblock:
|
|
||||||
*tblsize = i;
|
|
||||||
return tables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1117,52 +1129,70 @@ char** skygw_get_table_names(GWBUF* querybuf,int* tblsize, bool fullnames)
|
|||||||
*/
|
*/
|
||||||
char* skygw_get_created_table_name(GWBUF* querybuf)
|
char* skygw_get_created_table_name(GWBUF* querybuf)
|
||||||
{
|
{
|
||||||
LEX* lex;
|
LEX* lex;
|
||||||
|
|
||||||
if((lex = get_lex(querybuf)) == NULL)
|
if(querybuf == NULL || (lex = get_lex(querybuf)) == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lex->create_last_non_select_table &&
|
if (lex->create_last_non_select_table &&
|
||||||
lex->create_last_non_select_table->table_name){
|
lex->create_last_non_select_table->table_name)
|
||||||
char* name = strdup(lex->create_last_non_select_table->table_name);
|
{
|
||||||
return name;
|
char* name = strdup(lex->create_last_non_select_table->table_name);
|
||||||
}else{
|
return name;
|
||||||
return NULL;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the query is a "real" query ie. SELECT,UPDATE,INSERT,DELETE or any variation of these.
|
* Checks whether the query is a "real" query ie. SELECT,UPDATE,INSERT,DELETE or
|
||||||
* Queries that affect the underlying database are not considered as real queries and the queries that target
|
* any variation of these. Queries that affect the underlying database are not
|
||||||
* specific row or variable data are regarded as the real queries.
|
* considered as real queries and the queries that target specific row or
|
||||||
|
* variable data are regarded as the real queries.
|
||||||
|
*
|
||||||
* @param GWBUF to analyze
|
* @param GWBUF to analyze
|
||||||
|
*
|
||||||
* @return true if the query is a real query, otherwise false
|
* @return true if the query is a real query, otherwise false
|
||||||
*/
|
*/
|
||||||
bool skygw_is_real_query(GWBUF* querybuf)
|
bool skygw_is_real_query(GWBUF* querybuf)
|
||||||
{
|
{
|
||||||
LEX* lex = get_lex(querybuf);
|
bool succp;
|
||||||
if(lex){
|
LEX* lex;
|
||||||
switch(lex->sql_command){
|
|
||||||
case SQLCOM_SELECT:
|
if (querybuf == NULL ||
|
||||||
return lex->all_selects_list->table_list.elements > 0;
|
(lex = get_lex(querybuf)) == NULL)
|
||||||
case SQLCOM_UPDATE:
|
{
|
||||||
case SQLCOM_INSERT:
|
succp = false;
|
||||||
case SQLCOM_INSERT_SELECT:
|
goto retblock;
|
||||||
case SQLCOM_DELETE:
|
|
||||||
case SQLCOM_TRUNCATE:
|
|
||||||
case SQLCOM_REPLACE:
|
|
||||||
case SQLCOM_REPLACE_SELECT:
|
|
||||||
case SQLCOM_PREPARE:
|
|
||||||
case SQLCOM_EXECUTE:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
switch(lex->sql_command) {
|
||||||
return false;
|
case SQLCOM_SELECT:
|
||||||
|
succp = lex->all_selects_list->table_list.elements > 0;
|
||||||
|
goto retblock;
|
||||||
|
break;
|
||||||
|
case SQLCOM_UPDATE:
|
||||||
|
case SQLCOM_INSERT:
|
||||||
|
case SQLCOM_INSERT_SELECT:
|
||||||
|
case SQLCOM_DELETE:
|
||||||
|
case SQLCOM_TRUNCATE:
|
||||||
|
case SQLCOM_REPLACE:
|
||||||
|
case SQLCOM_REPLACE_SELECT:
|
||||||
|
case SQLCOM_PREPARE:
|
||||||
|
case SQLCOM_EXECUTE:
|
||||||
|
succp = true;
|
||||||
|
goto retblock;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
succp = false;
|
||||||
|
goto retblock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retblock:
|
||||||
|
return succp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1173,10 +1203,11 @@ bool skygw_is_real_query(GWBUF* querybuf)
|
|||||||
*/
|
*/
|
||||||
bool is_drop_table_query(GWBUF* querybuf)
|
bool is_drop_table_query(GWBUF* querybuf)
|
||||||
{
|
{
|
||||||
LEX* lex;
|
LEX* lex;
|
||||||
|
|
||||||
return (lex = get_lex(querybuf)) != NULL &&
|
return (querybuf != NULL &&
|
||||||
lex->sql_command == SQLCOM_DROP_TABLE;
|
(lex = get_lex(querybuf)) != NULL &&
|
||||||
|
lex->sql_command == SQLCOM_DROP_TABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1202,7 +1233,8 @@ char* skygw_get_canonical(
|
|||||||
Item* item;
|
Item* item;
|
||||||
char* querystr;
|
char* querystr;
|
||||||
|
|
||||||
if (!GWBUF_IS_PARSED(querybuf))
|
if (querybuf == NULL ||
|
||||||
|
!GWBUF_IS_PARSED(querybuf))
|
||||||
{
|
{
|
||||||
querystr = NULL;
|
querystr = NULL;
|
||||||
goto retblock;
|
goto retblock;
|
||||||
@ -1339,25 +1371,30 @@ retblock:
|
|||||||
void parsing_info_done(
|
void parsing_info_done(
|
||||||
void* ptr)
|
void* ptr)
|
||||||
{
|
{
|
||||||
parsing_info_t* pi = (parsing_info_t *)ptr;
|
parsing_info_t* pi;
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
pi = (parsing_info_t *)ptr;
|
||||||
|
|
||||||
if (pi->pi_handle != NULL)
|
if (pi->pi_handle != NULL)
|
||||||
{
|
{
|
||||||
MYSQL* mysql = (MYSQL *)pi->pi_handle;
|
MYSQL* mysql = (MYSQL *)pi->pi_handle;
|
||||||
|
|
||||||
if (mysql->thd != NULL)
|
if (mysql->thd != NULL)
|
||||||
{
|
{
|
||||||
(*mysql->methods->free_embedded_thd)(mysql);
|
(*mysql->methods->free_embedded_thd)(mysql);
|
||||||
mysql->thd = NULL;
|
mysql->thd = NULL;
|
||||||
}
|
}
|
||||||
mysql_close(mysql);
|
mysql_close(mysql);
|
||||||
}
|
}
|
||||||
/** Free plain text query string */
|
/** Free plain text query string */
|
||||||
if (pi->pi_query_plain_str != NULL)
|
if (pi->pi_query_plain_str != NULL)
|
||||||
{
|
{
|
||||||
free(pi->pi_query_plain_str);
|
free(pi->pi_query_plain_str);
|
||||||
}
|
}
|
||||||
free(pi);
|
free(pi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,12 +83,13 @@ typedef struct parsing_info_st {
|
|||||||
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
|
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
|
||||||
|
|
||||||
/** Free THD context and close MYSQL */
|
/** Free THD context and close MYSQL */
|
||||||
char* skygw_query_classifier_get_stmtname(MYSQL* mysql);
|
#if defined(NOT_USED)
|
||||||
|
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
|
||||||
|
#endif
|
||||||
char* skygw_get_created_table_name(GWBUF* querybuf);
|
char* skygw_get_created_table_name(GWBUF* querybuf);
|
||||||
bool is_drop_table_query(GWBUF* querybuf);
|
bool is_drop_table_query(GWBUF* querybuf);
|
||||||
bool skygw_is_real_query(GWBUF* querybuf);
|
bool skygw_is_real_query(GWBUF* querybuf);
|
||||||
void* skygw_get_affected_tables(void* lexptr);
|
char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames);
|
||||||
char** skygw_get_table_names(GWBUF* querybuf,int* tblsize,bool fullnames);
|
|
||||||
char* skygw_get_canonical(GWBUF* querybuf);
|
char* skygw_get_canonical(GWBUF* querybuf);
|
||||||
bool parse_query (GWBUF* querybuf);
|
bool parse_query (GWBUF* querybuf);
|
||||||
parsing_info_t* parsing_info_init(void (*donefun)(void *));
|
parsing_info_t* parsing_info_init(void (*donefun)(void *));
|
||||||
|
Reference in New Issue
Block a user