summaryrefslogtreecommitdiff
path: root/sql/item_sum.cc
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.local>2006-11-29 02:44:12 +0300
committerunknown <kostja@bodhi.local>2006-11-29 02:44:12 +0300
commit15584161e22595559cd3883aebe3b35793fba153 (patch)
treef9f728e4fd94cdcf8bc3f5ea8270ee291aa94890 /sql/item_sum.cc
parentcf9038e97973f8bbe387887af9b9f489316b3629 (diff)
parent00fec63a38f90d873a18e849cf0dc191d1ad42eb (diff)
downloadmariadb-git-15584161e22595559cd3883aebe3b35793fba153.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into bodhi.local:/opt/local/work/mysql-5.0-runtime libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged mysql-test/t/func_str.test: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_sum.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_yacc.yy: Auto merged tests/mysql_client_test.c: Auto merged mysql-test/t/wait_for_socket.sh: Manual merge. sql/sql_cache.cc: Manual merge.
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r--sql/item_sum.cc70
1 files changed, 53 insertions, 17 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4cd0d01fce3..4d84fa20300 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -897,6 +897,7 @@ bool Item_sum_distinct::setup(THD *thd)
tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
thd->variables.max_heap_table_size);
+ is_evaluated= FALSE;
DBUG_RETURN(tree == 0);
}
@@ -904,6 +905,7 @@ bool Item_sum_distinct::setup(THD *thd)
bool Item_sum_distinct::add()
{
args[0]->save_in_field(table->field[0], FALSE);
+ is_evaluated= FALSE;
if (!table->field[0]->is_null())
{
DBUG_ASSERT(tree);
@@ -933,6 +935,7 @@ void Item_sum_distinct::clear()
DBUG_ASSERT(tree != 0); /* we always have a tree */
null_value= 1;
tree->reset();
+ is_evaluated= FALSE;
DBUG_VOID_RETURN;
}
@@ -942,6 +945,7 @@ void Item_sum_distinct::cleanup()
delete tree;
tree= 0;
table= 0;
+ is_evaluated= FALSE;
}
Item_sum_distinct::~Item_sum_distinct()
@@ -953,16 +957,20 @@ Item_sum_distinct::~Item_sum_distinct()
void Item_sum_distinct::calculate_val_and_count()
{
- count= 0;
- 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)
+ if (!is_evaluated)
{
- table->field[0]->set_notnull();
- tree->walk(item_sum_distinct_walk, (void*) this);
+ count= 0;
+ 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;
}
}
@@ -1018,9 +1026,13 @@ Item_sum_avg_distinct::fix_length_and_dec()
void
Item_sum_avg_distinct::calculate_val_and_count()
{
- Item_sum_distinct::calculate_val_and_count();
- if (count)
- val.traits->div(&val, count);
+ if (!is_evaluated)
+ {
+ Item_sum_distinct::calculate_val_and_count();
+ if (count)
+ val.traits->div(&val, count);
+ is_evaluated= TRUE;
+ }
}
@@ -2482,6 +2494,7 @@ void Item_sum_count_distinct::cleanup()
*/
delete tree;
tree= 0;
+ is_evaluated= FALSE;
if (table)
{
free_tmp_table(table->in_use, table);
@@ -2503,6 +2516,7 @@ void Item_sum_count_distinct::make_unique()
original= 0;
force_copy_fields= 1;
tree= 0;
+ is_evaluated= FALSE;
tmp_table_param= 0;
always_null= FALSE;
}
@@ -2622,6 +2636,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
but this has to be handled - otherwise someone can crash
the server with a DoS attack
*/
+ is_evaluated= FALSE;
if (! tree)
return TRUE;
}
@@ -2638,8 +2653,11 @@ Item *Item_sum_count_distinct::copy_or_same(THD* thd)
void Item_sum_count_distinct::clear()
{
/* tree and table can be both null only if always_null */
+ is_evaluated= FALSE;
if (tree)
+ {
tree->reset();
+ }
else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
@@ -2660,6 +2678,7 @@ bool Item_sum_count_distinct::add()
if ((*field)->is_real_null(0))
return 0; // Don't count NULL
+ is_evaluated= FALSE;
if (tree)
{
/*
@@ -2686,12 +2705,14 @@ longlong Item_sum_count_distinct::val_int()
return LL(0);
if (tree)
{
- ulonglong count;
+ if (is_evaluated)
+ return count;
if (tree->elements == 0)
return (longlong) tree->elements_in_tree(); // everything fits in memory
count= 0;
tree->walk(count_distinct_walk, (void*) &count);
+ is_evaluated= TRUE;
return (longlong) count;
}
@@ -3005,6 +3026,7 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
String tmp2;
String *result= &item->result;
Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
+ uint old_length= result->length();
if (item->no_appended)
item->no_appended= FALSE;
@@ -3039,8 +3061,22 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
/* stop if length of result more than max_length */
if (result->length() > item->max_length)
{
+ int well_formed_error;
+ CHARSET_INFO *cs= item->collation.collation;
+ const char *ptr= result->ptr();
+ uint add_length;
+ /*
+ It's ok to use item->result.length() as the fourth argument
+ as this is never used to limit the length of the data.
+ Cut is done with the third argument.
+ */
+ add_length= cs->cset->well_formed_len(cs,
+ ptr + old_length,
+ ptr + item->max_length,
+ result->length(),
+ &well_formed_error);
+ result->length(old_length + add_length);
item->count_cut_values++;
- result->length(item->max_length);
item->warning_for_row= TRUE;
return 1;
}
@@ -3230,8 +3266,7 @@ bool Item_func_group_concat::add()
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
instead of doing tree traverse later.
*/
- if (result.length() <= max_length &&
- !warning_for_row &&
+ if (!warning_for_row &&
(!tree || (el->count == 1 && distinct && !arg_count_order)))
dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this);
@@ -3300,7 +3335,8 @@ bool Item_func_group_concat::setup(THD *thd)
DBUG_RETURN(TRUE);
/* We'll convert all blobs to varchar fields in the temporary table */
- tmp_table_param->convert_blob_length= max_length;
+ tmp_table_param->convert_blob_length= max_length *
+ collation.collation->mbmaxlen;
/* Push all not constant fields to the list and create a temp table */
always_null= 0;
for (uint i= 0; i < arg_count_field; i++)