Implementation of SUM(DISTINCT), tests cases

sql/filesort.cc:
  Snippet of filesort() code moved to function reuse_freed_buff() - 
  change buffpek pointers to use buff from freed BUFFPEK
  Used in filesort() and merge_walk().
sql/item_sum.cc:
  Implementation of Item_sum_sum_distinct - SUM(DISTINCT) item, 
  which uses Unique to resolve duplicates
sql/item_sum.h:
  New sum Item added - Item_sum_sum_distinct - for SUM(DISTINCT) function
sql/sql_class.h:
  added walk() and reset() methods to Unique, used in Item_sum_sum_distinct.
sql/sql_sort.h:
  declaration for reuse_freed_buff() to be able to use it in uniques.cc
sql/sql_yacc.yy:
  parser extended to handle MIN(DISTICNT), MAX(DISTINCT), SUM(DISTINCT)
sql/uniques.cc:
  Implementation for Unique::reset(), Unique::walk() as well as for merge_walk() 
  algorithm.
This commit is contained in:
unknown 2003-12-19 19:04:03 +03:00
commit 58a52a2a84
9 changed files with 834 additions and 35 deletions

View file

@ -756,6 +756,39 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
} /* read_to_buffer */
/*
Put all room used by freed buffer to use in adjacent buffer. Note, that
we can't simply distribute memory evenly between all buffers, because
new areas must not overlap with old ones.
SYNOPSYS
reuse_freed_buff()
queue IN list of non-empty buffers, without freed buffer
reuse IN empty buffer
key_length IN key length
*/
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
{
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
for (uint i= 0; i < queue->elements; ++i)
{
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
if (bp->base + bp->max_keys * key_length == reuse->base)
{
bp->max_keys+= reuse->max_keys;
return;
}
else if (bp->base == reuse_end)
{
bp->base= reuse->base;
bp->max_keys+= reuse->max_keys;
return;
}
}
DBUG_ASSERT(0);
}
/*
Merge buffers to one buffer
*/
@ -881,29 +914,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
if (!(error= (int) read_to_buffer(from_file,buffpek,
rec_length)))
{
uchar *base= buffpek->base;
ulong max_keys= buffpek->max_keys;
VOID(queue_remove(&queue,0));
/* Put room used by buffer to use in other buffer */
for (refpek= (BUFFPEK**) &queue_top(&queue);
refpek <= (BUFFPEK**) &queue_end(&queue);
refpek++)
{
buffpek= *refpek;
if (buffpek->base+buffpek->max_keys*rec_length == base)
{
buffpek->max_keys+= max_keys;
break;
}
else if (base+max_keys*rec_length == buffpek->base)
{
buffpek->base= base;
buffpek->max_keys+= max_keys;
break;
}
}
reuse_freed_buff(&queue, buffpek, rec_length);
break; /* One buffer have been removed */
}
else if (error == -1)