mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rakia.gmz:/home/kgeorge/mysql/autopush/B23184-5.0-opt
This commit is contained in:
@ -1029,3 +1029,29 @@ t1 CREATE TABLE `t1` (
|
|||||||
`stddev(0)` double(8,4) default NULL
|
`stddev(0)` double(8,4) default NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8);
|
||||||
|
INSERT INTO t1 SELECT a, b+8 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+16 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+32 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+64 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+128 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+256 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+512 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+1024 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+2048 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+4096 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+8192 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+16384 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+32768 FROM t1;
|
||||||
|
SELECT a,COUNT(DISTINCT b) AS cnt FROM t1 GROUP BY a HAVING cnt > 50;
|
||||||
|
a cnt
|
||||||
|
1 65536
|
||||||
|
SELECT a,SUM(DISTINCT b) AS sumation FROM t1 GROUP BY a HAVING sumation > 50;
|
||||||
|
a sumation
|
||||||
|
1 2147516416
|
||||||
|
SELECT a,AVG(DISTINCT b) AS average FROM t1 GROUP BY a HAVING average > 50;
|
||||||
|
a average
|
||||||
|
1 32768.5000
|
||||||
|
DROP TABLE t1;
|
||||||
|
End of 5.0 tests
|
||||||
|
@ -700,3 +700,28 @@ create table t1 select stddev(0);
|
|||||||
show create table t1;
|
show create table t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #23184: SELECT causes server crash
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8);
|
||||||
|
INSERT INTO t1 SELECT a, b+8 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+16 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+32 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+64 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+128 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+256 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+512 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+1024 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+2048 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+4096 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+8192 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+16384 FROM t1;
|
||||||
|
INSERT INTO t1 SELECT a, b+32768 FROM t1;
|
||||||
|
SELECT a,COUNT(DISTINCT b) AS cnt FROM t1 GROUP BY a HAVING cnt > 50;
|
||||||
|
SELECT a,SUM(DISTINCT b) AS sumation FROM t1 GROUP BY a HAVING sumation > 50;
|
||||||
|
SELECT a,AVG(DISTINCT b) AS average FROM t1 GROUP BY a HAVING average > 50;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo End of 5.0 tests
|
||||||
|
@ -893,6 +893,7 @@ bool Item_sum_distinct::setup(THD *thd)
|
|||||||
tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
|
tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
|
||||||
thd->variables.max_heap_table_size);
|
thd->variables.max_heap_table_size);
|
||||||
|
|
||||||
|
is_evaluated= FALSE;
|
||||||
DBUG_RETURN(tree == 0);
|
DBUG_RETURN(tree == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,6 +901,7 @@ bool Item_sum_distinct::setup(THD *thd)
|
|||||||
bool Item_sum_distinct::add()
|
bool Item_sum_distinct::add()
|
||||||
{
|
{
|
||||||
args[0]->save_in_field(table->field[0], FALSE);
|
args[0]->save_in_field(table->field[0], FALSE);
|
||||||
|
is_evaluated= FALSE;
|
||||||
if (!table->field[0]->is_null())
|
if (!table->field[0]->is_null())
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(tree);
|
DBUG_ASSERT(tree);
|
||||||
@ -929,6 +931,7 @@ void Item_sum_distinct::clear()
|
|||||||
DBUG_ASSERT(tree != 0); /* we always have a tree */
|
DBUG_ASSERT(tree != 0); /* we always have a tree */
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
tree->reset();
|
tree->reset();
|
||||||
|
is_evaluated= FALSE;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,6 +941,7 @@ void Item_sum_distinct::cleanup()
|
|||||||
delete tree;
|
delete tree;
|
||||||
tree= 0;
|
tree= 0;
|
||||||
table= 0;
|
table= 0;
|
||||||
|
is_evaluated= FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_sum_distinct::~Item_sum_distinct()
|
Item_sum_distinct::~Item_sum_distinct()
|
||||||
@ -949,16 +953,20 @@ Item_sum_distinct::~Item_sum_distinct()
|
|||||||
|
|
||||||
void Item_sum_distinct::calculate_val_and_count()
|
void Item_sum_distinct::calculate_val_and_count()
|
||||||
{
|
{
|
||||||
count= 0;
|
if (!is_evaluated)
|
||||||
val.traits->set_zero(&val);
|
|
||||||
/*
|
|
||||||
We don't have a tree only if 'setup()' hasn't been called;
|
|
||||||
this is the case of sql_select.cc:return_zero_rows.
|
|
||||||
*/
|
|
||||||
if (tree)
|
|
||||||
{
|
{
|
||||||
table->field[0]->set_notnull();
|
count= 0;
|
||||||
tree->walk(item_sum_distinct_walk, (void*) this);
|
val.traits->set_zero(&val);
|
||||||
|
/*
|
||||||
|
We don't have a tree only if 'setup()' hasn't been called;
|
||||||
|
this is the case of sql_select.cc:return_zero_rows.
|
||||||
|
*/
|
||||||
|
if (tree)
|
||||||
|
{
|
||||||
|
table->field[0]->set_notnull();
|
||||||
|
tree->walk(item_sum_distinct_walk, (void*) this);
|
||||||
|
}
|
||||||
|
is_evaluated= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,9 +1022,13 @@ Item_sum_avg_distinct::fix_length_and_dec()
|
|||||||
void
|
void
|
||||||
Item_sum_avg_distinct::calculate_val_and_count()
|
Item_sum_avg_distinct::calculate_val_and_count()
|
||||||
{
|
{
|
||||||
Item_sum_distinct::calculate_val_and_count();
|
if (!is_evaluated)
|
||||||
if (count)
|
{
|
||||||
val.traits->div(&val, count);
|
Item_sum_distinct::calculate_val_and_count();
|
||||||
|
if (count)
|
||||||
|
val.traits->div(&val, count);
|
||||||
|
is_evaluated= TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2477,6 +2489,7 @@ void Item_sum_count_distinct::cleanup()
|
|||||||
*/
|
*/
|
||||||
delete tree;
|
delete tree;
|
||||||
tree= 0;
|
tree= 0;
|
||||||
|
is_evaluated= FALSE;
|
||||||
if (table)
|
if (table)
|
||||||
{
|
{
|
||||||
free_tmp_table(table->in_use, table);
|
free_tmp_table(table->in_use, table);
|
||||||
@ -2498,6 +2511,7 @@ void Item_sum_count_distinct::make_unique()
|
|||||||
original= 0;
|
original= 0;
|
||||||
force_copy_fields= 1;
|
force_copy_fields= 1;
|
||||||
tree= 0;
|
tree= 0;
|
||||||
|
is_evaluated= FALSE;
|
||||||
tmp_table_param= 0;
|
tmp_table_param= 0;
|
||||||
always_null= FALSE;
|
always_null= FALSE;
|
||||||
}
|
}
|
||||||
@ -2617,6 +2631,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
|
|||||||
but this has to be handled - otherwise someone can crash
|
but this has to be handled - otherwise someone can crash
|
||||||
the server with a DoS attack
|
the server with a DoS attack
|
||||||
*/
|
*/
|
||||||
|
is_evaluated= FALSE;
|
||||||
if (! tree)
|
if (! tree)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -2633,8 +2648,11 @@ Item *Item_sum_count_distinct::copy_or_same(THD* thd)
|
|||||||
void Item_sum_count_distinct::clear()
|
void Item_sum_count_distinct::clear()
|
||||||
{
|
{
|
||||||
/* tree and table can be both null only if always_null */
|
/* tree and table can be both null only if always_null */
|
||||||
|
is_evaluated= FALSE;
|
||||||
if (tree)
|
if (tree)
|
||||||
|
{
|
||||||
tree->reset();
|
tree->reset();
|
||||||
|
}
|
||||||
else if (table)
|
else if (table)
|
||||||
{
|
{
|
||||||
table->file->extra(HA_EXTRA_NO_CACHE);
|
table->file->extra(HA_EXTRA_NO_CACHE);
|
||||||
@ -2655,6 +2673,7 @@ bool Item_sum_count_distinct::add()
|
|||||||
if ((*field)->is_real_null(0))
|
if ((*field)->is_real_null(0))
|
||||||
return 0; // Don't count NULL
|
return 0; // Don't count NULL
|
||||||
|
|
||||||
|
is_evaluated= FALSE;
|
||||||
if (tree)
|
if (tree)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2680,12 +2699,14 @@ longlong Item_sum_count_distinct::val_int()
|
|||||||
return LL(0);
|
return LL(0);
|
||||||
if (tree)
|
if (tree)
|
||||||
{
|
{
|
||||||
ulonglong count;
|
if (is_evaluated)
|
||||||
|
return count;
|
||||||
|
|
||||||
if (tree->elements == 0)
|
if (tree->elements == 0)
|
||||||
return (longlong) tree->elements_in_tree(); // everything fits in memory
|
return (longlong) tree->elements_in_tree(); // everything fits in memory
|
||||||
count= 0;
|
count= 0;
|
||||||
tree->walk(count_distinct_walk, (void*) &count);
|
tree->walk(count_distinct_walk, (void*) &count);
|
||||||
|
is_evaluated= TRUE;
|
||||||
return (longlong) count;
|
return (longlong) count;
|
||||||
}
|
}
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
|
@ -321,12 +321,23 @@ public:
|
|||||||
|
|
||||||
class Item_sum_num :public Item_sum
|
class Item_sum_num :public Item_sum
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
/*
|
||||||
|
val_xxx() functions may be called several times during the execution of a
|
||||||
|
query. Derived classes that require extensive calculation in val_xxx()
|
||||||
|
maintain cache of aggregate value. This variable governs the validity of
|
||||||
|
that cache.
|
||||||
|
*/
|
||||||
|
bool is_evaluated;
|
||||||
public:
|
public:
|
||||||
Item_sum_num() :Item_sum() {}
|
Item_sum_num() :Item_sum(),is_evaluated(FALSE) {}
|
||||||
Item_sum_num(Item *item_par) :Item_sum(item_par) {}
|
Item_sum_num(Item *item_par)
|
||||||
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
|
:Item_sum(item_par), is_evaluated(FALSE) {}
|
||||||
Item_sum_num(List<Item> &list) :Item_sum(list) {}
|
Item_sum_num(Item *a, Item* b) :Item_sum(a,b),is_evaluated(FALSE) {}
|
||||||
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
|
Item_sum_num(List<Item> &list)
|
||||||
|
:Item_sum(list), is_evaluated(FALSE) {}
|
||||||
|
Item_sum_num(THD *thd, Item_sum_num *item)
|
||||||
|
:Item_sum(thd, item),is_evaluated(item->is_evaluated) {}
|
||||||
bool fix_fields(THD *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
{
|
{
|
||||||
@ -508,6 +519,12 @@ class Item_sum_count_distinct :public Item_sum_int
|
|||||||
to help get things set up, but we insert nothing in it
|
to help get things set up, but we insert nothing in it
|
||||||
*/
|
*/
|
||||||
Unique *tree;
|
Unique *tree;
|
||||||
|
/*
|
||||||
|
Storage for the value of count between calls to val_int() so val_int()
|
||||||
|
will not recalculate on each call. Validitiy of the value is stored in
|
||||||
|
is_evaluated.
|
||||||
|
*/
|
||||||
|
longlong count;
|
||||||
/*
|
/*
|
||||||
Following is 0 normal object and pointer to original one for copy
|
Following is 0 normal object and pointer to original one for copy
|
||||||
(to correctly free resources)
|
(to correctly free resources)
|
||||||
@ -525,14 +542,15 @@ class Item_sum_count_distinct :public Item_sum_int
|
|||||||
public:
|
public:
|
||||||
Item_sum_count_distinct(List<Item> &list)
|
Item_sum_count_distinct(List<Item> &list)
|
||||||
:Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0),
|
:Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0),
|
||||||
force_copy_fields(0), tree(0), original(0), always_null(FALSE)
|
force_copy_fields(0), tree(0), count(0),
|
||||||
|
original(0), always_null(FALSE)
|
||||||
{ quick_group= 0; }
|
{ quick_group= 0; }
|
||||||
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
|
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
|
||||||
:Item_sum_int(thd, item), table(item->table),
|
:Item_sum_int(thd, item), table(item->table),
|
||||||
field_lengths(item->field_lengths),
|
field_lengths(item->field_lengths),
|
||||||
tmp_table_param(item->tmp_table_param),
|
tmp_table_param(item->tmp_table_param),
|
||||||
force_copy_fields(0), tree(item->tree), original(item),
|
force_copy_fields(0), tree(item->tree), count(item->count),
|
||||||
tree_key_length(item->tree_key_length),
|
original(item), tree_key_length(item->tree_key_length),
|
||||||
always_null(item->always_null)
|
always_null(item->always_null)
|
||||||
{}
|
{}
|
||||||
~Item_sum_count_distinct();
|
~Item_sum_count_distinct();
|
||||||
|
Reference in New Issue
Block a user