Loading innobase/row/row0ins.c +39 −9 Original line number Diff line number Diff line Loading @@ -522,18 +522,48 @@ row_ins_cascade_calc_update_vec( && ufield->new_val.len < dtype_get_fixed_size(type)) { ulint cset; ufield->new_val.data = mem_heap_alloc(heap, dtype_get_fixed_size(type)); ufield->new_val.len = dtype_get_fixed_size(type); /* Handle UCS2 strings differently. As no new collations will be introduced in 4.1, we hardcode the charset-collation codes here. In 5.0, the logic is based on mbminlen. */ cset = dtype_get_charset_coll( dtype_get_prtype(type)); if (cset == 35/*ucs2_general_ci*/ || cset == 90/*ucs2_bin*/ || (cset >= 128/*ucs2_unicode_ci*/ && cset <= 144 /*ucs2_persian_ci*/)) { /* space=0x0020 */ ulint i; for (i = 0; i < ufield->new_val.len; i += 2) { mach_write_to_2(((byte*) ufield->new_val.data) + i, 0x0020); } } else { ut_a(dtype_get_pad_char(type) != ULINT_UNDEFINED); memset(ufield->new_val.data, (byte)dtype_get_pad_char(type), dtype_get_fixed_size(type)); ut_memcpy(ufield->new_val.data, (byte)dtype_get_pad_char( type), ufield->new_val.len); } memcpy(ufield->new_val.data, parent_ufield->new_val.data, parent_ufield->new_val.len); } Loading mysql-test/r/analyse.result +26 −0 Original line number Diff line number Diff line Loading @@ -108,3 +108,29 @@ select * from t1 procedure analyse (1,1); 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; mysql-test/t/analyse.test +25 −0 Original line number Diff line number Diff line Loading @@ -57,4 +57,29 @@ insert into t1 values (100000); 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 sql/sql_select.cc +14 −11 Original line number Diff line number Diff line Loading @@ -1044,18 +1044,21 @@ JOIN::save_join_tab() void JOIN::exec() { List<Item> *columns_list= &fields_list; int tmp_error; 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)) Loading @@ -1072,7 +1075,7 @@ JOIN::exec() (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 Loading @@ -1082,9 +1085,9 @@ JOIN::exec() (!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 { Loading @@ -1108,7 +1111,7 @@ JOIN::exec() 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, Loading Loading @@ -5845,13 +5848,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) 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)); Loading Loading @@ -5913,7 +5916,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) 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 { Loading Loading @@ -6612,7 +6615,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), 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) Loading sql/sql_select.h +1 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ class JOIN :public Sql_alloc //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 Loading Loading
innobase/row/row0ins.c +39 −9 Original line number Diff line number Diff line Loading @@ -522,18 +522,48 @@ row_ins_cascade_calc_update_vec( && ufield->new_val.len < dtype_get_fixed_size(type)) { ulint cset; ufield->new_val.data = mem_heap_alloc(heap, dtype_get_fixed_size(type)); ufield->new_val.len = dtype_get_fixed_size(type); /* Handle UCS2 strings differently. As no new collations will be introduced in 4.1, we hardcode the charset-collation codes here. In 5.0, the logic is based on mbminlen. */ cset = dtype_get_charset_coll( dtype_get_prtype(type)); if (cset == 35/*ucs2_general_ci*/ || cset == 90/*ucs2_bin*/ || (cset >= 128/*ucs2_unicode_ci*/ && cset <= 144 /*ucs2_persian_ci*/)) { /* space=0x0020 */ ulint i; for (i = 0; i < ufield->new_val.len; i += 2) { mach_write_to_2(((byte*) ufield->new_val.data) + i, 0x0020); } } else { ut_a(dtype_get_pad_char(type) != ULINT_UNDEFINED); memset(ufield->new_val.data, (byte)dtype_get_pad_char(type), dtype_get_fixed_size(type)); ut_memcpy(ufield->new_val.data, (byte)dtype_get_pad_char( type), ufield->new_val.len); } memcpy(ufield->new_val.data, parent_ufield->new_val.data, parent_ufield->new_val.len); } Loading
mysql-test/r/analyse.result +26 −0 Original line number Diff line number Diff line Loading @@ -108,3 +108,29 @@ select * from t1 procedure analyse (1,1); 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;
mysql-test/t/analyse.test +25 −0 Original line number Diff line number Diff line Loading @@ -57,4 +57,29 @@ insert into t1 values (100000); 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
sql/sql_select.cc +14 −11 Original line number Diff line number Diff line Loading @@ -1044,18 +1044,21 @@ JOIN::save_join_tab() void JOIN::exec() { List<Item> *columns_list= &fields_list; int tmp_error; 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)) Loading @@ -1072,7 +1075,7 @@ JOIN::exec() (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 Loading @@ -1082,9 +1085,9 @@ JOIN::exec() (!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 { Loading @@ -1108,7 +1111,7 @@ JOIN::exec() 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, Loading Loading @@ -5845,13 +5848,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) 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)); Loading Loading @@ -5913,7 +5916,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) 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 { Loading Loading @@ -6612,7 +6615,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), 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) Loading
sql/sql_select.h +1 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,7 @@ class JOIN :public Sql_alloc //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 Loading