Add functionality for bypassing MySQL whitespace/comments
This functionality is needed both in the query classifier, where it was first created, and in the cache.
This commit is contained in:
@ -53,9 +53,29 @@ GWBUF* modutil_create_mysql_err_msg(int packet_number,
|
|||||||
int merrno,
|
int merrno,
|
||||||
const char *statemsg,
|
const char *statemsg,
|
||||||
const char *msg);
|
const char *msg);
|
||||||
|
|
||||||
int modutil_count_signal_packets(GWBUF*, int, int, int*);
|
int modutil_count_signal_packets(GWBUF*, int, int, int*);
|
||||||
mxs_pcre2_result_t modutil_mysql_wildcard_match(const char* pattern, const char* string);
|
mxs_pcre2_result_t modutil_mysql_wildcard_match(const char* pattern, const char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a buffer containing a MySQL statement, this function will return
|
||||||
|
* a pointer to the first character that is not whitespace. In this context,
|
||||||
|
* comments are also counted as whitespace. For instance:
|
||||||
|
*
|
||||||
|
* "SELECT" => "SELECT"
|
||||||
|
* " SELECT => "SELECT"
|
||||||
|
* " / * A comment * / SELECT" => "SELECT"
|
||||||
|
* "-- comment\nSELECT" => "SELECT"
|
||||||
|
*
|
||||||
|
* @param sql Pointer to buffer containing a MySQL statement
|
||||||
|
* @param len Length of sql.
|
||||||
|
*
|
||||||
|
* @return The first non whitespace (including comments) character. If the
|
||||||
|
* entire buffer is only whitespace, the returned pointer will point
|
||||||
|
* to the character following the buffer (i.e. sql + len).
|
||||||
|
*/
|
||||||
|
char* modutil_MySQL_bypass_whitespace(char* sql, size_t len);
|
||||||
|
|
||||||
/** Character and token searching functions */
|
/** Character and token searching functions */
|
||||||
char* strnchr_esc(char* ptr, char c, int len);
|
char* strnchr_esc(char* ptr, char c, int len);
|
||||||
char* strnchr_esc_mysql(char* ptr, char c, int len);
|
char* strnchr_esc_mysql(char* ptr, char c, int len);
|
||||||
|
@ -1213,3 +1213,111 @@ char* modutil_get_canonical(GWBUF* querybuf)
|
|||||||
|
|
||||||
return querystr;
|
return querystr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* modutil_MySQL_bypass_whitespace(char* sql, size_t len)
|
||||||
|
{
|
||||||
|
char *i = sql;
|
||||||
|
char *end = i + len;
|
||||||
|
|
||||||
|
while (i != end)
|
||||||
|
{
|
||||||
|
if (isspace(*i))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else if (*i == '/') // Might be a comment
|
||||||
|
{
|
||||||
|
if ((i + 1 != end) && (*(i + 1) == '*')) // Indeed it was
|
||||||
|
{
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
while (i != end)
|
||||||
|
{
|
||||||
|
if (*i == '*') // Might be the end of the comment
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (i != end)
|
||||||
|
{
|
||||||
|
if (*i == '/') // Indeed it was
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
break; // Out of this inner while.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// It was not the end of the comment.
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Was not a comment, so we'll bail out.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*i == '-') // Might be the start of a comment to the end of line
|
||||||
|
{
|
||||||
|
bool is_comment = false;
|
||||||
|
|
||||||
|
if (i + 1 != end)
|
||||||
|
{
|
||||||
|
if (*(i + 1) == '-') // Might be, yes.
|
||||||
|
{
|
||||||
|
if (i + 2 != end)
|
||||||
|
{
|
||||||
|
if (isspace(*(i + 2))) // Yes, it is.
|
||||||
|
{
|
||||||
|
is_comment = true;
|
||||||
|
|
||||||
|
i += 3;
|
||||||
|
|
||||||
|
while ((i != end) && (*i != '\n'))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != end)
|
||||||
|
{
|
||||||
|
ss_dassert(*i == '\n');
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_comment)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*i == '#')
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
|
||||||
|
while ((i != end) && (*i != '\n'))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != end)
|
||||||
|
{
|
||||||
|
ss_dassert(*i == '\n');
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Neither whitespace not start of a comment, so we bail out.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
@ -578,6 +578,43 @@ void test_large_packets()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* bypass_whitespace(char* sql)
|
||||||
|
{
|
||||||
|
return modutil_MySQL_bypass_whitespace(sql, strlen(sql));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_bypass_whitespace()
|
||||||
|
{
|
||||||
|
char* sql;
|
||||||
|
|
||||||
|
sql = bypass_whitespace("SELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "1");
|
||||||
|
|
||||||
|
sql = bypass_whitespace(" SELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "2");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("\tSELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "3");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("\nSELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "4");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("/* comment */SELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "5");
|
||||||
|
|
||||||
|
sql = bypass_whitespace(" /* comment */ SELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "6");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("-- comment\nSELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "7");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("-- comment\n /* comment */ SELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "8");
|
||||||
|
|
||||||
|
sql = bypass_whitespace("# comment\nSELECT");
|
||||||
|
ss_info_dassert(*sql == 'S', "9");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -591,5 +628,6 @@ int main(int argc, char **argv)
|
|||||||
test_strnchr_esc();
|
test_strnchr_esc();
|
||||||
test_strnchr_esc_mysql();
|
test_strnchr_esc_mysql();
|
||||||
test_large_packets();
|
test_large_packets();
|
||||||
|
test_bypass_whitespace();
|
||||||
exit(result);
|
exit(result);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user