Commit b2159871 authored by Mattias Jonsson's avatar Mattias Jonsson

Bug#16589511: MYSQL_UPGRADE FAILS TO WRITE OUT ENTIRE

ALTER TABLE ... ALGORITHM= ... STATEMENT

The problem was an intermediate buffer of smaller size,
which truncated the alter statement.

Solved by providing the size of the buffer to be allocated through
the function call, instead of using an one-size-fits-all stack buffer
inside the function.
parent 1cfa4eb0
...@@ -1088,34 +1088,42 @@ int ha_partition::handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt, ...@@ -1088,34 +1088,42 @@ int ha_partition::handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
/* /*
print a message row formatted for ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE print a message row formatted for ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE
(modelled after mi_check_print_msg) (modelled after mi_check_print_msg)
TODO: move this into the handler, or rewrite mysql_admin_table. TODO: move this into the handler, or rewrite mysql_admin_table.
*/ */
static bool print_admin_msg(THD* thd, const char* msg_type, static bool print_admin_msg(THD* thd, uint len,
const char* msg_type,
const char* db_name, const char* table_name, const char* db_name, const char* table_name,
const char* op_name, const char *fmt, ...) const char* op_name, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 6, 7); ATTRIBUTE_FORMAT(printf, 7, 8);
static bool print_admin_msg(THD* thd, const char* msg_type, static bool print_admin_msg(THD* thd, uint len,
const char* msg_type,
const char* db_name, const char* table_name, const char* db_name, const char* table_name,
const char* op_name, const char *fmt, ...) const char* op_name, const char *fmt, ...)
{ {
va_list args; va_list args;
Protocol *protocol= thd->protocol; Protocol *protocol= thd->protocol;
uint length, msg_length; uint length;
char msgbuf[MI_MAX_MSG_BUF]; uint msg_length;
char name[NAME_LEN*2+2]; char name[NAME_LEN*2+2];
char *msgbuf;
bool error= true;
if (!(msgbuf= (char*) my_malloc(len, MYF(0))))
return true;
va_start(args, fmt); va_start(args, fmt);
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); msg_length= my_vsnprintf(msgbuf, len, fmt, args);
va_end(args); va_end(args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia if (msg_length >= (len - 1))
goto err;
msgbuf[len - 1] = 0; // healthy paranoia
if (!thd->vio_ok()) if (!thd->vio_ok())
{ {
sql_print_error("%s", msgbuf); sql_print_error("%s", msgbuf);
return TRUE; goto err;
} }
length=(uint) (strxmov(name, db_name, ".", table_name,NullS) - name); length=(uint) (strxmov(name, db_name, ".", table_name,NullS) - name);
...@@ -1138,9 +1146,12 @@ static bool print_admin_msg(THD* thd, const char* msg_type, ...@@ -1138,9 +1146,12 @@ static bool print_admin_msg(THD* thd, const char* msg_type,
{ {
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n", sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf); msgbuf);
return TRUE; goto err;
} }
return FALSE; error= false;
err:
my_free(msgbuf);
return error;
} }
...@@ -1197,7 +1208,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, ...@@ -1197,7 +1208,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
error != HA_ADMIN_ALREADY_DONE && error != HA_ADMIN_ALREADY_DONE &&
error != HA_ADMIN_TRY_ALTER) error != HA_ADMIN_TRY_ALTER)
{ {
print_admin_msg(thd, "error", table_share->db.str, table->alias, print_admin_msg(thd, MI_MAX_MSG_BUF, "error",
table_share->db.str, table->alias,
opt_op_name[flag], opt_op_name[flag],
"Subpartition %s returned error", "Subpartition %s returned error",
sub_elem->partition_name); sub_elem->partition_name);
...@@ -1223,8 +1235,9 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, ...@@ -1223,8 +1235,9 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
error != HA_ADMIN_ALREADY_DONE && error != HA_ADMIN_ALREADY_DONE &&
error != HA_ADMIN_TRY_ALTER) error != HA_ADMIN_TRY_ALTER)
{ {
print_admin_msg(thd, "error", table_share->db.str, table->alias, print_admin_msg(thd, MI_MAX_MSG_BUF, "error",
opt_op_name[flag], "Partition %s returned error", table_share->db.str, table->alias,
opt_op_name[flag], "Partition %s returned error",
part_elem->partition_name); part_elem->partition_name);
} }
/* reset part_state for the remaining partitions */ /* reset part_state for the remaining partitions */
...@@ -7787,7 +7800,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair) ...@@ -7787,7 +7800,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
if (num_misplaced_rows > 0) if (num_misplaced_rows > 0)
{ {
print_admin_msg(ha_thd(), "warning", table_share->db.str, table->alias, print_admin_msg(ha_thd(), MI_MAX_MSG_BUF, "warning",
table_share->db.str, table->alias,
opt_op_name[REPAIR_PARTS], opt_op_name[REPAIR_PARTS],
"Moved %lld misplaced rows", "Moved %lld misplaced rows",
num_misplaced_rows); num_misplaced_rows);
...@@ -7808,7 +7822,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair) ...@@ -7808,7 +7822,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
if (!repair) if (!repair)
{ {
/* Check. */ /* Check. */
print_admin_msg(ha_thd(), "error", table_share->db.str, table->alias, print_admin_msg(ha_thd(), MI_MAX_MSG_BUF, "error",
table_share->db.str, table->alias,
opt_op_name[CHECK_PARTS], opt_op_name[CHECK_PARTS],
"Found a misplaced row"); "Found a misplaced row");
/* Break on first misplaced row! */ /* Break on first misplaced row! */
...@@ -7855,7 +7870,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair) ...@@ -7855,7 +7870,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
correct_part_id, correct_part_id,
str.c_ptr_safe()); str.c_ptr_safe());
} }
print_admin_msg(ha_thd(), "error", table_share->db.str, table->alias, print_admin_msg(ha_thd(), MI_MAX_MSG_BUF, "error",
table_share->db.str, table->alias,
opt_op_name[REPAIR_PARTS], opt_op_name[REPAIR_PARTS],
"Failed to move/insert a row" "Failed to move/insert a row"
" from part %d into part %d:\n%s", " from part %d into part %d:\n%s",
...@@ -7986,12 +8002,18 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt) ...@@ -7986,12 +8002,18 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt)
NULL, NULL,
NULL, NULL,
NULL)) || NULL)) ||
/* Also check that the length is smaller than the output field! */ print_admin_msg(thd, SQL_ADMIN_MSG_TEXT_SIZE + 1, "error",
(part_buf_len + db_name.length() + table_name.length()) >= table_share->db.str,
(SQL_ADMIN_MSG_TEXT_SIZE - table->alias,
(strlen(KEY_PARTITIONING_CHANGED_STR) - 3))) opt_op_name[CHECK_PARTS],
{ KEY_PARTITIONING_CHANGED_STR,
print_admin_msg(thd, "error", table_share->db.str, table->alias, db_name.c_ptr_safe(),
table_name.c_ptr_safe(),
part_buf))
{
/* Error creating admin message (too long string?). */
print_admin_msg(thd, MI_MAX_MSG_BUF, "error",
table_share->db.str, table->alias,
opt_op_name[CHECK_PARTS], opt_op_name[CHECK_PARTS],
KEY_PARTITIONING_CHANGED_STR, KEY_PARTITIONING_CHANGED_STR,
db_name.c_ptr_safe(), table_name.c_ptr_safe(), db_name.c_ptr_safe(), table_name.c_ptr_safe(),
...@@ -7999,14 +8021,6 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt) ...@@ -7999,14 +8021,6 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt)
" between 'KEY' and '(' to change the metadata" " between 'KEY' and '(' to change the metadata"
" without the need of a full table rebuild."); " without the need of a full table rebuild.");
} }
else
{
print_admin_msg(thd, "error", table_share->db.str, table->alias,
opt_op_name[CHECK_PARTS],
KEY_PARTITIONING_CHANGED_STR,
db_name.c_ptr_safe(), table_name.c_ptr_safe(),
part_buf);
}
m_part_info->key_algorithm= old_algorithm; m_part_info->key_algorithm= old_algorithm;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
......
...@@ -2459,7 +2459,7 @@ bool partition_info::has_same_partitioning(partition_info *new_part_info) ...@@ -2459,7 +2459,7 @@ bool partition_info::has_same_partitioning(partition_info *new_part_info)
partition_element *new_sub_part_elem= new_sub_part_it++; partition_element *new_sub_part_elem= new_sub_part_it++;
/* new_part_elem may not have engine_type set! */ /* new_part_elem may not have engine_type set! */
if (new_sub_part_elem->engine_type && if (new_sub_part_elem->engine_type &&
sub_part_elem->engine_type != new_part_elem->engine_type) sub_part_elem->engine_type != new_sub_part_elem->engine_type)
DBUG_RETURN(false); DBUG_RETURN(false);
if (strcmp(sub_part_elem->partition_name, if (strcmp(sub_part_elem->partition_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment