summaryrefslogtreecommitdiff
path: root/sql/ha_partition.cc
diff options
context:
space:
mode:
authorMattias Jonsson <mattias.jonsson@sun.com>2010-02-01 16:07:00 +0100
committerMattias Jonsson <mattias.jonsson@sun.com>2010-02-01 16:07:00 +0100
commit54c076e98471b2593c16e15c6aa8779f5962ed85 (patch)
tree21b6b2a9effa842bb49499a7a08703369795acdb /sql/ha_partition.cc
parentf81700aa4ead8af29ec34870eefa61abfab12bee (diff)
downloadmariadb-git-54c076e98471b2593c16e15c6aa8779f5962ed85.tar.gz
Bug#42438: Crash ha_partition::change_table_ptr
There was two problems: The first was the symptom, caused by bad error handling in ha_partition. It did not handle print_error etc. when having no partitions (when used by dummy handler). The second was the real problem that when dropping tables it reused the table type (storage engine) from when the lock was asked for, not the table type that it had when gaining the exclusive name lock. So that it tried to delete tables from wrong storage engines. Solutions for the first problem was to accept some handler calls to the partitioning handler even if it was not setup with any partitions, and also if possible fallback to use the base handler's default functions. Solution for the second problem was to remove the optimization to reuse the definition from the cache, instead always check the frm-file when holding the LOCK_open mutex (updated with a fix for a debug print crash and better comments as required by reviewer, and removed optimization to avoid reading the frm-file).
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r--sql/ha_partition.cc33
1 files changed, 27 insertions, 6 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 451631ff373..099b663f5c2 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1719,13 +1719,23 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info)
void ha_partition::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
{
- handler **file_array= m_file;
+ handler **file_array;
table= table_arg;
table_share= share;
- do
+ /*
+ m_file can be NULL when using an old cached table in DROP TABLE, when the
+ table just has REMOVED PARTITIONING, see Bug#42438
+ */
+ if (m_file)
{
- (*file_array)->change_table_ptr(table_arg, share);
- } while (*(++file_array));
+ file_array= m_file;
+ DBUG_ASSERT(*file_array);
+ do
+ {
+ (*file_array)->change_table_ptr(table_arg, share);
+ } while (*(++file_array));
+ }
+
if (m_added_file && m_added_file[0])
{
/* if in middle of a drop/rename etc */
@@ -5986,7 +5996,13 @@ void ha_partition::print_error(int error, myf errflag)
if (error == HA_ERR_NO_PARTITION_FOUND)
m_part_info->print_no_partition_found(table);
else
- m_file[m_last_part]->print_error(error, errflag);
+ {
+ /* In case m_file has not been initialized, like in bug#42438 */
+ if (m_file)
+ m_file[m_last_part]->print_error(error, errflag);
+ else
+ handler::print_error(error, errflag);
+ }
DBUG_VOID_RETURN;
}
@@ -5996,7 +6012,12 @@ bool ha_partition::get_error_message(int error, String *buf)
DBUG_ENTER("ha_partition::get_error_message");
/* Should probably look for my own errors first */
- DBUG_RETURN(m_file[m_last_part]->get_error_message(error, buf));
+
+ /* In case m_file has not been initialized, like in bug#42438 */
+ if (m_file)
+ DBUG_RETURN(m_file[m_last_part]->get_error_message(error, buf));
+ DBUG_RETURN(handler::get_error_message(error, buf));
+
}