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:
@ -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
|
* @brief Handling of query events
|
||||||
*
|
*
|
||||||
@ -1046,6 +1080,7 @@ void handle_query_event(AVRO_INSTANCE *router, REP_HEADER *hdr, int *pending_tra
|
|||||||
sql = tmp;
|
sql = tmp;
|
||||||
len = tmpsz;
|
len = tmpsz;
|
||||||
unify_whitespace(sql, len);
|
unify_whitespace(sql, len);
|
||||||
|
strip_executable_comments(sql, &len);
|
||||||
sql[len] = '\0';
|
sql[len] = '\0';
|
||||||
|
|
||||||
static bool warn_not_row_format = true;
|
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
|
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 */
|
/* A transaction starts with this event */
|
||||||
|
@ -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)
|
else if (ncolumns == map->columns && create->columns != map->columns)
|
||||||
{
|
{
|
||||||
MXS_ERROR("Table map event has a different column "
|
MXS_ERROR("Table map event has a different column count for table "
|
||||||
"count for table %s.%s than the CREATE TABLE statement.",
|
"%s.%s than the CREATE TABLE statement. Possible "
|
||||||
map->database, map->table);
|
"unsupported DDL detected.", map->database, map->table);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1392,6 +1392,14 @@ int get_column_index(TABLE_CREATE *create, const char *tok, int len)
|
|||||||
char safe_tok[len + 2];
|
char safe_tok[len + 2];
|
||||||
memcpy(safe_tok, tok, len);
|
memcpy(safe_tok, tok, len);
|
||||||
safe_tok[len] = '\0';
|
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);
|
fix_reserved_word(safe_tok);
|
||||||
|
|
||||||
for (int x = 0; x < create->columns; x++)
|
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;
|
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)
|
bool table_create_alter(TABLE_CREATE *create, const char *sql, const char *end)
|
||||||
{
|
{
|
||||||
const char *tbl = strcasestr(sql, "table"), *def;
|
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)
|
||||||
{
|
{
|
||||||
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
|
// Skip the optional COLUMN keyword
|
||||||
tok = get_tok(tok + len, &len, end);
|
tok = get_tok(tok + len, &len, end);
|
||||||
|
Reference in New Issue
Block a user