mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
RB-Tree indexes support in HEAP tables
Renamed _hp_func -> hp_func mi_key_cmp moved to /mysys/my_handler.c New tests for HEAP tables
This commit is contained in:
@ -31,8 +31,11 @@ int heap_check_heap(HP_INFO *info,my_bool print_status)
|
|||||||
DBUG_ENTER("heap_check_keys");
|
DBUG_ENTER("heap_check_keys");
|
||||||
|
|
||||||
for (error=key=0 ; key < share->keys ; key++)
|
for (error=key=0 ; key < share->keys ; key++)
|
||||||
error|=check_one_key(share->keydef+key,key, share->records,share->blength,
|
{
|
||||||
print_status);
|
if (!(share->keydef[key].algorithm == HA_KEY_ALG_BTREE))
|
||||||
|
error|=check_one_key(share->keydef+key,key, share->records,share->blength,
|
||||||
|
print_status);
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
@ -50,8 +53,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
|||||||
for (i=found=max_links=seek=0 ; i < records ; i++)
|
for (i=found=max_links=seek=0 ; i < records ; i++)
|
||||||
{
|
{
|
||||||
hash_info=hp_find_hash(&keydef->block,i);
|
hash_info=hp_find_hash(&keydef->block,i);
|
||||||
if (_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
|
if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
|
||||||
blength,records) == i)
|
blength,records) == i)
|
||||||
{
|
{
|
||||||
found++;
|
found++;
|
||||||
seek++;
|
seek++;
|
||||||
@ -59,8 +62,8 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
|||||||
while ((hash_info=hash_info->next_key) && found < records + 1)
|
while ((hash_info=hash_info->next_key) && found < records + 1)
|
||||||
{
|
{
|
||||||
seek+= ++links;
|
seek+= ++links;
|
||||||
if ((rec_link=_hp_mask(_hp_rec_hashnr(keydef,hash_info->ptr_to_rec),
|
if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec),
|
||||||
blength,records))
|
blength, records))
|
||||||
!= i)
|
!= i)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
|
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
#include "heapdef.h"
|
#include "heapdef.h"
|
||||||
|
|
||||||
int _hp_rectest(register HP_INFO *info, register const byte *old)
|
int hp_rectest(register HP_INFO *info, register const byte *old)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("_hp_rectest");
|
DBUG_ENTER("hp_rectest");
|
||||||
|
|
||||||
if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
|
if (memcmp(info->current_ptr,old,(size_t) info->s->reclength))
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <my_pthread.h>
|
#include <my_pthread.h>
|
||||||
#endif
|
#endif
|
||||||
#include "heap.h" /* Structs & some defines */
|
#include "heap.h" /* Structs & some defines */
|
||||||
|
#include "my_tree.h"
|
||||||
|
|
||||||
/* Some extern variables */
|
/* Some extern variables */
|
||||||
|
|
||||||
@ -29,10 +30,10 @@ extern LIST *heap_open_list,*heap_share_list;
|
|||||||
#define test_active(info) \
|
#define test_active(info) \
|
||||||
if (!(info->update & HA_STATE_AKTIV))\
|
if (!(info->update & HA_STATE_AKTIV))\
|
||||||
{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
|
{ my_errno=HA_ERR_NO_ACTIVE_RECORD; DBUG_RETURN(-1); }
|
||||||
#define hp_find_hash(A,B) ((HASH_INFO*) _hp_find_block((A),(B)))
|
#define hp_find_hash(A,B) ((HASH_INFO*) hp_find_block((A),(B)))
|
||||||
|
|
||||||
/* Find pos for record and update it in info->current_ptr */
|
/* Find pos for record and update it in info->current_ptr */
|
||||||
#define _hp_find_record(info,pos) (info)->current_ptr= _hp_find_block(&(info)->s->block,pos)
|
#define hp_find_record(info,pos) (info)->current_ptr= hp_find_block(&(info)->s->block,pos)
|
||||||
|
|
||||||
typedef struct st_hp_hash_info
|
typedef struct st_hp_hash_info
|
||||||
{
|
{
|
||||||
@ -40,40 +41,51 @@ typedef struct st_hp_hash_info
|
|||||||
byte *ptr_to_rec;
|
byte *ptr_to_rec;
|
||||||
} HASH_INFO;
|
} HASH_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MI_KEYSEG *keyseg;
|
||||||
|
uint key_length;
|
||||||
|
uint search_flag;
|
||||||
|
} heap_rb_param;
|
||||||
|
|
||||||
/* Prototypes for intern functions */
|
/* Prototypes for intern functions */
|
||||||
|
|
||||||
extern HP_SHARE *_hp_find_named_heap(const char *name);
|
extern HP_SHARE *hp_find_named_heap(const char *name);
|
||||||
extern int _hp_rectest(HP_INFO *info,const byte *old);
|
extern int hp_rectest(HP_INFO *info,const byte *old);
|
||||||
extern void _hp_delete_file_from_open_list(HP_INFO *info);
|
extern byte *hp_find_block(HP_BLOCK *info,ulong pos);
|
||||||
extern byte *_hp_find_block(HP_BLOCK *info,ulong pos);
|
extern int hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
|
||||||
extern int _hp_get_new_block(HP_BLOCK *info, ulong* alloc_length);
|
extern void hp_free(HP_SHARE *info);
|
||||||
extern void _hp_free(HP_SHARE *info);
|
extern byte *hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
|
||||||
extern byte *_hp_free_level(HP_BLOCK *block,uint level,HP_PTRS *pos,
|
byte *last_pos);
|
||||||
byte *last_pos);
|
extern int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||||
extern int _hp_write_key(HP_SHARE *info,HP_KEYDEF *keyinfo,
|
const byte *record, byte *recpos);
|
||||||
const byte *record,byte *recpos);
|
extern int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||||
extern int _hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
const byte *record, byte *recpos);
|
||||||
const byte *record,byte *recpos,int flag);
|
extern int hp_rb_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
||||||
|
const byte *record,byte *recpos,int flag);
|
||||||
|
extern int hp_delete_key(HP_INFO *info,HP_KEYDEF *keyinfo,
|
||||||
|
const byte *record,byte *recpos,int flag);
|
||||||
extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
|
extern HASH_INFO *_heap_find_hash(HP_BLOCK *block,ulong pos);
|
||||||
extern byte *_hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
|
extern byte *hp_search(HP_INFO *info,HP_KEYDEF *keyinfo,const byte *key,
|
||||||
uint nextflag);
|
uint nextflag);
|
||||||
extern byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
|
extern byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||||
const byte *key,
|
const byte *key, HASH_INFO *pos);
|
||||||
HASH_INFO *pos);
|
extern ulong hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
|
||||||
extern ulong _hp_hashnr(HP_KEYDEF *keyinfo,const byte *key);
|
extern ulong hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
|
||||||
extern ulong _hp_rec_hashnr(HP_KEYDEF *keyinfo,const byte *rec);
|
extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
|
||||||
extern ulong _hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
|
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
|
||||||
extern void _hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
|
|
||||||
HASH_INFO *newlink);
|
HASH_INFO *newlink);
|
||||||
extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
|
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
|
||||||
const byte *rec2);
|
const byte *rec2);
|
||||||
extern int _hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
|
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
|
||||||
const byte *key);
|
const byte *key);
|
||||||
extern void _hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
|
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
|
||||||
|
extern void hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
||||||
|
const byte *rec, byte *recpos);
|
||||||
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
|
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
|
||||||
extern int _hp_close(register HP_INFO *info);
|
extern int hp_close(register HP_INFO *info);
|
||||||
extern void _hp_clear(HP_SHARE *info);
|
extern void hp_clear(HP_SHARE *info);
|
||||||
|
extern uint hp_rb_pack_key(HP_INFO *info, uint inx, uchar *key,
|
||||||
|
const uchar *old, uint k_length);
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
extern pthread_mutex_t THR_LOCK_heap;
|
extern pthread_mutex_t THR_LOCK_heap;
|
||||||
#else
|
#else
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/* Find record according to record-position */
|
/* Find record according to record-position */
|
||||||
|
|
||||||
byte *_hp_find_block(HP_BLOCK *block, ulong pos)
|
byte *hp_find_block(HP_BLOCK *block, ulong pos)
|
||||||
{
|
{
|
||||||
reg1 int i;
|
reg1 int i;
|
||||||
reg3 HP_PTRS *ptr;
|
reg3 HP_PTRS *ptr;
|
||||||
@ -37,7 +37,7 @@ byte *_hp_find_block(HP_BLOCK *block, ulong pos)
|
|||||||
/* get one new block-of-records. Alloc ptr to block if neaded */
|
/* get one new block-of-records. Alloc ptr to block if neaded */
|
||||||
/* Interrupts are stopped to allow ha_panic in interrupts */
|
/* Interrupts are stopped to allow ha_panic in interrupts */
|
||||||
|
|
||||||
int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
||||||
{
|
{
|
||||||
reg1 uint i,j;
|
reg1 uint i,j;
|
||||||
HP_PTRS *root;
|
HP_PTRS *root;
|
||||||
@ -84,7 +84,7 @@ int _hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
|
|||||||
|
|
||||||
/* free all blocks under level */
|
/* free all blocks under level */
|
||||||
|
|
||||||
byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
byte *hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
||||||
{
|
{
|
||||||
int i,max_pos;
|
int i,max_pos;
|
||||||
byte *next_ptr;
|
byte *next_ptr;
|
||||||
@ -99,7 +99,7 @@ byte *_hp_free_level(HP_BLOCK *block, uint level, HP_PTRS *pos, byte *last_pos)
|
|||||||
|
|
||||||
next_ptr=(byte*) (pos+1);
|
next_ptr=(byte*) (pos+1);
|
||||||
for (i=0 ; i < max_pos ; i++)
|
for (i=0 ; i < max_pos ; i++)
|
||||||
next_ptr=_hp_free_level(block,level-1,
|
next_ptr=hp_free_level(block,level-1,
|
||||||
(HP_PTRS*) pos->blocks[i],next_ptr);
|
(HP_PTRS*) pos->blocks[i],next_ptr);
|
||||||
}
|
}
|
||||||
if ((byte*) pos != last_pos)
|
if ((byte*) pos != last_pos)
|
||||||
|
@ -24,25 +24,33 @@
|
|||||||
|
|
||||||
void heap_clear(HP_INFO *info)
|
void heap_clear(HP_INFO *info)
|
||||||
{
|
{
|
||||||
_hp_clear(info->s);
|
hp_clear(info->s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _hp_clear(HP_SHARE *info)
|
void hp_clear(HP_SHARE *info)
|
||||||
{
|
{
|
||||||
uint key;
|
uint key;
|
||||||
DBUG_ENTER("_hp_clear");
|
DBUG_ENTER("hp_clear");
|
||||||
|
|
||||||
if (info->block.levels)
|
if (info->block.levels)
|
||||||
VOID(_hp_free_level(&info->block,info->block.levels,info->block.root,
|
VOID(hp_free_level(&info->block,info->block.levels,info->block.root,
|
||||||
(byte*) 0));
|
(byte*) 0));
|
||||||
info->block.levels=0;
|
info->block.levels=0;
|
||||||
for (key=0 ; key < info->keys ; key++)
|
for (key=0 ; key < info->keys ; key++)
|
||||||
{
|
{
|
||||||
HP_BLOCK *block= &info->keydef[key].block;
|
HP_KEYDEF *keyinfo = info->keydef + key;
|
||||||
if (block->levels)
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
VOID(_hp_free_level(block,block->levels,block->root,(byte*) 0));
|
{
|
||||||
block->levels=0;
|
delete_tree(&keyinfo->rb_tree);
|
||||||
block->last_allocated=0;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HP_BLOCK *block= &keyinfo->block;
|
||||||
|
if (block->levels)
|
||||||
|
VOID(hp_free_level(block,block->levels,block->root,(byte*) 0));
|
||||||
|
block->levels=0;
|
||||||
|
block->last_allocated=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
info->records=info->deleted=info->data_length=info->index_length=0;
|
info->records=info->deleted=info->data_length=info->index_length=0;
|
||||||
info->blength=1;
|
info->blength=1;
|
||||||
|
@ -26,16 +26,16 @@ int heap_close(HP_INFO *info)
|
|||||||
int tmp;
|
int tmp;
|
||||||
DBUG_ENTER("heap_close");
|
DBUG_ENTER("heap_close");
|
||||||
pthread_mutex_lock(&THR_LOCK_heap);
|
pthread_mutex_lock(&THR_LOCK_heap);
|
||||||
tmp= _hp_close(info);
|
tmp= hp_close(info);
|
||||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||||
DBUG_RETURN(tmp);
|
DBUG_RETURN(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int _hp_close(register HP_INFO *info)
|
int hp_close(register HP_INFO *info)
|
||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
DBUG_ENTER("_hp_close");
|
DBUG_ENTER("hp_close");
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (info->s->changed && heap_check_heap(info,0))
|
if (info->s->changed && heap_check_heap(info,0))
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ int _hp_close(register HP_INFO *info)
|
|||||||
info->s->changed=0;
|
info->s->changed=0;
|
||||||
heap_open_list=list_delete(heap_open_list,&info->open_list);
|
heap_open_list=list_delete(heap_open_list,&info->open_list);
|
||||||
if (!--info->s->open_count && info->s->delete_on_close)
|
if (!--info->s->open_count && info->s->delete_on_close)
|
||||||
_hp_free(info->s); /* Table was deleted */
|
hp_free(info->s); /* Table was deleted */
|
||||||
my_free((gptr) info,MYF(0));
|
my_free((gptr) info,MYF(0));
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,15 @@
|
|||||||
|
|
||||||
#include "heapdef.h"
|
#include "heapdef.h"
|
||||||
|
|
||||||
|
|
||||||
int heap_create(const char *name)
|
int heap_create(const char *name)
|
||||||
{
|
{
|
||||||
reg1 HP_SHARE *share;
|
reg1 HP_SHARE *share;
|
||||||
DBUG_ENTER("heap_create");
|
DBUG_ENTER("heap_create");
|
||||||
pthread_mutex_lock(&THR_LOCK_heap);
|
pthread_mutex_lock(&THR_LOCK_heap);
|
||||||
if ((share=_hp_find_named_heap(name)))
|
if ((share=hp_find_named_heap(name)))
|
||||||
{
|
{
|
||||||
if (share->open_count == 0)
|
if (share->open_count == 0)
|
||||||
_hp_free(share);
|
hp_free(share);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -47,10 +46,10 @@ int heap_delete_table(const char *name)
|
|||||||
DBUG_ENTER("heap_delete_table");
|
DBUG_ENTER("heap_delete_table");
|
||||||
|
|
||||||
pthread_mutex_lock(&THR_LOCK_heap);
|
pthread_mutex_lock(&THR_LOCK_heap);
|
||||||
if ((share=_hp_find_named_heap(name)))
|
if ((share = hp_find_named_heap(name)))
|
||||||
{
|
{
|
||||||
if (share->open_count == 0)
|
if (share->open_count == 0)
|
||||||
_hp_free(share);
|
hp_free(share);
|
||||||
else
|
else
|
||||||
share->delete_on_close=1;
|
share->delete_on_close=1;
|
||||||
result=0;
|
result=0;
|
||||||
@ -64,10 +63,10 @@ int heap_delete_table(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _hp_free(HP_SHARE *share)
|
void hp_free(HP_SHARE *share)
|
||||||
{
|
{
|
||||||
heap_share_list=list_delete(heap_share_list,&share->open_list);
|
heap_share_list=list_delete(heap_share_list,&share->open_list);
|
||||||
_hp_clear(share); /* Remove blocks from memory */
|
hp_clear(share); /* Remove blocks from memory */
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
thr_lock_delete(&share->lock);
|
thr_lock_delete(&share->lock);
|
||||||
VOID(pthread_mutex_destroy(&share->intern_lock));
|
VOID(pthread_mutex_destroy(&share->intern_lock));
|
||||||
|
@ -20,25 +20,26 @@
|
|||||||
|
|
||||||
int heap_delete(HP_INFO *info, const byte *record)
|
int heap_delete(HP_INFO *info, const byte *record)
|
||||||
{
|
{
|
||||||
uint key;
|
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
|
HP_KEYDEF *keydef, *end, *p_lastinx;
|
||||||
DBUG_ENTER("heap_delete");
|
DBUG_ENTER("heap_delete");
|
||||||
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
|
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
|
||||||
|
|
||||||
test_active(info);
|
test_active(info);
|
||||||
|
|
||||||
if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,record))
|
if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,record))
|
||||||
DBUG_RETURN(my_errno); /* Record changed */
|
DBUG_RETURN(my_errno); /* Record changed */
|
||||||
share->changed=1;
|
share->changed=1;
|
||||||
|
|
||||||
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
|
if ( --(share->records) < share->blength >> 1) share->blength>>=1;
|
||||||
pos=info->current_ptr;
|
pos=info->current_ptr;
|
||||||
|
|
||||||
for (key=0 ; key < share->keys ; key++)
|
p_lastinx = share->keydef + info->lastinx;
|
||||||
|
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||||
|
keydef++)
|
||||||
{
|
{
|
||||||
if (_hp_delete_key(info,share->keydef+key,record,pos,
|
if ((*keydef->delete_key)(info, keydef, record, pos, keydef == p_lastinx))
|
||||||
key == (uint) info->lastinx))
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,22 +50,40 @@ int heap_delete(HP_INFO *info, const byte *record)
|
|||||||
share->deleted++;
|
share->deleted++;
|
||||||
info->current_hash_ptr=0;
|
info->current_hash_ptr=0;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
err:
|
err:
|
||||||
if (++(share->records) == share->blength)
|
if (++(share->records) == share->blength)
|
||||||
share->blength+= share->blength;
|
share->blength+= share->blength;
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove one key from rb-tree
|
||||||
|
*/
|
||||||
|
int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
||||||
|
const byte *record, byte *recpos, int flag)
|
||||||
|
{
|
||||||
|
heap_rb_param custom_arg;
|
||||||
|
|
||||||
|
if (flag)
|
||||||
|
info->last_pos = NULL; /* For heap_rnext/heap_rprev */
|
||||||
|
|
||||||
|
hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||||
|
custom_arg.keyseg = keyinfo->seg;
|
||||||
|
custom_arg.key_length = keyinfo->length;
|
||||||
|
custom_arg.search_flag = SEARCH_SAME;
|
||||||
|
return tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove one key from hash-table */
|
/* Remove one key from hash-table */
|
||||||
/* Flag is set if we want's to correct info->current_ptr */
|
/* Flag is set if we want's to correct info->current_ptr */
|
||||||
|
|
||||||
int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
||||||
const byte *record, byte *recpos, int flag)
|
const byte *record, byte *recpos, int flag)
|
||||||
{
|
{
|
||||||
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
|
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
|
||||||
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
|
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
DBUG_ENTER("_hp_delete_key");
|
DBUG_ENTER("hp_delete_key");
|
||||||
|
|
||||||
blength=share->blength;
|
blength=share->blength;
|
||||||
if (share->records+1 == blength)
|
if (share->records+1 == blength)
|
||||||
@ -74,13 +93,13 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||||||
|
|
||||||
/* Search after record with key */
|
/* Search after record with key */
|
||||||
pos= hp_find_hash(&keyinfo->block,
|
pos= hp_find_hash(&keyinfo->block,
|
||||||
_hp_mask(_hp_rec_hashnr(keyinfo,record),blength,
|
hp_mask(hp_rec_hashnr(keyinfo, record), blength,
|
||||||
share->records+1));
|
share->records + 1));
|
||||||
gpos = pos3 = 0;
|
gpos = pos3 = 0;
|
||||||
|
|
||||||
while (pos->ptr_to_rec != recpos)
|
while (pos->ptr_to_rec != recpos)
|
||||||
{
|
{
|
||||||
if (flag && !_hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
|
if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
|
||||||
last_ptr=pos; /* Previous same key */
|
last_ptr=pos; /* Previous same key */
|
||||||
gpos=pos;
|
gpos=pos;
|
||||||
if (!(pos=pos->next_key))
|
if (!(pos=pos->next_key))
|
||||||
@ -113,33 +132,33 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||||||
DBUG_RETURN (0);
|
DBUG_RETURN (0);
|
||||||
|
|
||||||
/* Move the last key (lastpos) */
|
/* Move the last key (lastpos) */
|
||||||
lastpos_hashnr=_hp_rec_hashnr(keyinfo,lastpos->ptr_to_rec);
|
lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec);
|
||||||
/* pos is where lastpos should be */
|
/* pos is where lastpos should be */
|
||||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(lastpos_hashnr,share->blength,
|
pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength,
|
||||||
share->records));
|
share->records));
|
||||||
if (pos == empty) /* Move to empty position. */
|
if (pos == empty) /* Move to empty position. */
|
||||||
{
|
{
|
||||||
empty[0]=lastpos[0];
|
empty[0]=lastpos[0];
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
pos_hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
|
pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
|
||||||
/* pos3 is where the pos should be */
|
/* pos3 is where the pos should be */
|
||||||
pos3= hp_find_hash(&keyinfo->block,
|
pos3= hp_find_hash(&keyinfo->block,
|
||||||
_hp_mask(pos_hashnr,share->blength,share->records));
|
hp_mask(pos_hashnr, share->blength, share->records));
|
||||||
if (pos != pos3)
|
if (pos != pos3)
|
||||||
{ /* pos is on wrong posit */
|
{ /* pos is on wrong posit */
|
||||||
empty[0]=pos[0]; /* Save it here */
|
empty[0]=pos[0]; /* Save it here */
|
||||||
pos[0]=lastpos[0]; /* This shold be here */
|
pos[0]=lastpos[0]; /* This shold be here */
|
||||||
_hp_movelink(pos,pos3,empty); /* Fix link to pos */
|
hp_movelink(pos, pos3, empty); /* Fix link to pos */
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
pos2= _hp_mask(lastpos_hashnr,blength,share->records+1);
|
pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
|
||||||
if (pos2 == _hp_mask(pos_hashnr,blength,share->records+1))
|
if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1))
|
||||||
{ /* Identical key-positions */
|
{ /* Identical key-positions */
|
||||||
if (pos2 != share->records)
|
if (pos2 != share->records)
|
||||||
{
|
{
|
||||||
empty[0]=lastpos[0];
|
empty[0]=lastpos[0];
|
||||||
_hp_movelink(lastpos,pos,empty);
|
hp_movelink(lastpos, pos, empty);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
pos3= pos; /* Link pos->next after lastpos */
|
pos3= pos; /* Link pos->next after lastpos */
|
||||||
@ -147,7 +166,7 @@ int _hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
|
|||||||
else pos3= 0; /* Different positions merge */
|
else pos3= 0; /* Different positions merge */
|
||||||
|
|
||||||
empty[0]=lastpos[0];
|
empty[0]=lastpos[0];
|
||||||
_hp_movelink(pos3,empty,pos->next_key);
|
hp_movelink(pos3, empty, pos->next_key);
|
||||||
pos->next_key=empty;
|
pos->next_key=empty;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
146
heap/hp_hash.c
146
heap/hp_hash.c
@ -19,30 +19,72 @@
|
|||||||
#include "heapdef.h"
|
#include "heapdef.h"
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
|
|
||||||
|
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
|
||||||
|
uint start_key_len,
|
||||||
|
enum ha_rkey_function start_search_flag,
|
||||||
|
const byte *end_key, uint end_key_len,
|
||||||
|
enum ha_rkey_function end_search_flag)
|
||||||
|
{
|
||||||
|
ha_rows start_pos, end_pos;
|
||||||
|
TREE *rb_tree = &info->s->keydef[inx].rb_tree;
|
||||||
|
heap_rb_param custom_arg;
|
||||||
|
|
||||||
|
info->lastinx = inx;
|
||||||
|
custom_arg.keyseg = info->s->keydef[inx].seg;
|
||||||
|
custom_arg.search_flag = SEARCH_FIND | SEARCH_SAME;
|
||||||
|
custom_arg.key_length = start_key_len;
|
||||||
|
if (start_key)
|
||||||
|
{
|
||||||
|
hp_rb_pack_key(info, inx, info->recbuf, start_key, start_key_len);
|
||||||
|
start_pos= tree_record_pos(rb_tree, info->recbuf, start_search_flag,
|
||||||
|
&custom_arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_pos= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_arg.key_length = end_key_len;
|
||||||
|
if (end_key)
|
||||||
|
{
|
||||||
|
hp_rb_pack_key(info, inx, info->recbuf, end_key, end_key_len);
|
||||||
|
end_pos= tree_record_pos(rb_tree, info->recbuf, end_search_flag,
|
||||||
|
&custom_arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end_pos= rb_tree->elements_in_tree + (ha_rows)1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
|
||||||
|
return HA_POS_ERROR;
|
||||||
|
return end_pos < start_pos ? (ha_rows) 0 :
|
||||||
|
(end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos);
|
||||||
|
}
|
||||||
|
|
||||||
/* Search after a record based on a key */
|
/* Search after a record based on a key */
|
||||||
/* Sets info->current_ptr to found record */
|
/* Sets info->current_ptr to found record */
|
||||||
/* next_flag: Search=0, next=1, prev =2, same =3 */
|
/* next_flag: Search=0, next=1, prev =2, same =3 */
|
||||||
|
|
||||||
byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||||
uint nextflag)
|
uint nextflag)
|
||||||
{
|
{
|
||||||
reg1 HASH_INFO *pos,*prev_ptr;
|
reg1 HASH_INFO *pos,*prev_ptr;
|
||||||
int flag;
|
int flag;
|
||||||
uint old_nextflag;
|
uint old_nextflag;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
DBUG_ENTER("_hp_search");
|
DBUG_ENTER("hp_search");
|
||||||
|
|
||||||
old_nextflag=nextflag;
|
old_nextflag=nextflag;
|
||||||
flag=1;
|
flag=1;
|
||||||
prev_ptr=0;
|
prev_ptr=0;
|
||||||
|
|
||||||
if (share->records)
|
if (share->records)
|
||||||
{
|
{
|
||||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_hashnr(keyinfo,key),
|
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key),
|
||||||
share->blength,share->records));
|
share->blength, share->records));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
|
if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
|
||||||
{
|
{
|
||||||
switch (nextflag) {
|
switch (nextflag) {
|
||||||
case 0: /* Search after key */
|
case 0: /* Search after key */
|
||||||
@ -74,8 +116,8 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||||||
{
|
{
|
||||||
flag=0; /* Reset flag */
|
flag=0; /* Reset flag */
|
||||||
if (hp_find_hash(&keyinfo->block,
|
if (hp_find_hash(&keyinfo->block,
|
||||||
_hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
|
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
|
||||||
share->blength,share->records)) != pos)
|
share->blength, share->records)) != pos)
|
||||||
break; /* Wrong link */
|
break; /* Wrong link */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,14 +144,14 @@ byte *_hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||||||
since last read !
|
since last read !
|
||||||
*/
|
*/
|
||||||
|
|
||||||
byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
||||||
HASH_INFO *pos)
|
HASH_INFO *pos)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("_hp_search_next");
|
DBUG_ENTER("hp_search_next");
|
||||||
|
|
||||||
while ((pos= pos->next_key))
|
while ((pos= pos->next_key))
|
||||||
{
|
{
|
||||||
if (!_hp_key_cmp(keyinfo,pos->ptr_to_rec,key))
|
if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
|
||||||
{
|
{
|
||||||
info->current_hash_ptr=pos;
|
info->current_hash_ptr=pos;
|
||||||
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
|
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
|
||||||
@ -124,7 +166,7 @@ byte *_hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
|
|||||||
|
|
||||||
/* Calculate pos according to keys */
|
/* Calculate pos according to keys */
|
||||||
|
|
||||||
ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
||||||
{
|
{
|
||||||
if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
|
if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
|
||||||
return (hashnr & ((buffmax >> 1) -1));
|
return (hashnr & ((buffmax >> 1) -1));
|
||||||
@ -133,7 +175,7 @@ ulong _hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
|
|||||||
|
|
||||||
/* Change link from pos to new_link */
|
/* Change link from pos to new_link */
|
||||||
|
|
||||||
void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
||||||
{
|
{
|
||||||
HASH_INFO *old_link;
|
HASH_INFO *old_link;
|
||||||
do
|
do
|
||||||
@ -149,11 +191,11 @@ void _hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
|
|||||||
|
|
||||||
/* Calc hashvalue for a key */
|
/* Calc hashvalue for a key */
|
||||||
|
|
||||||
ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||||
{
|
{
|
||||||
/*register*/
|
/*register*/
|
||||||
ulong nr=1, nr2=4;
|
ulong nr=1, nr2=4;
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -196,11 +238,11 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||||||
|
|
||||||
/* Calc hashvalue for a key in a record */
|
/* Calc hashvalue for a key in a record */
|
||||||
|
|
||||||
ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||||
{
|
{
|
||||||
/*register*/
|
/*register*/
|
||||||
ulong nr=1, nr2=4;
|
ulong nr=1, nr2=4;
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -255,10 +297,10 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||||||
* far, and works well on both numbers and strings.
|
* far, and works well on both numbers and strings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
||||||
{
|
{
|
||||||
register ulong nr=0;
|
register ulong nr=0;
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -296,10 +338,10 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
|
|||||||
|
|
||||||
/* Calc hashvalue for a key in a record */
|
/* Calc hashvalue for a key in a record */
|
||||||
|
|
||||||
ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
||||||
{
|
{
|
||||||
register ulong nr=0;
|
register ulong nr=0;
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -337,9 +379,9 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
|
|||||||
|
|
||||||
/* Compare keys for two records. Returns 0 if they are identical */
|
/* Compare keys for two records. Returns 0 if they are identical */
|
||||||
|
|
||||||
int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
||||||
{
|
{
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -351,13 +393,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
|||||||
if (rec1[seg->null_pos] & seg->null_bit)
|
if (rec1[seg->null_pos] & seg->null_bit)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (seg->type == HA_KEYTYPE_TEXT)
|
switch (seg->type) {
|
||||||
{
|
case HA_KEYTYPE_END:
|
||||||
|
return 0;
|
||||||
|
case HA_KEYTYPE_TEXT:
|
||||||
if (my_sortcmp(default_charset_info,rec1+seg->start,rec2+seg->start,seg->length))
|
if (my_sortcmp(default_charset_info,rec1+seg->start,rec2+seg->start,seg->length))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
break;
|
||||||
else
|
default:
|
||||||
{
|
|
||||||
if (bcmp(rec1+seg->start,rec2+seg->start,seg->length))
|
if (bcmp(rec1+seg->start,rec2+seg->start,seg->length))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -367,9 +410,9 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
|
|||||||
|
|
||||||
/* Compare a key in a record to a whole key */
|
/* Compare a key in a record to a whole key */
|
||||||
|
|
||||||
int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
||||||
{
|
{
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
|
||||||
seg < endseg ;
|
seg < endseg ;
|
||||||
@ -405,9 +448,9 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
|
|||||||
|
|
||||||
/* Copy a key from a record to a keybuffer */
|
/* Copy a key from a record to a keybuffer */
|
||||||
|
|
||||||
void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
||||||
{
|
{
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
|
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
@ -418,7 +461,44 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
||||||
|
const byte *rec, byte *recpos)
|
||||||
|
{
|
||||||
|
MI_KEYSEG *seg, *endseg;
|
||||||
|
|
||||||
|
/* -1 means that HA_KEYTYPE_END segment will not copy */
|
||||||
|
for (seg= keydef->seg, endseg= seg + keydef->keysegs - 1; seg < endseg;
|
||||||
|
seg++)
|
||||||
|
{
|
||||||
|
if (seg->null_bit)
|
||||||
|
*key++= 1 - test(rec[seg->null_pos] & seg->null_bit);
|
||||||
|
memcpy(key, rec + seg->start, (size_t) seg->length);
|
||||||
|
key+= seg->length;
|
||||||
|
}
|
||||||
|
memcpy(key, &recpos, sizeof(byte*));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint hp_rb_pack_key(HP_INFO *info, uint inx, uchar *key, const uchar *old,
|
||||||
|
uint k_length)
|
||||||
|
{
|
||||||
|
MI_KEYSEG *seg, *endseg;
|
||||||
|
uchar *start_key= key;
|
||||||
|
HP_KEYDEF *keydef= info->s->keydef + inx;
|
||||||
|
|
||||||
|
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg;
|
||||||
|
old+= seg->length, seg++)
|
||||||
|
{
|
||||||
|
if (seg->null_bit)
|
||||||
|
{
|
||||||
|
if (!(*key++= (char) 1 - *old++))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
memcpy((byte*) key, old, seg->length);
|
||||||
|
key+= seg->length;
|
||||||
|
}
|
||||||
|
return key - start_key;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if any of the key parts are NULL.
|
Test if any of the key parts are NULL.
|
||||||
Return:
|
Return:
|
||||||
@ -428,7 +508,7 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
|
|||||||
|
|
||||||
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
|
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record)
|
||||||
{
|
{
|
||||||
HP_KEYSEG *seg,*endseg;
|
MI_KEYSEG *seg,*endseg;
|
||||||
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
|
||||||
{
|
{
|
||||||
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
|
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
|
||||||
|
@ -21,6 +21,15 @@
|
|||||||
#include "hp_static.c" /* Stupid vms-linker */
|
#include "hp_static.c" /* Stupid vms-linker */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "my_sys.h"
|
||||||
|
|
||||||
|
static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2)
|
||||||
|
{
|
||||||
|
uint not_used;
|
||||||
|
return hp_rb_key_cmp(param->keyseg, key1, key2, param->key_length,
|
||||||
|
param->search_flag, ¬_used);
|
||||||
|
}
|
||||||
|
|
||||||
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
|
static void init_block(HP_BLOCK *block,uint reclength,ulong min_records,
|
||||||
ulong max_records);
|
ulong max_records);
|
||||||
|
|
||||||
@ -32,49 +41,70 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
|
|||||||
uint i,j,key_segs,max_length,length;
|
uint i,j,key_segs,max_length,length;
|
||||||
HP_INFO *info;
|
HP_INFO *info;
|
||||||
HP_SHARE *share;
|
HP_SHARE *share;
|
||||||
HP_KEYSEG *keyseg;
|
MI_KEYSEG *keyseg;
|
||||||
|
|
||||||
DBUG_ENTER("heap_open");
|
DBUG_ENTER("heap_open");
|
||||||
|
|
||||||
pthread_mutex_lock(&THR_LOCK_heap);
|
pthread_mutex_lock(&THR_LOCK_heap);
|
||||||
if (!(share=_hp_find_named_heap(name)))
|
if (!(share = hp_find_named_heap(name)))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("Initializing new table"));
|
DBUG_PRINT("info",("Initializing new table"));
|
||||||
for (i=key_segs=max_length=0 ; i < keys ; i++)
|
for (i=key_segs=max_length=0 ; i < keys ; i++)
|
||||||
{
|
{
|
||||||
key_segs+= keydef[i].keysegs;
|
key_segs+= keydef[i].keysegs;
|
||||||
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
|
bzero((char*) &keydef[i].block,sizeof(keydef[i].block));
|
||||||
|
bzero((char*) &keydef[i].rb_tree ,sizeof(keydef[i].rb_tree));
|
||||||
for (j=length=0 ; j < keydef[i].keysegs; j++)
|
for (j=length=0 ; j < keydef[i].keysegs; j++)
|
||||||
{
|
{
|
||||||
length+=keydef[i].seg[j].length;
|
length+=keydef[i].seg[j].length;
|
||||||
if (keydef[i].seg[j].null_bit &&
|
if (keydef[i].seg[j].null_bit &&
|
||||||
!(keydef[i].flag & HA_NULL_ARE_EQUAL))
|
!(keydef[i].flag & HA_NULL_ARE_EQUAL))
|
||||||
keydef[i].flag |= HA_NULL_PART_KEY;
|
keydef[i].flag |= HA_NULL_PART_KEY;
|
||||||
|
if (keydef[i].algorithm == HA_KEY_ALG_BTREE &&
|
||||||
|
keydef[i].seg[j].null_bit)
|
||||||
|
keydef[i].rb_tree.size_of_element++;
|
||||||
}
|
}
|
||||||
keydef[i].length=length;
|
keydef[i].length= length;
|
||||||
if (length > max_length)
|
keydef[i].ref_offs= length + keydef[i].rb_tree.size_of_element -
|
||||||
max_length=length;
|
sizeof(byte*);
|
||||||
|
if (length + keydef[i].rb_tree.size_of_element > max_length)
|
||||||
|
max_length= length + keydef[i].rb_tree.size_of_element;
|
||||||
}
|
}
|
||||||
if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
|
if (!(share = (HP_SHARE*) my_malloc((uint) sizeof(HP_SHARE)+
|
||||||
keys*sizeof(HP_KEYDEF)+
|
keys*sizeof(HP_KEYDEF)+
|
||||||
key_segs*sizeof(HP_KEYSEG),
|
key_segs*sizeof(MI_KEYSEG),
|
||||||
MYF(MY_ZEROFILL))))
|
MYF(MY_ZEROFILL))))
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
share->keydef=(HP_KEYDEF*) (share+1);
|
share->keydef=(HP_KEYDEF*) (share+1);
|
||||||
keyseg=(HP_KEYSEG*) (share->keydef+keys);
|
keyseg=(MI_KEYSEG*) (share->keydef+keys);
|
||||||
init_block(&share->block,reclength+1,min_records,max_records);
|
init_block(&share->block,reclength+1,min_records,max_records);
|
||||||
/* Fix keys */
|
/* Fix keys */
|
||||||
memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
|
memcpy(share->keydef,keydef,(size_t) (sizeof(keydef[0])*keys));
|
||||||
for (i=0 ; i < keys ; i++)
|
for (i=0 ; i < keys ; i++)
|
||||||
{
|
{
|
||||||
share->keydef[i].seg=keyseg;
|
HP_KEYDEF *keyinfo = share->keydef + i;
|
||||||
memcpy(keyseg,keydef[i].seg,
|
keyinfo->seg = keyseg;
|
||||||
(size_t) (sizeof(keyseg[0])*keydef[i].keysegs));
|
memcpy(keyseg, keydef[i].seg,
|
||||||
keyseg+=keydef[i].keysegs;
|
(size_t) (sizeof(keyseg[0]) * keydef[i].keysegs));
|
||||||
init_block(&share->keydef[i].block,sizeof(HASH_INFO),min_records,
|
keyseg += keydef[i].keysegs;
|
||||||
max_records);
|
if (keydef[i].algorithm == HA_KEY_ALG_BTREE)
|
||||||
|
{
|
||||||
|
init_tree(&keyinfo->rb_tree, 0, 0, keydef[i].length +
|
||||||
|
keydef[i].rb_tree.size_of_element,
|
||||||
|
(qsort_cmp2)keys_compare, 1, NULL, NULL);
|
||||||
|
keyinfo->delete_key = hp_rb_delete_key;
|
||||||
|
keyinfo->write_key = hp_rb_write_key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
init_block(&keyinfo->block, sizeof(HASH_INFO), min_records,
|
||||||
|
max_records);
|
||||||
|
keyinfo->delete_key = hp_delete_key;
|
||||||
|
keyinfo->write_key = hp_write_key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
share->min_records=min_records;
|
share->min_records=min_records;
|
||||||
@ -99,7 +129,7 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
|
|||||||
heap_share_list=list_add(heap_share_list,&share->open_list);
|
heap_share_list=list_add(heap_share_list,&share->open_list);
|
||||||
}
|
}
|
||||||
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
|
if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO)+
|
||||||
share->max_key_length,
|
2 * share->max_key_length,
|
||||||
MYF(MY_ZEROFILL))))
|
MYF(MY_ZEROFILL))))
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&THR_LOCK_heap);
|
pthread_mutex_unlock(&THR_LOCK_heap);
|
||||||
@ -115,6 +145,7 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
|
|||||||
|
|
||||||
info->s=share;
|
info->s=share;
|
||||||
info->lastkey=(byte*) (info+1);
|
info->lastkey=(byte*) (info+1);
|
||||||
|
info->recbuf = (byte*) (info->lastkey + share->max_key_length);
|
||||||
info->mode=mode;
|
info->mode=mode;
|
||||||
info->current_record= (ulong) ~0L; /* No current record */
|
info->current_record= (ulong) ~0L; /* No current record */
|
||||||
info->current_ptr=0;
|
info->current_ptr=0;
|
||||||
@ -132,7 +163,7 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
|
|||||||
|
|
||||||
/* map name to a heap-nr. If name isn't found return 0 */
|
/* map name to a heap-nr. If name isn't found return 0 */
|
||||||
|
|
||||||
HP_SHARE *_hp_find_named_heap(const char *name)
|
HP_SHARE *hp_find_named_heap(const char *name)
|
||||||
{
|
{
|
||||||
LIST *pos;
|
LIST *pos;
|
||||||
HP_SHARE *info;
|
HP_SHARE *info;
|
||||||
|
@ -31,7 +31,7 @@ int heap_panic(enum ha_panic_function flag)
|
|||||||
next_open=element->next; /* Save if close */
|
next_open=element->next; /* Save if close */
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case HA_PANIC_CLOSE:
|
case HA_PANIC_CLOSE:
|
||||||
_hp_close(info);
|
hp_close(info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -45,7 +45,7 @@ int heap_panic(enum ha_panic_function flag)
|
|||||||
case HA_PANIC_CLOSE:
|
case HA_PANIC_CLOSE:
|
||||||
{
|
{
|
||||||
if (!share->open_count)
|
if (!share->open_count)
|
||||||
_hp_free(share);
|
hp_free(share);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -27,7 +27,7 @@ int heap_rename(const char *old_name, const char *new_name)
|
|||||||
DBUG_ENTER("heap_rename");
|
DBUG_ENTER("heap_rename");
|
||||||
|
|
||||||
pthread_mutex_lock(&THR_LOCK_heap);
|
pthread_mutex_lock(&THR_LOCK_heap);
|
||||||
if ((info=_hp_find_named_heap(old_name)))
|
if ((info = hp_find_named_heap(old_name)))
|
||||||
{
|
{
|
||||||
if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
|
if (!(name_buff=(char*) my_strdup(new_name,MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
|
@ -20,14 +20,39 @@
|
|||||||
|
|
||||||
int heap_rfirst(HP_INFO *info, byte *record)
|
int heap_rfirst(HP_INFO *info, byte *record)
|
||||||
{
|
{
|
||||||
|
HP_SHARE *share = info->s;
|
||||||
|
HP_KEYDEF *keyinfo = share->keydef + info->lastinx;
|
||||||
|
|
||||||
DBUG_ENTER("heap_rfirst");
|
DBUG_ENTER("heap_rfirst");
|
||||||
if (!(info->s->records))
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
{
|
{
|
||||||
my_errno=HA_ERR_END_OF_FILE;
|
byte *pos;
|
||||||
DBUG_RETURN(my_errno);
|
|
||||||
|
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
|
||||||
|
&info->last_pos, offsetof(TREE_ELEMENT, left))))
|
||||||
|
{
|
||||||
|
memcpy(&pos, pos + keyinfo->ref_offs, sizeof(byte*));
|
||||||
|
info->current_ptr = pos;
|
||||||
|
memcpy(record, pos, (size_t)share->reclength);
|
||||||
|
info->update = HA_STATE_AKTIV;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_errno = HA_ERR_END_OF_FILE;
|
||||||
|
DBUG_RETURN(my_errno);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(info->s->records))
|
||||||
|
{
|
||||||
|
my_errno=HA_ERR_END_OF_FILE;
|
||||||
|
DBUG_RETURN(my_errno);
|
||||||
|
}
|
||||||
|
info->current_record=0;
|
||||||
|
info->current_hash_ptr=0;
|
||||||
|
info->update=HA_STATE_PREV_FOUND;
|
||||||
|
DBUG_RETURN(heap_rnext(info,record));
|
||||||
}
|
}
|
||||||
info->current_record=0;
|
|
||||||
info->current_hash_ptr=0;
|
|
||||||
info->update=HA_STATE_PREV_FOUND;
|
|
||||||
DBUG_RETURN(heap_rnext(info,record));
|
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
#include "heapdef.h"
|
#include "heapdef.h"
|
||||||
|
|
||||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
|
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||||
|
uint key_len, enum ha_rkey_function find_flag)
|
||||||
{
|
{
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
|
HP_KEYDEF *keyinfo = share->keydef+inx;
|
||||||
DBUG_ENTER("heap_rkey");
|
DBUG_ENTER("heap_rkey");
|
||||||
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
|
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
|
||||||
|
|
||||||
@ -30,15 +32,44 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
|
|||||||
info->lastinx=inx;
|
info->lastinx=inx;
|
||||||
info->current_record = (ulong) ~0L; /* For heap_rrnd() */
|
info->current_record = (ulong) ~0L; /* For heap_rrnd() */
|
||||||
|
|
||||||
if (!(pos=_hp_search(info,share->keydef+inx,key,0)))
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
{
|
{
|
||||||
info->update=0;
|
heap_rb_param custom_arg;
|
||||||
DBUG_RETURN(my_errno);
|
|
||||||
|
hp_rb_pack_key(info, inx, info->recbuf, key, key_len);
|
||||||
|
|
||||||
|
custom_arg.keyseg = info->s->keydef[inx].seg;
|
||||||
|
custom_arg.key_length = key_len;
|
||||||
|
custom_arg.search_flag = SEARCH_FIND | SEARCH_SAME;
|
||||||
|
/* for next rkey() after deletion */
|
||||||
|
if (find_flag == HA_READ_AFTER_KEY)
|
||||||
|
info->last_find_flag = HA_READ_KEY_OR_NEXT;
|
||||||
|
else if (find_flag == HA_READ_BEFORE_KEY)
|
||||||
|
info->last_find_flag = HA_READ_KEY_OR_PREV;
|
||||||
|
else
|
||||||
|
info->last_find_flag = find_flag;
|
||||||
|
info->lastkey_len = key_len;
|
||||||
|
if (!(pos = tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents,
|
||||||
|
&info->last_pos, find_flag, &custom_arg)))
|
||||||
|
{
|
||||||
|
info->update = 0;
|
||||||
|
DBUG_RETURN(my_errno = HA_ERR_KEY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
memcpy(&pos, pos + keyinfo->ref_offs, sizeof(byte*));
|
||||||
|
info->current_ptr = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(pos=hp_search(info,share->keydef+inx,key,0)))
|
||||||
|
{
|
||||||
|
info->update=0;
|
||||||
|
DBUG_RETURN(my_errno);
|
||||||
|
}
|
||||||
|
if (!(keyinfo->flag & HA_NOSAME))
|
||||||
|
memcpy(info->lastkey,key,(size_t) keyinfo->length);
|
||||||
}
|
}
|
||||||
memcpy(record,pos,(size_t) share->reclength);
|
memcpy(record,pos,(size_t) share->reclength);
|
||||||
info->update=HA_STATE_AKTIV;
|
info->update=HA_STATE_AKTIV;
|
||||||
if (!(share->keydef[inx].flag & HA_NOSAME))
|
|
||||||
memcpy(info->lastkey,key,(size_t) share->keydef[inx].length);
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,5 +78,5 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key)
|
|||||||
|
|
||||||
gptr heap_find(HP_INFO *info, int inx, const byte *key)
|
gptr heap_find(HP_INFO *info, int inx, const byte *key)
|
||||||
{
|
{
|
||||||
return _hp_search(info,info->s->keydef+inx,key,0);
|
return hp_search(info, info->s->keydef + inx, key, 0);
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,37 @@
|
|||||||
|
|
||||||
int heap_rlast(HP_INFO *info, byte *record)
|
int heap_rlast(HP_INFO *info, byte *record)
|
||||||
{
|
{
|
||||||
|
HP_SHARE *share = info->s;
|
||||||
|
HP_KEYDEF *keyinfo;
|
||||||
|
|
||||||
DBUG_ENTER("heap_rlast");
|
DBUG_ENTER("heap_rlast");
|
||||||
info->current_ptr=0;
|
if (info->lastinx < 0)
|
||||||
info->current_hash_ptr=0;
|
DBUG_RETURN(my_errno = HA_ERR_WRONG_INDEX);
|
||||||
info->update=HA_STATE_NEXT_FOUND;
|
keyinfo = share->keydef + info->lastinx;
|
||||||
DBUG_RETURN(heap_rprev(info,record));
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
|
{
|
||||||
|
byte *pos;
|
||||||
|
|
||||||
|
if ((pos = tree_search_edge(&keyinfo->rb_tree, info->parents,
|
||||||
|
&info->last_pos, offsetof(TREE_ELEMENT, right))))
|
||||||
|
{
|
||||||
|
memcpy(&pos, pos + keyinfo->ref_offs, sizeof(byte*));
|
||||||
|
info->current_ptr = pos;
|
||||||
|
memcpy(record, pos, (size_t)share->reclength);
|
||||||
|
info->update = HA_STATE_AKTIV;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_errno = HA_ERR_END_OF_FILE;
|
||||||
|
DBUG_RETURN(my_errno);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->current_ptr=0;
|
||||||
|
info->current_hash_ptr=0;
|
||||||
|
info->update=HA_STATE_NEXT_FOUND;
|
||||||
|
DBUG_RETURN(heap_rprev(info,record));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,27 +22,57 @@ int heap_rnext(HP_INFO *info, byte *record)
|
|||||||
{
|
{
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
|
HP_KEYDEF *keyinfo;
|
||||||
DBUG_ENTER("heap_rnext");
|
DBUG_ENTER("heap_rnext");
|
||||||
|
|
||||||
if (info->lastinx < 0)
|
if (info->lastinx < 0)
|
||||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||||
|
|
||||||
if (info->current_hash_ptr)
|
keyinfo = share->keydef + info->lastinx;
|
||||||
pos= _hp_search_next(info,share->keydef+info->lastinx, info->lastkey,
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
info->current_hash_ptr);
|
{
|
||||||
|
heap_rb_param custom_arg;
|
||||||
|
|
||||||
|
if (info->last_pos)
|
||||||
|
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
||||||
|
offsetof(TREE_ELEMENT, left),
|
||||||
|
offsetof(TREE_ELEMENT, right));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
custom_arg.keyseg = keyinfo->seg;
|
||||||
|
custom_arg.key_length = info->lastkey_len;
|
||||||
|
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
|
||||||
|
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
|
||||||
|
&info->last_pos, info->last_find_flag, &custom_arg);
|
||||||
|
}
|
||||||
|
if (pos)
|
||||||
|
{
|
||||||
|
memcpy(&pos, pos + keyinfo->ref_offs, sizeof(byte*));
|
||||||
|
info->current_ptr = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_errno = HA_ERR_KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
|
if (info->current_hash_ptr)
|
||||||
{
|
pos= hp_search_next(info, keyinfo, info->lastkey,
|
||||||
pos=0; /* Read next after last */
|
info->current_hash_ptr);
|
||||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
|
||||||
}
|
|
||||||
else if (!info->current_ptr) /* Deleted or first call */
|
|
||||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 0);
|
|
||||||
else
|
else
|
||||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 1);
|
{
|
||||||
|
if (!info->current_ptr && (info->update & HA_STATE_NEXT_FOUND))
|
||||||
|
{
|
||||||
|
pos=0; /* Read next after last */
|
||||||
|
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else if (!info->current_ptr) /* Deleted or first call */
|
||||||
|
pos= hp_search(info, keyinfo, info->lastkey, 0);
|
||||||
|
else
|
||||||
|
pos= hp_search(info, keyinfo, info->lastkey, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pos)
|
if (!pos)
|
||||||
{
|
{
|
||||||
info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
|
info->update=HA_STATE_NEXT_FOUND; /* For heap_rprev */
|
||||||
|
@ -23,22 +23,52 @@ int heap_rprev(HP_INFO *info, byte *record)
|
|||||||
{
|
{
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
|
HP_KEYDEF *keyinfo;
|
||||||
DBUG_ENTER("heap_rprev");
|
DBUG_ENTER("heap_rprev");
|
||||||
|
|
||||||
if (info->lastinx < 0)
|
if (info->lastinx < 0)
|
||||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||||
|
keyinfo = share->keydef + info->lastinx;
|
||||||
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
|
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
|
||||||
{
|
{
|
||||||
if ((info->update & HA_STATE_DELETED))
|
heap_rb_param custom_arg;
|
||||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 3);
|
|
||||||
|
if (info->last_pos)
|
||||||
|
pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
|
||||||
|
offsetof(TREE_ELEMENT, right),
|
||||||
|
offsetof(TREE_ELEMENT, left));
|
||||||
else
|
else
|
||||||
pos= _hp_search(info,share->keydef+info->lastinx, info->lastkey, 2);
|
{
|
||||||
|
custom_arg.keyseg = keyinfo->seg;
|
||||||
|
custom_arg.key_length = keyinfo->length;
|
||||||
|
custom_arg.search_flag = SEARCH_SAME;
|
||||||
|
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
|
||||||
|
&info->last_pos, info->last_find_flag, &custom_arg);
|
||||||
|
}
|
||||||
|
if (pos)
|
||||||
|
{
|
||||||
|
memcpy(&pos, pos + keyinfo->ref_offs, sizeof(byte*));
|
||||||
|
info->current_ptr = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_errno = HA_ERR_KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos=0; /* Read next after last */
|
if (info->current_ptr || (info->update & HA_STATE_NEXT_FOUND))
|
||||||
my_errno=HA_ERR_KEY_NOT_FOUND;
|
{
|
||||||
|
if ((info->update & HA_STATE_DELETED))
|
||||||
|
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 3);
|
||||||
|
else
|
||||||
|
pos= hp_search(info, share->keydef + info->lastinx, info->lastkey, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos=0; /* Read next after last */
|
||||||
|
my_errno=HA_ERR_KEY_NOT_FOUND;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!pos)
|
if (!pos)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find record number pos */
|
/* Find record number pos */
|
||||||
_hp_find_record(info,pos);
|
hp_find_record(info, pos);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (!info->current_ptr[share->reclength])
|
if (!info->current_ptr[share->reclength])
|
||||||
|
@ -41,8 +41,8 @@ int heap_rsame(register HP_INFO *info, byte *record, int inx)
|
|||||||
else if (inx != -1)
|
else if (inx != -1)
|
||||||
{
|
{
|
||||||
info->lastinx=inx;
|
info->lastinx=inx;
|
||||||
_hp_make_key(share->keydef+inx,info->lastkey,record);
|
hp_make_key(share->keydef + inx, info->lastkey, record);
|
||||||
if (!_hp_search(info,share->keydef+inx,info->lastkey,3))
|
if (!hp_search(info, share->keydef + inx, info->lastkey, 3))
|
||||||
{
|
{
|
||||||
info->update=0;
|
info->update=0;
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
|
@ -58,7 +58,7 @@ int heap_scan(register HP_INFO *info, byte *record)
|
|||||||
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
|
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_hp_find_record(info,pos);
|
hp_find_record(info, pos);
|
||||||
}
|
}
|
||||||
if (!info->current_ptr[share->reclength])
|
if (!info->current_ptr[share->reclength])
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ int main(int argc, char **argv)
|
|||||||
char record[128],key[32];
|
char record[128],key[32];
|
||||||
const char *filename;
|
const char *filename;
|
||||||
HP_KEYDEF keyinfo[10];
|
HP_KEYDEF keyinfo[10];
|
||||||
HP_KEYSEG keyseg[4];
|
MI_KEYSEG keyseg[4];
|
||||||
MY_INIT(argv[0]);
|
MY_INIT(argv[0]);
|
||||||
|
|
||||||
filename= "test1";
|
filename= "test1";
|
||||||
@ -85,7 +85,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (i == remove_ant) { VOID(heap_close(file)) ; return (0) ; }
|
if (i == remove_ant) { VOID(heap_close(file)) ; return (0) ; }
|
||||||
sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
|
sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
|
||||||
if ((error = heap_rkey(file,record,0,key)))
|
if ((error = heap_rkey(file,record,0,key,0,6)))
|
||||||
{
|
{
|
||||||
if (verbose || (flags[j] == 1 ||
|
if (verbose || (flags[j] == 1 ||
|
||||||
(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
|
(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
|
||||||
@ -113,7 +113,7 @@ int main(int argc, char **argv)
|
|||||||
sprintf(key,"%6d",i);
|
sprintf(key,"%6d",i);
|
||||||
bmove(record+1,key,6);
|
bmove(record+1,key,6);
|
||||||
my_errno=0;
|
my_errno=0;
|
||||||
error=heap_rkey(file,record,0,key);
|
error=heap_rkey(file,record,0,key,0,6);
|
||||||
if (verbose ||
|
if (verbose ||
|
||||||
(error == 0 && flags[i] != 1) ||
|
(error == 0 && flags[i] != 1) ||
|
||||||
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
|
(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#define SAFEMALLOC
|
#define SAFEMALLOC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "heapdef.h" /* Because of _hp_find_block */
|
#include "heapdef.h" /* Because of hp_find_block */
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define MAX_RECORDS 100000
|
#define MAX_RECORDS 100000
|
||||||
@ -61,7 +61,7 @@ int main(int argc, char *argv[])
|
|||||||
const char *filename,*filename2;
|
const char *filename,*filename2;
|
||||||
HP_INFO *file,*file2;
|
HP_INFO *file,*file2;
|
||||||
HP_KEYDEF keyinfo[MAX_KEYS];
|
HP_KEYDEF keyinfo[MAX_KEYS];
|
||||||
HP_KEYSEG keyseg[MAX_KEYS*5];
|
MI_KEYSEG keyseg[MAX_KEYS*5];
|
||||||
HEAP_PTR position;
|
HEAP_PTR position;
|
||||||
MY_INIT(argv[0]); /* init my_sys library & pthreads */
|
MY_INIT(argv[0]); /* init my_sys library & pthreads */
|
||||||
LINT_INIT(position);
|
LINT_INIT(position);
|
||||||
@ -167,14 +167,14 @@ int main(int argc, char *argv[])
|
|||||||
if (j != 0)
|
if (j != 0)
|
||||||
{
|
{
|
||||||
sprintf(key,"%6d",j);
|
sprintf(key,"%6d",j);
|
||||||
if (heap_rkey(file,record,0,key))
|
if (heap_rkey(file,record,0,key,6,0))
|
||||||
{
|
{
|
||||||
printf("can't find key1: \"%s\"\n",key);
|
printf("can't find key1: \"%s\"\n",key);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
if (file->current_ptr == _hp_find_block(&file->s->block,0) ||
|
if (file->current_ptr == hp_find_block(&file->s->block,0) ||
|
||||||
file->current_ptr == _hp_find_block(&file->s->block,1))
|
file->current_ptr == hp_find_block(&file->s->block,1))
|
||||||
continue; /* Don't remove 2 first records */
|
continue; /* Don't remove 2 first records */
|
||||||
#endif
|
#endif
|
||||||
if (heap_delete(file,record))
|
if (heap_delete(file,record))
|
||||||
@ -227,7 +227,7 @@ int main(int argc, char *argv[])
|
|||||||
if (!key1[j])
|
if (!key1[j])
|
||||||
continue;
|
continue;
|
||||||
sprintf(key,"%6d",j);
|
sprintf(key,"%6d",j);
|
||||||
if (heap_rkey(file,record,0,key))
|
if (heap_rkey(file,record,0,key,6,0))
|
||||||
{
|
{
|
||||||
printf("can't find key1: \"%s\"\n",key);
|
printf("can't find key1: \"%s\"\n",key);
|
||||||
goto err;
|
goto err;
|
||||||
@ -277,7 +277,7 @@ int main(int argc, char *argv[])
|
|||||||
printf("- Read first key - next - delete - next -> last\n");
|
printf("- Read first key - next - delete - next -> last\n");
|
||||||
DBUG_PRINT("progpos",("first - next - delete - next -> last"));
|
DBUG_PRINT("progpos",("first - next - delete - next -> last"));
|
||||||
|
|
||||||
if (heap_rkey(file,record,0,key))
|
if (heap_rkey(file,record,0,key,6,0))
|
||||||
goto err;
|
goto err;
|
||||||
if (heap_rnext(file,record3)) goto err;
|
if (heap_rnext(file,record3)) goto err;
|
||||||
if (heap_delete(file,record3)) goto err;
|
if (heap_delete(file,record3)) goto err;
|
||||||
@ -501,7 +501,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
printf("- Read through all keys with first-next-last-prev\n");
|
printf("- Read through all keys with first-next-last-prev\n");
|
||||||
ant=0;
|
ant=0;
|
||||||
for (error=heap_rkey(file,record,0,key) ;
|
for (error=heap_rkey(file,record,0,key,6,0);
|
||||||
! error ;
|
! error ;
|
||||||
error=heap_rnext(file,record))
|
error=heap_rnext(file,record))
|
||||||
ant++;
|
ant++;
|
||||||
@ -538,7 +538,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
{
|
{
|
||||||
if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start))
|
if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8,0))
|
||||||
{
|
{
|
||||||
printf("can't find key3: \"%.8s\"\n",
|
printf("can't find key3: \"%.8s\"\n",
|
||||||
record+keyinfo[2].seg[0].start);
|
record+keyinfo[2].seg[0].start);
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
||||||
{
|
{
|
||||||
uint key;
|
HP_KEYDEF *keydef, *end, *p_lastinx;
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
DBUG_ENTER("heap_update");
|
DBUG_ENTER("heap_update");
|
||||||
@ -28,19 +28,20 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
|||||||
test_active(info);
|
test_active(info);
|
||||||
pos=info->current_ptr;
|
pos=info->current_ptr;
|
||||||
|
|
||||||
if (info->opt_flag & READ_CHECK_USED && _hp_rectest(info,old))
|
if (info->opt_flag & READ_CHECK_USED && hp_rectest(info,old))
|
||||||
DBUG_RETURN(my_errno); /* Record changed */
|
DBUG_RETURN(my_errno); /* Record changed */
|
||||||
if (--(share->records) < share->blength >> 1) share->blength>>= 1;
|
if (--(share->records) < share->blength >> 1) share->blength>>= 1;
|
||||||
share->changed=1;
|
share->changed=1;
|
||||||
|
|
||||||
for (key=0 ; key < share->keys ; key++)
|
p_lastinx = share->keydef + info->lastinx;
|
||||||
|
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||||
|
keydef++)
|
||||||
{
|
{
|
||||||
if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
|
if (hp_rec_key_cmp(keydef, old, heap_new))
|
||||||
{
|
{
|
||||||
if (_hp_delete_key(info,share->keydef+key,old,pos,key ==
|
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
|
||||||
(uint) info->lastinx) ||
|
(*keydef->write_key)(info, keydef, heap_new, pos))
|
||||||
_hp_write_key(share,share->keydef+key,heap_new,pos))
|
goto err;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,16 +52,27 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
|||||||
err:
|
err:
|
||||||
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
|
if (my_errno == HA_ERR_FOUND_DUPP_KEY)
|
||||||
{
|
{
|
||||||
info->errkey=key;
|
info->errkey = keydef - share->keydef;
|
||||||
do
|
if (keydef->algorithm == HA_KEY_ALG_BTREE)
|
||||||
{
|
{
|
||||||
if (_hp_rec_key_cmp(share->keydef+key,old,heap_new))
|
/* we don't need to delete non-inserted key from rb-tree */
|
||||||
|
if ((*keydef->write_key)(info, keydef, old, pos))
|
||||||
{
|
{
|
||||||
if (_hp_delete_key(info,share->keydef+key,heap_new,pos,0) ||
|
if (++(share->records) == share->blength) share->blength+= share->blength;
|
||||||
_hp_write_key(share,share->keydef+key,old,pos))
|
DBUG_RETURN(my_errno);
|
||||||
|
}
|
||||||
|
keydef--;
|
||||||
|
}
|
||||||
|
while (keydef >= share->keydef)
|
||||||
|
{
|
||||||
|
if (hp_rec_key_cmp(keydef, old, heap_new))
|
||||||
|
{
|
||||||
|
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
|
||||||
|
(*keydef->write_key)(info, keydef, old, pos))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (key-- > 0);
|
keydef--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (++(share->records) == share->blength) share->blength+= share->blength;
|
if (++(share->records) == share->blength) share->blength+= share->blength;
|
||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
|
@ -27,12 +27,12 @@
|
|||||||
#define HIGHUSED 8
|
#define HIGHUSED 8
|
||||||
|
|
||||||
static byte *next_free_record_pos(HP_SHARE *info);
|
static byte *next_free_record_pos(HP_SHARE *info);
|
||||||
static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
|
static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
|
||||||
ulong records);
|
ulong records);
|
||||||
|
|
||||||
int heap_write(HP_INFO *info, const byte *record)
|
int heap_write(HP_INFO *info, const byte *record)
|
||||||
{
|
{
|
||||||
uint key;
|
HP_KEYDEF *keydef, *end;
|
||||||
byte *pos;
|
byte *pos;
|
||||||
HP_SHARE *share=info->s;
|
HP_SHARE *share=info->s;
|
||||||
DBUG_ENTER("heap_write");
|
DBUG_ENTER("heap_write");
|
||||||
@ -47,9 +47,10 @@ int heap_write(HP_INFO *info, const byte *record)
|
|||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
share->changed=1;
|
share->changed=1;
|
||||||
|
|
||||||
for (key=0 ; key < share->keys ; key++)
|
for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
|
||||||
|
keydef++)
|
||||||
{
|
{
|
||||||
if (_hp_write_key(share,share->keydef+key,record,pos))
|
if ((*keydef->write_key)(info, keydef, record, pos))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +63,19 @@ int heap_write(HP_INFO *info, const byte *record)
|
|||||||
info->update|=HA_STATE_AKTIV;
|
info->update|=HA_STATE_AKTIV;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
err:
|
err:
|
||||||
DBUG_PRINT("info",("Duplicate key: %d",key));
|
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
|
||||||
info->errkey= key;
|
info->errkey= keydef - share->keydef;
|
||||||
do
|
if (keydef->algorithm == HA_KEY_ALG_BTREE)
|
||||||
{
|
{
|
||||||
if (_hp_delete_key(info,share->keydef+key,record,pos,0))
|
/* we don't need to delete non-inserted key from rb-tree */
|
||||||
|
keydef--;
|
||||||
|
}
|
||||||
|
while (keydef >= share->keydef)
|
||||||
|
{
|
||||||
|
if ((*keydef->delete_key)(info, keydef, record, pos, 0))
|
||||||
break;
|
break;
|
||||||
} while (key-- > 0);
|
keydef--;
|
||||||
|
}
|
||||||
|
|
||||||
share->deleted++;
|
share->deleted++;
|
||||||
*((byte**) pos)=share->del_link;
|
*((byte**) pos)=share->del_link;
|
||||||
@ -77,6 +84,35 @@ err:
|
|||||||
DBUG_RETURN(my_errno);
|
DBUG_RETURN(my_errno);
|
||||||
} /* heap_write */
|
} /* heap_write */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write a key to rb_tree-index
|
||||||
|
*/
|
||||||
|
|
||||||
|
int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
|
||||||
|
byte *recpos)
|
||||||
|
{
|
||||||
|
heap_rb_param custom_arg;
|
||||||
|
|
||||||
|
info->last_pos = NULL; /* For heap_rnext/heap_rprev */
|
||||||
|
hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
|
||||||
|
custom_arg.keyseg = keyinfo->seg;
|
||||||
|
custom_arg.key_length = keyinfo->length;
|
||||||
|
if ((keyinfo->flag & HA_NOSAME) &&
|
||||||
|
(!(keyinfo->flag & HA_NULL_PART_KEY) ||
|
||||||
|
!hp_if_null_in_key(keyinfo, record)))
|
||||||
|
{
|
||||||
|
custom_arg.search_flag = SEARCH_FIND | SEARCH_SAME;
|
||||||
|
if (tree_search_key(&keyinfo->rb_tree, info->recbuf, info->parents,
|
||||||
|
&info->last_pos, 0, &custom_arg))
|
||||||
|
{
|
||||||
|
my_errno = HA_ERR_FOUND_DUPP_KEY;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
custom_arg.search_flag = SEARCH_SAME;
|
||||||
|
return tree_insert(&keyinfo->rb_tree, (void*)info->recbuf, keyinfo->length +
|
||||||
|
sizeof(byte*), &custom_arg) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find where to place new record */
|
/* Find where to place new record */
|
||||||
|
|
||||||
@ -102,7 +138,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
|
|||||||
my_errno=HA_ERR_RECORD_FILE_FULL;
|
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
if (_hp_get_new_block(&info->block,&length))
|
if (hp_get_new_block(&info->block,&length))
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
info->data_length+=length;
|
info->data_length+=length;
|
||||||
}
|
}
|
||||||
@ -113,12 +149,12 @@ static byte *next_free_record_pos(HP_SHARE *info)
|
|||||||
block_pos*info->block.recbuffer);
|
block_pos*info->block.recbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write a hash-key to the hash-index */
|
/* Write a hash-key to the hash-index */
|
||||||
|
|
||||||
int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
|
||||||
const byte *record, byte *recpos)
|
const byte *record, byte *recpos)
|
||||||
{
|
{
|
||||||
|
HP_SHARE *share = info->s;
|
||||||
int flag;
|
int flag;
|
||||||
ulong halfbuff,hashnr,first_index;
|
ulong halfbuff,hashnr,first_index;
|
||||||
byte *ptr_to_rec,*ptr_to_rec2;
|
byte *ptr_to_rec,*ptr_to_rec2;
|
||||||
@ -129,18 +165,18 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
|
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
|
||||||
|
|
||||||
flag=0;
|
flag=0;
|
||||||
if (!(empty= _hp_find_free_hash(info,&keyinfo->block,info->records)))
|
if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records)))
|
||||||
DBUG_RETURN(-1); /* No more memory */
|
DBUG_RETURN(-1); /* No more memory */
|
||||||
halfbuff= (long) info->blength >> 1;
|
halfbuff= (long) share->blength >> 1;
|
||||||
pos= hp_find_hash(&keyinfo->block,(first_index=info->records-halfbuff));
|
pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
|
||||||
|
|
||||||
if (pos != empty) /* If some records */
|
if (pos != empty) /* If some records */
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
|
hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
|
||||||
if (flag == 0) /* First loop; Check if ok */
|
if (flag == 0) /* First loop; Check if ok */
|
||||||
if (_hp_mask(hashnr,info->blength,info->records) != first_index)
|
if (hp_mask(hashnr, share->blength, share->records) != first_index)
|
||||||
break;
|
break;
|
||||||
if (!(hashnr & halfbuff))
|
if (!(hashnr & halfbuff))
|
||||||
{ /* Key will not move */
|
{ /* Key will not move */
|
||||||
@ -212,8 +248,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
}
|
}
|
||||||
/* Check if we are at the empty position */
|
/* Check if we are at the empty position */
|
||||||
|
|
||||||
pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_rec_hashnr(keyinfo,record),
|
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
|
||||||
info->blength,info->records+1));
|
share->blength, share->records + 1));
|
||||||
if (pos == empty)
|
if (pos == empty)
|
||||||
{
|
{
|
||||||
pos->ptr_to_rec=recpos;
|
pos->ptr_to_rec=recpos;
|
||||||
@ -224,8 +260,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
/* Check if more records in same hash-nr family */
|
/* Check if more records in same hash-nr family */
|
||||||
empty[0]=pos[0];
|
empty[0]=pos[0];
|
||||||
gpos=hp_find_hash(&keyinfo->block,
|
gpos=hp_find_hash(&keyinfo->block,
|
||||||
_hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
|
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
|
||||||
info->blength,info->records+1));
|
share->blength, share->records + 1));
|
||||||
if (pos == gpos)
|
if (pos == gpos)
|
||||||
{
|
{
|
||||||
pos->ptr_to_rec=recpos;
|
pos->ptr_to_rec=recpos;
|
||||||
@ -235,7 +271,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
{
|
{
|
||||||
pos->ptr_to_rec=recpos;
|
pos->ptr_to_rec=recpos;
|
||||||
pos->next_key=0;
|
pos->next_key=0;
|
||||||
_hp_movelink(pos,gpos,empty);
|
hp_movelink(pos, gpos, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if duplicated keys */
|
/* Check if duplicated keys */
|
||||||
@ -246,7 +282,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
pos=empty;
|
pos=empty;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (! _hp_rec_key_cmp(keyinfo,record,pos->ptr_to_rec))
|
if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
|
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
|
||||||
}
|
}
|
||||||
@ -258,7 +294,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
|
|||||||
|
|
||||||
/* Returns ptr to block, and allocates block if neaded */
|
/* Returns ptr to block, and allocates block if neaded */
|
||||||
|
|
||||||
static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
|
static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
|
||||||
HP_BLOCK *block, ulong records)
|
HP_BLOCK *block, ulong records)
|
||||||
{
|
{
|
||||||
uint block_pos;
|
uint block_pos;
|
||||||
@ -268,7 +304,7 @@ static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
|
|||||||
return hp_find_hash(block,records);
|
return hp_find_hash(block,records);
|
||||||
if (!(block_pos=(records % block->records_in_block)))
|
if (!(block_pos=(records % block->records_in_block)))
|
||||||
{
|
{
|
||||||
if (_hp_get_new_block(block,&length))
|
if (hp_get_new_block(block,&length))
|
||||||
return(NULL);
|
return(NULL);
|
||||||
info->index_length+=length;
|
info->index_length+=length;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ noinst_HEADERS = config-win.h \
|
|||||||
my_nosys.h my_alarm.h queues.h \
|
my_nosys.h my_alarm.h queues.h \
|
||||||
my_tree.h hash.h thr_alarm.h thr_lock.h \
|
my_tree.h hash.h thr_alarm.h thr_lock.h \
|
||||||
getopt.h my_getopt.h t_ctype.h violite.h md5.h \
|
getopt.h my_getopt.h t_ctype.h violite.h md5.h \
|
||||||
mysql_version.h.in
|
my_handler.h mysql_version.h.in
|
||||||
|
|
||||||
# mysql_version.h are generated
|
# mysql_version.h are generated
|
||||||
SUPERCLEANFILES = mysql_version.h my_config.h
|
SUPERCLEANFILES = mysql_version.h my_config.h
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
/* This file should be included when using heap_database_funktions */
|
/* This file should be included when using heap_database_functions */
|
||||||
/* Author: Michael Widenius */
|
/* Author: Michael Widenius */
|
||||||
|
|
||||||
#ifndef _heap_h
|
#ifndef _heap_h
|
||||||
@ -31,6 +31,9 @@ extern "C" {
|
|||||||
#include <thr_lock.h>
|
#include <thr_lock.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "my_handler.h"
|
||||||
|
#include "my_tree.h"
|
||||||
|
|
||||||
/* defines used by heap-funktions */
|
/* defines used by heap-funktions */
|
||||||
|
|
||||||
#define HP_MAX_LEVELS 4 /* 128^5 records is enough */
|
#define HP_MAX_LEVELS 4 /* 128^5 records is enough */
|
||||||
@ -73,22 +76,22 @@ typedef struct st_heap_block /* The data is saved in blocks */
|
|||||||
ulong last_allocated; /* Blocks allocated, used by keys */
|
ulong last_allocated; /* Blocks allocated, used by keys */
|
||||||
} HP_BLOCK;
|
} HP_BLOCK;
|
||||||
|
|
||||||
typedef struct st_hp_keyseg /* Key-portion */
|
struct st_heap_info; /* For referense */
|
||||||
{
|
|
||||||
uint start; /* Start of key in record (from 0) */
|
|
||||||
uint length; /* Keylength */
|
|
||||||
uint type;
|
|
||||||
uint null_bit; /* bit set in row+null_pos */
|
|
||||||
uint null_pos;
|
|
||||||
} HP_KEYSEG;
|
|
||||||
|
|
||||||
typedef struct st_hp_keydef /* Key definition with open */
|
typedef struct st_hp_keydef /* Key definition with open */
|
||||||
{
|
{
|
||||||
uint flag; /* HA_NOSAME |<7C>HA_NULL_PART_KEY */
|
uint flag; /* HA_NOSAME |<7C>HA_NULL_PART_KEY */
|
||||||
uint keysegs; /* Number of key-segment */
|
uint keysegs; /* Number of key-segment */
|
||||||
uint length; /* Length of key (automatic) */
|
uint length; /* Length of key (automatic) */
|
||||||
HP_KEYSEG *seg;
|
uint8 algorithm; /* HASH / BTREE */
|
||||||
|
uint ref_offs; /* Data reference offset */
|
||||||
|
MI_KEYSEG *seg;
|
||||||
HP_BLOCK block; /* Where keys are saved */
|
HP_BLOCK block; /* Where keys are saved */
|
||||||
|
TREE rb_tree;
|
||||||
|
int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
|
||||||
|
const byte *record, byte *recpos);
|
||||||
|
int (*delete_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
|
||||||
|
const byte *record, byte *recpos, int flag);
|
||||||
} HP_KEYDEF;
|
} HP_KEYDEF;
|
||||||
|
|
||||||
typedef struct st_heap_share
|
typedef struct st_heap_share
|
||||||
@ -126,6 +129,11 @@ typedef struct st_heap_info
|
|||||||
int mode; /* Mode of file (READONLY..) */
|
int mode; /* Mode of file (READONLY..) */
|
||||||
uint opt_flag,update;
|
uint opt_flag,update;
|
||||||
byte *lastkey; /* Last used key with rkey */
|
byte *lastkey; /* Last used key with rkey */
|
||||||
|
byte *recbuf; /* Record buffer for rb-tree keys */
|
||||||
|
enum ha_rkey_function last_find_flag;
|
||||||
|
TREE_ELEMENT *parents[MAX_TREE_HIGHT+1];
|
||||||
|
TREE_ELEMENT **last_pos;
|
||||||
|
uint lastkey_len;
|
||||||
#ifdef THREAD
|
#ifdef THREAD
|
||||||
THR_LOCK_DATA lock;
|
THR_LOCK_DATA lock;
|
||||||
#endif
|
#endif
|
||||||
@ -156,7 +164,14 @@ extern int heap_rprev(HP_INFO *info,byte *record);
|
|||||||
extern int heap_rfirst(HP_INFO *info,byte *record);
|
extern int heap_rfirst(HP_INFO *info,byte *record);
|
||||||
extern int heap_rlast(HP_INFO *info,byte *record);
|
extern int heap_rlast(HP_INFO *info,byte *record);
|
||||||
extern void heap_clear(HP_INFO *info);
|
extern void heap_clear(HP_INFO *info);
|
||||||
extern int heap_rkey(HP_INFO *info,byte *record,int inx,const byte *key);
|
|
||||||
|
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, const byte *start_key,
|
||||||
|
uint start_key_len,
|
||||||
|
enum ha_rkey_function start_search_flag,
|
||||||
|
const byte *end_key, uint end_key_len,
|
||||||
|
enum ha_rkey_function end_search_flag);
|
||||||
|
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||||
|
uint key_len, enum ha_rkey_function find_flag);
|
||||||
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
|
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
|
||||||
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
|
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
|
||||||
extern byte *heap_position(HP_INFO *info);
|
extern byte *heap_position(HP_INFO *info);
|
||||||
|
63
include/my_handler.h
Normal file
63
include/my_handler.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
MA 02111-1307, USA */
|
||||||
|
|
||||||
|
#ifndef _my_handler_h
|
||||||
|
#define _my_handler_h
|
||||||
|
|
||||||
|
#include "my_global.h"
|
||||||
|
#include "my_base.h"
|
||||||
|
#include "m_ctype.h"
|
||||||
|
#include "myisampack.h"
|
||||||
|
|
||||||
|
typedef struct st_MI_KEYSEG /* Key-portion */
|
||||||
|
{
|
||||||
|
uint8 type; /* Type of key (for sort) */
|
||||||
|
uint8 language;
|
||||||
|
uint8 null_bit; /* bitmask to test for NULL */
|
||||||
|
uint8 bit_start,bit_end; /* if bit field */
|
||||||
|
uint16 flag;
|
||||||
|
uint16 length; /* Keylength */
|
||||||
|
uint32 start; /* Start of key in record */
|
||||||
|
uint32 null_pos; /* position to NULL indicator */
|
||||||
|
CHARSET_INFO *charset;
|
||||||
|
} MI_KEYSEG;
|
||||||
|
|
||||||
|
#define get_key_length(length,key) \
|
||||||
|
{ if ((uchar) *(key) != 255) \
|
||||||
|
length= (uint) (uchar) *((key)++); \
|
||||||
|
else \
|
||||||
|
{ length=mi_uint2korr((key)+1); (key)+=3; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define get_key_pack_length(length,length_pack,key) \
|
||||||
|
{ if ((uchar) *(key) != 255) \
|
||||||
|
{ length= (uint) (uchar) *((key)++); length_pack=1; }\
|
||||||
|
else \
|
||||||
|
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int _mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
|
||||||
|
my_bool);
|
||||||
|
extern int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
||||||
|
register uchar *b, uint key_length, uint nextflag,
|
||||||
|
uint *diff_pos);
|
||||||
|
|
||||||
|
extern int hp_rb_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
||||||
|
register uchar *b, uint key_length, uint nextflag,
|
||||||
|
uint *diff_pos);
|
||||||
|
|
||||||
|
#endif /* _my_handler_h */
|
@ -48,6 +48,8 @@ typedef struct st_tree_element {
|
|||||||
} TREE_ELEMENT;
|
} TREE_ELEMENT;
|
||||||
#endif /* MSDOS */
|
#endif /* MSDOS */
|
||||||
|
|
||||||
|
#define ELEMENT_CHILD(element, offs) (*(TREE_ELEMENT**)((char*)element + offs))
|
||||||
|
|
||||||
typedef struct st_tree {
|
typedef struct st_tree {
|
||||||
TREE_ELEMENT *root,null_element;
|
TREE_ELEMENT *root,null_element;
|
||||||
TREE_ELEMENT **parents[MAX_TREE_HIGHT];
|
TREE_ELEMENT **parents[MAX_TREE_HIGHT];
|
||||||
@ -70,12 +72,22 @@ void reset_tree(TREE*);
|
|||||||
#define is_tree_inited(tree) ((tree)->root != 0)
|
#define is_tree_inited(tree) ((tree)->root != 0)
|
||||||
|
|
||||||
/* Functions on leafs */
|
/* Functions on leafs */
|
||||||
TREE_ELEMENT *tree_insert(TREE *tree,void *key,uint key_size);
|
TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
|
||||||
void *tree_search(TREE *tree,void *key);
|
void *custom_arg);
|
||||||
|
void *tree_search(TREE *tree, void *key, void *custom_arg);
|
||||||
int tree_walk(TREE *tree,tree_walk_action action,
|
int tree_walk(TREE *tree,tree_walk_action action,
|
||||||
void *argument, TREE_WALK visit);
|
void *argument, TREE_WALK visit);
|
||||||
int tree_delete(TREE *tree,void *key);
|
int tree_delete(TREE *tree, void *key, void *custom_arg);
|
||||||
|
|
||||||
|
void *tree_search_key(TREE *tree, const void *key,
|
||||||
|
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
|
||||||
|
enum ha_rkey_function flag, void *custom_arg);
|
||||||
|
void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
|
||||||
|
TREE_ELEMENT ***last_pos, int child_offs);
|
||||||
|
void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
|
||||||
|
int r_offs);
|
||||||
|
uint tree_record_pos(TREE *tree, const void *key,
|
||||||
|
enum ha_rkey_function search_flag, void *custom_arg);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,6 +28,7 @@ extern "C" {
|
|||||||
#ifndef _m_ctype_h
|
#ifndef _m_ctype_h
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "my_handler.h"
|
||||||
|
|
||||||
/* defines used by myisam-funktions */
|
/* defines used by myisam-funktions */
|
||||||
|
|
||||||
@ -105,20 +106,6 @@ typedef struct st_mi_create_info
|
|||||||
struct st_myisam_info; /* For referense */
|
struct st_myisam_info; /* For referense */
|
||||||
typedef struct st_myisam_info MI_INFO;
|
typedef struct st_myisam_info MI_INFO;
|
||||||
|
|
||||||
typedef struct st_mi_keyseg /* Key-portion */
|
|
||||||
{
|
|
||||||
uint8 type; /* Type of key (for sort) */
|
|
||||||
uint8 language;
|
|
||||||
uint8 null_bit; /* bitmask to test for NULL */
|
|
||||||
uint8 bit_start,bit_end; /* if bit field */
|
|
||||||
uint16 flag;
|
|
||||||
uint16 length; /* Keylength */
|
|
||||||
uint32 start; /* Start of key in record */
|
|
||||||
uint32 null_pos; /* position to NULL indicator */
|
|
||||||
CHARSET_INFO *charset;
|
|
||||||
} MI_KEYSEG;
|
|
||||||
|
|
||||||
|
|
||||||
struct st_mi_s_param;
|
struct st_mi_s_param;
|
||||||
|
|
||||||
typedef struct st_mi_keydef /* Key definition with open & info */
|
typedef struct st_mi_keydef /* Key definition with open & info */
|
||||||
|
@ -342,7 +342,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
file_info.process=0;
|
file_info.process=0;
|
||||||
result=uint2korr(head+7);
|
result=uint2korr(head+7);
|
||||||
if ((curr_file_info=(struct isamlog_file_info*)
|
if ((curr_file_info=(struct isamlog_file_info*)
|
||||||
tree_search(&tree,&file_info)))
|
tree_search(&tree, &file_info, tree.custom_arg)))
|
||||||
{
|
{
|
||||||
curr_file_info->accessed=access_time;
|
curr_file_info->accessed=access_time;
|
||||||
if (update && curr_file_info->used && curr_file_info->closed)
|
if (update && curr_file_info->used && curr_file_info->closed)
|
||||||
@ -444,7 +444,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
files_open++;
|
files_open++;
|
||||||
file_info.closed=0;
|
file_info.closed=0;
|
||||||
}
|
}
|
||||||
VOID(tree_insert(&tree,(gptr) &file_info,0));
|
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
|
||||||
if (file_info.used)
|
if (file_info.used)
|
||||||
{
|
{
|
||||||
if (verbose && !record_pos_file)
|
if (verbose && !record_pos_file)
|
||||||
@ -463,7 +463,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
{
|
{
|
||||||
if (!curr_file_info->closed)
|
if (!curr_file_info->closed)
|
||||||
files_open--;
|
files_open--;
|
||||||
VOID(tree_delete(&tree,(gptr) curr_file_info));
|
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOG_EXTRA:
|
case LOG_EXTRA:
|
||||||
|
@ -762,7 +762,8 @@ static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
|
|||||||
if (count->tree_buff)
|
if (count->tree_buff)
|
||||||
{
|
{
|
||||||
global_count=count;
|
global_count=count;
|
||||||
if (!(element=tree_insert(&count->int_tree,pos,0)) ||
|
if (!(element=tree_insert(&count->int_tree, pos, 0,
|
||||||
|
count->int_tree.custom_arg)) ||
|
||||||
((element->count == 1 &&
|
((element->count == 1 &&
|
||||||
count->tree_buff + tree_buff_length <
|
count->tree_buff + tree_buff_length <
|
||||||
count->tree_pos + count->field_length) ||
|
count->tree_pos + count->field_length) ||
|
||||||
@ -1733,7 +1734,8 @@ static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||||||
break;
|
break;
|
||||||
case FIELD_INTERVALL:
|
case FIELD_INTERVALL:
|
||||||
global_count=count;
|
global_count=count;
|
||||||
pos=(byte*) tree_search(&count->int_tree,start_pos);
|
pos=(byte*) tree_search(&count->int_tree, start_pos,
|
||||||
|
count->int_tree.custom_arg);
|
||||||
intervall=(uint) (pos - count->tree_buff)/field_length;
|
intervall=(uint) (pos - count->tree_buff)/field_length;
|
||||||
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
|
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
|
||||||
start_pos=end_pos;
|
start_pos=end_pos;
|
||||||
|
@ -115,7 +115,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
|
|||||||
sdoc.doc.dpos=aio->info->lastpos;
|
sdoc.doc.dpos=aio->info->lastpos;
|
||||||
|
|
||||||
/* saving document matched into dtree */
|
/* saving document matched into dtree */
|
||||||
if(!(selem=tree_insert(&aio->dtree, &sdoc, 0))) return 1;
|
if(!(selem=tree_insert(&aio->dtree, &sdoc, 0, aio->dtree.custom_arg))) return 1;
|
||||||
|
|
||||||
sptr=(FT_SUPERDOC *)ELEMENT_KEY((&aio->dtree), selem);
|
sptr=(FT_SUPERDOC *)ELEMENT_KEY((&aio->dtree), selem);
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ int ft_parse(TREE *wtree, byte *doc, int doclen)
|
|||||||
|
|
||||||
while (ft_simple_get_word(&doc,end,&w))
|
while (ft_simple_get_word(&doc,end,&w))
|
||||||
{
|
{
|
||||||
if (!tree_insert(wtree, &w, 0))
|
if (!tree_insert(wtree, &w, 0, wtree->custom_arg))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -50,7 +50,7 @@ int ft_init_stopwords(const char **sws)
|
|||||||
for(;*sws;sws++)
|
for(;*sws;sws++)
|
||||||
{
|
{
|
||||||
if( (sw.len= (uint) strlen(sw.pos=*sws)) < ft_min_word_len) continue;
|
if( (sw.len= (uint) strlen(sw.pos=*sws)) < ft_min_word_len) continue;
|
||||||
if(!tree_insert(stopwords3, &sw, 0))
|
if(!tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg))
|
||||||
{
|
{
|
||||||
delete_tree(stopwords3); /* purecov: inspected */
|
delete_tree(stopwords3); /* purecov: inspected */
|
||||||
return -1; /* purecov: inspected */
|
return -1; /* purecov: inspected */
|
||||||
@ -64,7 +64,7 @@ int is_stopword(char *word, uint len)
|
|||||||
FT_STOPWORD sw;
|
FT_STOPWORD sw;
|
||||||
sw.pos=word;
|
sw.pos=word;
|
||||||
sw.len=len;
|
sw.len=len;
|
||||||
return tree_search(stopwords3,&sw) != NULL;
|
return tree_search(stopwords3, &sw, stopwords3->custom_arg) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -651,388 +651,6 @@ void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
|
|||||||
} /* _mi_dpointer */
|
} /* _mi_dpointer */
|
||||||
|
|
||||||
|
|
||||||
int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
|
|
||||||
uchar *b, uint b_length, my_bool part_key)
|
|
||||||
{
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
#ifdef USE_STRCOLL
|
|
||||||
if (use_strcoll(charset_info))
|
|
||||||
{
|
|
||||||
/* QQ: This needs to work with part keys at some point */
|
|
||||||
return my_strnncoll(charset_info, a, a_length, b, b_length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
uint length= min(a_length,b_length);
|
|
||||||
uchar *end= a+ length;
|
|
||||||
uchar *sort_order=charset_info->sort_order;
|
|
||||||
while (a < end)
|
|
||||||
if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++]))
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
if (part_key && b_length < a_length)
|
|
||||||
return 0;
|
|
||||||
return (int) (a_length-b_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
|
|
||||||
my_bool part_key)
|
|
||||||
{
|
|
||||||
uint length= min(a_length,b_length);
|
|
||||||
uchar *end= a+ length;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
while (a < end)
|
|
||||||
if ((flag= (int) *a++ - (int) *b++))
|
|
||||||
return flag;
|
|
||||||
if (part_key && b_length < a_length)
|
|
||||||
return 0;
|
|
||||||
return (int) (a_length-b_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Compare two keys
|
|
||||||
** Returns <0, 0, >0 acording to which is bigger
|
|
||||||
** Key_length specifies length of key to use. Number-keys can't
|
|
||||||
** be splited
|
|
||||||
** If flag <> SEARCH_FIND compare also position
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FCMP(A,B) ((int) (A) - (int) (B))
|
|
||||||
|
|
||||||
int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
|
||||||
register uchar *b, uint key_length, uint nextflag,
|
|
||||||
uint *diff_pos)
|
|
||||||
{
|
|
||||||
int flag;
|
|
||||||
int16 s_1,s_2;
|
|
||||||
int32 l_1,l_2;
|
|
||||||
uint32 u_1,u_2;
|
|
||||||
float f_1,f_2;
|
|
||||||
double d_1,d_2;
|
|
||||||
uint next_key_length;
|
|
||||||
|
|
||||||
*diff_pos=0;
|
|
||||||
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
|
|
||||||
{
|
|
||||||
uchar *end;
|
|
||||||
uint piks=! (keyseg->flag & HA_NO_SORT);
|
|
||||||
(*diff_pos)++;
|
|
||||||
|
|
||||||
/* Handle NULL part */
|
|
||||||
if (keyseg->null_bit)
|
|
||||||
{
|
|
||||||
key_length--;
|
|
||||||
if (*a != *b && piks)
|
|
||||||
{
|
|
||||||
flag = (int) *a - (int) *b;
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
}
|
|
||||||
b++;
|
|
||||||
if (!*a++) /* If key was NULL */
|
|
||||||
{
|
|
||||||
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
|
|
||||||
nextflag=SEARCH_SAME; /* Allow duplicate keys */
|
|
||||||
next_key_length=key_length;
|
|
||||||
continue; /* To next key part */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end= a+ min(keyseg->length,key_length);
|
|
||||||
next_key_length=key_length-keyseg->length;
|
|
||||||
|
|
||||||
switch ((enum ha_base_keytype) keyseg->type) {
|
|
||||||
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
|
|
||||||
if (keyseg->flag & HA_SPACE_PACK)
|
|
||||||
{
|
|
||||||
int a_length,b_length,pack_length;
|
|
||||||
get_key_length(a_length,a);
|
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
|
||||||
next_key_length=key_length-b_length-pack_length;
|
|
||||||
|
|
||||||
if (piks &&
|
|
||||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a+=a_length;
|
|
||||||
b+=b_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint length=(uint) (end-a), a_length=length, b_length=length;
|
|
||||||
if (!(nextflag & SEARCH_PREFIX))
|
|
||||||
{
|
|
||||||
while (a_length && a[a_length-1] == ' ')
|
|
||||||
a_length--;
|
|
||||||
while (b_length && b[b_length-1] == ' ')
|
|
||||||
b_length--;
|
|
||||||
}
|
|
||||||
if (piks &&
|
|
||||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a=end;
|
|
||||||
b+=length;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_BINARY:
|
|
||||||
if (keyseg->flag & HA_SPACE_PACK)
|
|
||||||
{
|
|
||||||
int a_length,b_length,pack_length;
|
|
||||||
get_key_length(a_length,a);
|
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
|
||||||
next_key_length=key_length-b_length-pack_length;
|
|
||||||
|
|
||||||
if (piks &&
|
|
||||||
(flag=compare_bin(a,a_length,b,b_length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a+=a_length;
|
|
||||||
b+=b_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint length=keyseg->length;
|
|
||||||
if (piks &&
|
|
||||||
(flag=compare_bin(a,length,b,length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a+=length;
|
|
||||||
b+=length;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_VARTEXT:
|
|
||||||
{
|
|
||||||
int a_length,b_length,pack_length;
|
|
||||||
get_key_length(a_length,a);
|
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
|
||||||
next_key_length=key_length-b_length-pack_length;
|
|
||||||
|
|
||||||
if (piks &&
|
|
||||||
(flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a+=a_length;
|
|
||||||
b+=b_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_VARBINARY:
|
|
||||||
{
|
|
||||||
int a_length,b_length,pack_length;
|
|
||||||
get_key_length(a_length,a);
|
|
||||||
get_key_pack_length(b_length,pack_length,b);
|
|
||||||
next_key_length=key_length-b_length-pack_length;
|
|
||||||
|
|
||||||
if (piks &&
|
|
||||||
(flag=compare_bin(a,a_length,b,b_length,
|
|
||||||
(my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0))))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a+=a_length;
|
|
||||||
b+=b_length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_INT8:
|
|
||||||
{
|
|
||||||
int i_1= (int) *((signed char*) a);
|
|
||||||
int i_2= (int) *((signed char*) b);
|
|
||||||
if (piks && (flag = CMP_NUM(i_1,i_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HA_KEYTYPE_SHORT_INT:
|
|
||||||
s_1= mi_sint2korr(a);
|
|
||||||
s_2= mi_sint2korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(s_1,s_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 2; /* sizeof(short int); */
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_USHORT_INT:
|
|
||||||
{
|
|
||||||
uint16 us_1,us_2;
|
|
||||||
us_1= mi_sint2korr(a);
|
|
||||||
us_2= mi_sint2korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(us_1,us_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+=2; /* sizeof(short int); */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HA_KEYTYPE_LONG_INT:
|
|
||||||
l_1= mi_sint4korr(a);
|
|
||||||
l_2= mi_sint4korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 4; /* sizeof(long int); */
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_ULONG_INT:
|
|
||||||
u_1= mi_sint4korr(a);
|
|
||||||
u_2= mi_sint4korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(u_1,u_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 4; /* sizeof(long int); */
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_INT24:
|
|
||||||
l_1=mi_sint3korr(a);
|
|
||||||
l_2=mi_sint3korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 3;
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_UINT24:
|
|
||||||
l_1=mi_uint3korr(a);
|
|
||||||
l_2=mi_uint3korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(l_1,l_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 3;
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_FLOAT:
|
|
||||||
mi_float4get(f_1,a);
|
|
||||||
mi_float4get(f_2,b);
|
|
||||||
if (piks && (flag = CMP_NUM(f_1,f_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 4; /* sizeof(float); */
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_DOUBLE:
|
|
||||||
mi_float8get(d_1,a);
|
|
||||||
mi_float8get(d_2,b);
|
|
||||||
if (piks && (flag = CMP_NUM(d_1,d_2)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 8; /* sizeof(double); */
|
|
||||||
break;
|
|
||||||
case HA_KEYTYPE_NUM: /* Numeric key */
|
|
||||||
{
|
|
||||||
int swap_flag= 0;
|
|
||||||
int alength,blength;
|
|
||||||
|
|
||||||
if (keyseg->flag & HA_REVERSE_SORT)
|
|
||||||
{
|
|
||||||
swap(uchar*,a,b);
|
|
||||||
swap_flag=1; /* Remember swap of a & b */
|
|
||||||
end= a+ (int) (end-b);
|
|
||||||
}
|
|
||||||
if (keyseg->flag & HA_SPACE_PACK)
|
|
||||||
{
|
|
||||||
alength= *a++; blength= *b++;
|
|
||||||
end=a+alength;
|
|
||||||
next_key_length=key_length-blength-1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alength= (int) (end-a);
|
|
||||||
blength=keyseg->length;
|
|
||||||
/* remove pre space from keys */
|
|
||||||
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
|
||||||
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
|
||||||
}
|
|
||||||
if (piks)
|
|
||||||
{
|
|
||||||
if (*a == '-')
|
|
||||||
{
|
|
||||||
if (*b != '-')
|
|
||||||
return -1;
|
|
||||||
a++; b++;
|
|
||||||
swap(uchar*,a,b);
|
|
||||||
swap(int,alength,blength);
|
|
||||||
swap_flag=1-swap_flag;
|
|
||||||
alength--; blength--;
|
|
||||||
end=a+alength;
|
|
||||||
}
|
|
||||||
else if (*b == '-')
|
|
||||||
return 1;
|
|
||||||
while (alength && (*a == '+' || *a == '0'))
|
|
||||||
{
|
|
||||||
a++; alength--;
|
|
||||||
}
|
|
||||||
while (blength && (*b == '+' || *b == '0'))
|
|
||||||
{
|
|
||||||
b++; blength--;
|
|
||||||
}
|
|
||||||
if (alength != blength)
|
|
||||||
return (alength < blength) ? -1 : 1;
|
|
||||||
while (a < end)
|
|
||||||
if (*a++ != *b++)
|
|
||||||
return ((int) a[-1] - (int) b[-1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b+=(end-a);
|
|
||||||
a=end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swap_flag) /* Restore pointers */
|
|
||||||
swap(uchar*,a,b);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_LONG_LONG
|
|
||||||
case HA_KEYTYPE_LONGLONG:
|
|
||||||
{
|
|
||||||
longlong ll_a,ll_b;
|
|
||||||
ll_a= mi_sint8korr(a);
|
|
||||||
ll_b= mi_sint8korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HA_KEYTYPE_ULONGLONG:
|
|
||||||
{
|
|
||||||
ulonglong ll_a,ll_b;
|
|
||||||
ll_a= mi_uint8korr(a);
|
|
||||||
ll_b= mi_uint8korr(b);
|
|
||||||
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
|
|
||||||
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
|
||||||
a= end;
|
|
||||||
b+= 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case HA_KEYTYPE_END: /* Ready */
|
|
||||||
goto end; /* diff_pos is incremented */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*diff_pos)++;
|
|
||||||
end:
|
|
||||||
if (!(nextflag & SEARCH_FIND))
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
|
|
||||||
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
|
|
||||||
flag=0;
|
|
||||||
for (i=keyseg->length ; i-- > 0 ; )
|
|
||||||
{
|
|
||||||
if (*a++ != *b++)
|
|
||||||
{
|
|
||||||
flag= FCMP(a[-1],b[-1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nextflag & SEARCH_SAME)
|
|
||||||
return (flag); /* read same */
|
|
||||||
if (nextflag & SEARCH_BIGGER)
|
|
||||||
return (flag <= 0 ? -1 : 1); /* read next */
|
|
||||||
return (flag < 0 ? -1 : 1); /* read previous */
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} /* _mi_key_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
/* Get key from key-block */
|
/* Get key from key-block */
|
||||||
/* page points at previous key; its advanced to point at next key */
|
/* page points at previous key; its advanced to point at next key */
|
||||||
/* key should contain previous key */
|
/* key should contain previous key */
|
||||||
|
@ -753,7 +753,8 @@ int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key,
|
|||||||
DBUG_ENTER("_mi_ck_write_tree");
|
DBUG_ENTER("_mi_ck_write_tree");
|
||||||
|
|
||||||
error= tree_insert(& info->bulk_insert[keynr], key,
|
error= tree_insert(& info->bulk_insert[keynr], key,
|
||||||
key_length + info->s->rec_reflength) ? 0 : HA_ERR_OUT_OF_MEM ;
|
key_length + info->s->rec_reflength,
|
||||||
|
info->bulk_insert[keynr].custom_arg) ? 0 : HA_ERR_OUT_OF_MEM ;
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
} /* _mi_ck_write_tree */
|
} /* _mi_ck_write_tree */
|
||||||
|
@ -329,13 +329,6 @@ struct st_myisam_info {
|
|||||||
{ *(key)=255; mi_int2store((key)+1,(length)); } \
|
{ *(key)=255; mi_int2store((key)+1,(length)); } \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define get_key_length(length,key) \
|
|
||||||
{ if ((uchar) *(key) != 255) \
|
|
||||||
length= (uint) (uchar) *((key)++); \
|
|
||||||
else \
|
|
||||||
{ length=mi_uint2korr((key)+1); (key)+=3; } \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define get_key_full_length(length,key) \
|
#define get_key_full_length(length,key) \
|
||||||
{ if ((uchar) *(key) != 255) \
|
{ if ((uchar) *(key) != 255) \
|
||||||
length= ((uint) (uchar) *((key)++))+1; \
|
length= ((uint) (uchar) *((key)++))+1; \
|
||||||
@ -343,13 +336,6 @@ struct st_myisam_info {
|
|||||||
{ length=mi_uint2korr((key)+1)+3; (key)+=3; } \
|
{ length=mi_uint2korr((key)+1)+3; (key)+=3; } \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define get_key_pack_length(length,length_pack,key) \
|
|
||||||
{ if ((uchar) *(key) != 255) \
|
|
||||||
{ length= (uint) (uchar) *((key)++); length_pack=1; }\
|
|
||||||
else \
|
|
||||||
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
||||||
|
|
||||||
#define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
#define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
||||||
@ -484,8 +470,6 @@ extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
|||||||
extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
||||||
uchar *key,uint key_len,uint comp_flag,
|
uchar *key,uint key_len,uint comp_flag,
|
||||||
uchar **ret_pos,uchar *buff, my_bool *was_last_key);
|
uchar **ret_pos,uchar *buff, my_bool *was_last_key);
|
||||||
extern int _mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
|
|
||||||
my_bool);
|
|
||||||
extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key);
|
extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key);
|
||||||
extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos);
|
extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos);
|
||||||
extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key);
|
extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key);
|
||||||
|
@ -345,7 +345,8 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
if (!opt_processes)
|
if (!opt_processes)
|
||||||
file_info.process=0;
|
file_info.process=0;
|
||||||
result= mi_uint2korr(head+7);
|
result= mi_uint2korr(head+7);
|
||||||
if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info)))
|
if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
|
||||||
|
tree.custom_arg)))
|
||||||
{
|
{
|
||||||
curr_file_info->accessed=access_time;
|
curr_file_info->accessed=access_time;
|
||||||
if (update && curr_file_info->used && curr_file_info->closed)
|
if (update && curr_file_info->used && curr_file_info->closed)
|
||||||
@ -452,7 +453,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
else
|
else
|
||||||
file_info.isam->s->rnd= isamlog_process;
|
file_info.isam->s->rnd= isamlog_process;
|
||||||
}
|
}
|
||||||
VOID(tree_insert(&tree,(gptr) &file_info,0));
|
VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
|
||||||
if (file_info.used)
|
if (file_info.used)
|
||||||
{
|
{
|
||||||
if (verbose && !record_pos_file)
|
if (verbose && !record_pos_file)
|
||||||
@ -471,7 +472,7 @@ static int examine_log(my_string file_name, char **table_names)
|
|||||||
{
|
{
|
||||||
if (!curr_file_info->closed)
|
if (!curr_file_info->closed)
|
||||||
files_open--;
|
files_open--;
|
||||||
VOID(tree_delete(&tree,(gptr) curr_file_info));
|
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MI_LOG_EXTRA:
|
case MI_LOG_EXTRA:
|
||||||
|
@ -765,7 +765,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
|
|||||||
if (count->tree_buff)
|
if (count->tree_buff)
|
||||||
{
|
{
|
||||||
global_count=count;
|
global_count=count;
|
||||||
if (!(element=tree_insert(&count->int_tree,pos,0)) ||
|
if (!(element=tree_insert(&count->int_tree,pos, 0,
|
||||||
|
count->int_tree.custom_arg)) ||
|
||||||
(element->count == 1 &&
|
(element->count == 1 &&
|
||||||
count->tree_buff + tree_buff_length <
|
count->tree_buff + tree_buff_length <
|
||||||
count->tree_pos + count->field_length) ||
|
count->tree_pos + count->field_length) ||
|
||||||
@ -1788,7 +1789,8 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
|
|||||||
break;
|
break;
|
||||||
case FIELD_INTERVALL:
|
case FIELD_INTERVALL:
|
||||||
global_count=count;
|
global_count=count;
|
||||||
pos=(byte*) tree_search(&count->int_tree,start_pos);
|
pos=(byte*) tree_search(&count->int_tree, start_pos,
|
||||||
|
count->int_tree.custom_arg);
|
||||||
intervall=(uint) (pos - count->tree_buff)/field_length;
|
intervall=(uint) (pos - count->tree_buff)/field_length;
|
||||||
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
|
write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
|
||||||
start_pos=end_pos;
|
start_pos=end_pos;
|
||||||
|
205
mysql-test/r/heap_btree.result
Normal file
205
mysql-test/r/heap_btree.result
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a=1 or a=0;
|
||||||
|
show keys from t1;
|
||||||
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
|
t1 0 PRIMARY 1 a A NULL NULL NULL BTREE
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 4
|
||||||
|
select * from t1 where a=4;
|
||||||
|
a b
|
||||||
|
4 4
|
||||||
|
update t1 set b=5 where a=4;
|
||||||
|
update t1 set b=b+1 where a>=3;
|
||||||
|
replace t1 values (3,3);
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 6
|
||||||
|
alter table t1 add c int not null, add key using BTREE (c,a);
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a > 0;
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 4
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null) type=heap;
|
||||||
|
insert into t1 values (869751),(736494),(226312),(802616);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
a
|
||||||
|
869751
|
||||||
|
802616
|
||||||
|
alter table t1 add unique uniq_id using BTREE (a);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
a
|
||||||
|
802616
|
||||||
|
869751
|
||||||
|
select * from t1 where a = 736494;
|
||||||
|
a
|
||||||
|
736494
|
||||||
|
select * from t1 where a=869751 or a=736494;
|
||||||
|
a
|
||||||
|
736494
|
||||||
|
869751
|
||||||
|
select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
a
|
||||||
|
226312
|
||||||
|
736494
|
||||||
|
802616
|
||||||
|
869751
|
||||||
|
alter table t1 type=myisam;
|
||||||
|
explain select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 range uniq_id uniq_id 4 NULL 4 where used; Using index
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (x int not null, y int not null, key x using BTREE (x), unique y using BTREE (y))
|
||||||
|
type=heap;
|
||||||
|
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
|
||||||
|
select * from t1 where x=1;
|
||||||
|
x y
|
||||||
|
1 1
|
||||||
|
1 3
|
||||||
|
select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
x y x y
|
||||||
|
1 1 1 1
|
||||||
|
2 2 2 2
|
||||||
|
1 3 1 1
|
||||||
|
2 4 2 2
|
||||||
|
2 5 2 2
|
||||||
|
2 6 2 2
|
||||||
|
explain select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ALL x NULL NULL NULL 6
|
||||||
|
t2 eq_ref y y 4 t1.x 1
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int) type=heap;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(a) from t1;
|
||||||
|
max(a)
|
||||||
|
1
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using BTREE (a), key using BTREE (b) ) TYPE=HEAP;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 4
|
||||||
|
1 5
|
||||||
|
1 6
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 4
|
||||||
|
1 5
|
||||||
|
1 6
|
||||||
|
1 1
|
||||||
|
1 2
|
||||||
|
1 3
|
||||||
|
1 4
|
||||||
|
1 5
|
||||||
|
1 6
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (id int unsigned not null, primary key using BTREE (id)) type=HEAP;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(id) from t1;
|
||||||
|
max(id)
|
||||||
|
NULL
|
||||||
|
insert into t1 values(2);
|
||||||
|
select max(id) from t1;
|
||||||
|
max(id)
|
||||||
|
NULL
|
||||||
|
replace into t1 values(1);
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table if exists t1;
|
||||||
|
CREATE table t1(f1 int not null,f2 char(20) not
|
||||||
|
null,index(f2)) type=heap;
|
||||||
|
INSERT into t1 set f1=12,f2="bill";
|
||||||
|
INSERT into t1 set f1=13,f2="bill";
|
||||||
|
INSERT into t1 set f1=14,f2="bill";
|
||||||
|
INSERT into t1 set f1=15,f2="bill";
|
||||||
|
INSERT into t1 set f1=16,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
delete from t1 where f2="bill";
|
||||||
|
select * from t1;
|
||||||
|
f1 f2
|
||||||
|
16 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (btn char(10) not null, key using BTREE (btn)) type=heap;
|
||||||
|
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
|
||||||
|
explain select * from t1 where btn like "q%";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ALL btn NULL NULL NULL 14 where used
|
||||||
|
select * from t1 where btn like "q%";
|
||||||
|
btn
|
||||||
|
alter table t1 add column new_col char(1) not null, add key using BTREE (btn,new_col), drop key btn;
|
||||||
|
update t1 set new_col=btn;
|
||||||
|
explain select * from t1 where btn="a";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref btn btn 10 const 1 where used
|
||||||
|
explain select * from t1 where btn="a" and new_col="a";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref btn btn 11 const,const 1 where used
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int default NULL,
|
||||||
|
b int default NULL,
|
||||||
|
KEY a using BTREE (a),
|
||||||
|
UNIQUE b using BTREE (b)
|
||||||
|
) type=heap;
|
||||||
|
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
|
||||||
|
SELECT * FROM t1 WHERE a=NULL;
|
||||||
|
a b
|
||||||
|
explain SELECT * FROM t1 WHERE a IS NULL;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref a a 5 const 1 where used
|
||||||
|
SELECT * FROM t1 WHERE a<=>NULL;
|
||||||
|
a b
|
||||||
|
NULL 99
|
||||||
|
SELECT * FROM t1 WHERE b=NULL;
|
||||||
|
a b
|
||||||
|
explain SELECT * FROM t1 WHERE b IS NULL;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref b b 5 const 1 where used
|
||||||
|
SELECT * FROM t1 WHERE b<=>NULL;
|
||||||
|
a b
|
||||||
|
99 NULL
|
||||||
|
INSERT INTO t1 VALUES (1,3);
|
||||||
|
Duplicate entry '3' for key 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int not null, primary key using BTREE (a)) type=heap;
|
||||||
|
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
|
||||||
|
DELETE from t1 where a < 100;
|
||||||
|
SELECT * from t1;
|
||||||
|
a
|
||||||
|
DROP TABLE t1;
|
205
mysql-test/r/heap_hash.result
Normal file
205
mysql-test/r/heap_hash.result
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a=1 or a=0;
|
||||||
|
show keys from t1;
|
||||||
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
|
t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 4
|
||||||
|
select * from t1 where a=4;
|
||||||
|
a b
|
||||||
|
4 4
|
||||||
|
update t1 set b=5 where a=4;
|
||||||
|
update t1 set b=b+1 where a>=3;
|
||||||
|
replace t1 values (3,3);
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 6
|
||||||
|
alter table t1 add c int not null, add key using HASH (c,a);
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a > 0;
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 4
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int not null) type=heap;
|
||||||
|
insert into t1 values (869751),(736494),(226312),(802616);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
a
|
||||||
|
869751
|
||||||
|
802616
|
||||||
|
alter table t1 add unique uniq_id using HASH (a);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
a
|
||||||
|
869751
|
||||||
|
802616
|
||||||
|
select * from t1 where a = 736494;
|
||||||
|
a
|
||||||
|
736494
|
||||||
|
select * from t1 where a=869751 or a=736494;
|
||||||
|
a
|
||||||
|
736494
|
||||||
|
869751
|
||||||
|
select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
a
|
||||||
|
226312
|
||||||
|
736494
|
||||||
|
802616
|
||||||
|
869751
|
||||||
|
alter table t1 type=myisam;
|
||||||
|
explain select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 range uniq_id uniq_id 4 NULL 4 where used; Using index
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (x int not null, y int not null, key x using HASH (x), unique y using HASH (y))
|
||||||
|
type=heap;
|
||||||
|
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
|
||||||
|
select * from t1 where x=1;
|
||||||
|
x y
|
||||||
|
1 3
|
||||||
|
1 1
|
||||||
|
select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
x y x y
|
||||||
|
1 1 1 1
|
||||||
|
2 2 2 2
|
||||||
|
1 3 1 1
|
||||||
|
2 4 2 2
|
||||||
|
2 5 2 2
|
||||||
|
2 6 2 2
|
||||||
|
explain select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ALL x NULL NULL NULL 6
|
||||||
|
t2 eq_ref y y 4 t1.x 1
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int) type=heap;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(a) from t1;
|
||||||
|
max(a)
|
||||||
|
1
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using HASH (a), key using HASH (b) ) TYPE=HEAP;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
a b
|
||||||
|
1 6
|
||||||
|
1 5
|
||||||
|
1 4
|
||||||
|
1 3
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
a b
|
||||||
|
1 6
|
||||||
|
1 5
|
||||||
|
1 4
|
||||||
|
1 3
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
1 6
|
||||||
|
1 5
|
||||||
|
1 4
|
||||||
|
1 3
|
||||||
|
1 2
|
||||||
|
1 1
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (id int unsigned not null, primary key using HASH (id)) type=HEAP;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(id) from t1;
|
||||||
|
max(id)
|
||||||
|
1
|
||||||
|
insert into t1 values(2);
|
||||||
|
select max(id) from t1;
|
||||||
|
max(id)
|
||||||
|
2
|
||||||
|
replace into t1 values(1);
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table if exists t1;
|
||||||
|
CREATE table t1(f1 int not null,f2 char(20) not
|
||||||
|
null,index(f2)) type=heap;
|
||||||
|
INSERT into t1 set f1=12,f2="bill";
|
||||||
|
INSERT into t1 set f1=13,f2="bill";
|
||||||
|
INSERT into t1 set f1=14,f2="bill";
|
||||||
|
INSERT into t1 set f1=15,f2="bill";
|
||||||
|
INSERT into t1 set f1=16,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
delete from t1 where f2="bill";
|
||||||
|
select * from t1;
|
||||||
|
f1 f2
|
||||||
|
16 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
12 ted
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (btn char(10) not null, key using HASH (btn)) type=heap;
|
||||||
|
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
|
||||||
|
explain select * from t1 where btn like "q%";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ALL btn NULL NULL NULL 14 where used
|
||||||
|
select * from t1 where btn like "q%";
|
||||||
|
btn
|
||||||
|
alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
|
||||||
|
update t1 set new_col=btn;
|
||||||
|
explain select * from t1 where btn="a";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ALL btn NULL NULL NULL 14 where used
|
||||||
|
explain select * from t1 where btn="a" and new_col="a";
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref btn btn 11 const,const 10 where used
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int default NULL,
|
||||||
|
b int default NULL,
|
||||||
|
KEY a using HASH (a),
|
||||||
|
UNIQUE b using HASH (b)
|
||||||
|
) type=heap;
|
||||||
|
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
|
||||||
|
SELECT * FROM t1 WHERE a=NULL;
|
||||||
|
a b
|
||||||
|
explain SELECT * FROM t1 WHERE a IS NULL;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref a a 5 const 10 where used
|
||||||
|
SELECT * FROM t1 WHERE a<=>NULL;
|
||||||
|
a b
|
||||||
|
NULL 99
|
||||||
|
SELECT * FROM t1 WHERE b=NULL;
|
||||||
|
a b
|
||||||
|
explain SELECT * FROM t1 WHERE b IS NULL;
|
||||||
|
table type possible_keys key key_len ref rows Extra
|
||||||
|
t1 ref b b 5 const 1 where used
|
||||||
|
SELECT * FROM t1 WHERE b<=>NULL;
|
||||||
|
a b
|
||||||
|
99 NULL
|
||||||
|
INSERT INTO t1 VALUES (1,3);
|
||||||
|
Duplicate entry '3' for key 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap;
|
||||||
|
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
|
||||||
|
DELETE from t1 where a < 100;
|
||||||
|
SELECT * from t1;
|
||||||
|
a
|
||||||
|
DROP TABLE t1;
|
140
mysql-test/t/heap_btree.test
Normal file
140
mysql-test/t/heap_btree.test
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#
|
||||||
|
# Test of heap tables.
|
||||||
|
#
|
||||||
|
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a=1 or a=0;
|
||||||
|
#show table status like "t1";
|
||||||
|
show keys from t1;
|
||||||
|
select * from t1;
|
||||||
|
select * from t1 where a=4;
|
||||||
|
update t1 set b=5 where a=4;
|
||||||
|
update t1 set b=b+1 where a>=3;
|
||||||
|
replace t1 values (3,3);
|
||||||
|
select * from t1;
|
||||||
|
alter table t1 add c int not null, add key using BTREE (c,a);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a > 0;
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null,b int not null, primary key using BTREE (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
|
||||||
|
#show table status like "t1";
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null) type=heap;
|
||||||
|
insert into t1 values (869751),(736494),(226312),(802616);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
alter table t1 add unique uniq_id using BTREE (a);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
select * from t1 where a = 736494;
|
||||||
|
select * from t1 where a=869751 or a=736494;
|
||||||
|
select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
alter table t1 type=myisam;
|
||||||
|
explain select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (x int not null, y int not null, key x using BTREE (x), unique y using BTREE (y))
|
||||||
|
type=heap;
|
||||||
|
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
|
||||||
|
select * from t1 where x=1;
|
||||||
|
select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
explain select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int) type=heap;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(a) from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using BTREE (a), key using BTREE (b) ) TYPE=HEAP;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (id int unsigned not null, primary key using BTREE (id)) type=HEAP;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(id) from t1;
|
||||||
|
insert into t1 values(2);
|
||||||
|
select max(id) from t1;
|
||||||
|
replace into t1 values(1);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table if exists t1;
|
||||||
|
|
||||||
|
# Test of non unique index
|
||||||
|
|
||||||
|
CREATE table t1(f1 int not null,f2 char(20) not
|
||||||
|
null,index(f2)) type=heap;
|
||||||
|
INSERT into t1 set f1=12,f2="bill";
|
||||||
|
INSERT into t1 set f1=13,f2="bill";
|
||||||
|
INSERT into t1 set f1=14,f2="bill";
|
||||||
|
INSERT into t1 set f1=15,f2="bill";
|
||||||
|
INSERT into t1 set f1=16,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
delete from t1 where f2="bill";
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when using part key searches
|
||||||
|
#
|
||||||
|
|
||||||
|
create table t1 (btn char(10) not null, key using BTREE (btn)) type=heap;
|
||||||
|
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
|
||||||
|
explain select * from t1 where btn like "q%";
|
||||||
|
select * from t1 where btn like "q%";
|
||||||
|
alter table t1 add column new_col char(1) not null, add key using BTREE (btn,new_col), drop key btn;
|
||||||
|
update t1 set new_col=btn;
|
||||||
|
explain select * from t1 where btn="a";
|
||||||
|
explain select * from t1 where btn="a" and new_col="a";
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test of NULL keys
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int default NULL,
|
||||||
|
b int default NULL,
|
||||||
|
KEY a using BTREE (a),
|
||||||
|
UNIQUE b using BTREE (b)
|
||||||
|
) type=heap;
|
||||||
|
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
|
||||||
|
SELECT * FROM t1 WHERE a=NULL;
|
||||||
|
explain SELECT * FROM t1 WHERE a IS NULL;
|
||||||
|
SELECT * FROM t1 WHERE a<=>NULL;
|
||||||
|
SELECT * FROM t1 WHERE b=NULL;
|
||||||
|
explain SELECT * FROM t1 WHERE b IS NULL;
|
||||||
|
SELECT * FROM t1 WHERE b<=>NULL;
|
||||||
|
|
||||||
|
--error 1062
|
||||||
|
INSERT INTO t1 VALUES (1,3);
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when deleting all rows
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int not null, primary key using BTREE (a)) type=heap;
|
||||||
|
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
|
||||||
|
DELETE from t1 where a < 100;
|
||||||
|
SELECT * from t1;
|
||||||
|
DROP TABLE t1;
|
140
mysql-test/t/heap_hash.test
Normal file
140
mysql-test/t/heap_hash.test
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#
|
||||||
|
# Test of heap tables.
|
||||||
|
#
|
||||||
|
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a=1 or a=0;
|
||||||
|
#show table status like "t1";
|
||||||
|
show keys from t1;
|
||||||
|
select * from t1;
|
||||||
|
select * from t1 where a=4;
|
||||||
|
update t1 set b=5 where a=4;
|
||||||
|
update t1 set b=b+1 where a>=3;
|
||||||
|
replace t1 values (3,3);
|
||||||
|
select * from t1;
|
||||||
|
alter table t1 add c int not null, add key using HASH (c,a);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
delete from t1 where a > 0;
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null,b int not null, primary key using HASH (a)) type=heap comment="testing heaps";
|
||||||
|
insert into t1 values(1,1),(2,2),(3,3),(4,4);
|
||||||
|
alter table t1 modify a int not null auto_increment, type=myisam, comment="new myisam table";
|
||||||
|
#show table status like "t1";
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int not null) type=heap;
|
||||||
|
insert into t1 values (869751),(736494),(226312),(802616);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
alter table t1 add unique uniq_id using HASH (a);
|
||||||
|
select * from t1 where a > 736494;
|
||||||
|
select * from t1 where a = 736494;
|
||||||
|
select * from t1 where a=869751 or a=736494;
|
||||||
|
select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
alter table t1 type=myisam;
|
||||||
|
explain select * from t1 where a in (869751,736494,226312,802616);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (x int not null, y int not null, key x using HASH (x), unique y using HASH (y))
|
||||||
|
type=heap;
|
||||||
|
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
|
||||||
|
select * from t1 where x=1;
|
||||||
|
select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
explain select * from t1,t1 as t2 where t1.x=t2.y;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (a int) type=heap;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(a) from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 ( a int not null default 0, b int not null default 0, key using HASH (a), key using HASH (b) ) TYPE=HEAP;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
insert into t1 values(1,1),(1,2),(2,3),(1,3),(1,4),(1,5),(1,6);
|
||||||
|
select * from t1 where a=1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (id int unsigned not null, primary key using HASH (id)) type=HEAP;
|
||||||
|
insert into t1 values(1);
|
||||||
|
select max(id) from t1;
|
||||||
|
insert into t1 values(2);
|
||||||
|
select max(id) from t1;
|
||||||
|
replace into t1 values(1);
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
create table t1 (n int) type=heap;
|
||||||
|
drop table if exists t1;
|
||||||
|
|
||||||
|
# Test of non unique index
|
||||||
|
|
||||||
|
CREATE table t1(f1 int not null,f2 char(20) not
|
||||||
|
null,index(f2)) type=heap;
|
||||||
|
INSERT into t1 set f1=12,f2="bill";
|
||||||
|
INSERT into t1 set f1=13,f2="bill";
|
||||||
|
INSERT into t1 set f1=14,f2="bill";
|
||||||
|
INSERT into t1 set f1=15,f2="bill";
|
||||||
|
INSERT into t1 set f1=16,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
INSERT into t1 set f1=12,f2="ted";
|
||||||
|
delete from t1 where f2="bill";
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when using part key searches
|
||||||
|
#
|
||||||
|
|
||||||
|
create table t1 (btn char(10) not null, key using HASH (btn)) type=heap;
|
||||||
|
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
|
||||||
|
explain select * from t1 where btn like "q%";
|
||||||
|
select * from t1 where btn like "q%";
|
||||||
|
alter table t1 add column new_col char(1) not null, add key using HASH (btn,new_col), drop key btn;
|
||||||
|
update t1 set new_col=btn;
|
||||||
|
explain select * from t1 where btn="a";
|
||||||
|
explain select * from t1 where btn="a" and new_col="a";
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test of NULL keys
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
a int default NULL,
|
||||||
|
b int default NULL,
|
||||||
|
KEY a using HASH (a),
|
||||||
|
UNIQUE b using HASH (b)
|
||||||
|
) type=heap;
|
||||||
|
INSERT INTO t1 VALUES (NULL,99),(99,NULL),(1,1),(2,2),(1,3);
|
||||||
|
SELECT * FROM t1 WHERE a=NULL;
|
||||||
|
explain SELECT * FROM t1 WHERE a IS NULL;
|
||||||
|
SELECT * FROM t1 WHERE a<=>NULL;
|
||||||
|
SELECT * FROM t1 WHERE b=NULL;
|
||||||
|
explain SELECT * FROM t1 WHERE b IS NULL;
|
||||||
|
SELECT * FROM t1 WHERE b<=>NULL;
|
||||||
|
|
||||||
|
--error 1062
|
||||||
|
INSERT INTO t1 VALUES (1,3);
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when deleting all rows
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap;
|
||||||
|
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
|
||||||
|
DELETE from t1 where a < 100;
|
||||||
|
SELECT * from t1;
|
||||||
|
DROP TABLE t1;
|
@ -46,7 +46,8 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
|
|||||||
my_quick.c my_lockmem.c my_static.c \
|
my_quick.c my_lockmem.c my_static.c \
|
||||||
getopt.c getopt1.c my_getopt.c getvar.c my_mkdir.c \
|
getopt.c getopt1.c my_getopt.c getvar.c my_mkdir.c \
|
||||||
default.c my_compress.c checksum.c raid.cc my_net.c \
|
default.c my_compress.c checksum.c raid.cc my_net.c \
|
||||||
my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c
|
my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c \
|
||||||
|
my_handler.c
|
||||||
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
||||||
thr_mutex.c thr_rwlock.c
|
thr_mutex.c thr_rwlock.c
|
||||||
libmysys_a_LIBADD = @THREAD_LOBJECTS@
|
libmysys_a_LIBADD = @THREAD_LOBJECTS@
|
||||||
|
717
mysys/my_handler.c
Normal file
717
mysys/my_handler.c
Normal file
@ -0,0 +1,717 @@
|
|||||||
|
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
MA 02111-1307, USA */
|
||||||
|
|
||||||
|
#include "my_handler.h"
|
||||||
|
|
||||||
|
int _mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
|
||||||
|
uchar *b, uint b_length, my_bool part_key)
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
#ifdef USE_STRCOLL
|
||||||
|
if (use_strcoll(charset_info))
|
||||||
|
{
|
||||||
|
/* QQ: This needs to work with part keys at some point */
|
||||||
|
return my_strnncoll(charset_info, a, a_length, b, b_length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
uint length= min(a_length,b_length);
|
||||||
|
uchar *end= a+ length;
|
||||||
|
uchar *sort_order=charset_info->sort_order;
|
||||||
|
while (a < end)
|
||||||
|
if ((flag= (int) sort_order[*a++] - (int) sort_order[*b++]))
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
if (part_key && b_length < a_length)
|
||||||
|
return 0;
|
||||||
|
return (int) (a_length-b_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
|
||||||
|
my_bool part_key)
|
||||||
|
{
|
||||||
|
uint length= min(a_length,b_length);
|
||||||
|
uchar *end= a+ length;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
while (a < end)
|
||||||
|
if ((flag= (int) *a++ - (int) *b++))
|
||||||
|
return flag;
|
||||||
|
if (part_key && b_length < a_length)
|
||||||
|
return 0;
|
||||||
|
return (int) (a_length-b_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
|
||||||
|
#define FCMP(A,B) ((int) (A) - (int) (B))
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compare two keys
|
||||||
|
Returns <0, 0, >0 acording to which is bigger
|
||||||
|
Key_length specifies length of key to use. Number-keys can't be splited
|
||||||
|
If flag <> SEARCH_FIND compare also position
|
||||||
|
*/
|
||||||
|
int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
||||||
|
register uchar *b, uint key_length, uint nextflag,
|
||||||
|
uint *diff_pos)
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
|
int16 s_1,s_2;
|
||||||
|
int32 l_1,l_2;
|
||||||
|
uint32 u_1,u_2;
|
||||||
|
float f_1,f_2;
|
||||||
|
double d_1,d_2;
|
||||||
|
uint next_key_length;
|
||||||
|
|
||||||
|
*diff_pos=0;
|
||||||
|
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
|
||||||
|
{
|
||||||
|
uchar *end;
|
||||||
|
(*diff_pos)++;
|
||||||
|
|
||||||
|
/* Handle NULL part */
|
||||||
|
if (keyseg->null_bit)
|
||||||
|
{
|
||||||
|
key_length--;
|
||||||
|
if (*a != *b)
|
||||||
|
{
|
||||||
|
flag = (int) *a - (int) *b;
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
}
|
||||||
|
b++;
|
||||||
|
if (!*a++) /* If key was NULL */
|
||||||
|
{
|
||||||
|
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
|
||||||
|
nextflag=SEARCH_SAME; /* Allow duplicate keys */
|
||||||
|
next_key_length=key_length;
|
||||||
|
continue; /* To next key part */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end= a+ min(keyseg->length,key_length);
|
||||||
|
next_key_length=key_length-keyseg->length;
|
||||||
|
|
||||||
|
switch ((enum ha_base_keytype) keyseg->type) {
|
||||||
|
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint length=(uint) (end-a), a_length=length, b_length=length;
|
||||||
|
if (!(nextflag & SEARCH_PREFIX))
|
||||||
|
{
|
||||||
|
while (a_length && a[a_length-1] == ' ')
|
||||||
|
a_length--;
|
||||||
|
while (b_length && b[b_length-1] == ' ')
|
||||||
|
b_length--;
|
||||||
|
}
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a=end;
|
||||||
|
b+=length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_BINARY:
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=compare_bin(a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint length=keyseg->length;
|
||||||
|
if ((flag=compare_bin(a,length,b,length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=length;
|
||||||
|
b+=length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_VARTEXT:
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_VARBINARY:
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=compare_bin(a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_INT8:
|
||||||
|
{
|
||||||
|
int i_1= (int) *((signed char*) a);
|
||||||
|
int i_2= (int) *((signed char*) b);
|
||||||
|
if ((flag = CMP(i_1,i_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_SHORT_INT:
|
||||||
|
s_1= mi_sint2korr(a);
|
||||||
|
s_2= mi_sint2korr(b);
|
||||||
|
if ((flag = CMP(s_1,s_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 2; /* sizeof(short int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_USHORT_INT:
|
||||||
|
{
|
||||||
|
uint16 us_1,us_2;
|
||||||
|
us_1= mi_sint2korr(a);
|
||||||
|
us_2= mi_sint2korr(b);
|
||||||
|
if ((flag = CMP(us_1,us_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+=2; /* sizeof(short int); */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_LONG_INT:
|
||||||
|
l_1= mi_sint4korr(a);
|
||||||
|
l_2= mi_sint4korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(long int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_ULONG_INT:
|
||||||
|
u_1= mi_sint4korr(a);
|
||||||
|
u_2= mi_sint4korr(b);
|
||||||
|
if ((flag = CMP(u_1,u_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(long int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_INT24:
|
||||||
|
l_1=mi_sint3korr(a);
|
||||||
|
l_2=mi_sint3korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 3;
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_UINT24:
|
||||||
|
l_1=mi_uint3korr(a);
|
||||||
|
l_2=mi_uint3korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 3;
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_FLOAT:
|
||||||
|
mi_float4get(f_1,a);
|
||||||
|
mi_float4get(f_2,b);
|
||||||
|
if ((flag = CMP(f_1,f_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(float); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_DOUBLE:
|
||||||
|
mi_float8get(d_1,a);
|
||||||
|
mi_float8get(d_2,b);
|
||||||
|
if ((flag = CMP(d_1,d_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8; /* sizeof(double); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_NUM: /* Numeric key */
|
||||||
|
{
|
||||||
|
int swap_flag= 0;
|
||||||
|
int alength,blength;
|
||||||
|
|
||||||
|
if (keyseg->flag & HA_REVERSE_SORT)
|
||||||
|
{
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
swap_flag=1; /* Remember swap of a & b */
|
||||||
|
end= a+ (int) (end-b);
|
||||||
|
}
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
alength= *a++; blength= *b++;
|
||||||
|
end=a+alength;
|
||||||
|
next_key_length=key_length-blength-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alength= (int) (end-a);
|
||||||
|
blength=keyseg->length;
|
||||||
|
/* remove pre space from keys */
|
||||||
|
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
||||||
|
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*a == '-')
|
||||||
|
{
|
||||||
|
if (*b != '-')
|
||||||
|
return -1;
|
||||||
|
a++; b++;
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
swap(int,alength,blength);
|
||||||
|
swap_flag=1-swap_flag;
|
||||||
|
alength--; blength--;
|
||||||
|
end=a+alength;
|
||||||
|
}
|
||||||
|
else if (*b == '-')
|
||||||
|
return 1;
|
||||||
|
while (alength && (*a == '+' || *a == '0'))
|
||||||
|
{
|
||||||
|
a++; alength--;
|
||||||
|
}
|
||||||
|
while (blength && (*b == '+' || *b == '0'))
|
||||||
|
{
|
||||||
|
b++; blength--;
|
||||||
|
}
|
||||||
|
if (alength != blength)
|
||||||
|
return (alength < blength) ? -1 : 1;
|
||||||
|
while (a < end)
|
||||||
|
if (*a++ != *b++)
|
||||||
|
return ((int) a[-1] - (int) b[-1]);
|
||||||
|
|
||||||
|
if (swap_flag) /* Restore pointers */
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_LONG_LONG
|
||||||
|
case HA_KEYTYPE_LONGLONG:
|
||||||
|
{
|
||||||
|
longlong ll_a,ll_b;
|
||||||
|
ll_a= mi_sint8korr(a);
|
||||||
|
ll_b= mi_sint8korr(b);
|
||||||
|
if ((flag = CMP(ll_a,ll_b)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_ULONGLONG:
|
||||||
|
{
|
||||||
|
ulonglong ll_a,ll_b;
|
||||||
|
ll_a= mi_uint8korr(a);
|
||||||
|
ll_b= mi_uint8korr(b);
|
||||||
|
if ((flag = CMP(ll_a,ll_b)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case HA_KEYTYPE_END: /* Ready */
|
||||||
|
goto end; /* diff_pos is incremented */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*diff_pos)++;
|
||||||
|
end:
|
||||||
|
if (!(nextflag & SEARCH_FIND))
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
|
||||||
|
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
|
||||||
|
flag=0;
|
||||||
|
for (i=keyseg->length ; i-- > 0 ; )
|
||||||
|
{
|
||||||
|
if (*a++ != *b++)
|
||||||
|
{
|
||||||
|
flag= FCMP(a[-1],b[-1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextflag & SEARCH_SAME)
|
||||||
|
return (flag); /* read same */
|
||||||
|
if (nextflag & SEARCH_BIGGER)
|
||||||
|
return (flag <= 0 ? -1 : 1); /* read next */
|
||||||
|
return (flag < 0 ? -1 : 1); /* read previous */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} /* my_key_cmp */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compare two keys
|
||||||
|
Returns <0, 0, >0 acording to which is bigger
|
||||||
|
Key_length specifies length of key to use. Number-keys can't be splited
|
||||||
|
If flag <> SEARCH_FIND compare also position
|
||||||
|
*/
|
||||||
|
int hp_rb_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
||||||
|
register uchar *b, uint key_length, uint nextflag,
|
||||||
|
uint *diff_pos)
|
||||||
|
{
|
||||||
|
int flag;
|
||||||
|
int16 s_1,s_2;
|
||||||
|
int32 l_1,l_2;
|
||||||
|
uint32 u_1,u_2;
|
||||||
|
float f_1,f_2;
|
||||||
|
double d_1,d_2;
|
||||||
|
uint next_key_length;
|
||||||
|
|
||||||
|
*diff_pos=0;
|
||||||
|
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
|
||||||
|
{
|
||||||
|
uchar *end;
|
||||||
|
(*diff_pos)++;
|
||||||
|
|
||||||
|
/* Handle NULL part */
|
||||||
|
if (keyseg->null_bit)
|
||||||
|
{
|
||||||
|
key_length--;
|
||||||
|
if (*a != *b)
|
||||||
|
{
|
||||||
|
flag = (int) *a - (int) *b;
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
}
|
||||||
|
b++;
|
||||||
|
if (!*a++) /* If key was NULL */
|
||||||
|
{
|
||||||
|
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
|
||||||
|
nextflag=SEARCH_SAME; /* Allow duplicate keys */
|
||||||
|
next_key_length=key_length;
|
||||||
|
a+= keyseg->length;
|
||||||
|
b+= keyseg->length;
|
||||||
|
key_length-= keyseg->length;
|
||||||
|
continue; /* To next key part */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end= a+ min(keyseg->length,key_length);
|
||||||
|
next_key_length=key_length-keyseg->length;
|
||||||
|
|
||||||
|
switch ((enum ha_base_keytype) keyseg->type) {
|
||||||
|
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint length=(uint) (end-a), a_length=length, b_length=length;
|
||||||
|
if (!(nextflag & SEARCH_PREFIX))
|
||||||
|
{
|
||||||
|
while (a_length && a[a_length-1] == ' ')
|
||||||
|
a_length--;
|
||||||
|
while (b_length && b[b_length-1] == ' ')
|
||||||
|
b_length--;
|
||||||
|
}
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a=end;
|
||||||
|
b+=length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_BINARY:
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=compare_bin(a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint length=keyseg->length;
|
||||||
|
if ((flag=compare_bin(a,length,b,length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=length;
|
||||||
|
b+=length;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_VARTEXT:
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=_mi_compare_text(keyseg->charset,a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_VARBINARY:
|
||||||
|
{
|
||||||
|
int a_length,b_length,pack_length;
|
||||||
|
get_key_length(a_length,a);
|
||||||
|
get_key_pack_length(b_length,pack_length,b);
|
||||||
|
next_key_length=key_length-b_length-pack_length;
|
||||||
|
|
||||||
|
if ((flag=compare_bin(a,a_length,b,b_length,
|
||||||
|
(my_bool) ((nextflag & SEARCH_PREFIX) &&
|
||||||
|
next_key_length <= 0))))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a+=a_length;
|
||||||
|
b+=b_length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_INT8:
|
||||||
|
{
|
||||||
|
int i_1= (int) *((signed char*) a);
|
||||||
|
int i_2= (int) *((signed char*) b);
|
||||||
|
if ((flag = CMP(i_1,i_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_SHORT_INT:
|
||||||
|
s_1= mi_sint2korr(a);
|
||||||
|
s_2= mi_sint2korr(b);
|
||||||
|
if ((flag = CMP(s_1,s_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 2; /* sizeof(short int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_USHORT_INT:
|
||||||
|
{
|
||||||
|
uint16 us_1,us_2;
|
||||||
|
us_1= mi_sint2korr(a);
|
||||||
|
us_2= mi_sint2korr(b);
|
||||||
|
if ((flag = CMP(us_1,us_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+=2; /* sizeof(short int); */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_LONG_INT:
|
||||||
|
l_1= mi_sint4korr(a);
|
||||||
|
l_2= mi_sint4korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(long int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_ULONG_INT:
|
||||||
|
u_1= mi_sint4korr(a);
|
||||||
|
u_2= mi_sint4korr(b);
|
||||||
|
if ((flag = CMP(u_1,u_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(long int); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_INT24:
|
||||||
|
l_1=mi_sint3korr(a);
|
||||||
|
l_2=mi_sint3korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 3;
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_UINT24:
|
||||||
|
l_1=mi_uint3korr(a);
|
||||||
|
l_2=mi_uint3korr(b);
|
||||||
|
if ((flag = CMP(l_1,l_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 3;
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_FLOAT:
|
||||||
|
mi_float4get(f_1,a);
|
||||||
|
mi_float4get(f_2,b);
|
||||||
|
if ((flag = CMP(f_1,f_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 4; /* sizeof(float); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_DOUBLE:
|
||||||
|
mi_float8get(d_1,a);
|
||||||
|
mi_float8get(d_2,b);
|
||||||
|
if ((flag = CMP(d_1,d_2)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8; /* sizeof(double); */
|
||||||
|
break;
|
||||||
|
case HA_KEYTYPE_NUM: /* Numeric key */
|
||||||
|
{
|
||||||
|
int swap_flag= 0;
|
||||||
|
int alength,blength;
|
||||||
|
|
||||||
|
if (keyseg->flag & HA_REVERSE_SORT)
|
||||||
|
{
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
swap_flag=1; /* Remember swap of a & b */
|
||||||
|
end= a+ (int) (end-b);
|
||||||
|
}
|
||||||
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
|
{
|
||||||
|
alength= *a++; blength= *b++;
|
||||||
|
end=a+alength;
|
||||||
|
next_key_length=key_length-blength-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alength= (int) (end-a);
|
||||||
|
blength=keyseg->length;
|
||||||
|
/* remove pre space from keys */
|
||||||
|
for ( ; alength && *a == ' ' ; a++, alength--) ;
|
||||||
|
for ( ; blength && *b == ' ' ; b++, blength--) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*a == '-')
|
||||||
|
{
|
||||||
|
if (*b != '-')
|
||||||
|
return -1;
|
||||||
|
a++; b++;
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
swap(int,alength,blength);
|
||||||
|
swap_flag=1-swap_flag;
|
||||||
|
alength--; blength--;
|
||||||
|
end=a+alength;
|
||||||
|
}
|
||||||
|
else if (*b == '-')
|
||||||
|
return 1;
|
||||||
|
while (alength && (*a == '+' || *a == '0'))
|
||||||
|
{
|
||||||
|
a++; alength--;
|
||||||
|
}
|
||||||
|
while (blength && (*b == '+' || *b == '0'))
|
||||||
|
{
|
||||||
|
b++; blength--;
|
||||||
|
}
|
||||||
|
if (alength != blength)
|
||||||
|
return (alength < blength) ? -1 : 1;
|
||||||
|
while (a < end)
|
||||||
|
if (*a++ != *b++)
|
||||||
|
return ((int) a[-1] - (int) b[-1]);
|
||||||
|
|
||||||
|
if (swap_flag) /* Restore pointers */
|
||||||
|
swap(uchar*,a,b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_LONG_LONG
|
||||||
|
case HA_KEYTYPE_LONGLONG:
|
||||||
|
{
|
||||||
|
longlong ll_a,ll_b;
|
||||||
|
ll_a= mi_sint8korr(a);
|
||||||
|
ll_b= mi_sint8korr(b);
|
||||||
|
if ((flag = CMP(ll_a,ll_b)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HA_KEYTYPE_ULONGLONG:
|
||||||
|
{
|
||||||
|
ulonglong ll_a,ll_b;
|
||||||
|
ll_a= mi_uint8korr(a);
|
||||||
|
ll_b= mi_uint8korr(b);
|
||||||
|
if ((flag = CMP(ll_a,ll_b)))
|
||||||
|
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
|
||||||
|
a= end;
|
||||||
|
b+= 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case HA_KEYTYPE_END: /* Ready */
|
||||||
|
goto end; /* diff_pos is incremented */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*diff_pos)++;
|
||||||
|
end:
|
||||||
|
if (!(nextflag & SEARCH_FIND))
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
|
||||||
|
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
|
||||||
|
flag=0;
|
||||||
|
for (i=keyseg->length ; i-- > 0 ; )
|
||||||
|
{
|
||||||
|
if (*a++ != *b++)
|
||||||
|
{
|
||||||
|
flag= FCMP(a[-1],b[-1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextflag & SEARCH_SAME)
|
||||||
|
return (flag); /* read same */
|
||||||
|
if (nextflag & SEARCH_BIGGER)
|
||||||
|
return (flag <= 0 ? -1 : 1); /* read next */
|
||||||
|
return (flag < 0 ? -1 : 1); /* read previous */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} /* my_key_cmp */
|
189
mysys/tree.c
189
mysys/tree.c
@ -42,6 +42,7 @@
|
|||||||
#include "mysys_priv.h"
|
#include "mysys_priv.h"
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <my_tree.h>
|
#include <my_tree.h>
|
||||||
|
#include "my_base.h"
|
||||||
|
|
||||||
#define BLACK 1
|
#define BLACK 1
|
||||||
#define RED 0
|
#define RED 0
|
||||||
@ -167,7 +168,8 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
|
|||||||
parent[0] = & parent[-1][0]->right */
|
parent[0] = & parent[-1][0]->right */
|
||||||
|
|
||||||
|
|
||||||
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
|
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
|
||||||
|
void* custom_arg)
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
TREE_ELEMENT *element,***parent;
|
TREE_ELEMENT *element,***parent;
|
||||||
@ -177,8 +179,8 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (element == &tree->null_element ||
|
if (element == &tree->null_element ||
|
||||||
(cmp=(*tree->compare)(tree->custom_arg,
|
(cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
|
||||||
ELEMENT_KEY(tree,element),key)) == 0)
|
key)) == 0)
|
||||||
break;
|
break;
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
@ -198,7 +200,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
|
|||||||
&& tree->allocated > tree->memory_limit)
|
&& tree->allocated > tree->memory_limit)
|
||||||
{
|
{
|
||||||
reset_tree(tree);
|
reset_tree(tree);
|
||||||
return tree_insert(tree, key, key_size);
|
return tree_insert(tree, key, key_size, custom_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
key_size+=tree->size_of_element;
|
key_size+=tree->size_of_element;
|
||||||
@ -234,8 +236,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size)
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tree_delete(TREE *tree, void *key, void *custom_arg)
|
||||||
int tree_delete(TREE *tree, void *key)
|
|
||||||
{
|
{
|
||||||
int cmp,remove_colour;
|
int cmp,remove_colour;
|
||||||
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
|
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
|
||||||
@ -248,8 +249,8 @@ int tree_delete(TREE *tree, void *key)
|
|||||||
{
|
{
|
||||||
if (element == &tree->null_element)
|
if (element == &tree->null_element)
|
||||||
return 1; /* Was not in tree */
|
return 1; /* Was not in tree */
|
||||||
if ((cmp=(*tree->compare)(tree->custom_arg,
|
if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
|
||||||
ELEMENT_KEY(tree,element),key)) == 0)
|
key)) == 0)
|
||||||
break;
|
break;
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
{
|
{
|
||||||
@ -296,7 +297,7 @@ int tree_delete(TREE *tree, void *key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *tree_search(TREE *tree, void *key)
|
void *tree_search(TREE *tree, void *key, void *custom_arg)
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
TREE_ELEMENT *element=tree->root;
|
TREE_ELEMENT *element=tree->root;
|
||||||
@ -305,8 +306,8 @@ void *tree_search(TREE *tree, void *key)
|
|||||||
{
|
{
|
||||||
if (element == &tree->null_element)
|
if (element == &tree->null_element)
|
||||||
return (void*) 0;
|
return (void*) 0;
|
||||||
if ((cmp=(*tree->compare)(tree->custom_arg,
|
if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element),
|
||||||
ELEMENT_KEY(tree,element),key)) == 0)
|
key)) == 0)
|
||||||
return ELEMENT_KEY(tree,element);
|
return ELEMENT_KEY(tree,element);
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
element=element->right;
|
element=element->right;
|
||||||
@ -315,6 +316,172 @@ void *tree_search(TREE *tree, void *key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *tree_search_key(TREE *tree, const void *key,
|
||||||
|
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
|
||||||
|
enum ha_rkey_function flag, void *custom_arg)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
TREE_ELEMENT *element = tree->root;
|
||||||
|
TREE_ELEMENT **last_left_step_parent = NULL;
|
||||||
|
TREE_ELEMENT **last_equal_element = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: handle HA_READ_KEY_OR_PREV, HA_READ_BEFORE_KEY, HA_READ_PREFIX,
|
||||||
|
HA_READ_PREFIX_LAST flags if needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
*parents = &tree->null_element;
|
||||||
|
while (element != &tree->null_element)
|
||||||
|
{
|
||||||
|
*++parents = element;
|
||||||
|
if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
|
||||||
|
key)) == 0)
|
||||||
|
{
|
||||||
|
switch (flag) {
|
||||||
|
case HA_READ_KEY_EXACT:
|
||||||
|
case HA_READ_KEY_OR_NEXT:
|
||||||
|
last_equal_element = parents;
|
||||||
|
cmp = 1;
|
||||||
|
break;
|
||||||
|
case HA_READ_AFTER_KEY:
|
||||||
|
cmp = -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cmp < 0) /* element < key */
|
||||||
|
{
|
||||||
|
element = element->right;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_left_step_parent = parents;
|
||||||
|
element = element->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (flag) {
|
||||||
|
case HA_READ_KEY_EXACT:
|
||||||
|
*last_pos = last_equal_element;
|
||||||
|
break;
|
||||||
|
case HA_READ_KEY_OR_NEXT:
|
||||||
|
*last_pos = last_equal_element ? last_equal_element : last_left_step_parent;
|
||||||
|
break;
|
||||||
|
case HA_READ_AFTER_KEY:
|
||||||
|
*last_pos = last_left_step_parent;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return *last_pos ? ELEMENT_KEY(tree, **last_pos) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Search first (the most left) or last (the most right) tree element
|
||||||
|
*/
|
||||||
|
void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents,
|
||||||
|
TREE_ELEMENT ***last_pos, int child_offs)
|
||||||
|
{
|
||||||
|
TREE_ELEMENT *element = tree->root;
|
||||||
|
|
||||||
|
*parents = &tree->null_element;
|
||||||
|
while (element != &tree->null_element)
|
||||||
|
{
|
||||||
|
*++parents = element;
|
||||||
|
element = ELEMENT_CHILD(element, child_offs);
|
||||||
|
}
|
||||||
|
*last_pos = parents;
|
||||||
|
return **last_pos != &tree->null_element ?
|
||||||
|
ELEMENT_KEY(tree, **last_pos) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
|
||||||
|
int r_offs)
|
||||||
|
{
|
||||||
|
TREE_ELEMENT *x = **last_pos;
|
||||||
|
|
||||||
|
if (ELEMENT_CHILD(x, r_offs) != &tree->null_element)
|
||||||
|
{
|
||||||
|
x = ELEMENT_CHILD(x, r_offs);
|
||||||
|
*++*last_pos = x;
|
||||||
|
while (ELEMENT_CHILD(x, l_offs) != &tree->null_element)
|
||||||
|
{
|
||||||
|
x = ELEMENT_CHILD(x, l_offs);
|
||||||
|
*++*last_pos = x;
|
||||||
|
}
|
||||||
|
return ELEMENT_KEY(tree, x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TREE_ELEMENT *y = *--*last_pos;
|
||||||
|
while (y != &tree->null_element && x == ELEMENT_CHILD(y, r_offs))
|
||||||
|
{
|
||||||
|
x = y;
|
||||||
|
y = *--*last_pos;
|
||||||
|
}
|
||||||
|
return y == &tree->null_element ? NULL : ELEMENT_KEY(tree, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Expected that tree is fully balanced
|
||||||
|
(each path from root to leaf has the same length)
|
||||||
|
*/
|
||||||
|
uint tree_record_pos(TREE *tree, const void *key,
|
||||||
|
enum ha_rkey_function flag, void *custom_arg)
|
||||||
|
{
|
||||||
|
int cmp;
|
||||||
|
TREE_ELEMENT *element = tree->root;
|
||||||
|
uint left = 1;
|
||||||
|
uint right = tree->elements_in_tree;
|
||||||
|
uint last_left_step_pos = tree->elements_in_tree;
|
||||||
|
uint last_right_step_pos = 1;
|
||||||
|
uint last_equal_pos = HA_POS_ERROR;
|
||||||
|
|
||||||
|
while (element != &tree->null_element)
|
||||||
|
{
|
||||||
|
if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element),
|
||||||
|
key)) == 0)
|
||||||
|
{
|
||||||
|
switch (flag) {
|
||||||
|
case HA_READ_KEY_EXACT:
|
||||||
|
last_equal_pos = (left + right) >> 1;
|
||||||
|
cmp = 1;
|
||||||
|
break;
|
||||||
|
case HA_READ_BEFORE_KEY:
|
||||||
|
cmp = 1;
|
||||||
|
break;
|
||||||
|
case HA_READ_AFTER_KEY:
|
||||||
|
cmp = -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return HA_POS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cmp < 0) /* element < key */
|
||||||
|
{
|
||||||
|
last_right_step_pos = (left + right) >> 1;
|
||||||
|
element = element->right;
|
||||||
|
left = last_right_step_pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_left_step_pos = (left + right) >> 1;
|
||||||
|
element = element->left;
|
||||||
|
right = last_left_step_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (flag) {
|
||||||
|
case HA_READ_KEY_EXACT:
|
||||||
|
return last_equal_pos;
|
||||||
|
case HA_READ_BEFORE_KEY:
|
||||||
|
return last_right_step_pos;
|
||||||
|
case HA_READ_AFTER_KEY:
|
||||||
|
return last_left_step_pos;
|
||||||
|
default:
|
||||||
|
return HA_POS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit)
|
int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit)
|
||||||
{
|
{
|
||||||
|
103
sql/ha_heap.cc
103
sql/ha_heap.cc
@ -36,42 +36,59 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
|
|||||||
uint key,parts,mem_per_row=0;
|
uint key,parts,mem_per_row=0;
|
||||||
ulong max_rows;
|
ulong max_rows;
|
||||||
HP_KEYDEF *keydef;
|
HP_KEYDEF *keydef;
|
||||||
HP_KEYSEG *seg;
|
MI_KEYSEG *seg;
|
||||||
|
|
||||||
for (key=parts=0 ; key < table->keys ; key++)
|
for (key=parts=0 ; key < table->keys ; key++)
|
||||||
|
{
|
||||||
parts+=table->key_info[key].key_parts;
|
parts+=table->key_info[key].key_parts;
|
||||||
|
if (table->key_info[key].algorithm == HA_KEY_ALG_BTREE)
|
||||||
|
{
|
||||||
|
parts++; /* additional HA_KEYTYPE_END keyseg */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(keydef=(HP_KEYDEF*) my_malloc(table->keys*sizeof(HP_KEYDEF)+
|
if (!(keydef=(HP_KEYDEF*) my_malloc(table->keys*sizeof(HP_KEYDEF)+
|
||||||
parts*sizeof(HP_KEYSEG),MYF(MY_WME))))
|
parts*sizeof(MI_KEYSEG),MYF(MY_WME))))
|
||||||
return my_errno;
|
return my_errno;
|
||||||
seg=my_reinterpret_cast(HP_KEYSEG*) (keydef+table->keys);
|
seg=my_reinterpret_cast(MI_KEYSEG*) (keydef+table->keys);
|
||||||
for (key=0 ; key < table->keys ; key++)
|
for (key=0 ; key < table->keys ; key++)
|
||||||
{
|
{
|
||||||
KEY *pos=table->key_info+key;
|
KEY *pos=table->key_info+key;
|
||||||
KEY_PART_INFO *key_part= pos->key_part;
|
KEY_PART_INFO *key_part= pos->key_part;
|
||||||
KEY_PART_INFO *key_part_end= key_part+pos->key_parts;
|
KEY_PART_INFO *key_part_end= key_part+pos->key_parts;
|
||||||
|
|
||||||
mem_per_row += (pos->key_length + (sizeof(char*) * 2));
|
mem_per_row+= (pos->key_length + (sizeof(char*) * 2));
|
||||||
|
|
||||||
keydef[key].keysegs=(uint) pos->key_parts;
|
keydef[key].keysegs= (uint) pos->key_parts;
|
||||||
keydef[key].flag = (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
|
keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
|
||||||
keydef[key].seg=seg;
|
keydef[key].seg= seg;
|
||||||
|
keydef[key].algorithm= pos->algorithm == HA_KEY_ALG_UNDEF ?
|
||||||
|
HA_KEY_ALG_HASH : pos->algorithm;
|
||||||
|
|
||||||
for (; key_part != key_part_end ; key_part++, seg++)
|
for (; key_part != key_part_end ; key_part++, seg++)
|
||||||
{
|
{
|
||||||
uint flag=key_part->key_type;
|
uint flag= key_part->key_type;
|
||||||
Field *field=key_part->field;
|
Field *field= key_part->field;
|
||||||
if (!f_is_packed(flag) &&
|
if (pos->algorithm == HA_KEY_ALG_BTREE)
|
||||||
f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
|
{
|
||||||
!(flag & FIELDFLAG_BINARY))
|
seg->type= field->key_type();
|
||||||
seg->type= (int) HA_KEYTYPE_TEXT;
|
}
|
||||||
else
|
else
|
||||||
seg->type= (int) HA_KEYTYPE_BINARY;
|
{
|
||||||
seg->start=(uint) key_part->offset;
|
if (!f_is_packed(flag) &&
|
||||||
seg->length=(uint) key_part->length;
|
f_packtype(flag) == (int) FIELD_TYPE_DECIMAL &&
|
||||||
|
!(flag & FIELDFLAG_BINARY))
|
||||||
|
seg->type= (int) HA_KEYTYPE_TEXT;
|
||||||
|
else
|
||||||
|
seg->type= (int) HA_KEYTYPE_BINARY;
|
||||||
|
}
|
||||||
|
seg->start= (uint) key_part->offset;
|
||||||
|
seg->length= (uint) key_part->length;
|
||||||
|
seg->flag = 0;
|
||||||
|
seg->charset= default_charset_info;
|
||||||
if (field->null_ptr)
|
if (field->null_ptr)
|
||||||
{
|
{
|
||||||
seg->null_bit=field->null_bit;
|
seg->null_bit= field->null_bit;
|
||||||
seg->null_pos= (uint) (field->null_ptr-
|
seg->null_pos= (uint) (field->null_ptr-
|
||||||
(uchar*) table->record[0]);
|
(uchar*) table->record[0]);
|
||||||
}
|
}
|
||||||
@ -81,6 +98,16 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
|
|||||||
seg->null_pos=0;
|
seg->null_pos=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pos->algorithm == HA_KEY_ALG_BTREE)
|
||||||
|
{
|
||||||
|
/* additional HA_KEYTYPE_END keyseg */
|
||||||
|
keydef[key].keysegs++;
|
||||||
|
seg->type= HA_KEYTYPE_END;
|
||||||
|
seg->length= sizeof(byte*);
|
||||||
|
seg->flag= 0;
|
||||||
|
seg->null_bit= 0;
|
||||||
|
seg++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
|
mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
|
||||||
max_rows = (ulong) (max_heap_table_size / mem_per_row);
|
max_rows = (ulong) (max_heap_table_size / mem_per_row);
|
||||||
@ -124,25 +151,21 @@ int ha_heap::delete_row(const byte * buf)
|
|||||||
return heap_delete(file,buf);
|
return heap_delete(file,buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ha_heap::index_read(byte * buf, const byte * key,
|
int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
|
||||||
uint key_len __attribute__((unused)),
|
enum ha_rkey_function find_flag)
|
||||||
enum ha_rkey_function find_flag
|
|
||||||
__attribute__((unused)))
|
|
||||||
{
|
{
|
||||||
statistic_increment(ha_read_key_count,&LOCK_status);
|
statistic_increment(ha_read_key_count, &LOCK_status);
|
||||||
int error=heap_rkey(file,buf,active_index, key);
|
int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
|
||||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
table->status = error ? STATUS_NOT_FOUND : 0;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
|
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
|
||||||
uint key_len __attribute__((unused)),
|
uint key_len, enum ha_rkey_function find_flag)
|
||||||
enum ha_rkey_function find_flag
|
|
||||||
__attribute__((unused)))
|
|
||||||
{
|
{
|
||||||
statistic_increment(ha_read_key_count,&LOCK_status);
|
statistic_increment(ha_read_key_count, &LOCK_status);
|
||||||
int error=heap_rkey(file, buf, index, key);
|
int error = heap_rkey(file, buf, index, key, key_len, find_flag);
|
||||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
table->status = error ? STATUS_NOT_FOUND : 0;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,12 +302,20 @@ ha_rows ha_heap::records_in_range(int inx,
|
|||||||
enum ha_rkey_function end_search_flag)
|
enum ha_rkey_function end_search_flag)
|
||||||
{
|
{
|
||||||
KEY *pos=table->key_info+inx;
|
KEY *pos=table->key_info+inx;
|
||||||
if (start_key_len != end_key_len ||
|
if (pos->algorithm == HA_KEY_ALG_BTREE)
|
||||||
start_key_len != pos->key_length ||
|
{
|
||||||
start_search_flag != HA_READ_KEY_EXACT ||
|
return hp_rb_records_in_range(file, inx, start_key, start_key_len,
|
||||||
end_search_flag != HA_READ_AFTER_KEY)
|
start_search_flag, end_key, end_key_len, end_search_flag);
|
||||||
return HA_POS_ERROR; // Can't only use exact keys
|
}
|
||||||
return 10; // Good guess
|
else
|
||||||
|
{
|
||||||
|
if (start_key_len != end_key_len ||
|
||||||
|
start_key_len != pos->key_length ||
|
||||||
|
start_search_flag != HA_READ_KEY_EXACT ||
|
||||||
|
end_search_flag != HA_READ_AFTER_KEY)
|
||||||
|
return HA_POS_ERROR; // Can't only use exact keys
|
||||||
|
return 10; // Good guess
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1010,7 +1010,8 @@ int ha_myisam::create(const char *name, register TABLE *table,
|
|||||||
for (i=0; i < table->keys ; i++, pos++)
|
for (i=0; i < table->keys ; i++, pos++)
|
||||||
{
|
{
|
||||||
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
|
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
|
||||||
keydef[i].key_alg=pos->algorithm;
|
keydef[i].key_alg=pos->algorithm == HA_KEY_ALG_UNDEF ?
|
||||||
|
HA_KEY_ALG_BTREE : pos->algorithm;
|
||||||
keydef[i].seg=keyseg;
|
keydef[i].seg=keyseg;
|
||||||
keydef[i].keysegs=pos->key_parts;
|
keydef[i].keysegs=pos->key_parts;
|
||||||
for (j=0 ; j < pos->key_parts ; j++)
|
for (j=0 ; j < pos->key_parts ; j++)
|
||||||
|
@ -1106,7 +1106,7 @@ bool Item_sum_count_distinct::add()
|
|||||||
if(tree_to_myisam())
|
if(tree_to_myisam())
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0))
|
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0, tree.custom_arg))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if ((error=table->file->write_row(table->record[0])))
|
else if ((error=table->file->write_row(table->record[0])))
|
||||||
|
@ -309,10 +309,10 @@ void field_str::add()
|
|||||||
{
|
{
|
||||||
if (res != &s)
|
if (res != &s)
|
||||||
s.copy(*res);
|
s.copy(*res);
|
||||||
if (!tree_search(&tree, (void*) &s)) // If not in tree
|
if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
|
||||||
{
|
{
|
||||||
s.copy(); // slow, when SAFE_MALLOC is in use
|
s.copy(); // slow, when SAFE_MALLOC is in use
|
||||||
if (!tree_insert(&tree, (void*) &s, 0))
|
if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
|
||||||
{
|
{
|
||||||
room_in_tree = 0; // Remove tree, out of RAM ?
|
room_in_tree = 0; // Remove tree, out of RAM ?
|
||||||
delete_tree(&tree);
|
delete_tree(&tree);
|
||||||
@ -411,7 +411,7 @@ void field_real::add()
|
|||||||
|
|
||||||
if (room_in_tree)
|
if (room_in_tree)
|
||||||
{
|
{
|
||||||
if (!(element = tree_insert(&tree, (void*) &num, 0)))
|
if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
|
||||||
{
|
{
|
||||||
room_in_tree = 0; // Remove tree, out of RAM ?
|
room_in_tree = 0; // Remove tree, out of RAM ?
|
||||||
delete_tree(&tree);
|
delete_tree(&tree);
|
||||||
@ -464,7 +464,7 @@ void field_longlong::add()
|
|||||||
|
|
||||||
if (room_in_tree)
|
if (room_in_tree)
|
||||||
{
|
{
|
||||||
if (!(element = tree_insert(&tree, (void*) &num, 0)))
|
if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
|
||||||
{
|
{
|
||||||
room_in_tree = 0; // Remove tree, out of RAM ?
|
room_in_tree = 0; // Remove tree, out of RAM ?
|
||||||
delete_tree(&tree);
|
delete_tree(&tree);
|
||||||
@ -518,7 +518,7 @@ void field_ulonglong::add()
|
|||||||
|
|
||||||
if (room_in_tree)
|
if (room_in_tree)
|
||||||
{
|
{
|
||||||
if (!(element = tree_insert(&tree, (void*) &num, 0)))
|
if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
|
||||||
{
|
{
|
||||||
room_in_tree = 0; // Remove tree, out of RAM ?
|
room_in_tree = 0; // Remove tree, out of RAM ?
|
||||||
delete_tree(&tree);
|
delete_tree(&tree);
|
||||||
|
@ -751,7 +751,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (tree.elements_in_tree > max_elements && flush())
|
if (tree.elements_in_tree > max_elements && flush())
|
||||||
return 1;
|
return 1;
|
||||||
return !tree_insert(&tree,ptr,0);
|
return !tree_insert(&tree, ptr, 0, tree.custom_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get(TABLE *table);
|
bool get(TABLE *table);
|
||||||
|
@ -454,7 +454,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||||||
key_info->flags = HA_NOSAME;
|
key_info->flags = HA_NOSAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_info->algorithm = key->algorithm;
|
|
||||||
key_info->key_parts=(uint8) key->columns.elements;
|
key_info->key_parts=(uint8) key->columns.elements;
|
||||||
key_info->key_part=key_part_info;
|
key_info->key_part=key_part_info;
|
||||||
key_info->usable_key_parts= key_number;
|
key_info->usable_key_parts= key_number;
|
||||||
|
@ -1153,7 +1153,7 @@ opt_unique_or_fulltext:
|
|||||||
| SPATIAL_SYM { $$= Key::SPATIAL; }
|
| SPATIAL_SYM { $$= Key::SPATIAL; }
|
||||||
|
|
||||||
key_alg:
|
key_alg:
|
||||||
/* empty */ { $$= HA_KEY_ALG_BTREE; }
|
/* empty */ { $$= HA_KEY_ALG_UNDEF; }
|
||||||
| USING opt_btree_or_rtree { $$= $2; }
|
| USING opt_btree_or_rtree { $$= $2; }
|
||||||
|
|
||||||
opt_btree_or_rtree:
|
opt_btree_or_rtree:
|
||||||
|
22
sql/table.cc
22
sql/table.cc
@ -415,28 +415,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyinfo->name[0]=='S')
|
|
||||||
keyinfo->flags |= HA_SPATIAL;
|
|
||||||
|
|
||||||
#ifdef BAR_DIRTY_HACK
|
|
||||||
keyinfo->key_alg=HA_KEY_ALG_BTREE; // BAR : btree by default
|
|
||||||
|
|
||||||
// BAR FIXME: Dirty hack while waiting for new .frm format
|
|
||||||
switch(keyinfo->name[0]){
|
|
||||||
case 'R':
|
|
||||||
keyinfo->key_alg=HA_KEY_ALG_RTREE;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
keyinfo->key_alg = HA_KEY_ALG_RTREE;
|
|
||||||
keyinfo->flags |= HA_SPATIAL;
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
default:
|
|
||||||
keyinfo->key_alg=HA_KEY_ALG_BTREE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
|
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
|
||||||
{
|
{
|
||||||
if (new_field_pack_flag <= 1)
|
if (new_field_pack_flag <= 1)
|
||||||
|
Reference in New Issue
Block a user