summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2012-03-09 15:04:49 +0200
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2012-03-09 15:04:49 +0200
commit35d865f2fe497fb5bf15810cf31f717d5d9c4e46 (patch)
treea990125f7d3483f930365a582a79772c487d7362
parent2a3aa3f9023f5f07517c9f9539a1eda34c884178 (diff)
downloadmariadb-git-35d865f2fe497fb5bf15810cf31f717d5d9c4e46.tar.gz
Bug #12408412: GROUP_CONCAT + ORDER BY + INPUT/OUTPUT SAME
USER VARIABLE = CRASH Moved the preparation of the variables that receive the output from SELECT INTO from execution time (JOIN:execute) to compile time (JOIN::prepare). This ensures that if the same variable is used in the SELECT part of SELECT INTO it will be properly marked as non-const for this query. Test case added. Used proper fast iterator.
-rw-r--r--mysql-test/r/user_var.result6
-rw-r--r--mysql-test/t/user_var.test9
-rw-r--r--sql/sql_class.cc43
-rw-r--r--sql/sql_class.h1
4 files changed, 52 insertions, 7 deletions
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 589186184c3..b0859658077 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -485,4 +485,10 @@ f1 f2
1 4
DROP TRIGGER trg1;
DROP TABLE t1;
+#
+# Bug #12408412: GROUP_CONCAT + ORDER BY + INPUT/OUTPUT
+# SAME USER VARIABLE = CRASH
+#
+SET @bug12408412=1;
+SELECT GROUP_CONCAT(@bug12408412 ORDER BY 1) INTO @bug12408412;
End of 5.5 tests
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 6a64343b609..fa23d118634 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -404,4 +404,13 @@ SELECT f1, f2 FROM t1 ORDER BY f2;
DROP TRIGGER trg1;
DROP TABLE t1;
+
+--echo #
+--echo # Bug #12408412: GROUP_CONCAT + ORDER BY + INPUT/OUTPUT
+--echo # SAME USER VARIABLE = CRASH
+--echo #
+
+SET @bug12408412=1;
+SELECT GROUP_CONCAT(@bug12408412 ORDER BY 1) INTO @bug12408412;
+
--echo End of 5.5 tests
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b68726c2920..20ab1b71542 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2855,13 +2855,42 @@ bool select_exists_subselect::send_data(List<Item> &items)
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
+ List_iterator_fast<my_var> var_li(var_list);
+ List_iterator_fast<Item> it(list);
+ Item *item;
+ my_var *mv;
+ Item_func_set_user_var **suv;
if (var_list.elements != list.elements)
{
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
return 1;
- }
+ }
+
+ /*
+ Iterate over the destination variables and mark them as being
+ updated in this query.
+ We need to do this at JOIN::prepare time to ensure proper
+ const detection of Item_func_get_user_var that is determined
+ by the presence of Item_func_set_user_vars
+ */
+
+ suv= set_var_items= (Item_func_set_user_var **)
+ sql_alloc(sizeof(Item_func_set_user_var *) * list.elements);
+
+ while ((mv= var_li++) && (item= it++))
+ {
+ if (!mv->local)
+ {
+ *suv= new Item_func_set_user_var(mv->s, item);
+ (*suv)->fix_fields(thd, 0);
+ }
+ else
+ *suv= NULL;
+ suv++;
+ }
+
return 0;
}
@@ -3178,6 +3207,7 @@ bool select_dumpvar::send_data(List<Item> &items)
List_iterator<Item> it(items);
Item *item;
my_var *mv;
+ Item_func_set_user_var **suv;
DBUG_ENTER("select_dumpvar::send_data");
if (unit->offset_limit_cnt)
@@ -3190,20 +3220,19 @@ bool select_dumpvar::send_data(List<Item> &items)
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
DBUG_RETURN(1);
}
- while ((mv= var_li++) && (item= it++))
+ for (suv= set_var_items; ((mv= var_li++) && (item= it++)); suv++)
{
if (mv->local)
{
+ DBUG_ASSERT(!*suv);
if (thd->spcont->set_variable(thd, mv->offset, &item))
DBUG_RETURN(1);
}
else
{
- Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
- if (suv->fix_fields(thd, 0))
- DBUG_RETURN (1);
- suv->save_item_result(item);
- if (suv->update())
+ DBUG_ASSERT(*suv);
+ (*suv)->save_item_result(item);
+ if ((*suv)->update())
DBUG_RETURN (1);
}
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 36091546ff4..5434d5ae325 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3531,6 +3531,7 @@ public:
class select_dumpvar :public select_result_interceptor {
ha_rows row_count;
+ Item_func_set_user_var **set_var_items;
public:
List<my_var> var_list;
select_dumpvar() { var_list.empty(); row_count= 0;}