Commit ab9c0df7 authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi

Merge work:/home/bk/mysql-4.0 into donna.mysql.fi:/home/my/bk/mysql-4.0

parents ebae7e6a 4aedfb92
......@@ -108,7 +108,11 @@ extern int NEAR my_errno; /* Last error in mysys */
/* root_alloc flags */
#define MY_KEEP_PREALLOC 1
#define MY_MARK_BLOCKS_FREE 2 /* do not my_free() blocks,
just move used into free list
and mark all blocks as fully free
*/
/* defines when allocating data */
#ifdef SAFEMALLOC
......
......@@ -62,6 +62,9 @@ void init_tree(TREE *tree,uint default_alloc_size, int element_size,
qsort_cmp2 compare, my_bool with_delete,
void (*free_element)(void*));
void delete_tree(TREE*);
void reset_tree(TREE*);
/* similar to delete tree, except we do not my_free() blocks in mem_root
*/
#define is_tree_inited(tree) ((tree)->root != 0)
/* Functions on leafs */
......
......@@ -463,7 +463,7 @@ start_master()
--core \
--tmpdir=$MYSQL_TMP_DIR \
--language=english \
--innobase_data_file_path=ibdata1:50M \
--innodb_data_file_path=ibdata1:50M \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
fi
......
n1
1
2
NULL
count(distinct n1)
2
n2
11
12
13
NULL
count(distinct n2)
3
s
one
two
NULL
count(distinct s)
2
vs
eleven
twevle
thirteen
NULL
count(distinct vs)
3
t
eleven
twelve
foo
bar
NULL
count(distinct t)
4
n1 n2
1 11
2 11
2 12
2 13
NULL 13
2 NULL
count(distinct n1,n2)
4
n1 s
1 one
2 two
NULL two
2 NULL
count(distinct n1,s)
2
s n1 vs
one 1 eleven
two 2 eleven
two 2 twevle
two 2 thirteen
two NULL thirteen
NULL 2 thirteen
two 2 NULL
count(distinct s,n1,vs)
4
s t
one eleven
two eleven
two twelve
two foo
two bar
NULL bar
two NULL
count(distinct s,t)
5
count(distinct n1) count(distinct n2)
2 3
count(distinct n2) n1
1 NULL
1 1
3 2
create table t1(n1 int, n2 int, s char(20), vs varchar(20), t text);
insert into t1 values (1,11, 'one','eleven', 'eleven'),
(1,11, 'one','eleven', 'eleven'),
(2,11, 'two','eleven', 'eleven'),
(2,12, 'two','twevle', 'twelve'),
(2,13, 'two','thirteen', 'foo'),
(2,13, 'two','thirteen', 'foo'),
(2,13, 'two','thirteen', 'bar'),
(NULL,13, 'two','thirteen', 'bar'),
(2,NULL, 'two','thirteen', 'bar'),
(2,13, NULL,'thirteen', 'bar'),
(2,13, 'two',NULL, 'bar'),
(2,13, 'two','thirteen', NULL);
select distinct n1 from t1;
select count(distinct n1) from t1;
select distinct n2 from t1;
select count(distinct n2) from t1;
select distinct s from t1;
select count(distinct s) from t1;
select distinct vs from t1;
select count(distinct vs) from t1;
select distinct t from t1;
select count(distinct t) from t1;
select distinct n1,n2 from t1;
select count(distinct n1,n2) from t1;
select distinct n1,s from t1;
select count(distinct n1,s) from t1;
select distinct s,n1,vs from t1;
select count(distinct s,n1,vs) from t1;
select distinct s,t from t1;
select count(distinct s,t) from t1;
select count(distinct n1), count(distinct n2) from t1;
select count(distinct n2), n1 from t1 group by n1;
drop table t1;
......@@ -100,7 +100,41 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
#endif
}
/* deallocate everything used by alloc_root */
static inline void mark_blocks_free(MEM_ROOT* root)
{
reg1 USED_MEM *next,*last = 0;
/* iterate through (partially) free blocks, mark them fully free */
for(next = root->free; next; next = next->next )
{
last = next;
next->left = next->size - ALIGN_SIZE(sizeof(USED_MEM));
}
/* if free block list was not empty, point the next of the
last free block to the beginning of the used list */
next = root->used; /* a little optimization to avoid dereferencing root
twice - we will shortly start iterating through used
list */
if(last)
last->next = next;
else /* if free list is empty, just point it to the current used*/
root->free = next;
/* now go through the current used list, and mark each block
as fully free. Note that because of our optimization, we do not
need to initialize next here - see above
*/
for(;next; next = next->next)
next->left = next->size - ALIGN_SIZE(sizeof(USED_MEM));
/* Now everything is set - we just need to indicate that nothing is used
anymore
*/
root->used = 0;
}
/* deallocate everything used by alloc_root or just move
used blocks to free list if called with MY_USED_TO_FREE */
void free_root(MEM_ROOT *root, myf MyFlags)
{
......@@ -109,6 +143,11 @@ void free_root(MEM_ROOT *root, myf MyFlags)
if (!root)
DBUG_VOID_RETURN; /* purecov: inspected */
if(MyFlags & MY_MARK_BLOCKS_FREE)
{
mark_blocks_free(root);
DBUG_VOID_RETURN;
}
if (!(MyFlags & MY_KEEP_PREALLOC))
root->pre_alloc=0;
......
......@@ -103,9 +103,9 @@ void init_tree(TREE *tree, uint default_alloc_size, int size,
DBUG_VOID_RETURN;
}
void delete_tree(TREE *tree)
static void free_tree(TREE *tree, myf free_flags)
{
DBUG_ENTER("delete_tree");
DBUG_ENTER("free_tree");
DBUG_PRINT("enter",("tree: %lx",tree));
if (tree->root) /* If initialized */
......@@ -116,7 +116,7 @@ void delete_tree(TREE *tree)
{
if (tree->free)
delete_tree_element(tree,tree->root);
free_root(&tree->mem_root,MYF(0));
free_root(&tree->mem_root, free_flags);
}
}
tree->root= &tree->null_element;
......@@ -125,6 +125,18 @@ void delete_tree(TREE *tree)
DBUG_VOID_RETURN;
}
void delete_tree(TREE* tree)
{
free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */
}
void reset_tree(TREE* tree)
{
free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
/* do not my_free() mem_root if applicable, just mark blocks as free */
}
static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
{
if (element != &tree->null_element)
......
......@@ -810,12 +810,13 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2)
for(; field < field_end; ++field)
{
int res;
int len = (*field)->field_length;
Field* f = *field;
int len = f->field_length;
switch((*field)->type())
{
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
res = my_sortcmp(key1, key2, len);
res = f->key_cmp(key1, key2);
break;
default:
res = memcmp(key1, key2, len);
......@@ -879,20 +880,22 @@ bool Item_sum_count_distinct::setup(THD *thd)
// to use a simpler key compare method that can take advantage
// of not having to worry about other fields
{
switch(table->field[0]->type())
Field* field = table->field[0];
switch(field->type())
{
// if we have a string, we must take care of charsets
// and case sensitivity
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
compare_key = (qsort_cmp2)simple_str_key_cmp;
compare_key = (qsort_cmp2)(field->binary() ? simple_raw_key_cmp:
simple_str_key_cmp);
break;
default: // since at this point we cannot have blobs
// anything else can be compared with memcmp
compare_key = (qsort_cmp2)simple_raw_key_cmp;
break;
}
cmp_arg = (void*)(key_len = table->field[0]->field_length);
cmp_arg = (void*)(key_len = field->field_length);
rec_offset = 1;
}
else // too bad, cannot cheat - there is more than one field
......@@ -908,7 +911,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
rec_offset = table->reclength - key_len;
}
init_tree(&tree, 0, key_len, compare_key, 0, 0);
init_tree(&tree, min(max_heap_table_size, sortbuff_size/16),
key_len, compare_key, 0, 0);
tree.cmp_arg = cmp_arg;
use_tree = 1;
}
......@@ -919,11 +923,14 @@ bool Item_sum_count_distinct::setup(THD *thd)
void Item_sum_count_distinct::reset()
{
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
if(use_tree)
delete_tree(&tree);
reset_tree(&tree);
else
{
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
}
(void) add();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment