summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-06-21 22:26:03 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-06-21 22:26:03 +0400
commitcebdf3de2ef2604f3459762fc05a50dd54c1c9f2 (patch)
treee23a75abd0b2376b437b595a61510e3d9eb0c6d7
parentaf5e128e50cac8881f7bfca44cc473600abdce86 (diff)
downloadmariadb-git-cebdf3de2ef2604f3459762fc05a50dd54c1c9f2.tar.gz
[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring
- Handle another specific case where there the JOIN never had a query plan, but had multiple join->cleanup(full=true) calls - The idea that there can only be MAX_TABLES subuqeries/unions was wrong. Switch QPF_query to using a Dynamic_array. = make Dynamic_array template support size growth. its underlying DYNAMIC_ARRAY supports it. (this part will need more polishing)
-rw-r--r--sql/opt_qpf.cc42
-rw-r--r--sql/opt_qpf.h8
-rw-r--r--sql/sql_array.h18
-rw-r--r--sql/sql_select.cc3
4 files changed, 55 insertions, 16 deletions
diff --git a/sql/opt_qpf.cc b/sql/opt_qpf.cc
index d5a228e8f41..204a7e00350 100644
--- a/sql/opt_qpf.cc
+++ b/sql/opt_qpf.cc
@@ -13,8 +13,8 @@
QPF_query::QPF_query()
{
upd_del_plan= NULL;
- memset(&unions, 0, sizeof(unions));
- memset(&selects, 0, sizeof(selects));
+ //memset(&unions, 0, sizeof(unions));
+ //memset(&selects, 0, sizeof(selects));
}
@@ -22,25 +22,30 @@ QPF_query::~QPF_query()
{
delete upd_del_plan;
uint i;
- for (i=0 ; i < MAX_TABLES; i++)
- delete unions[i];
- for (i=0 ; i < MAX_TABLES; i++)
- delete selects[i];
+ for (i= 0 ; i < unions.elements(); i++)
+ delete unions.at(i);
+ for (i= 0 ; i < selects.elements(); i++)
+ delete selects.at(i);
}
QPF_node *QPF_query::get_node(uint select_id)
{
- if (unions[select_id])
- return unions[select_id];
+ QPF_union *u;
+ if ((u= get_union(select_id)))
+ return u;
else
- return selects[select_id];
+ return get_select(select_id);
}
+QPF_union *QPF_query::get_union(uint select_id)
+{
+ return (unions.elements() > select_id) ? unions.at(select_id) : NULL;
+}
QPF_select *QPF_query::get_select(uint select_id)
{
- return selects[select_id];
+ return (selects.elements() > select_id) ? selects.at(select_id) : NULL;
}
@@ -49,8 +54,13 @@ void QPF_query::add_node(QPF_node *node)
if (node->get_type() == QPF_node::QPF_UNION)
{
QPF_union *u= (QPF_union*)node;
- DBUG_ASSERT(!unions[u->get_select_id()]);
- unions[u->get_select_id()]= u;
+ uint select_id= u->get_select_id();
+ DBUG_ASSERT(!get_union(select_id));
+
+ if (unions.elements() <= select_id)
+ unions.resize(max(select_id+1, unions.elements()*2), NULL);
+
+ unions.at(select_id)= u;
}
else
{
@@ -62,8 +72,12 @@ void QPF_query::add_node(QPF_node *node)
}
else
{
- DBUG_ASSERT(!selects[sel->select_id]);
- selects[sel->select_id] = sel;
+ uint select_id= sel->select_id;
+ DBUG_ASSERT(!get_select(select_id));
+
+ if (selects.elements() <= select_id)
+ selects.resize(max(select_id+1, selects.elements()*2), NULL);
+ selects.at(select_id)= sel;
}
}
}
diff --git a/sql/opt_qpf.h b/sql/opt_qpf.h
index 501ac7c609e..1944f79254d 100644
--- a/sql/opt_qpf.h
+++ b/sql/opt_qpf.h
@@ -209,6 +209,8 @@ public:
/* This will return a select (even if there is a union with this id) */
QPF_select *get_select(uint select_id);
+ QPF_union *get_union(uint select_id);
+
/* QPF_delete inherits from QPF_update */
QPF_update *upd_del_plan;
@@ -217,8 +219,10 @@ public:
MEM_ROOT *mem_root;
private:
- QPF_union *unions[MAX_TABLES];
- QPF_select *selects[MAX_TABLES];
+ Dynamic_array<QPF_union*> unions;
+ Dynamic_array<QPF_select*> selects;
+ //QPF_union *unions[MAX_TABLES];
+ //QPF_select *selects[MAX_TABLES];
};
diff --git a/sql/sql_array.h b/sql/sql_array.h
index 43ca4ef4219..18f1fbd9f2f 100644
--- a/sql/sql_array.h
+++ b/sql/sql_array.h
@@ -106,6 +106,7 @@ public:
Elem& at(size_t idx)
{
+ DBUG_ASSERT(idx < array.elements);
return *(((Elem*)array.buffer) + idx);
}
@@ -139,6 +140,23 @@ public:
array.elements= n;
}
+ bool resize(size_t new_size, Elem default_val)
+ {
+ size_t old_size= elements();
+ if (allocate_dynamic(&array, new_size))
+ return true;
+
+ if (new_size > old_size)
+ {
+ set_dynamic(&array, (uchar*)&default_val, new_size - 1);
+ /*for (size_t i= old_size; i != new_size; i++)
+ {
+ at(i)= default_val;
+ }*/
+ }
+ return false;
+ }
+
~Dynamic_array()
{
delete_dynamic(&array);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bad29d70af9..1b98d0b12ee 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -11112,6 +11112,9 @@ void JOIN::cleanup(bool full)
if (select_lex->select_number != UINT_MAX &&
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
have_query_plan != QEP_NOT_PRESENT_YET &&
+ have_query_plan != QEP_DELETED && // this happens when there was no QEP ever, but then
+ //cleanup() is called multiple times
+
thd->lex->query_plan_footprint && // for "SET" command in SPs.
!thd->lex->query_plan_footprint->get_select(select_lex->select_number))
{