diff options
author | Arun Kuruvila <arun.kuruvila@oracle.com> | 2013-12-30 11:39:55 +0530 |
---|---|---|
committer | Arun Kuruvila <arun.kuruvila@oracle.com> | 2013-12-30 11:39:55 +0530 |
commit | 1f8d86b42ede6264ed258973c69bb9bb1a39338a (patch) | |
tree | 20e07dc02e20e4b09464bf1a22205d88d556c228 /storage | |
parent | 64b697ca999d678692ca8db93ed7e42761cc56d6 (diff) | |
download | mariadb-git-1f8d86b42ede6264ed258973c69bb9bb1a39338a.tar.gz |
Bug #16324629 : SERVER CRASHES ON UPDATE/JOIN FEDERATED +
LOCAL TABLE WHEN ONLY 1 LOCAL ROW
Description: When updating a federated table with UPDATE...
JOIN, the server consistently crashes with Signal 11 when
only 1 row exists in the local table involved in the join
and that 1 row can be joined with a row in the federated
table.
Analysis: Interaction between the federated engine and the
optimizer results in the crash. In our scenario, ie, local
table having only one row, the program is following a
different path because the table is treated as a constant
table by the join optimizer. So in this scenario
"index_read()" is happening in the prepare phase,
since optimizer plan is different for constant table joins.
In this case, "index_read_idx_map()" (inside handler.cc) is
calling "index_read()" and inside "index_read()", matching
rows are fetched and "stored_result" gets populated by
calling "store_result()". And just after "index_read()",
"index_end()" function is called. And in the "index_end()",
its freeing the "stored_result" by calling "free_result()".
So when it reaches the execution phase, in "position()"
function, we are getting assertion at
"DBUG_ASSERT(stored_result);". In all other scenarios (ie,
table with more than 1 row), optimizer plan is different
and "index_read()" is happening in the execution phase.
Fix: So my fix is to have a separate ha_federated member
function for "index_read_idx_map()" which will handle
federated engine separately. So that position() will be
called before index_end() call in constant table scenario.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/federated/ha_federated.cc | 18 | ||||
-rw-r--r-- | storage/federated/ha_federated.h | 5 |
2 files changed, 21 insertions, 2 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index db2f749b6d4..409b4c40804 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2349,6 +2349,22 @@ int ha_federated::delete_row(const uchar *buf) DBUG_RETURN(0); } +int ha_federated::index_read_idx_map(uchar *buf, uint index, const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + int error= index_init(index, 0); + if (error) + return error; + error= index_read_map(buf, key, keypart_map, find_flag); + if(!error && stored_result) + { + uchar *dummy_arg=NULL; + position(dummy_arg); + } + int error1= index_end(); + return error ? error : error1; +} /* Positions an index cursor to the index specified in the handle. Fetches the diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index da20bf1e5d5..237b7777067 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -217,6 +217,9 @@ public: int delete_row(const uchar *buf); int index_init(uint keynr, bool sorted); ha_rows estimate_rows_upper_bound(); + int index_read_idx_map(uchar *buf, uint index, const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function find_flag); int index_read(uchar *buf, const uchar *key, uint key_len, enum ha_rkey_function find_flag); int index_read_idx(uchar *buf, uint idx, const uchar *key, |