MXS-1621: Skip unneeded ALTER TABLE operations

Some ALTER TABLE operations (e.g. ADD INDEX) are not useful to the
avrorouter. These need to be detected and skipped.
This commit is contained in:
Markus Mäkelä 2018-01-29 14:05:52 +02:00
parent e14710ab2b
commit 93923acafb
3 changed files with 82 additions and 5 deletions

View File

@ -1021,6 +1021,40 @@ void unify_whitespace(char *sql, int len)
}
}
/**
* A very simple function for stripping auto-generated executable comments
*
* Note that the string will not strip the trailing part of the comment, making
* the SQL invalid.
*
* @param sql String to modify
* @param len Pointer to current length of string, updated to new length if
* @c sql is modified
*/
static void strip_executable_comments(char *sql, int* len)
{
if (strncmp(sql, "/*!", 3) == 0 || strncmp(sql, "/*M!", 4) == 0)
{
// Executable comment, remove it
char* p = sql + 3;
if (*p == '!')
{
p++;
}
// Skip the versioning part
while (*p && isdigit(*p))
{
p++;
}
int n_extra = p - sql;
int new_len = *len - n_extra;
memmove(sql, sql + n_extra, new_len);
*len = new_len;
}
}
/**
* @brief Handling of query events
*
@ -1046,6 +1080,7 @@ void handle_query_event(AVRO_INSTANCE *router, REP_HEADER *hdr, int *pending_tra
sql = tmp;
len = tmpsz;
unify_whitespace(sql, len);
strip_executable_comments(sql, &len);
sql[len] = '\0';
static bool warn_not_row_format = true;
@ -1107,7 +1142,7 @@ void handle_query_event(AVRO_INSTANCE *router, REP_HEADER *hdr, int *pending_tra
}
else
{
MXS_ERROR("Alter statement to a table with no create statement.");
MXS_ERROR("Alter statement to table '%s' has no preceding create statement.", ident);
}
}
/* A transaction starts with this event */

View File

@ -337,9 +337,9 @@ bool handle_row_event(AVRO_INSTANCE *router, REP_HEADER *hdr, uint8_t *ptr)
}
else if (ncolumns == map->columns && create->columns != map->columns)
{
MXS_ERROR("Table map event has a different column "
"count for table %s.%s than the CREATE TABLE statement.",
map->database, map->table);
MXS_ERROR("Table map event has a different column count for table "
"%s.%s than the CREATE TABLE statement. Possible "
"unsupported DDL detected.", map->database, map->table);
}
else
{

View File

@ -1392,6 +1392,14 @@ int get_column_index(TABLE_CREATE *create, const char *tok, int len)
char safe_tok[len + 2];
memcpy(safe_tok, tok, len);
safe_tok[len] = '\0';
if (*safe_tok == '`')
{
int toklen = strlen(safe_tok) - 2; // Token length without backticks
memmove(safe_tok, safe_tok + 1, toklen); // Overwrite first backtick
safe_tok[toklen] = '\0'; // Null-terminate the string before the second backtick
}
fix_reserved_word(safe_tok);
for (int x = 0; x < create->columns; x++)
@ -1406,6 +1414,35 @@ int get_column_index(TABLE_CREATE *create, const char *tok, int len)
return idx;
}
static bool not_column_operation(const char* tok, int len)
{
const char* keywords[] =
{
"PRIMARY",
"UNIQUE",
"FULLTEXT",
"SPATIAL",
"PERIOD",
"PRIMARY",
"KEY",
"KEYS",
"INDEX",
"FOREIGN",
"CONSTRAINT",
NULL
};
for (int i = 0; keywords[i]; i++)
{
if (tok_eq(tok, keywords[i], strlen(keywords[i])))
{
return true;
}
}
return false;
}
bool table_create_alter(TABLE_CREATE *create, const char *sql, const char *end)
{
const char *tbl = strcasestr(sql, "table"), *def;
@ -1431,7 +1468,12 @@ bool table_create_alter(TABLE_CREATE *create, const char *sql, const char *end)
if (tok)
{
if (tok_eq(tok, "column", len))
if (not_column_operation(tok, len))
{
MXS_INFO("Statement doesn't affect columns, not processing: %s", sql);
return true;
}
else if (tok_eq(tok, "column", len))
{
// Skip the optional COLUMN keyword
tok = get_tok(tok + len, &len, end);