From 2e1a0c031a0ea3d7505690c6999d5d13e2a3dfe6 Mon Sep 17 00:00:00 2001 From: "ram@mysql.r18.ru" <> Date: Mon, 7 Oct 2002 17:49:03 +0500 Subject: [PATCH] auto_increment for heap tables test case --- heap/hp_create.c | 6 ++++- heap/hp_hash.c | 48 ++++++++++++++++++++++++++++++++++++++ heap/hp_info.c | 2 ++ heap/hp_test1.c | 6 ++++- heap/hp_test2.c | 7 ++++-- heap/hp_update.c | 12 ++++++---- heap/hp_write.c | 2 ++ include/heap.h | 16 +++++++++++-- mysql-test/r/create.result | 3 +-- mysql-test/t/create.test | 4 ++-- sql/ha_heap.cc | 35 ++++++++++++++++++++++++--- sql/ha_heap.h | 5 ++-- 12 files changed, 127 insertions(+), 19 deletions(-) diff --git a/heap/hp_create.c b/heap/hp_create.c index 7eee6eaa64d..6c38d54cb12 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -21,7 +21,8 @@ static void init_block(HP_BLOCK *block,uint reclength,ulong min_records, ulong max_records); int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, - uint reclength, ulong max_records, ulong min_records) + uint reclength, ulong max_records, ulong min_records, + HP_CREATE_INFO *create_info) { uint i, j, key_segs, max_length, length; HP_SHARE *share; @@ -120,6 +121,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, share->keys= keys; share->max_key_length= max_length; share->changed= 0; + share->auto_key= create_info->auto_key; + share->auto_key_type= create_info->auto_key_type; + share->auto_increment= create_info->auto_increment; if (!(share->name= my_strdup(name,MYF(0)))) { my_free((gptr) share,MYF(0)); diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 4f7dc956cba..0145e0d503c 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -537,3 +537,51 @@ my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const byte *record) } return 0; } + +void heap_update_auto_increment(HP_INFO *info, const byte *record) +{ + ulonglong value; + HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg; + const uchar *key= (uchar*) record + keyseg->start; + + switch (info->s->auto_key_type) { + case HA_KEYTYPE_INT8: + case HA_KEYTYPE_BINARY: + value= (ulonglong) *(uchar*) key; + break; + case HA_KEYTYPE_SHORT_INT: + case HA_KEYTYPE_USHORT_INT: + value= (ulonglong) uint2korr(key); + break; + case HA_KEYTYPE_LONG_INT: + case HA_KEYTYPE_ULONG_INT: + value= (ulonglong) uint4korr(key); + break; + case HA_KEYTYPE_INT24: + case HA_KEYTYPE_UINT24: + value= (ulonglong) uint3korr(key); + break; + case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ + { + float f_1; + float4get(f_1, key); + value= (ulonglong) f_1; + break; + } + case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ + { + double f_1; + float8get(f_1, key); + value= (ulonglong) f_1; + break; + } + case HA_KEYTYPE_LONGLONG: + case HA_KEYTYPE_ULONGLONG: + value= uint8korr(key); + break; + default: + value= 0; /* Error */ + break; + } + set_if_bigger(info->s->auto_increment, value); +} diff --git a/heap/hp_info.c b/heap/hp_info.c index 3e9d6b6a90b..3122a665fac 100644 --- a/heap/hp_info.c +++ b/heap/hp_info.c @@ -55,5 +55,7 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x, x->index_length= info->s->index_length; x->max_records = info->s->max_records; x->errkey = info->errkey; + if (flag & HA_STATUS_AUTO) + x->auto_increment= info->s->auto_increment + 1; DBUG_RETURN(0); } /* heap_info */ diff --git a/heap/hp_test1.c b/heap/hp_test1.c index 58a13efc12f..2e0a57a12d3 100644 --- a/heap/hp_test1.c +++ b/heap/hp_test1.c @@ -37,11 +37,14 @@ int main(int argc, char **argv) const char *filename; HP_KEYDEF keyinfo[10]; HA_KEYSEG keyseg[4]; + HP_CREATE_INFO hp_create_info; MY_INIT(argv[0]); filename= "test1"; get_options(argc,argv); + bzero(&hp_create_info, sizeof(hp_create_info)); + keyinfo[0].keysegs=1; keyinfo[0].seg=keyseg; keyinfo[0].algorithm= HA_KEY_ALG_HASH; @@ -55,7 +58,8 @@ int main(int argc, char **argv) bzero((gptr) flags,sizeof(flags)); printf("- Creating heap-file\n"); - if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l) || + if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l, + &hp_create_info) || !(file= heap_open(filename, 2))) goto err; printf("- Writing records:s\n"); diff --git a/heap/hp_test2.c b/heap/hp_test2.c index 3355c94727b..73e8039d125 100644 --- a/heap/hp_test2.c +++ b/heap/hp_test2.c @@ -63,6 +63,7 @@ int main(int argc, char *argv[]) HP_KEYDEF keyinfo[MAX_KEYS]; HA_KEYSEG keyseg[MAX_KEYS*5]; HEAP_PTR position; + HP_CREATE_INFO hp_create_info; MY_INIT(argv[0]); /* init my_sys library & pthreads */ LINT_INIT(position); @@ -70,6 +71,8 @@ int main(int argc, char *argv[]) filename2= "test2_2"; file=file2=0; get_options(argc,argv); + + bzero(&hp_create_info, sizeof(hp_create_info)); write_count=update=opt_delete=0; key_check=0; @@ -122,7 +125,7 @@ int main(int argc, char *argv[]) printf("- Creating heap-file\n"); if (heap_create(filename,keys,keyinfo,reclength,(ulong) flag*100000L, - (ulong) recant/2) || + (ulong) recant/2, &hp_create_info) || !(file= heap_open(filename, 2))) goto err; signal(SIGINT,endprog); @@ -557,7 +560,7 @@ int main(int argc, char *argv[]) heap_close(file2); printf("- Creating output heap-file 2\n"); - if (heap_create(filename2,1,keyinfo,reclength,0L,0L) || + if (heap_create(filename2,1,keyinfo,reclength,0L,0L,&hp_create_info) || !(file2= heap_open(filename2, 2))) goto err; diff --git a/heap/hp_update.c b/heap/hp_update.c index dd47e04ebc2..dd7374f506c 100644 --- a/heap/hp_update.c +++ b/heap/hp_update.c @@ -22,7 +22,8 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) { HP_KEYDEF *keydef, *end, *p_lastinx; byte *pos; - HP_SHARE *share=info->s; + bool auto_key_changed= 0; + HP_SHARE *share= info->s; DBUG_ENTER("heap_update"); test_active(info); @@ -33,20 +34,23 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new) if (--(share->records) < share->blength >> 1) share->blength>>= 1; share->changed=1; - p_lastinx = share->keydef + info->lastinx; - for (keydef = share->keydef, end = keydef + share->keys; keydef < end; - keydef++) + p_lastinx= share->keydef + info->lastinx; + for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++) { if (hp_rec_key_cmp(keydef, old, heap_new)) { if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) || (*keydef->write_key)(info, keydef, heap_new, pos)) goto err; + if (share->auto_key == (uint) (keydef - share->keydef + 1)) + auto_key_changed= 1; } } memcpy(pos,heap_new,(size_t) share->reclength); if (++(share->records) == share->blength) share->blength+= share->blength; + if (auto_key_changed) + heap_update_auto_increment(info, heap_new); DBUG_RETURN(0); err: diff --git a/heap/hp_write.c b/heap/hp_write.c index 33527855e60..9edd897eb34 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -61,6 +61,8 @@ int heap_write(HP_INFO *info, const byte *record) info->current_ptr=pos; info->current_hash_ptr=0; info->update|=HA_STATE_AKTIV; + if (share->auto_key) + heap_update_auto_increment(info, record); DBUG_RETURN(0); err: DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef)); diff --git a/include/heap.h b/include/heap.h index 359c4346a5d..3702d88ac70 100644 --- a/include/heap.h +++ b/include/heap.h @@ -50,6 +50,7 @@ typedef struct st_heapinfo /* Struct from heap_info */ ulong index_length; uint reclength; /* Length of one record */ int errkey; + ulonglong auto_increment; } HEAPINFO; @@ -115,6 +116,9 @@ typedef struct st_heap_share #endif my_bool delete_on_close; LIST open_list; + uint auto_key; + uint auto_key_type; /* real type of the auto key segment */ + ulonglong auto_increment; } HP_SHARE; struct st_hp_hash_info; @@ -140,6 +144,13 @@ typedef struct st_heap_info LIST open_list; } HP_INFO; +typedef struct st_heap_create_info +{ + uint auto_key; + uint auto_key_type; + ulonglong auto_increment; +} HP_CREATE_INFO; + /* Prototypes for heap-functions */ extern HP_INFO *heap_open(const char *name, int mode); @@ -152,7 +163,8 @@ extern int heap_scan(register HP_INFO *info, byte *record); extern int heap_delete(HP_INFO *info,const byte *buff); extern int heap_info(HP_INFO *info,HEAPINFO *x,int flag); extern int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, - uint reclength, ulong max_records, ulong min_records); + uint reclength, ulong max_records, ulong min_records, + HP_CREATE_INFO *create_info); extern int heap_delete_table(const char *name); extern int heap_extra(HP_INFO *info,enum ha_extra_function function); extern int heap_rename(const char *old_name,const char *new_name); @@ -163,7 +175,7 @@ extern int heap_rprev(HP_INFO *info,byte *record); extern int heap_rfirst(HP_INFO *info,byte *record,int inx); extern int heap_rlast(HP_INFO *info,byte *record,int inx); extern void heap_clear(HP_INFO *info); - +extern void heap_update_auto_increment(HP_INFO *info, const byte *record); 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, diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 9b56b2b5160..6eaef1f5d24 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -22,14 +22,13 @@ drop table if exists t1,t2; create table t1 (b char(0) not null, index(b)); The used table handler can't index column 'b' create table t1 (a int not null auto_increment,primary key (a)) type=heap; -The used table type doesn't support AUTO_INCREMENT columns create table t1 (a int not null,b text) type=heap; The used table type doesn't support BLOB/TEXT columns create table t1 (a int ,primary key(a)) type=heap; All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead drop table if exists t1; create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; -The used table type doesn't support AUTO_INCREMENT columns +Incorrect table definition; There can only be one auto column and it must be defined as a key create table t1 (ordid int(8), primary key (ordid)); All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead create table not_existing_database.test (a int); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 47ee55620e4..65be9683061 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -22,12 +22,12 @@ drop table if exists t1; !$1146 create table t2 select auto+1 from t1; drop table if exists t1,t2; !$1167 create table t1 (b char(0) not null, index(b)); -!$1164 create table t1 (a int not null auto_increment,primary key (a)) type=heap; +create table t1 (a int not null auto_increment,primary key (a)) type=heap; !$1163 create table t1 (a int not null,b text) type=heap; !$1171 create table t1 (a int ,primary key(a)) type=heap; drop table if exists t1; -!$1164 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; +!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap; !$1171 create table t1 (ordid int(8), primary key (ordid)); -- error 1044,1 diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 5c314462666..6cfd3c881cc 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -35,7 +35,9 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { if (!(file= heap_open(name, mode)) && my_errno == ENOENT) { - if (!create(name, table, NULL)) + HA_CREATE_INFO create_info; + bzero(&create_info, sizeof(create_info)); + if (!create(name, table, &create_info)) file= heap_open(name, mode); } return (file ? 0 : 1); @@ -51,6 +53,8 @@ int ha_heap::write_row(byte * buf) statistic_increment(ha_write_count,&LOCK_status); if (table->time_stamp) update_timestamp(buf+table->time_stamp-1); + if (table->next_number_field && buf == table->record[0]) + update_auto_increment(); return heap_write(file,buf); } @@ -161,6 +165,8 @@ void ha_heap::info(uint flag) index_file_length=info.index_length; max_data_file_length= info.max_records* info.reclength; delete_length= info.deleted * info.reclength; + if (flag & HA_STATUS_AUTO) + auto_increment_value= info.auto_increment; } int ha_heap::extra(enum ha_extra_function operation) @@ -234,11 +240,11 @@ ha_rows ha_heap::records_in_range(int inx, } } - int ha_heap::create(const char *name, TABLE *table, HA_CREATE_INFO *create_info) { uint key, parts, mem_per_row= 0; + uint auto_key= 0, auto_key_type= 0; ulong max_rows; HP_KEYDEF *keydef; HA_KEYSEG *seg; @@ -296,19 +302,42 @@ int ha_heap::create(const char *name, TABLE *table, seg->null_bit= 0; seg->null_pos= 0; } + if (field->flags & AUTO_INCREMENT_FLAG) + { + auto_key= key + 1; + auto_key_type= field->key_type(); + } } } mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*)); max_rows = (ulong) (current_thd->variables.max_heap_table_size / mem_per_row); + HP_CREATE_INFO hp_create_info; + hp_create_info.auto_key= auto_key; + hp_create_info.auto_key_type= auto_key_type; + hp_create_info.auto_increment= (create_info->auto_increment_value ? + create_info->auto_increment_value - 1 : 0); error= heap_create(fn_format(buff,name,"","",4+2), table->keys,keydef, table->reclength, ((table->max_rows < max_rows && table->max_rows) ? table->max_rows : max_rows), - table->min_rows); + table->min_rows, &hp_create_info); my_free((gptr) keydef, MYF(0)); if (file) info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); ref_length= sizeof(HEAP_PTR); return (error); } + +void ha_heap::update_create_info(HA_CREATE_INFO *create_info) +{ + table->file->info(HA_STATUS_AUTO); + if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) + create_info->auto_increment_value= auto_increment_value; +} + +longlong ha_heap::get_auto_increment() +{ + ha_heap::info(HA_STATUS_AUTO); + return auto_increment_value; +} diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 504f5262bf3..f82a1a460d8 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -40,8 +40,7 @@ class ha_heap: public handler ulong table_flags() const { return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS | - HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ | - HA_NO_AUTO_INCREMENT); + HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ); } ulong index_flags(uint inx) const { @@ -63,6 +62,7 @@ class ha_heap: public handler int write_row(byte * buf); int update_row(const byte * old_data, byte * new_data); int delete_row(const byte * buf); + longlong get_auto_increment(); int index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag); int index_read_idx(byte * buf, uint idx, const byte * key, @@ -87,6 +87,7 @@ class ha_heap: public handler int delete_table(const char *from); int rename_table(const char * from, const char * to); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); + void update_create_info(HA_CREATE_INFO *create_info); THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type);