diff options
author | Mattias Jonsson <mattias.jonsson@oracle.com> | 2013-06-28 13:18:16 +0200 |
---|---|---|
committer | Mattias Jonsson <mattias.jonsson@oracle.com> | 2013-06-28 13:18:16 +0200 |
commit | 4fdb955542b542f4b84892739960721adad8d621 (patch) | |
tree | 3304066715e85b94b51ea9f75cf20563347bdbb4 /sql/ha_partition.cc | |
parent | cacac93dfd7d1040c6481711d840ec3d57695633 (diff) | |
download | mariadb-git-4fdb955542b542f4b84892739960721adad8d621.tar.gz |
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.
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r-- | sql/ha_partition.cc | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index bfd4c093b36..17f02c24422 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -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) 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,8 +1235,9 @@ 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, - opt_op_name[flag], "Partition %s returned error", + 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); } /* reset part_state for the remaining partitions */ @@ -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, "error", table_share->db.str, table->alias, + 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)) + { + /* 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); } |