Merge branch 'develop' into firewall
Conflicts: server/modules/filter/test/CMakeLists.txt
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)
|
||||
|
||||
static THD* get_or_create_thd_for_parsing(
|
||||
MYSQL* mysql,
|
||||
char* query_str);
|
||||
|
||||
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 THD* get_or_create_thd_for_parsing(MYSQL* mysql, char* query_str);
|
||||
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(
|
||||
LEX* lex,
|
||||
int* autocommit_stmt);
|
||||
|
||||
static int is_autocommit_stmt(
|
||||
LEX* lex);
|
||||
static int is_autocommit_stmt(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
|
||||
@ -107,6 +97,11 @@ skygw_query_type_t query_classifier_get_type(
|
||||
|
||||
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 */
|
||||
succp = query_is_parsed(querybuf);
|
||||
|
||||
@ -133,6 +128,7 @@ skygw_query_type_t query_classifier_get_type(
|
||||
}
|
||||
}
|
||||
}
|
||||
retblock:
|
||||
return qtype;
|
||||
}
|
||||
|
||||
@ -158,7 +154,7 @@ bool parse_query (
|
||||
/** Do not parse without releasing previous parse info first */
|
||||
ss_dassert(!query_is_parsed(querybuf));
|
||||
|
||||
if (query_is_parsed(querybuf))
|
||||
if (querybuf == NULL || query_is_parsed(querybuf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -174,8 +170,8 @@ bool parse_query (
|
||||
data = (uint8_t*)GWBUF_DATA(querybuf);
|
||||
len = MYSQL_GET_PACKET_LEN(data)-1; /*< distract 1 for packet type byte */
|
||||
|
||||
|
||||
if (len < 1 || (query_str = (char *)malloc(len+1)) == NULL)
|
||||
|
||||
if (len < 1 || len >= ~((size_t)0) - 1 || (query_str = (char *)malloc(len+1)) == NULL)
|
||||
{
|
||||
/** Free parsing info data */
|
||||
parsing_info_done(pi);
|
||||
@ -225,7 +221,7 @@ bool query_is_parsed(
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#if defined(NOT_USED)
|
||||
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;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the parse tree from parsed querybuf.
|
||||
@ -975,31 +983,29 @@ char* skygw_query_classifier_get_stmtname(
|
||||
LEX* get_lex(GWBUF* querybuf)
|
||||
{
|
||||
|
||||
parsing_info_t* pi;
|
||||
MYSQL* mysql;
|
||||
THD* thd;
|
||||
|
||||
if (!GWBUF_IS_PARSED(querybuf))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf,
|
||||
GWBUF_PARSING_INFO);
|
||||
parsing_info_t* pi;
|
||||
MYSQL* mysql;
|
||||
THD* thd;
|
||||
|
||||
if (querybuf == NULL || !GWBUF_IS_PARSED(querybuf))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pi = (parsing_info_t *)gwbuf_get_buffer_object_data(querybuf,
|
||||
GWBUF_PARSING_INFO);
|
||||
|
||||
if (pi == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((mysql = (MYSQL *)pi->pi_handle) == NULL ||
|
||||
(thd = (THD *)mysql->thd) == NULL)
|
||||
{
|
||||
ss_dassert(mysql != NULL &&
|
||||
thd != NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return thd->lex;
|
||||
if (pi == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((mysql = (MYSQL *)pi->pi_handle) == NULL ||
|
||||
(thd = (THD *)mysql->thd) == NULL)
|
||||
{
|
||||
ss_dassert(mysql != NULL && thd != NULL);
|
||||
return NULL;
|
||||
}
|
||||
return thd->lex;
|
||||
}
|
||||
|
||||
|
||||
@ -1009,7 +1015,7 @@ LEX* get_lex(GWBUF* querybuf)
|
||||
* @param thd Pointer to a valid THD
|
||||
* @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;
|
||||
|
||||
@ -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.
|
||||
* In the case of an error, the size of the table is set to zero and no memory is allocated.
|
||||
* The caller must free the allocated memory.
|
||||
* In the case of an error, the size of the table is set to zero and no memory
|
||||
* is allocated. The caller must free the allocated memory.
|
||||
*
|
||||
* @param querybuf GWBUF where the table names are extracted from
|
||||
* @param tblsize Pointer where the number of tables is written
|
||||
* @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;
|
||||
TABLE_LIST* tbl;
|
||||
int i = 0,
|
||||
LEX* lex;
|
||||
TABLE_LIST* tbl;
|
||||
int i = 0,
|
||||
currtblsz = 0;
|
||||
char **tables = NULL,
|
||||
char **tables = NULL,
|
||||
**tmp = NULL;
|
||||
|
||||
if( (lex = get_lex(querybuf)) == NULL ||
|
||||
lex->current_select == NULL )
|
||||
if(querybuf == 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){
|
||||
|
||||
tbl = (TABLE_LIST*)skygw_get_affected_tables(lex);
|
||||
while(lex->current_select)
|
||||
{
|
||||
tbl = (TABLE_LIST*)skygw_get_affected_tables(lex);
|
||||
|
||||
while (tbl)
|
||||
{
|
||||
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)
|
||||
while (tbl)
|
||||
{
|
||||
if (i >= currtblsz)
|
||||
{
|
||||
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);
|
||||
strcat(catnm,".");
|
||||
strcat(catnm,tbl->table_name);
|
||||
}
|
||||
}
|
||||
|
||||
if(catnm)
|
||||
{
|
||||
tables[i++] = catnm;
|
||||
}
|
||||
else
|
||||
{
|
||||
tables[i++] = strdup(tbl->table_name);
|
||||
}
|
||||
tbl=tbl->next_local;
|
||||
}
|
||||
|
||||
if(catnm)
|
||||
{
|
||||
tables[i++] = catnm;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
} /*< while (tbl) */
|
||||
lex->current_select = lex->current_select->next_select_in_list();
|
||||
} /*< while(lex->current_select) */
|
||||
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)
|
||||
{
|
||||
LEX* lex;
|
||||
|
||||
if((lex = get_lex(querybuf)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
LEX* lex;
|
||||
|
||||
if(querybuf == NULL || (lex = get_lex(querybuf)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(lex->create_last_non_select_table &&
|
||||
lex->create_last_non_select_table->table_name){
|
||||
char* name = strdup(lex->create_last_non_select_table->table_name);
|
||||
return name;
|
||||
}else{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lex->create_last_non_select_table &&
|
||||
lex->create_last_non_select_table->table_name)
|
||||
{
|
||||
char* name = strdup(lex->create_last_non_select_table->table_name);
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the query is a "real" query ie. SELECT,UPDATE,INSERT,DELETE or any variation of these.
|
||||
* Queries that affect the underlying database are not considered as real queries and the queries that target
|
||||
* specific row or variable data are regarded as the real queries.
|
||||
* Checks whether the query is a "real" query ie. SELECT,UPDATE,INSERT,DELETE or
|
||||
* any variation of these. Queries that affect the underlying database are not
|
||||
* considered as real queries and the queries that target specific row or
|
||||
* variable data are regarded as the real queries.
|
||||
*
|
||||
* @param GWBUF to analyze
|
||||
*
|
||||
* @return true if the query is a real query, otherwise false
|
||||
*/
|
||||
bool skygw_is_real_query(GWBUF* querybuf)
|
||||
{
|
||||
LEX* lex = get_lex(querybuf);
|
||||
if(lex){
|
||||
switch(lex->sql_command){
|
||||
case SQLCOM_SELECT:
|
||||
return lex->all_selects_list->table_list.elements > 0;
|
||||
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:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
bool succp;
|
||||
LEX* lex;
|
||||
|
||||
if (querybuf == NULL ||
|
||||
(lex = get_lex(querybuf)) == NULL)
|
||||
{
|
||||
succp = false;
|
||||
goto retblock;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
switch(lex->sql_command) {
|
||||
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)
|
||||
{
|
||||
LEX* lex;
|
||||
LEX* lex;
|
||||
|
||||
return (lex = get_lex(querybuf)) != NULL &&
|
||||
lex->sql_command == SQLCOM_DROP_TABLE;
|
||||
return (querybuf != NULL &&
|
||||
(lex = get_lex(querybuf)) != NULL &&
|
||||
lex->sql_command == SQLCOM_DROP_TABLE);
|
||||
}
|
||||
|
||||
inline void add_str(char** buf, int* buflen, int* bufsize, char* str)
|
||||
@ -1319,7 +1350,8 @@ char* skygw_get_canonical(
|
||||
Item* item;
|
||||
char* querystr;
|
||||
|
||||
if (!GWBUF_IS_PARSED(querybuf))
|
||||
if (querybuf == NULL ||
|
||||
!GWBUF_IS_PARSED(querybuf))
|
||||
{
|
||||
querystr = NULL;
|
||||
goto retblock;
|
||||
@ -1456,25 +1488,30 @@ retblock:
|
||||
void parsing_info_done(
|
||||
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)
|
||||
{
|
||||
MYSQL* mysql = (MYSQL *)pi->pi_handle;
|
||||
|
||||
if (mysql->thd != NULL)
|
||||
{
|
||||
(*mysql->methods->free_embedded_thd)(mysql);
|
||||
mysql->thd = NULL;
|
||||
}
|
||||
mysql_close(mysql);
|
||||
}
|
||||
/** Free plain text query string */
|
||||
if (pi->pi_query_plain_str != NULL)
|
||||
{
|
||||
free(pi->pi_query_plain_str);
|
||||
}
|
||||
free(pi);
|
||||
if (pi->pi_handle != NULL)
|
||||
{
|
||||
MYSQL* mysql = (MYSQL *)pi->pi_handle;
|
||||
|
||||
if (mysql->thd != NULL)
|
||||
{
|
||||
(*mysql->methods->free_embedded_thd)(mysql);
|
||||
mysql->thd = NULL;
|
||||
}
|
||||
mysql_close(mysql);
|
||||
}
|
||||
/** Free plain text query string */
|
||||
if (pi->pi_query_plain_str != NULL)
|
||||
{
|
||||
free(pi->pi_query_plain_str);
|
||||
}
|
||||
free(pi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user