MXS-1346: Move query parsing and query type matching into Rule

The Rule base class now checks whether the query needs to be fully parsed
and if the type of the query matches the rule.

Also added a base rule matching method that should be extended by the rule
types to do their matching. Currently no rule type uses it.
This commit is contained in:
Markus Mäkelä
2017-08-30 19:28:22 +03:00
parent 824962d59a
commit b7f922bf6d

View File

@ -290,6 +290,49 @@ struct Rule
{
}
virtual bool matches_query(GWBUF* buffer, char** msg)
{
return false;
}
virtual bool need_full_parsing(GWBUF* buffer) const
{
bool rval = false;
qc_query_op_t optype = qc_get_operation(buffer);
if (type == RT_COLUMN ||
type == RT_FUNCTION ||
type == RT_USES_FUNCTION ||
type == RT_WILDCARD ||
type == RT_CLAUSE)
{
switch (optype)
{
case QUERY_OP_SELECT:
case QUERY_OP_UPDATE:
case QUERY_OP_INSERT:
case QUERY_OP_DELETE:
rval = true;
break;
default:
break;
}
}
return rval;
}
bool matches_query_type(GWBUF* buffer)
{
qc_query_op_t optype = qc_get_operation(buffer);
return on_queries == FW_OP_UNDEFINED ||
(on_queries & qc_op_to_fw_op(optype)) ||
(MYSQL_IS_COM_INIT_DB(GWBUF_DATA(buffer)) &&
(on_queries & FW_OP_CHANGE_DB));
}
void* data; /*< Actual implementation of the rule */
std::string name; /*< Name of the rule */
ruletype_t type; /*< Type of the rule */
@ -2069,8 +2112,8 @@ bool rule_matches(FW_INSTANCE* my_instance,
SRule rule,
char* query)
{
ss_dassert(GWBUF_IS_CONTIGUOUS(queue));
char *msg = NULL;
qc_query_op_t optype = QUERY_OP_UNDEFINED;
bool matches = false;
bool is_sql = modutil_is_SQL(queue) || modutil_is_SQL_prepare(queue);
@ -2083,42 +2126,23 @@ bool rule_matches(FW_INSTANCE* my_instance,
msg = create_parse_error(my_instance, "tokenized", query, &matches);
goto queryresolved;
}
else
else if (parse_result != QC_QUERY_PARSED && rule->need_full_parsing(queue))
{
optype = qc_get_operation(queue);
if (parse_result != QC_QUERY_PARSED)
{
if ((rule->type == RT_COLUMN) ||
(rule->type == RT_FUNCTION) ||
(rule->type == RT_USES_FUNCTION) ||
(rule->type == RT_WILDCARD) ||
(rule->type == RT_CLAUSE))
{
switch (optype)
{
case QUERY_OP_SELECT:
case QUERY_OP_UPDATE:
case QUERY_OP_INSERT:
case QUERY_OP_DELETE:
// In these cases, we have to be able to trust what qc_get_field_info
// returns. Unless the query was parsed completely, we cannot do that.
msg = create_parse_error(my_instance, "parsed completely", query, &matches);
goto queryresolved;
default:
break;
}
}
}
msg = create_parse_error(my_instance, "parsed completely", query, &matches);
goto queryresolved;
}
}
if (rule->on_queries == FW_OP_UNDEFINED ||
rule->on_queries & qc_op_to_fw_op(optype) ||
(MYSQL_IS_COM_INIT_DB((uint8_t*)GWBUF_DATA(queue)) &&
rule->on_queries & FW_OP_CHANGE_DB))
if (rule->matches_query_type(queue))
{
if (rule->matches_query(queue, &msg))
{
/** New style rule matched */
matches = true;
goto queryresolved;
}
/** No match, try old the style rule */
switch (rule->type)
{
case RT_UNDEFINED: