Streamline query classifier API interface

- Only types of fixed size used in API interface
- The actual function return value specifies whether the parsing
  process succeeded, while "logical" return values are returned
  as out arguments.

The wrapper function currently ignores the function return value.
This commit is contained in:
Johan Wikman
2017-01-16 14:11:19 +02:00
parent 8d2f4707a4
commit 7fee90a399
6 changed files with 595 additions and 250 deletions

View File

@ -127,6 +127,16 @@ typedef struct qc_function_info
uint32_t usage; /** Bitfield denoting where the column appears. */
} QC_FUNCTION_INFO;
/**
* Each API function returns @c QC_RESULT_OK if the actual parsing process
* succeeded, and some error code otherwise.
*/
typedef enum qc_result
{
QC_RESULT_OK,
QC_RESULT_ERROR
} qc_result_t;
/**
* QUERY_CLASSIFIER defines the object a query classifier plugin must
* implement and return.
@ -136,29 +146,202 @@ typedef struct qc_function_info
*/
typedef struct query_classifier
{
bool (*qc_setup)(const char* args);
/**
* Called once to setup the query classifier
*
* @param args The value of `query_classifier_args` in the configuration file.
*
* @return QC_RESULT_OK, if the query classifier could be setup, otherwise
* some specific error code.
*/
int32_t (*qc_setup)(const char* args);
int (*qc_process_init)(void);
/**
* Called once at process startup, after @c qc_setup has successfully
* been called.
*
* @return QC_RESULT_OK, if the process initialization succeeded.
*/
int32_t (*qc_process_init)(void);
/**
* Called once at process shutdown.
*/
void (*qc_process_end)(void);
int (*qc_thread_init)(void);
/**
* Called once per each thread, except for the thread for which @c qc_process_init
* was called.
*
* @return QC_RESULT_OK, if the thread initialization succeeded.
*/
int32_t (*qc_thread_init)(void);
/**
* Called once when a thread finishes, except for the thread for which @c qc_process_init
* was called.
*/
void (*qc_thread_end)(void);
qc_parse_result_t (*qc_parse)(GWBUF* stmt);
/**
* Called to explicitly parse a statement.
*
* @param stmt The statement to be parsed.
* @param result On return, the parse result, if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_parse)(GWBUF* stmt, int32_t* result);
uint32_t (*qc_get_type)(GWBUF* stmt);
qc_query_op_t (*qc_get_operation)(GWBUF* stmt);
/**
* Reports the type of the statement.
*
* @param stmt A statement.
* @param type On return, the type mask (combination of @c qc_query_type_t),
* if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_type)(GWBUF* stmt, uint32_t* type);
char* (*qc_get_created_table_name)(GWBUF* stmt);
bool (*qc_is_drop_table_query)(GWBUF* stmt);
char** (*qc_get_table_names)(GWBUF* stmt, int* tblsize, bool fullnames);
char* (*qc_get_canonical)(GWBUF* stmt);
bool (*qc_query_has_clause)(GWBUF* stmt);
char** (*qc_get_database_names)(GWBUF* stmt, int* size);
char* (*qc_get_prepare_name)(GWBUF* stmt);
qc_query_op_t (*qc_get_prepare_operation)(GWBUF* stmt);
void (*qc_get_field_info)(GWBUF* stmt, const QC_FIELD_INFO** infos, size_t* n_infos);
void (*qc_get_function_info)(GWBUF* stmt, const QC_FUNCTION_INFO** infos, size_t* n_infos);
/**
* Reports the operation of the statement.
*
* @param stmt A statement.
* @param type On return, the operation (one of @c qc_query_op_t), if
* @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_operation)(GWBUF* stmt, int32_t* op);
/**
* Reports the name of a created table.
*
* @param stmt A statement.
* @param name On return, the name of the created table, if
* @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_created_table_name)(GWBUF* stmt, char** name);
/**
* Reports whether a statement is a "DROP TABLE ..." statement.
*
* @param stmt A statement
* @param is_drop_table On return, non-zero if the statement is a DROP TABLE
* statement, if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_is_drop_table_query)(GWBUF* stmt, int32_t* is_drop_table);
/**
* Returns all table names.
*
* @param stmt A statement.
* @param fullnames If non-zero, the full (i.e. qualified) names are returned.
* @param names On return, the names of the statement, if @c QC_RESULT_OK
* is returned.
* @param n_names On return, how many names were returned, if @c QC_RESULT_OK
* is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_table_names)(GWBUF* stmt, int32_t full_names, char*** names, int32_t *n_names);
/**
* The canonical version of a statement.
*
* @param stmt A statement.
* @param canonical On return, the canonical version of the statement, if @c QC_RESULT_OK
* is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_canonical)(GWBUF* stmt, char** canonical);
/**
* Reports whether the statement has a where clause.
*
* @param stmt A statement.
* @param has_clause On return, non-zero if the statement has a where clause, if
* @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_query_has_clause)(GWBUF* stmt, int32_t* has_clause);
/**
* Reports the database names.
*
* @param stmt A statement.
* @param names On return, the database names, if
* @c QC_RESULT_OK is returned.
* @param size On return, the number of names in @names, if
* @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_database_names)(GWBUF* stmt, char*** names, int32_t* size);
/**
* Reports the prepare name.
*
* @param stmt A statement.
* @param name On return, the name of a prepare statement, if
* @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_prepare_name)(GWBUF* stmt, char** name);
/**
* Reports the prepare operation.
*
* @param stmt A statement.
* @param name On return, the operation (one of @c qc_query_op_t) of a prepare
* statement, if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_prepare_operation)(GWBUF* stmt, int32_t* op);
/**
* Reports field information.
*
* @param stmt A statement.
* @param infos On return, array of field infos, if @c QC_RESULT_OK is returned.
* @param n_infos On return, the size of @c infos, if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_field_info)(GWBUF* stmt, const QC_FIELD_INFO** infos, uint32_t* n_infos);
/**
* The canonical version of a statement.
*
* @param stmt A statement.
* @param infos On return, array of function infos, if @c QC_RESULT_OK is returned.
* @param n_infos On return, the size of @c infos, if @c QC_RESULT_OK is returned.
*
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
* exhaustion or equivalent.
*/
int32_t (*qc_get_function_info)(GWBUF* stmt, const QC_FUNCTION_INFO** infos, uint32_t* n_infos);
} QUERY_CLASSIFIER;
/**

View File

@ -15,72 +15,90 @@
#include <maxscale/modules.h>
#include <maxscale/query_classifier.h>
qc_parse_result_t qc_parse(GWBUF* querybuf)
int32_t qc_dummy_parse(GWBUF* querybuf, int32_t* pResult)
{
return QC_QUERY_INVALID;
*pResult = QC_QUERY_INVALID;
return QC_RESULT_OK;
}
uint32_t qc_get_type(GWBUF* querybuf)
int32_t qc_dummy_get_type(GWBUF* querybuf, uint32_t* pType_mask)
{
return QUERY_TYPE_UNKNOWN;
*pType_mask = QUERY_TYPE_UNKNOWN;
return QC_RESULT_OK;
}
char** qc_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames)
int32_t qc_dummy_get_table_names(GWBUF* querybuf, int32_t fullnames, char*** ppzNames, int32_t* pSize)
{
*tblsize = 0;
return NULL;
*ppzNames = NULL;
*pSize = 0;
return QC_RESULT_OK;
}
char* qc_get_created_table_name(GWBUF* querybuf)
int32_t qc_dummy_get_created_table_name(GWBUF* querybuf, char** pzName)
{
return NULL;
*pzName = NULL;
return QC_RESULT_OK;
}
bool qc_is_drop_table_query(GWBUF* querybuf)
int32_t qc_dummy_is_drop_table_query(GWBUF* querybuf, int32_t* pIs_drop_table)
{
return false;
*pIs_drop_table = 0;
return QC_RESULT_OK;
}
bool qc_query_has_clause(GWBUF* buf)
int32_t qc_dummy_query_has_clause(GWBUF* buf, int32_t *pHas_clause)
{
return false;
*pHas_clause = 0;
return QC_RESULT_OK;
}
char** qc_get_database_names(GWBUF* querybuf, int* size)
int32_t qc_dummy_get_database_names(GWBUF* querybuf, char*** ppzNames, int32_t* pSize)
{
*size = 0;
return NULL;
*ppzNames = NULL;
*pSize = 0;
return QC_RESULT_OK;
}
qc_query_op_t qc_get_operation(GWBUF* querybuf)
int32_t qc_dummy_get_operation(GWBUF* querybuf, int32_t* pOp)
{
return QUERY_OP_UNDEFINED;
*pOp = QUERY_OP_UNDEFINED;
return QC_RESULT_OK;
}
char* qc_sqlite_get_prepare_name(GWBUF* query)
int32_t qc_dummy_get_prepare_name(GWBUF* query, char** pzName)
{
return NULL;
*pzName = NULL;
return QC_RESULT_OK;
}
qc_query_op_t qc_sqlite_get_prepare_operation(GWBUF* query)
int32_t qc_dummy_get_prepare_operation(GWBUF* query, int32_t* pOp)
{
return QUERY_OP_UNDEFINED;
*pOp = QUERY_OP_UNDEFINED;
return QC_RESULT_OK;
}
void qc_sqlite_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t* n_infos)
int32_t qc_dummy_get_field_info(GWBUF* query, const QC_FIELD_INFO** ppInfos, uint32_t* nInfos)
{
*infos = NULL;
*n_infos = 0;
*ppInfos = NULL;
*nInfos = 0;
return QC_RESULT_OK;
}
bool qc_setup(const char* args)
int32_t qc_dummy_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** ppInfos, uint32_t* nInfos)
{
return true;
*ppInfos = NULL;
*nInfos = 0;
return QC_RESULT_OK;
}
int32_t qc_dummy_setup(const char* args)
{
return QC_RESULT_OK;
}
int qc_dummy_process_init(void)
{
return 0;
return QC_RESULT_OK;
}
void qc_dummy_process_end(void)
@ -89,7 +107,7 @@ void qc_dummy_process_end(void)
int qc_dummy_thread_init(void)
{
return 0;
return QC_RESULT_OK;
}
void qc_dummy_thread_end(void)
@ -102,23 +120,24 @@ extern "C"
{
static QUERY_CLASSIFIER qc =
{
qc_setup,
qc_dummy_setup,
qc_dummy_process_init,
qc_dummy_process_end,
qc_dummy_thread_init,
qc_dummy_thread_end,
qc_parse,
qc_get_type,
qc_get_operation,
qc_get_created_table_name,
qc_is_drop_table_query,
qc_get_table_names,
qc_dummy_parse,
qc_dummy_get_type,
qc_dummy_get_operation,
qc_dummy_get_created_table_name,
qc_dummy_is_drop_table_query,
qc_dummy_get_table_names,
NULL,
qc_query_has_clause,
qc_get_database_names,
qc_get_prepare_name,
qc_get_prepare_operation,
qc_get_field_info,
qc_dummy_query_has_clause,
qc_dummy_get_database_names,
qc_dummy_get_prepare_name,
qc_dummy_get_prepare_operation,
qc_dummy_get_field_info,
qc_dummy_get_function_info,
};
static MXS_MODULE info =

View File

@ -135,7 +135,7 @@ bool ensure_query_is_parsed(GWBUF* query)
return parsed;
}
qc_parse_result_t qc_parse(GWBUF* querybuf)
int32_t qc_mysql_parse(GWBUF* querybuf, int32_t* result)
{
bool parsed = ensure_query_is_parsed(querybuf);
@ -144,13 +144,23 @@ qc_parse_result_t qc_parse(GWBUF* querybuf)
// query is valid and hence correctly parsed, or the query is invalid in
// which case the server will also consider it invalid and reject it. So,
// it's always ok to claim it has been parsed.
return parsed ? QC_QUERY_PARSED : QC_QUERY_INVALID;
if (parsed)
{
*result = QC_QUERY_PARSED;
}
else
{
*result = QC_QUERY_INVALID;
}
return QC_RESULT_OK;
}
uint32_t qc_get_type(GWBUF* querybuf)
int32_t qc_mysql_get_type(GWBUF* querybuf, uint32_t* type_mask)
{
*type_mask = QUERY_TYPE_UNKNOWN;
MYSQL* mysql;
uint32_t qtype = QUERY_TYPE_UNKNOWN;
bool succp;
ss_info_dassert(querybuf != NULL, ("querybuf is NULL"));
@ -178,13 +188,13 @@ uint32_t qc_get_type(GWBUF* querybuf)
/** Find out the query type */
if (mysql != NULL)
{
qtype = resolve_query_type(pi, (THD *) mysql->thd);
*type_mask = resolve_query_type(pi, (THD *) mysql->thd);
}
}
}
retblock:
return qtype;
return QC_RESULT_OK;
}
/**
@ -1254,7 +1264,7 @@ static TABLE_LIST* skygw_get_affected_tables(void* lexptr)
return tbl;
}
char** qc_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames)
int32_t qc_mysql_get_table_names(GWBUF* querybuf, int32_t fullnames, char*** tablesp, int32_t* tblsize)
{
LEX* lex;
TABLE_LIST* tbl;
@ -1347,24 +1357,25 @@ char** qc_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames)
retblock:
*tblsize = i;
*tablesp = tables;
return tables;
return QC_RESULT_OK;
}
char* qc_get_created_table_name(GWBUF* querybuf)
int32_t qc_mysql_get_created_table_name(GWBUF* querybuf, char** table_name)
{
*table_name = NULL;
if (querybuf == NULL)
{
return NULL;
return QC_RESULT_OK;
}
if (!ensure_query_is_parsed(querybuf))
{
return NULL;
return QC_RESULT_ERROR;
}
char* table_name = NULL;
LEX* lex = get_lex(querybuf);
if (lex && (lex->sql_command == SQLCOM_CREATE_TABLE))
@ -1372,16 +1383,16 @@ char* qc_get_created_table_name(GWBUF* querybuf)
if (lex->create_last_non_select_table &&
lex->create_last_non_select_table->table_name)
{
table_name = strdup(lex->create_last_non_select_table->table_name);
*table_name = strdup(lex->create_last_non_select_table->table_name);
}
}
return table_name;
return QC_RESULT_OK;
}
bool qc_is_drop_table_query(GWBUF* querybuf)
int32_t qc_mysql_is_drop_table_query(GWBUF* querybuf, int32_t* answer)
{
bool answer = false;
*answer = 0;
if (querybuf)
{
@ -1389,16 +1400,16 @@ bool qc_is_drop_table_query(GWBUF* querybuf)
{
LEX* lex = get_lex(querybuf);
answer = lex && lex->sql_command == SQLCOM_DROP_TABLE;
*answer = lex && lex->sql_command == SQLCOM_DROP_TABLE;
}
}
return answer;
return QC_RESULT_OK;
}
bool qc_query_has_clause(GWBUF* buf)
int32_t qc_mysql_query_has_clause(GWBUF* buf, int32_t* has_clause)
{
bool clause = false;
*has_clause = false;
if (buf)
{
@ -1410,11 +1421,11 @@ bool qc_query_has_clause(GWBUF* buf)
{
SELECT_LEX* current = lex->all_selects_list;
while (current && !clause)
while (current && !*has_clause)
{
if (current->where || current->having)
{
clause = true;
*has_clause = true;
}
current = current->next_select_in_list();
@ -1423,7 +1434,7 @@ bool qc_query_has_clause(GWBUF* buf)
}
}
return clause;
return QC_RESULT_OK;
}
/**
@ -1556,7 +1567,7 @@ static void parsing_info_set_plain_str(void* ptr, char* str)
pi->pi_query_plain_str = str;
}
char** qc_get_database_names(GWBUF* querybuf, int* size)
int32_t qc_mysql_get_database_names(GWBUF* querybuf, char*** databasesp, int* size)
{
LEX* lex;
TABLE_LIST* tbl;
@ -1624,12 +1635,14 @@ char** qc_get_database_names(GWBUF* querybuf, int* size)
retblock:
*size = i;
return databases;
*databasesp = databases;
return QC_RESULT_OK;
}
qc_query_op_t qc_get_operation(GWBUF* querybuf)
int32_t qc_mysql_get_operation(GWBUF* querybuf, int32_t* operation)
{
qc_query_op_t operation = QUERY_OP_UNDEFINED;
*operation = QUERY_OP_UNDEFINED;
if (querybuf)
{
@ -1642,7 +1655,7 @@ qc_query_op_t qc_get_operation(GWBUF* querybuf)
switch (lex->sql_command)
{
case SQLCOM_SELECT:
operation = QUERY_OP_SELECT;
*operation = QUERY_OP_SELECT;
break;
case SQLCOM_CREATE_DB:
@ -1656,7 +1669,7 @@ qc_query_op_t qc_get_operation(GWBUF* querybuf)
case SQLCOM_CREATE_TRIGGER:
case SQLCOM_CREATE_USER:
case SQLCOM_CREATE_VIEW:
operation = QUERY_OP_CREATE;
*operation = QUERY_OP_CREATE;
break;
case SQLCOM_ALTER_DB:
@ -1667,28 +1680,28 @@ qc_query_op_t qc_get_operation(GWBUF* querybuf)
case SQLCOM_ALTER_SERVER:
case SQLCOM_ALTER_TABLE:
case SQLCOM_ALTER_TABLESPACE:
operation = QUERY_OP_ALTER;
*operation = QUERY_OP_ALTER;
break;
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
operation = QUERY_OP_UPDATE;
*operation = QUERY_OP_UPDATE;
break;
case SQLCOM_INSERT:
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE:
case SQLCOM_REPLACE_SELECT:
operation = QUERY_OP_INSERT;
*operation = QUERY_OP_INSERT;
break;
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
operation = QUERY_OP_DELETE;
*operation = QUERY_OP_DELETE;
break;
case SQLCOM_TRUNCATE:
operation = QUERY_OP_TRUNCATE;
*operation = QUERY_OP_TRUNCATE;
break;
case SQLCOM_DROP_DB:
@ -1701,37 +1714,37 @@ qc_query_op_t qc_get_operation(GWBUF* querybuf)
case SQLCOM_DROP_TRIGGER:
case SQLCOM_DROP_USER:
case SQLCOM_DROP_VIEW:
operation = QUERY_OP_DROP;
*operation = QUERY_OP_DROP;
break;
case SQLCOM_CHANGE_DB:
operation = QUERY_OP_CHANGE_DB;
*operation = QUERY_OP_CHANGE_DB;
break;
case SQLCOM_LOAD:
operation = QUERY_OP_LOAD;
*operation = QUERY_OP_LOAD;
break;
case SQLCOM_GRANT:
operation = QUERY_OP_GRANT;
break;
*operation = QUERY_OP_GRANT;
break;
case SQLCOM_REVOKE:
case SQLCOM_REVOKE_ALL:
operation = QUERY_OP_REVOKE;
break;
*operation = QUERY_OP_REVOKE;
break;
default:
operation = QUERY_OP_UNDEFINED;
*operation = QUERY_OP_UNDEFINED;
}
}
}
}
return operation;
return QC_RESULT_OK;
}
char* qc_get_prepare_name(GWBUF* stmt)
int32_t qc_mysql_get_prepare_name(GWBUF* stmt, char** namep)
{
char* name = NULL;
@ -1755,12 +1768,14 @@ char* qc_get_prepare_name(GWBUF* stmt)
}
}
return name;
*namep = name;
return QC_RESULT_OK;
}
qc_query_op_t qc_get_prepare_operation(GWBUF* stmt)
int32_t qc_mysql_get_prepare_operation(GWBUF* stmt, int32_t* operation)
{
qc_query_op_t operation = QUERY_OP_UNDEFINED;
*operation = QUERY_OP_UNDEFINED;
if (stmt)
{
@ -1826,14 +1841,14 @@ qc_query_op_t qc_get_prepare_operation(GWBUF* stmt)
++s;
}
operation = qc_get_operation(prepare_stmt);
qc_mysql_get_operation(prepare_stmt, operation);
gwbuf_free(prepare_stmt);
}
}
}
}
return operation;
return QC_RESULT_OK;
}
static bool should_exclude(const char* name, List<Item>* excludep)
@ -2453,16 +2468,16 @@ static void update_field_infos(parsing_info_t* pi,
}
}
void qc_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, size_t* n_infos)
int32_t qc_mysql_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, uint32_t* n_infos)
{
if (!buf)
{
return;
return QC_RESULT_OK;
}
if (!ensure_query_is_parsed(buf))
{
return;
return QC_RESULT_ERROR;;
}
parsing_info_t* pi = get_pinfo(buf);
@ -2475,7 +2490,7 @@ void qc_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, size_t* n_infos)
if (!lex)
{
return;
return QC_RESULT_ERROR;
}
uint32_t usage = 0;
@ -2558,24 +2573,30 @@ void qc_get_field_info(GWBUF* buf, const QC_FIELD_INFO** infos, size_t* n_infos)
*infos = pi->field_infos;
*n_infos = pi->field_infos_len;
return QC_RESULT_OK;
}
void qc_get_function_info(GWBUF* buf, const QC_FUNCTION_INFO** function_infos, size_t* n_function_infos)
int32_t qc_mysql_get_function_info(GWBUF* buf,
const QC_FUNCTION_INFO** function_infos,
uint32_t* n_function_infos)
{
*function_infos = NULL;
*n_function_infos = 0;
const QC_FIELD_INFO* field_infos;
size_t n_field_infos;
uint32_t n_field_infos;
// We ensure the information has been collected by querying the fields first.
qc_get_field_info(buf, &field_infos, &n_field_infos);
qc_mysql_get_field_info(buf, &field_infos, &n_field_infos);
parsing_info_t* pi = get_pinfo(buf);
ss_dassert(pi);
*function_infos = pi->function_infos;
*n_function_infos = pi->function_infos_len;
return QC_RESULT_OK;
}
namespace
@ -2633,7 +2654,7 @@ void configure_options(const char* datadir, const char* langdir)
}
bool qc_setup(const char* args)
int32_t qc_mysql_setup(const char* args)
{
if (args)
{
@ -2641,10 +2662,10 @@ bool qc_setup(const char* args)
"even though no arguments are supported.", args);
}
return true;
return QC_RESULT_OK;
}
int qc_mysql_process_init(void)
int32_t qc_mysql_process_init(void)
{
bool inited = false;
@ -2676,7 +2697,7 @@ int qc_mysql_process_init(void)
}
}
return inited ? 0 : -1;
return inited ? QC_RESULT_OK : QC_RESULT_ERROR;
}
void qc_mysql_process_end(void)
@ -2684,7 +2705,7 @@ void qc_mysql_process_end(void)
mysql_library_end();
}
int qc_mysql_thread_init(void)
int32_t qc_mysql_thread_init(void)
{
bool inited = (mysql_thread_init() == 0);
@ -2693,7 +2714,7 @@ int qc_mysql_thread_init(void)
MXS_ERROR("mysql_thread_init() failed.");
}
return inited ? 0 : -1;
return inited ? QC_RESULT_OK : QC_RESULT_ERROR;
}
void qc_mysql_thread_end(void)
@ -2712,24 +2733,24 @@ MXS_MODULE* MXS_CREATE_MODULE()
{
static QUERY_CLASSIFIER qc =
{
qc_setup,
qc_mysql_setup,
qc_mysql_process_init,
qc_mysql_process_end,
qc_mysql_thread_init,
qc_mysql_thread_end,
qc_parse,
qc_get_type,
qc_get_operation,
qc_get_created_table_name,
qc_is_drop_table_query,
qc_get_table_names,
qc_mysql_parse,
qc_mysql_get_type,
qc_mysql_get_operation,
qc_mysql_get_created_table_name,
qc_mysql_is_drop_table_query,
qc_mysql_get_table_names,
NULL,
qc_query_has_clause,
qc_get_database_names,
qc_get_prepare_name,
qc_get_prepare_operation,
qc_get_field_info,
qc_get_function_info
qc_mysql_query_has_clause,
qc_mysql_get_database_names,
qc_mysql_get_prepare_name,
qc_mysql_get_prepare_operation,
qc_mysql_get_field_info,
qc_mysql_get_function_info
};
static MXS_MODULE info =

View File

@ -2782,20 +2782,20 @@ void maxscaleUse(Parse* pParse, Token* pToken)
/**
* API
*/
static bool qc_sqlite_setup(const char* args);
static int qc_sqlite_process_init(void);
static int32_t qc_sqlite_setup(const char* args);
static int32_t qc_sqlite_process_init(void);
static void qc_sqlite_process_end(void);
static int qc_sqlite_thread_init(void);
static int32_t qc_sqlite_thread_init(void);
static void qc_sqlite_thread_end(void);
static qc_parse_result_t qc_sqlite_parse(GWBUF* query);
static uint32_t qc_sqlite_get_type(GWBUF* query);
static qc_query_op_t qc_sqlite_get_operation(GWBUF* query);
static char* qc_sqlite_get_created_table_name(GWBUF* query);
static bool qc_sqlite_is_drop_table_query(GWBUF* query);
static char** qc_sqlite_get_table_names(GWBUF* query, int* tblsize, bool fullnames);
static char* qc_sqlite_get_canonical(GWBUF* query);
static bool qc_sqlite_query_has_clause(GWBUF* query);
static char** qc_sqlite_get_database_names(GWBUF* query, int* sizep);
static int32_t qc_sqlite_parse(GWBUF* query, int32_t* result);
static int32_t qc_sqlite_get_type(GWBUF* query, uint32_t* typemask);
static int32_t qc_sqlite_get_operation(GWBUF* query, int32_t* op);
static int32_t qc_sqlite_get_created_table_name(GWBUF* query, char** name);
static int32_t qc_sqlite_is_drop_table_query(GWBUF* query, int32_t* is_drop_table);
static int32_t qc_sqlite_get_table_names(GWBUF* query, int32_t fullnames, char*** names, int* tblsize);
static int32_t qc_sqlite_get_canonical(GWBUF* query, char** canonical);
static int32_t qc_sqlite_query_has_clause(GWBUF* query, int32_t* has_clause);
static int32_t qc_sqlite_get_database_names(GWBUF* query, char*** names, int* sizep);
static bool get_key_and_value(char* arg, const char** pkey, const char** pvalue)
{
@ -2814,7 +2814,7 @@ static bool get_key_and_value(char* arg, const char** pkey, const char** pvalue)
static char ARG_LOG_UNRECOGNIZED_STATEMENTS[] = "log_unrecognized_statements";
static bool qc_sqlite_setup(const char* args)
static int32_t qc_sqlite_setup(const char* args)
{
QC_TRACE();
assert(!this_unit.setup);
@ -2861,10 +2861,10 @@ static bool qc_sqlite_setup(const char* args)
this_unit.setup = true;
this_unit.log_level = log_level;
return this_unit.setup;
return this_unit.setup ? QC_RESULT_OK : QC_RESULT_ERROR;
}
static int qc_sqlite_process_init(void)
static int32_t qc_sqlite_process_init(void)
{
QC_TRACE();
assert(this_unit.setup);
@ -2915,7 +2915,7 @@ static int qc_sqlite_process_init(void)
MXS_ERROR("Failed to initialize sqlite3.");
}
return this_unit.initialized ? 0 : -1;
return this_unit.initialized ? QC_RESULT_OK : QC_RESULT_ERROR;
}
static void qc_sqlite_process_end(void)
@ -2931,7 +2931,7 @@ static void qc_sqlite_process_end(void)
this_unit.initialized = false;
}
static int qc_sqlite_thread_init(void)
static int32_t qc_sqlite_thread_init(void)
{
QC_TRACE();
ss_dassert(this_unit.initialized);
@ -2982,7 +2982,7 @@ static int qc_sqlite_thread_init(void)
(unsigned long) pthread_self(), rc, sqlite3_errstr(rc));
}
return this_thread.initialized ? 0 : -1;
return this_thread.initialized ? QC_RESULT_OK : QC_RESULT_ERROR;
}
static void qc_sqlite_thread_end(void)
@ -3004,7 +3004,7 @@ static void qc_sqlite_thread_end(void)
this_thread.initialized = false;
}
static qc_parse_result_t qc_sqlite_parse(GWBUF* query)
static int32_t qc_sqlite_parse(GWBUF* query, int32_t* result)
{
QC_TRACE();
ss_dassert(this_unit.initialized);
@ -3012,23 +3012,34 @@ static qc_parse_result_t qc_sqlite_parse(GWBUF* query)
QC_SQLITE_INFO* info = get_query_info(query);
return info ? info->status : QC_QUERY_INVALID;
if (info)
{
*result = info->status;
}
else
{
*result = QC_QUERY_INVALID;
}
return info ? QC_RESULT_OK : QC_RESULT_ERROR;
}
static uint32_t qc_sqlite_get_type(GWBUF* query)
static int32_t qc_sqlite_get_type(GWBUF* query, uint32_t* type_mask)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
uint32_t types = QUERY_TYPE_UNKNOWN;
*type_mask = QUERY_TYPE_UNKNOWN;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
if (qc_info_is_valid(info->status))
{
types = info->types;
*type_mask = info->types;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3040,23 +3051,25 @@ static uint32_t qc_sqlite_get_type(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return types;
return rv;
}
static qc_query_op_t qc_sqlite_get_operation(GWBUF* query)
static int32_t qc_sqlite_get_operation(GWBUF* query, int32_t* op)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
qc_query_op_t op = QUERY_OP_UNDEFINED;
*op = QUERY_OP_UNDEFINED;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
if (qc_info_is_valid(info->status))
{
op = info->operation;
*op = info->operation;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3068,16 +3081,17 @@ static qc_query_op_t qc_sqlite_get_operation(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return op;
return rv;
}
static char* qc_sqlite_get_created_table_name(GWBUF* query)
static int32_t qc_sqlite_get_created_table_name(GWBUF* query, char** created_table_name)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
char* created_table_name = NULL;
*created_table_name = NULL;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
@ -3086,8 +3100,9 @@ static char* qc_sqlite_get_created_table_name(GWBUF* query)
{
if (info->created_table_name)
{
created_table_name = MXS_STRDUP(info->created_table_name);
*created_table_name = MXS_STRDUP(info->created_table_name);
MXS_ABORT_IF_NULL(created_table_name);
rv = QC_RESULT_OK;
}
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
@ -3100,23 +3115,25 @@ static char* qc_sqlite_get_created_table_name(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return created_table_name;
return rv;
}
static bool qc_sqlite_is_drop_table_query(GWBUF* query)
static int32_t qc_sqlite_is_drop_table_query(GWBUF* query, int32_t* is_drop_table)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
bool is_drop_table = false;
*is_drop_table = 0;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
if (qc_info_is_valid(info->status))
{
is_drop_table = info->is_drop_table;
*is_drop_table = info->is_drop_table;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3128,19 +3145,22 @@ static bool qc_sqlite_is_drop_table_query(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return is_drop_table;
return rv;
}
static char** qc_sqlite_get_table_names(GWBUF* query, int* tblsize, bool fullnames)
static int32_t qc_sqlite_get_table_names(GWBUF* query,
int32_t fullnames,
char*** table_names,
int32_t* tblsize)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
char** table_names = NULL;
QC_SQLITE_INFO* info = get_query_info(query);
*table_names = NULL;
*tblsize = 0;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
@ -3148,21 +3168,23 @@ static char** qc_sqlite_get_table_names(GWBUF* query, int* tblsize, bool fullnam
{
if (fullnames)
{
table_names = info->table_fullnames;
*table_names = info->table_fullnames;
}
else
{
table_names = info->table_names;
*table_names = info->table_names;
}
if (table_names)
if (*table_names)
{
table_names = copy_string_array(table_names, tblsize);
*table_names = copy_string_array(*table_names, tblsize);
}
else
{
*tblsize = 0;
}
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3174,34 +3196,39 @@ static char** qc_sqlite_get_table_names(GWBUF* query, int* tblsize, bool fullnam
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return table_names;
return rv;
}
static char* qc_sqlite_get_canonical(GWBUF* query)
static int32_t qc_sqlite_get_canonical(GWBUF* query, char** canonical)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
*canonical = NULL;
MXS_ERROR("qc_get_canonical not implemented yet.");
return NULL;
return rv;
}
static bool qc_sqlite_query_has_clause(GWBUF* query)
static int32_t qc_sqlite_query_has_clause(GWBUF* query, int32_t* has_clause)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
bool has_clause = false;
*has_clause = false;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
if (qc_info_is_valid(info->status))
{
has_clause = info->has_clause;
*has_clause = info->has_clause;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3213,19 +3240,19 @@ static bool qc_sqlite_query_has_clause(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return has_clause;
return rv;
}
static char** qc_sqlite_get_database_names(GWBUF* query, int* sizep)
static int32_t qc_sqlite_get_database_names(GWBUF* query, char*** database_names, int* sizep)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
char** database_names = NULL;
QC_SQLITE_INFO* info = get_query_info(query);
*database_names = NULL;
*sizep = 0;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
@ -3233,8 +3260,10 @@ static char** qc_sqlite_get_database_names(GWBUF* query, int* sizep)
{
if (info->database_names)
{
database_names = copy_string_array(info->database_names, sizep);
*database_names = copy_string_array(info->database_names, sizep);
}
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3246,16 +3275,17 @@ static char** qc_sqlite_get_database_names(GWBUF* query, int* sizep)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return database_names;
return rv;
}
static char* qc_sqlite_get_prepare_name(GWBUF* query)
static int32_t qc_sqlite_get_prepare_name(GWBUF* query, char** prepare_name)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
char* name = NULL;
*prepare_name = NULL;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
@ -3264,8 +3294,10 @@ static char* qc_sqlite_get_prepare_name(GWBUF* query)
{
if (info->prepare_name)
{
name = MXS_STRDUP(info->prepare_name);
*prepare_name = MXS_STRDUP(info->prepare_name);
}
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3277,40 +3309,44 @@ static char* qc_sqlite_get_prepare_name(GWBUF* query)
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return name;
return rv;
}
static qc_query_op_t qc_sqlite_get_prepare_operation(GWBUF* query)
static int32_t qc_sqlite_get_prepare_operation(GWBUF* query, int32_t* op)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
qc_query_op_t op = QUERY_OP_UNDEFINED;
*op = QUERY_OP_UNDEFINED;
QC_SQLITE_INFO* info = get_query_info(query);
if (info)
{
if (qc_info_is_valid(info->status))
{
op = info->prepare_operation;
*op = info->prepare_operation;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
log_invalid_data(query, "cannot report the operation of a prepared statement");
}
rv = QC_RESULT_OK;
}
else
{
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return op;
return rv;
}
void qc_sqlite_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t* n_infos)
int32_t qc_sqlite_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, uint32_t* n_infos)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
@ -3325,6 +3361,8 @@ void qc_sqlite_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t*
{
*infos = info->field_infos;
*n_infos = info->field_infos_len;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3335,11 +3373,14 @@ void qc_sqlite_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t*
{
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return rv;
}
void qc_sqlite_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, size_t* n_infos)
int32_t qc_sqlite_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, uint32_t* n_infos)
{
QC_TRACE();
int32_t rv = QC_RESULT_ERROR;
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
@ -3354,6 +3395,8 @@ void qc_sqlite_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, s
{
*infos = info->function_infos;
*n_infos = info->function_infos_len;
rv = QC_RESULT_OK;
}
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
@ -3364,6 +3407,8 @@ void qc_sqlite_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, s
{
MXS_ERROR("The query could not be parsed. Response not valid.");
}
return rv;
}
/**

View File

@ -163,7 +163,8 @@ QUERY_CLASSIFIER* get_classifier(const char* zName, const char* zArgs)
if (pClassifier)
{
if (!pClassifier->qc_setup(zArgs) || (pClassifier->qc_process_init() != 0))
if ((pClassifier->qc_setup(zArgs) != QC_RESULT_OK) ||
((pClassifier->qc_process_init() != QC_RESULT_OK)))
{
cerr << "error: Could not setup or init classifier " << zName << "." << endl;
qc_unload(pClassifier);
@ -307,12 +308,14 @@ bool compare_parse(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
struct timespec finish;
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
qc_parse_result_t rv1 = pClassifier1->qc_parse(pCopy1);
int32_t rv1;
pClassifier1->qc_parse(pCopy1, &rv1);
clock_gettime(CLOCK_MONOTONIC_RAW, &finish);
update_time(&global.time1, start, finish);
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
qc_parse_result_t rv2 = pClassifier2->qc_parse(pCopy2);
int32_t rv2;
pClassifier2->qc_parse(pCopy2, &rv2);
clock_gettime(CLOCK_MONOTONIC_RAW, &finish);
update_time(&global.time2, start, finish);
@ -336,7 +339,7 @@ bool compare_parse(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
success = true;
}
ss << rv1 << " != " << rv2;
ss << static_cast<qc_parse_result_t>(rv1) << " != " << static_cast<qc_parse_result_t>(rv2);
}
report(success, ss.str());
@ -350,8 +353,10 @@ bool compare_get_type(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
bool success = false;
const char HEADING[] = "qc_get_type : ";
uint32_t rv1 = pClassifier1->qc_get_type(pCopy1);
uint32_t rv2 = pClassifier2->qc_get_type(pCopy2);
uint32_t rv1;
pClassifier1->qc_get_type(pCopy1, &rv1);
uint32_t rv2;
pClassifier2->qc_get_type(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
@ -416,20 +421,25 @@ bool compare_get_operation(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
bool success = false;
const char HEADING[] = "qc_get_operation : ";
qc_query_op_t rv1 = pClassifier1->qc_get_operation(pCopy1);
qc_query_op_t rv2 = pClassifier2->qc_get_operation(pCopy2);
int32_t rv1;
pClassifier1->qc_get_operation(pCopy1, &rv1);
int32_t rv2;
pClassifier2->qc_get_operation(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
if (rv1 == rv2)
{
ss << "Ok : " << qc_op_to_string(rv1);
ss << "Ok : " << qc_op_to_string(static_cast<qc_query_op_t>(rv1));
success = true;
}
else
{
ss << "ERR: " << qc_op_to_string(rv1) << " != " << qc_op_to_string(rv2);
ss << "ERR: "
<< qc_op_to_string(static_cast<qc_query_op_t>(rv1))
<< " != "
<< qc_op_to_string(static_cast<qc_query_op_t>(rv2));
}
report(success, ss.str());
@ -443,8 +453,10 @@ bool compare_get_created_table_name(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy
bool success = false;
const char HEADING[] = "qc_get_created_table_name: ";
char* rv1 = pClassifier1->qc_get_created_table_name(pCopy1);
char* rv2 = pClassifier2->qc_get_created_table_name(pCopy2);
char* rv1;
pClassifier1->qc_get_created_table_name(pCopy1, &rv1);
char* rv2;
pClassifier2->qc_get_created_table_name(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
@ -473,20 +485,22 @@ bool compare_is_drop_table_query(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
bool success = false;
const char HEADING[] = "qc_is_drop_table_query : ";
bool rv1 = pClassifier1->qc_is_drop_table_query(pCopy1);
bool rv2 = pClassifier2->qc_is_drop_table_query(pCopy2);
int32_t rv1;
pClassifier1->qc_is_drop_table_query(pCopy1, &rv1);
int32_t rv2;
pClassifier2->qc_is_drop_table_query(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
if (rv1 == rv2)
{
ss << "Ok : " << rv1;
ss << "Ok : " << static_cast<bool>(rv1);
success = true;
}
else
{
ss << "ERR: " << rv1 << " != " << rv2;
ss << "ERR: " << static_cast<bool>(rv1) << " != " << static_cast<bool>(rv2);
}
report(success, ss.str());
@ -561,8 +575,10 @@ bool compare_get_table_names(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
int n1 = 0;
int n2 = 0;
char** rv1 = pClassifier1->qc_get_table_names(pCopy1, &n1, full);
char** rv2 = pClassifier2->qc_get_table_names(pCopy2, &n2, full);
char** rv1;
pClassifier1->qc_get_table_names(pCopy1, full, &rv1, &n1);
char** rv2;
pClassifier2->qc_get_table_names(pCopy2, full, &rv2, &n2);
// The order need not be the same, so let's compare a set.
std::set<string> names1;
@ -620,20 +636,22 @@ bool compare_query_has_clause(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
bool success = false;
const char HEADING[] = "qc_query_has_clause : ";
bool rv1 = pClassifier1->qc_query_has_clause(pCopy1);
bool rv2 = pClassifier2->qc_query_has_clause(pCopy2);
int32_t rv1;
pClassifier1->qc_query_has_clause(pCopy1, &rv1);
int32_t rv2;
pClassifier2->qc_query_has_clause(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
if (rv1 == rv2)
{
ss << "Ok : " << rv1;
ss << "Ok : " << static_cast<bool>(rv1);
success = true;
}
else
{
ss << "ERR: " << rv1 << " != " << rv2;
ss << "ERR: " << static_cast<bool>(rv1) << " != " << static_cast<bool>(rv2);
}
report(success, ss.str());
@ -701,8 +719,10 @@ bool compare_get_database_names(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
int n1 = 0;
int n2 = 0;
char** rv1 = pClassifier1->qc_get_database_names(pCopy1, &n1);
char** rv2 = pClassifier2->qc_get_database_names(pCopy2, &n2);
char** rv1;
pClassifier1->qc_get_database_names(pCopy1, &rv1, &n1);
char** rv2;
pClassifier2->qc_get_database_names(pCopy2, &rv2, &n2);
stringstream ss;
ss << HEADING;
@ -735,8 +755,10 @@ bool compare_get_prepare_name(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
bool success = false;
const char HEADING[] = "qc_get_prepare_name : ";
char* rv1 = pClassifier1->qc_get_prepare_name(pCopy1);
char* rv2 = pClassifier2->qc_get_prepare_name(pCopy2);
char* rv1;
pClassifier1->qc_get_prepare_name(pCopy1, &rv1);
char* rv2;
pClassifier2->qc_get_prepare_name(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
@ -765,20 +787,25 @@ bool compare_get_prepare_operation(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1
bool success = false;
const char HEADING[] = "qc_get_prepare_operation : ";
qc_query_op_t rv1 = pClassifier1->qc_get_prepare_operation(pCopy1);
qc_query_op_t rv2 = pClassifier2->qc_get_prepare_operation(pCopy2);
int32_t rv1;
pClassifier1->qc_get_prepare_operation(pCopy1, &rv1);
int32_t rv2;
pClassifier2->qc_get_prepare_operation(pCopy2, &rv2);
stringstream ss;
ss << HEADING;
if (rv1 == rv2)
{
ss << "Ok : " << qc_op_to_string(rv1);
ss << "Ok : " << qc_op_to_string(static_cast<qc_query_op_t>(rv1));
success = true;
}
else
{
ss << "ERR: " << qc_op_to_string(rv1) << " != " << qc_op_to_string(rv2);
ss << "ERR: "
<< qc_op_to_string(static_cast<qc_query_op_t>(rv1))
<< " != "
<< qc_op_to_string(static_cast<qc_query_op_t>(rv2));
}
report(success, ss.str());
@ -999,8 +1026,8 @@ bool compare_get_field_info(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
const QC_FIELD_INFO* infos1;
const QC_FIELD_INFO* infos2;
size_t n_infos1;
size_t n_infos2;
uint32_t n_infos1;
uint32_t n_infos2;
pClassifier1->qc_get_field_info(pCopy1, &infos1, &n_infos1);
pClassifier2->qc_get_field_info(pCopy2, &infos2, &n_infos2);
@ -1128,8 +1155,8 @@ bool compare_get_function_info(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
const QC_FUNCTION_INFO* infos1;
const QC_FUNCTION_INFO* infos2;
size_t n_infos1;
size_t n_infos2;
uint32_t n_infos1;
uint32_t n_infos2;
pClassifier1->qc_get_function_info(pCopy1, &infos1, &n_infos1);
pClassifier2->qc_get_function_info(pCopy2, &infos2, &n_infos2);

View File

@ -49,21 +49,21 @@ bool qc_setup(const char* plugin_name, const char* plugin_args)
plugin_name = default_qc_name;
}
bool success = false;
int32_t rv = QC_RESULT_ERROR;
classifier = qc_load(plugin_name);
if (classifier)
{
success = classifier->qc_setup(plugin_args);
rv = classifier->qc_setup(plugin_args);
if (!success)
if (rv != QC_RESULT_OK)
{
qc_unload(classifier);
classifier = NULL;
}
}
return success;
return (rv == QC_RESULT_OK) ? true : false;
}
bool qc_process_init(void)
@ -126,7 +126,11 @@ qc_parse_result_t qc_parse(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_parse(query);
int32_t result = QC_QUERY_INVALID;
classifier->qc_parse(query, &result);
return (qc_parse_result_t)result;
}
uint32_t qc_get_type(GWBUF* query)
@ -134,7 +138,11 @@ uint32_t qc_get_type(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_type(query);
uint32_t type_mask = QUERY_TYPE_UNKNOWN;
classifier->qc_get_type(query, &type_mask);
return type_mask;
}
qc_query_op_t qc_get_operation(GWBUF* query)
@ -142,7 +150,11 @@ qc_query_op_t qc_get_operation(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_operation(query);
int32_t op = QUERY_OP_UNDEFINED;
classifier->qc_get_operation(query, &op);
return (qc_query_op_t)op;
}
char* qc_get_created_table_name(GWBUF* query)
@ -150,7 +162,11 @@ char* qc_get_created_table_name(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_created_table_name(query);
char* name = NULL;
classifier->qc_get_created_table_name(query, &name);
return name;
}
bool qc_is_drop_table_query(GWBUF* query)
@ -158,7 +174,11 @@ bool qc_is_drop_table_query(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_is_drop_table_query(query);
int32_t is_drop_table = 0;
classifier->qc_is_drop_table_query(query, &is_drop_table);
return (is_drop_table != 0) ? true : false;
}
char** qc_get_table_names(GWBUF* query, int* tblsize, bool fullnames)
@ -166,7 +186,12 @@ char** qc_get_table_names(GWBUF* query, int* tblsize, bool fullnames)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_table_names(query, tblsize, fullnames);
char** names = NULL;
*tblsize = 0;
classifier->qc_get_table_names(query, fullnames, &names, tblsize);
return names;
}
char* qc_get_canonical(GWBUF* query)
@ -178,7 +203,7 @@ char* qc_get_canonical(GWBUF* query)
if (classifier->qc_get_canonical)
{
rval = classifier->qc_get_canonical(query);
classifier->qc_get_canonical(query, &rval);
}
else
{
@ -198,7 +223,11 @@ bool qc_query_has_clause(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_query_has_clause(query);
int32_t has_clause = 0;
classifier->qc_query_has_clause(query, &has_clause);
return (has_clause != 0) ? true : false;
}
void qc_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t* n_infos)
@ -206,7 +235,13 @@ void qc_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t* n_info
QC_TRACE();
ss_dassert(classifier);
classifier->qc_get_field_info(query, infos, n_infos);
*infos = NULL;
uint32_t n = 0;
classifier->qc_get_field_info(query, infos, &n);
*n_infos = n;
}
void qc_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, size_t* n_infos)
@ -214,7 +249,13 @@ void qc_get_function_info(GWBUF* query, const QC_FUNCTION_INFO** infos, size_t*
QC_TRACE();
ss_dassert(classifier);
classifier->qc_get_function_info(query, infos, n_infos);
*infos = NULL;
uint32_t n = 0;
classifier->qc_get_function_info(query, infos, &n);
*n_infos = n;
}
char** qc_get_database_names(GWBUF* query, int* sizep)
@ -222,7 +263,12 @@ char** qc_get_database_names(GWBUF* query, int* sizep)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_database_names(query, sizep);
char** names = NULL;
*sizep = 0;
classifier->qc_get_database_names(query, &names, sizep);
return names;
}
char* qc_get_prepare_name(GWBUF* query)
@ -230,7 +276,11 @@ char* qc_get_prepare_name(GWBUF* query)
QC_TRACE();
ss_dassert(classifier);
return classifier->qc_get_prepare_name(query);
char* name = NULL;
classifier->qc_get_prepare_name(query, &name);
return name;
}
struct type_name_info field_usage_to_type_name_info(qc_field_usage_t usage)