Below is the list of changes that have just been committed into a local
4.1 repository of evgen. When evgen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2467 05/10/27 00:59:51 evgen@stripped +4 -0
Fix bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
Procedure analyse() redefines select's fields_list. setup_copy_fields() assumes
that fields_list is a part of all_fields_list. Because select have only
3 columns and analyse() redefines it to have 10 columns, int overrun in
setup_copy_fields() occurs and server goes to almost infinite loop.
Because fields_list used not only to send data ad fields types, it's wrong
to allow procedure redefine it. This patch separates select's fileds_list
and procedure's one. Now if procedure is present, copy of fields_list is
created in procedure_fields_list and it is used for sending data and fields.
mysql-test/t/analyse.test
1.15 05/10/27 00:58:50 evgen@stripped +25 -0
Test case for bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
mysql-test/r/analyse.result
1.18 05/10/27 00:58:39 evgen@stripped +26 -0
Test case for bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
sql/sql_select.h
1.77 05/10/27 00:58:28 evgen@stripped +1 -0
Fix bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
To JOIN Added separate fields_list for procedure.
sql/sql_select.cc
1.441 05/10/27 00:58:16 evgen@stripped +14 -11
Fix bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
SELECT's fields_list and procedure's fields_list made split. If procedure is defined
then procedure's fields_list is used to send fields and data.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: evgen
# Host: moonbone.local
# Root: /work/14138-bug-4.1-mysql
--- 1.440/sql/sql_select.cc 2005-10-13 18:25:25 +04:00
+++ 1.441/sql/sql_select.cc 2005-10-27 00:58:16 +04:00
@@ -1044,17 +1044,20 @@
JOIN::exec()
{
int tmp_error;
+ List<Item> *columns_list= &fields_list;
DBUG_ENTER("JOIN::exec");
error= 0;
if (procedure)
{
- if (procedure->change_columns(fields_list) ||
- result->prepare(fields_list, unit))
+ procedure_fields_list= fields_list;
+ if (procedure->change_columns(procedure_fields_list) ||
+ result->prepare(procedure_fields_list, unit))
{
thd->limit_found_rows= thd->examined_row_count= 0;
DBUG_VOID_RETURN;
}
+ columns_list= &procedure_fields_list;
}
else if (test(select_options & OPTION_BUFFER_RESULT) &&
result && result->prepare(fields_list, unit))
@@ -1071,7 +1074,7 @@
(zero_result_cause?zero_result_cause:"No tables used"));
else
{
- result->send_fields(fields_list,1);
+ result->send_fields(*columns_list, 1);
/*
We have to test for 'conds' here as the WHERE may not be constant
even if we don't have any tables for prepared statements or if
@@ -1081,9 +1084,9 @@
(!conds || conds->val_int()) &&
(!having || having->val_int()))
{
- if (do_send_rows && (procedure ? (procedure->send_row(fields_list) ||
- procedure->end_of_records())
- : result->send_data(fields_list)))
+ if (do_send_rows &&
+ (procedure ? (procedure->send_row(procedure_fields_list) ||
+ procedure->end_of_records()) : result->send_data(fields_list)))
error= 1;
else
{
@@ -1107,7 +1110,7 @@
if (zero_result_cause)
{
- (void) return_zero_rows(this, result, tables_list, fields_list,
+ (void) return_zero_rows(this, result, tables_list, *columns_list,
send_row_on_empty_set(),
select_options,
zero_result_cause,
@@ -5844,13 +5847,13 @@
JOIN_TAB *join_tab;
int (*end_select)(JOIN *, struct st_join_table *,bool);
DBUG_ENTER("do_select");
-
+ List<Item> *columns_list= procedure ? &join->procedure_fields_list :
fields;
join->procedure=procedure;
/*
Tell the client how many fields there are in a row
*/
if (!table)
- join->result->send_fields(*fields,1);
+ join->result->send_fields(*columns_list, 1);
else
{
VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
@@ -5912,7 +5915,7 @@
error=(*end_select)(join,join_tab,1);
}
else if (join->send_row_on_empty_set())
- error= join->result->send_data(*join->fields);
+ error= join->result->send_data(*columns_list);
}
else
{
@@ -6611,7 +6614,7 @@
DBUG_RETURN(0); // Didn't match having
error=0;
if (join->procedure)
- error=join->procedure->send_row(*join->fields);
+ error=join->procedure->send_row(join->procedure_fields_list);
else if (join->do_send_rows)
error=join->result->send_data(*join->fields);
if (error)
--- 1.76/sql/sql_select.h 2005-06-23 17:13:38 +04:00
+++ 1.77/sql/sql_select.h 2005-10-27 00:58:28 +04:00
@@ -204,6 +204,7 @@
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
List<Item> &fields_list; // hold field list passed to mysql_select
+ List<Item> procedure_fields_list;
int error;
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
--- 1.17/mysql-test/r/analyse.result 2005-09-09 18:29:51 +04:00
+++ 1.18/mysql-test/r/analyse.result 2005-10-27 00:58:39 +04:00
@@ -108,3 +108,29 @@
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
test.t1.d 100000 100000 6 6 0 0 100000 0 MEDIUMINT(6) UNSIGNED NOT NULL
drop table t1;
+create table t1 (product varchar(32), country_id int not null, year int,
+profit int);
+insert into t1 values ( 'Computer', 2,2000, 1200),
+( 'TV', 1, 1999, 150),
+( 'Calculator', 1, 1999,50),
+( 'Computer', 1, 1999,1500),
+( 'Computer', 1, 2000,1500),
+( 'TV', 1, 2000, 150),
+( 'TV', 2, 2000, 100),
+( 'TV', 2, 2000, 100),
+( 'Calculator', 1, 2000,75),
+( 'Calculator', 2, 2000,75),
+( 'TV', 1, 1999, 100),
+( 'Computer', 1, 1999,1200),
+( 'Computer', 2, 2000,1500),
+( 'Calculator', 2, 2000,75),
+( 'Phone', 3, 2003,10)
+;
+create table t2 (country_id int primary key, country char(20) not null);
+insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland');
+select product, sum(profit),avg(profit) from t1 group by product with rollup procedure
analyse();
+Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
+test.t1.product Computer TV 2 8 0 0 4.2500 NULL ENUM('Computer','Phone','TV') NOT NULL
+sum(profit) 10 6900 2 4 0 0 1946 2868 ENUM('10','275','600','6900') NOT NULL
+avg(profit) 10.0000 1380.0000 7 9 0 0 394.6875 570.2003 ENUM('10.0000','68.7500','120.0000','1380.0000')
NOT NULL
+drop table t1,t2;
--- 1.14/mysql-test/t/analyse.test 2005-09-09 18:29:52 +04:00
+++ 1.15/mysql-test/t/analyse.test 2005-10-27 00:58:50 +04:00
@@ -57,4 +57,29 @@
select * from t1 procedure analyse (1,1);
drop table t1;
+#
+# Bug #14138 ROLLUP and PROCEDURE ANALYSE() hang server
+#
+create table t1 (product varchar(32), country_id int not null, year int,
+ profit int);
+insert into t1 values ( 'Computer', 2,2000, 1200),
+ ( 'TV', 1, 1999, 150),
+ ( 'Calculator', 1, 1999,50),
+ ( 'Computer', 1, 1999,1500),
+ ( 'Computer', 1, 2000,1500),
+ ( 'TV', 1, 2000, 150),
+ ( 'TV', 2, 2000, 100),
+ ( 'TV', 2, 2000, 100),
+ ( 'Calculator', 1, 2000,75),
+ ( 'Calculator', 2, 2000,75),
+ ( 'TV', 1, 1999, 100),
+ ( 'Computer', 1, 1999,1200),
+ ( 'Computer', 2, 2000,1500),
+ ( 'Calculator', 2, 2000,75),
+ ( 'Phone', 3, 2003,10)
+ ;
+create table t2 (country_id int primary key, country char(20) not null);
+insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland');
+select product, sum(profit),avg(profit) from t1 group by product with rollup procedure
analyse();
+drop table t1,t2;
# End of 4.1 tests
| Thread |
|---|
| • bk commit into 4.1 tree (evgen:1.2467) BUG#14138 | eugene | 26 Oct |