Merge branch 'develop' into firewall

Conflicts:
	server/modules/filter/test/CMakeLists.txt
This commit is contained in:
Markus Makela
2015-01-13 07:48:43 +02:00
107 changed files with 2718 additions and 800 deletions

View File

@ -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);
}
}
/**