Loading include/my_sys.h +5 −1 Original line number Diff line number Diff line Loading @@ -108,6 +108,10 @@ 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 */ Loading include/my_tree.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading mysql-test/r/count_distinct2.result +4 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,7 @@ count(distinct s,t) 5 count(distinct n1) count(distinct n2) 2 3 count(distinct n2) n1 1 NULL 1 1 3 2 mysql-test/t/count_distinct2.test +3 −0 Original line number Diff line number Diff line Loading @@ -40,3 +40,6 @@ 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; mysys/my_alloc.c +40 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading Loading
include/my_sys.h +5 −1 Original line number Diff line number Diff line Loading @@ -108,6 +108,10 @@ 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 */ Loading
include/my_tree.h +3 −0 Original line number Diff line number Diff line Loading @@ -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 */ Loading
mysql-test/r/count_distinct2.result +4 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,7 @@ count(distinct s,t) 5 count(distinct n1) count(distinct n2) 2 3 count(distinct n2) n1 1 NULL 1 1 3 2
mysql-test/t/count_distinct2.test +3 −0 Original line number Diff line number Diff line Loading @@ -40,3 +40,6 @@ 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;
mysys/my_alloc.c +40 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; Loading