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
......@@ -1092,30 +1092,38 @@ int ha_partition::handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
(modelled after mi_check_print_msg)
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* op_name, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 6, 7);
static bool print_admin_msg(THD* thd, const char* msg_type,
ATTRIBUTE_FORMAT(printf, 7, 8);
static bool print_admin_msg(THD* thd, uint len,
const char* msg_type,
const char* db_name, const char* table_name,
const char* op_name, const char *fmt, ...)
{
va_list args;
Protocol *protocol= thd->protocol;
uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF];
uint length;
uint msg_length;
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);
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msg_length= my_vsnprintf(msgbuf, len, fmt, 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())
{
sql_print_error("%s", msgbuf);
return TRUE;
goto err;
}
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,
{
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
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,
error != HA_ADMIN_ALREADY_DONE &&
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],
"Subpartition %s returned error",
sub_elem->partition_name);
......@@ -1223,7 +1235,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
error != HA_ADMIN_ALREADY_DONE &&
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], "Partition %s returned error",
part_elem->partition_name);
}
......@@ -7787,7 +7800,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
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],
"Moved %lld misplaced rows",
num_misplaced_rows);
......@@ -7808,7 +7822,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
if (!repair)
{
/* 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],
"Found a misplaced row");
/* Break on first misplaced row! */
......@@ -7855,7 +7870,8 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool repair)
correct_part_id,
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],
"Failed to move/insert a row"
" from part %d into part %d:\n%s",
......@@ -7986,12 +8002,18 @@ int ha_partition::check_for_upgrade(HA_CHECK_OPT *check_opt)
NULL,
NULL,
NULL)) ||
/* Also check that the length is smaller than the output field! */
(part_buf_len + db_name.length() + table_name.length()) >=
(SQL_ADMIN_MSG_TEXT_SIZE -
(strlen(KEY_PARTITIONING_CHANGED_STR) - 3)))
print_admin_msg(thd, SQL_ADMIN_MSG_TEXT_SIZE + 1, "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))
{
print_admin_msg(thd, "error", table_share->db.str, table->alias,
/* 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],
KEY_PARTITIONING_CHANGED_STR,
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)
" between 'KEY' and '(' to change the metadata"
" 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;
DBUG_RETURN(error);
}
......
......@@ -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++;
/* new_part_elem may not have engine_type set! */
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);
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