Merge rurik.mysql.com:/home/igor/mysql-4.1
into rurik.mysql.com:/home/igor/dev/mysql-4.1-0
This commit is contained in:
commit
3103b4cae5
@ -307,3 +307,75 @@ day sample not_cancelled
|
|||||||
2004-06-07 1 0
|
2004-06-07 1 0
|
||||||
NULL 3 1
|
NULL 3 1
|
||||||
DROP TABLE user_day;
|
DROP TABLE user_day;
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,4),
|
||||||
|
(2,2), (2,2),
|
||||||
|
(4,1), (4,1), (4,1), (4,1),
|
||||||
|
(2,1), (2,1);
|
||||||
|
SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b)
|
||||||
|
4
|
||||||
|
6
|
||||||
|
4
|
||||||
|
14
|
||||||
|
SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b)
|
||||||
|
4
|
||||||
|
6
|
||||||
|
14
|
||||||
|
SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(DISTINCT b)
|
||||||
|
4 1
|
||||||
|
6 2
|
||||||
|
4 1
|
||||||
|
14 3
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(DISTINCT b)
|
||||||
|
4 1
|
||||||
|
6 2
|
||||||
|
14 3
|
||||||
|
SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(*)
|
||||||
|
4 1
|
||||||
|
6 4
|
||||||
|
4 4
|
||||||
|
14 9
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(*)
|
||||||
|
4 1
|
||||||
|
6 4
|
||||||
|
4 4
|
||||||
|
14 9
|
||||||
|
SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(DISTINCT b) COUNT(*)
|
||||||
|
4 1 1
|
||||||
|
6 2 4
|
||||||
|
4 1 4
|
||||||
|
14 3 9
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1
|
||||||
|
GROUP BY a WITH ROLLUP;
|
||||||
|
SUM(b) COUNT(DISTINCT b) COUNT(*)
|
||||||
|
4 1 1
|
||||||
|
6 2 4
|
||||||
|
4 1 4
|
||||||
|
14 3 9
|
||||||
|
SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
|
||||||
|
a sum(b)
|
||||||
|
1 4
|
||||||
|
1 4
|
||||||
|
2 2
|
||||||
|
2 4
|
||||||
|
2 6
|
||||||
|
4 4
|
||||||
|
4 4
|
||||||
|
NULL 14
|
||||||
|
SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
|
||||||
|
a sum(b)
|
||||||
|
1 4
|
||||||
|
2 2
|
||||||
|
2 4
|
||||||
|
2 6
|
||||||
|
4 4
|
||||||
|
NULL 14
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -125,3 +125,33 @@ SELECT
|
|||||||
|
|
||||||
DROP TABLE user_day;
|
DROP TABLE user_day;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tests for bugs #8616, #8615: distinct sum with rollup
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES
|
||||||
|
(1,4),
|
||||||
|
(2,2), (2,2),
|
||||||
|
(4,1), (4,1), (4,1), (4,1),
|
||||||
|
(2,1), (2,1);
|
||||||
|
|
||||||
|
SELECT SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT DISTINCT SUM(b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
SELECT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(DISTINCT b) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
SELECT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
SELECT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||||
|
SELECT DISTINCT SUM(b), COUNT(DISTINCT b), COUNT(*) FROM t1
|
||||||
|
GROUP BY a WITH ROLLUP;
|
||||||
|
|
||||||
|
SELECT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
|
||||||
|
SELECT DISTINCT a, sum(b) FROM t1 GROUP BY a,b WITH ROLLUP;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
11
sql/item.h
11
sql/item.h
@ -470,6 +470,17 @@ public:
|
|||||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Item_null_result :public Item_null
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Field *result_field;
|
||||||
|
Item_null_result() : Item_null(), result_field(0) {}
|
||||||
|
bool is_result_field() { return result_field != 0; }
|
||||||
|
void save_in_result_field(bool no_conversions)
|
||||||
|
{
|
||||||
|
save_in_field(result_field, no_conversions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Item represents one placeholder ('?') of prepared statement */
|
/* Item represents one placeholder ('?') of prepared statement */
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
|
|||||||
uint elements, List<Item> &items);
|
uint elements, List<Item> &items);
|
||||||
static void init_tmptable_sum_functions(Item_sum **func);
|
static void init_tmptable_sum_functions(Item_sum **func);
|
||||||
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
|
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
|
||||||
static void copy_sum_funcs(Item_sum **func_ptr);
|
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
|
||||||
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
|
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
|
||||||
static bool init_sum_functions(Item_sum **func, Item_sum **end);
|
static bool init_sum_functions(Item_sum **func, Item_sum **end);
|
||||||
static bool update_sum_func(Item_sum **func);
|
static bool update_sum_func(Item_sum **func);
|
||||||
@ -1269,7 +1269,6 @@ JOIN::exec()
|
|||||||
{
|
{
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
curr_join->group_list= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->proc_info="Copying to group table";
|
thd->proc_info="Copying to group table";
|
||||||
@ -1289,8 +1288,10 @@ JOIN::exec()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
|
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
|
||||||
1) ||
|
1))
|
||||||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
|
DBUG_VOID_RETURN;
|
||||||
|
curr_join->group_list= 0;
|
||||||
|
if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
|
||||||
0)))
|
0)))
|
||||||
{
|
{
|
||||||
error= tmp_error;
|
error= tmp_error;
|
||||||
@ -1328,7 +1329,7 @@ JOIN::exec()
|
|||||||
if (curr_join->tmp_having)
|
if (curr_join->tmp_having)
|
||||||
curr_join->tmp_having->update_used_tables();
|
curr_join->tmp_having->update_used_tables();
|
||||||
if (remove_duplicates(curr_join, curr_tmp_table,
|
if (remove_duplicates(curr_join, curr_tmp_table,
|
||||||
curr_join->fields_list, curr_join->tmp_having))
|
*curr_fields_list, curr_join->tmp_having))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
curr_join->tmp_having=0;
|
curr_join->tmp_having=0;
|
||||||
curr_join->select_distinct=0;
|
curr_join->select_distinct=0;
|
||||||
@ -6740,26 +6741,32 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
|||||||
{
|
{
|
||||||
if (join->procedure)
|
if (join->procedure)
|
||||||
join->procedure->end_group();
|
join->procedure->end_group();
|
||||||
if (idx < (int) join->send_group_parts)
|
int send_group_parts= join->send_group_parts;
|
||||||
|
if (idx < send_group_parts)
|
||||||
{
|
{
|
||||||
if (!join->first_record)
|
if (!join->first_record)
|
||||||
{
|
{
|
||||||
/* No matching rows for group function */
|
/* No matching rows for group function */
|
||||||
join->clear();
|
join->clear();
|
||||||
}
|
}
|
||||||
copy_sum_funcs(join->sum_funcs);
|
copy_sum_funcs(join->sum_funcs,
|
||||||
if (!join->having || join->having->val_int())
|
join->sum_funcs_end[send_group_parts]);
|
||||||
|
if (join->having && join->having->val_int() == 0)
|
||||||
|
error= -1;
|
||||||
|
else if ((error=table->file->write_row(table->record[0])))
|
||||||
{
|
{
|
||||||
if ((error=table->file->write_row(table->record[0])))
|
if (create_myisam_from_heap(join->thd, table,
|
||||||
{
|
&join->tmp_table_param,
|
||||||
if (create_myisam_from_heap(join->thd, table,
|
error, 0))
|
||||||
&join->tmp_table_param,
|
DBUG_RETURN(-1);
|
||||||
error, 0))
|
}
|
||||||
DBUG_RETURN(-1); // Not a table_is_full error
|
if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
|
||||||
}
|
{
|
||||||
else
|
if (join->rollup_write_data((uint) (idx+1), table))
|
||||||
join->send_records++;
|
error= 1;
|
||||||
}
|
}
|
||||||
|
if (error > 0)
|
||||||
|
DBUG_RETURN(-1);
|
||||||
if (end_of_records)
|
if (end_of_records)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -8888,11 +8895,10 @@ update_tmptable_sum_func(Item_sum **func_ptr,
|
|||||||
/* Copy result of sum functions to record in tmp_table */
|
/* Copy result of sum functions to record in tmp_table */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
copy_sum_funcs(Item_sum **func_ptr)
|
copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr)
|
||||||
{
|
{
|
||||||
Item_sum *func;
|
for (; func_ptr != end_ptr ; func_ptr++)
|
||||||
for (; (func = *func_ptr) ; func_ptr++)
|
(void) (*func_ptr)->save_in_result_field(1);
|
||||||
(void) func->save_in_result_field(1);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9013,14 +9019,16 @@ bool JOIN::rollup_init()
|
|||||||
*/
|
*/
|
||||||
tmp_table_param.group_parts= send_group_parts;
|
tmp_table_param.group_parts= send_group_parts;
|
||||||
|
|
||||||
if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) +
|
if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
|
||||||
sizeof(List<Item>) +
|
sizeof(Item**) +
|
||||||
ref_pointer_array_size)
|
sizeof(List<Item>) +
|
||||||
* send_group_parts)))
|
ref_pointer_array_size)
|
||||||
|
* send_group_parts )))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
|
||||||
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
|
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
|
||||||
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
|
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
|
||||||
rollup.item_null= new (thd->mem_root) Item_null();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepare space for field list for the different levels
|
Prepare space for field list for the different levels
|
||||||
@ -9028,12 +9036,16 @@ bool JOIN::rollup_init()
|
|||||||
*/
|
*/
|
||||||
for (i= 0 ; i < send_group_parts ; i++)
|
for (i= 0 ; i < send_group_parts ; i++)
|
||||||
{
|
{
|
||||||
|
rollup.null_items[i]= new (thd->mem_root) Item_null_result();
|
||||||
List<Item> *rollup_fields= &rollup.fields[i];
|
List<Item> *rollup_fields= &rollup.fields[i];
|
||||||
rollup_fields->empty();
|
rollup_fields->empty();
|
||||||
rollup.ref_pointer_arrays[i]= ref_array;
|
rollup.ref_pointer_arrays[i]= ref_array;
|
||||||
ref_array+= all_fields.elements;
|
ref_array+= all_fields.elements;
|
||||||
|
}
|
||||||
|
for (i= 0 ; i < send_group_parts; i++)
|
||||||
|
{
|
||||||
for (j=0 ; j < fields_list.elements ; j++)
|
for (j=0 ; j < fields_list.elements ; j++)
|
||||||
rollup_fields->push_back(rollup.item_null);
|
rollup.fields[i].push_back(rollup.null_items[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -9137,7 +9149,8 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
|
|||||||
{
|
{
|
||||||
/* Check if this is something that is part of this group by */
|
/* Check if this is something that is part of this group by */
|
||||||
ORDER *group_tmp;
|
ORDER *group_tmp;
|
||||||
for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next)
|
for (group_tmp= start_group, i-- ;
|
||||||
|
group_tmp ; group_tmp= group_tmp->next, i++)
|
||||||
{
|
{
|
||||||
if (*group_tmp->item == item)
|
if (*group_tmp->item == item)
|
||||||
{
|
{
|
||||||
@ -9146,7 +9159,9 @@ bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
|
|||||||
set to NULL in this level
|
set to NULL in this level
|
||||||
*/
|
*/
|
||||||
item->maybe_null= 1; // Value will be null sometimes
|
item->maybe_null= 1; // Value will be null sometimes
|
||||||
item= rollup.item_null;
|
Item_null_result *null_item= rollup.null_items[i];
|
||||||
|
null_item->result_field= ((Item_field *) item)->result_field;
|
||||||
|
item= null_item;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9206,6 +9221,58 @@ int JOIN::rollup_send_data(uint idx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write all rollup levels higher than the current one to a temp table
|
||||||
|
|
||||||
|
SYNOPSIS:
|
||||||
|
rollup_write_data()
|
||||||
|
idx Level we are on:
|
||||||
|
0 = Total sum level
|
||||||
|
1 = First group changed (a)
|
||||||
|
2 = Second group changed (a,b)
|
||||||
|
table reference to temp table
|
||||||
|
|
||||||
|
SAMPLE
|
||||||
|
SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 ok
|
||||||
|
1 if write_data_failed()
|
||||||
|
*/
|
||||||
|
|
||||||
|
int JOIN::rollup_write_data(uint idx, TABLE *table)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
for (i= send_group_parts ; i-- > idx ; )
|
||||||
|
{
|
||||||
|
/* Get reference pointers to sum functions in place */
|
||||||
|
memcpy((char*) ref_pointer_array,
|
||||||
|
(char*) rollup.ref_pointer_arrays[i],
|
||||||
|
ref_pointer_array_size);
|
||||||
|
if ((!having || having->val_int()))
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
Item *item;
|
||||||
|
List_iterator_fast<Item> it(rollup.fields[i]);
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
if (item->type() == Item::NULL_ITEM && item->is_result_field())
|
||||||
|
item->save_in_result_field(1);
|
||||||
|
}
|
||||||
|
copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
|
||||||
|
if ((error= table->file->write_row(table->record[0])))
|
||||||
|
{
|
||||||
|
if (create_myisam_from_heap(thd, table, &tmp_table_param,
|
||||||
|
error, 0))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Restore ref_pointer_array */
|
||||||
|
set_items_ref_array(current_ref_pointer_array);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
clear results if there are not rows found for group
|
clear results if there are not rows found for group
|
||||||
(end_send_group/end_write_group)
|
(end_send_group/end_write_group)
|
||||||
|
@ -124,7 +124,7 @@ typedef struct st_rollup
|
|||||||
{
|
{
|
||||||
enum State { STATE_NONE, STATE_INITED, STATE_READY };
|
enum State { STATE_NONE, STATE_INITED, STATE_READY };
|
||||||
State state;
|
State state;
|
||||||
Item *item_null;
|
Item_null_result **null_items;
|
||||||
Item ***ref_pointer_arrays;
|
Item ***ref_pointer_arrays;
|
||||||
List<Item> *fields;
|
List<Item> *fields;
|
||||||
} ROLLUP;
|
} ROLLUP;
|
||||||
@ -295,6 +295,7 @@ class JOIN :public Sql_alloc
|
|||||||
bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
|
bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
|
||||||
Item_sum ***func);
|
Item_sum ***func);
|
||||||
int rollup_send_data(uint idx);
|
int rollup_send_data(uint idx);
|
||||||
|
int rollup_write_data(uint idx, TABLE *table);
|
||||||
bool test_in_subselect(Item **where);
|
bool test_in_subselect(Item **where);
|
||||||
void join_free(bool full);
|
void join_free(bool full);
|
||||||
void clear();
|
void clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user