From 9195963f56122b3ca7fa480607b8da9ae969a364 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Oct 2002 17:49:03 +0500 Subject: [PATCH 01/11] auto_increment for heap tables test case heap/hp_create.c: auto_increment for heap tables heap/hp_hash.c: auto_increment for heap tables heap/hp_info.c: auto_increment for heap tables heap/hp_test1.c: auto_increment for heap tables heap/hp_test2.c: auto_increment for heap tables heap/hp_update.c: auto_increment for heap tables heap/hp_write.c: auto_increment for heap tables include/heap.h: auto_increment for heap tables mysql-test/r/create.result: auto_increment for heap tables mysql-test/t/create.test: auto_increment for heap tables sql/ha_heap.cc: auto_increment for heap tables sql/ha_heap.h: auto_increment for heap tables --- 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); From 0f623dcdeaf17f76272181a193acac387249da03 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Oct 2002 19:15:03 +0300 Subject: [PATCH 02/11] fixed dbd test results after EXPLAIN output changing --- mysql-test/r/bdb.result | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 7374e936c36..0abf48041d6 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -139,14 +139,14 @@ id parent_id level 1015 102 2 1010 102 2 explain select level from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 1 where used; Using index +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref level level 1 const 1 where used; Using index explain select level,id from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 1 where used; Using index +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref level level 1 const 1 where used; Using index explain select level,id,parent_id from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 1 where used +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref level level 1 const 1 where used select level,id from t1 where level=1; level id 1 1002 @@ -624,8 +624,8 @@ id parent_id level 1025 102 2 1016 102 2 explain select level from t1 where level=1; -table type possible_keys key key_len ref rows Extra -t1 ref level level 1 const 1 where used; Using index +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref level level 1 const 1 where used; Using index select level,id from t1 where level=1; level id 1 1004 From 31568581c557b8ed8d6b47874e50ddca808227e6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Oct 2002 22:21:17 +0300 Subject: [PATCH 03/11] fixed error handling bug mysql-test/r/subselect.result: test for error handling bug mysql-test/t/subselect.test: test for error handling bug --- mysql-test/r/subselect.result | 16 ++++++++++++++-- mysql-test/t/subselect.test | 19 +++++++++++++++++-- sql/item_subselect.cc | 18 ++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 911065890e2..ec5a12cdfc8 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1,7 +1,7 @@ select (select 2); (select 2) 2 -drop table if exists t1,t2,t3,t4,t5,attend,clinic; +drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; create table t1 (a int); create table t2 (a int, b int); create table t3 (a int); @@ -147,4 +147,16 @@ W 1 SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3); a b W a -drop table t1,t2,t3,t4,t5,attend,clinic; +drop table if exists inscrit; +CREATE TABLE `inscrit` ( +`pseudo` varchar(35) character set latin1 NOT NULL default '', +`email` varchar(60) character set latin1 NOT NULL default '', +PRIMARY KEY (`pseudo`), +UNIQUE KEY `email` (`email`) +) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC; +INSERT INTO inscrit (pseudo,email) VALUES ('joce','test'); +INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); +INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); +SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); +Subselect returns more than 1 record +drop table if exists inscrit; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index bf98090eb43..00d58c218aa 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1,6 +1,6 @@ select (select 2); -drop table if exists t1,t2,t3,t4,t5,attend,clinic; +drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; create table t1 (a int); create table t2 (a int, b int); create table t3 (a int); @@ -66,4 +66,19 @@ SELECT * FROM t1 WHERE b = (SELECT MIN(b) FROM t1); SELECT * FROM t2 WHERE b = (SELECT MIN(b) FROM t2); SELECT * FROM t3 WHERE b = (SELECT MIN(b) FROM t3); -drop table t1,t2,t3,t4,t5,attend,clinic; +drop table if exists inscrit; + +CREATE TABLE `inscrit` ( + `pseudo` varchar(35) character set latin1 NOT NULL default '', + `email` varchar(60) character set latin1 NOT NULL default '', + PRIMARY KEY (`pseudo`), + UNIQUE KEY `email` (`email`) +) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC; + +INSERT INTO inscrit (pseudo,email) VALUES ('joce','test'); +INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); +INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); +-- error 1240 +SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); + +drop table if exists inscrit; \ No newline at end of file diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 99fc0bcdb67..7e0b2e201ec 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -119,21 +119,30 @@ Item::Type Item_subselect::type() const double Item_singleval_subselect::val () { if (engine->exec()) + { + assign_null(); return 0; + } return real_value; } longlong Item_singleval_subselect::val_int () { if (engine->exec()) + { + assign_null(); return 0; + } return int_value; } String *Item_singleval_subselect::val_str (String *str) { if (engine->exec() || null_value) + { + assign_null(); return 0; + } return &str_value; } @@ -157,21 +166,30 @@ void Item_exists_subselect::fix_length_and_dec() double Item_exists_subselect::val () { if (engine->exec()) + { + assign_null(); return 0; + } return (double) value; } longlong Item_exists_subselect::val_int () { if (engine->exec()) + { + assign_null(); return 0; + } return value; } String *Item_exists_subselect::val_str(String *str) { if (engine->exec()) + { + assign_null(); return 0; + } str->set(value); return str; } From 12c336e7100c84a2b337dcf72bfe0c5947d81205 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 12:47:24 +1000 Subject: [PATCH 04/11] Syncing with 4.0 docs. --- Docs/manual.texi | 177 +++++++++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 76 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index d9e6afc4cfc..57b91920b36 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -6957,21 +6957,30 @@ Follow the instructions to install it. @item After @code{BitKeeper} is installed, first go to the directory you -want to work from, and then use this command if you want to clone -the MySQL 3.23 branch: +want to work from, and then use one of the following commands to clone +the MySQL version branch of your choice: + +To clone the 3.23 branch, use this command: @example -shell> bk clone bk://work.mysql.com:7000 mysql +shell> bk clone bk://work.mysql.com:7000 mysql-3.23 @end example -To clone the 4.0 branch, use this command instead: +To clone the 4.0 branch, use this command: @example shell> bk clone bk://work.mysql.com:7001 mysql-4.0 @end example -In the preceding examples the source tree will be set up in the @file{mysql/} -or @file{mysql-4.0/} subdirectory of your current directory. +To clone the 4.1 branch, use this command: + +@example +shell> bk clone bk://work.mysql.com:7004 mysql-4.1 +@end example + +In the preceding examples the source tree will be set up in the +@file{mysql-3.23/}, @file{mysql-4.0/}, or @file{mysql-4.1/} +subdirectory of your current directory. The initial download of the source tree may take a while, depending on the speed of your connection; be patient. @@ -8400,7 +8409,7 @@ or @code{myisamchk} for @code{MyISAM} tables (@file{.MYI}) and @item If you want your @code{mysqldump} files to be compatible between MySQL Version 3.22 and Version 3.23, you should not use the -@code{--opt} or @code{--full} option to @code{mysqldump}. +@code{--opt} or @code{--all} option to @code{mysqldump}. @item Check all your calls to @code{DATE_FORMAT()} to make sure there is a @@ -16051,7 +16060,9 @@ Values in the scope fields may be specified as follows: @itemize @bullet @item The wildcard characters @samp{%} and @samp{_} can be used in the @code{Host} -and @code{Db} fields of either table. +and @code{Db} fields of either table. If you wish to use for instance a +@samp{_} character as part of a database name, specify it as @samp{\_} in +the @code{GRANT} command. @item A @code{'%'} @code{Host} value in the @code{db} table means ``any host.'' A @@ -16676,6 +16687,13 @@ database privileges by using @code{ON db_name.*} syntax. If you specify that database. (@strong{Warning}: if you specify @code{ON *} and you @strong{don't} have a current database, you will affect the global privileges!) +@strong{Please note}: the @samp{_} and @samp{%} wildcards are allowed when +specifying database names in @code{GRANT} commands. This means that if you +wish to use for instance a @samp{_} character as part of a database name, +you should specify it as @samp{\_} in the @code{GRANT} command, to prevent +the user from being able to access additional databases matching the +wildcard pattern, e.g., @code{GRANT ... ON `foo\_bar`.* TO ...}. + In order to accommodate granting rights to users from arbitrary hosts, MySQL supports specifying the @code{user_name} value in the form @code{user@@host}. If you want to specify a @code{user} string @@ -16684,8 +16702,8 @@ containing special characters or wildcard characters (such as @samp{%}), you can quote the user or host name (for example, @code{'test-user'@@'test-hostname'}). You can specify wildcards in the hostname. For example, -@code{user@@"%.loc.gov"} applies to @code{user} for any host in the -@code{loc.gov} domain, and @code{user@@"144.155.166.%"} applies to @code{user} +@code{user@@'%.loc.gov'} applies to @code{user} for any host in the +@code{loc.gov} domain, and @code{user@@'144.155.166.%'} applies to @code{user} for any host in the @code{144.155.166} class C subnet. The simple form @code{user} is a synonym for @code{user@@"%"}. @@ -17703,7 +17721,7 @@ the @code{mysqlhotcopy script}. @xref{mysqldump, , @code{mysqldump}}. Do a full backup of your databases: @example -shell> mysqldump --tab=/path/to/some/dir --opt --full +shell> mysqldump --tab=/path/to/some/dir --opt --all or @@ -19931,7 +19949,7 @@ cache. The value of the @code{--bdb-home} option. @item @code{bdb_max_lock} -The maximum number of locks (1000 by default) you can have active on a +The maximum number of locks (10,000 by default) you can have active on a BDB table. You should increase this if you get errors of type @code{bdb: Lock table is out of available locks} or @code{Got error 12 from ...} when you have do long transactions or when @code{mysqld} has to examine @@ -20030,15 +20048,15 @@ The maximum length of the word to be included in a @code{FULLTEXT} index. @strong{Note: @code{FULLTEXT} indexes must be rebuilt after changing this variable.} (This option is new for MySQL 4.0.) -@item @code{ft_max_word_len_sort} +@item @code{ft_max_word_len_for_sort} The maximum length of the word in a @code{FULLTEXT} index to be used in fast index recreation method in @code{REPAIR}, @code{CREATE INDEX}, or @code{ALTER TABLE}. Longer words are inserted the slow way. The rule of the thumb is as follows: with -@code{ft_max_word_len_sort} increasing, @strong{MySQL} will create bigger +@code{ft_max_word_len_for_sort} increasing, @strong{MySQL} will create bigger temporary files (thus slowing the process down, due to disk I/O), and will put fewer keys in one sort block (again, decreasing the efficiency). When -@code{ft_max_word_len_sort} is too small, instead, @strong{MySQL} will insert a +@code{ft_max_word_len_for_sort} is too small, instead, @strong{MySQL} will insert a lot of words into index the slow way, but short words will be inserted very quickly. @@ -23324,7 +23342,7 @@ If you need better performance when you start using MySQL in a production environment, you can remove the @code{--log} option from @code{mysql.server} or change it to @code{--log-bin}. @xref{Binary log}. -The entries in this log are written as @code{mysqld} receives the queries. +The entries in this log are written as @code{mysqld} receives the questions. This may be different from the order in which the statements are executed. This is in contrast to the update log and the binary log which are written after the query is executed, but before any locks are released. @@ -23337,7 +23355,7 @@ after the query is executed, but before any locks are released. @cindex files, update log @strong{Note}: the update log is replaced by the binary -log. @xref{Binary log}. You can do anything with the binary log that you can do +log. @xref{Binary log}. With this you can do anything that you can do with the update log. When started with the @code{--log-update[=file_name]} option, @@ -23352,7 +23370,7 @@ flush-logs}, execute the @code{FLUSH LOGS} statement, or restart the server. @strong{Note}: for the above scheme to work, you must not create your own files with the same filename as the update log + some extensions -that may be regarded as a number in the directory used by the update log! +that may be regarded as a number, in the directory used by the update log! If you use the @code{--log} or @code{-l} options, @code{mysqld} writes a general log with a filename of @file{hostname.log}, and restarts and @@ -23396,8 +23414,8 @@ and the crash. @cindex binary log @cindex files, binary log -The binary log will replace the now deprecated update log, so -we recommend you to switch to this log format as soon as possible. +The intention is that the binary log should replace the update log, so +we recommend you to switch to this log format as soon as possible! The binary log contains all information that is available in the update log in a more efficient format. It also contains information about how long @@ -23408,10 +23426,10 @@ find a problem query) you should use the general query log. @xref{Query log}. The binary log is also used when you are replicating a slave from a master. @xref{Replication}. -When started with the @code{--log-bin[=file_name]} option @code{mysqld} +When started with the @code{--log-bin[=file_name]} option, @code{mysqld} writes a log file containing all SQL commands that update data. If no -file name is given it defaults to the name of the host machine followed -by @code{-bin}. If a file name is given, but doesn't contain a path, the +file name is given, it defaults to the name of the host machine followed +by @code{-bin}. If file name is given, but it doesn't contain a path, the file is written in the data directory. If you supply an extension to @code{--log-bin=filename.extension}, the @@ -23431,9 +23449,14 @@ to the binary log: @multitable @columnfractions .38 .62 @item @strong{Option} @tab @strong{Description} -@item @code{binlog-do-db=database_name} @tab Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned. (Example: @code{binlog-do-db=some_database}) +@item @code{binlog-do-db=database_name} @tab +Tells the master it should log updates for the specified database, and +exclude all others not explicitly mentioned. +(Example: @code{binlog-do-db=some_database}) -@item @code{binlog-ignore-db=database_name} @tab Tells the master that updates to the given database should not be logged to the binary log (Example: @code{binlog-ignore-db=some_database}) +@item @code{binlog-ignore-db=database_name} @tab +Tells the master that updates to the given database should not be logged +to the binary log (Example: @code{binlog-ignore-db=some_database}) @end multitable To be able to know which different binary log files have been used, @@ -23458,10 +23481,10 @@ shell> mysqlbinlog log-file | mysql -h server_name @end example You can also use the @code{mysqlbinlog} program to read the binary log -directly from a remote MySQL server. +directly from a remote MySQL server! @code{mysqlbinlog --help} will give you more information of how to use -this program. +this program! If you are using @code{BEGIN [WORK]} or @code{SET AUTOCOMMIT=0}, you must use the MySQL binary log for backups instead of the old update log. @@ -23470,13 +23493,14 @@ The binary logging is done immediately after a query completes but before any locks are released or any commit is done. This ensures that the log will be logged in the execution order. -Updates to a non-transactional table are stored in the binary log at -once. For transactional tables such as @code{BDB} ! or @code{InnoDB} -tables, all updates are cached until a @code{COMMIT}. Every thread -will, on start, allocate a buffer of @code{binlog_cache_size} to buffer -queries. If a query is bigger than this, the thread will open a -temporary file to handle the bigger cache. The temporary file will be -deleted when the thread ends. +Updates to non-transactional tables are stored in the binary log +immediately after execution. For transactional tables such as @code{BDB} +or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE} +or @code{INSERT}) that change tables are cached until a @code{COMMIT}. +Every thread will, on start, allocate a buffer of @code{binlog_cache_size} +to buffer queries. If a query is bigger than this, the thread will open +a temporary file to handle the bigger cache. The temporary file will +be deleted when the thread ends. The @code{max_binlog_cache_size} can be used to restrict the total size used to cache a multi-query transaction. @@ -23499,10 +23523,10 @@ more than @code{long_query_time} to execute. The time to get the initial table locks are not counted as execution time. The slow query log is logged after the query is executed and after all -locks have been released. This may be different from the order in which +locks has been released. This may be different from the order in which the statements are executed. -If no filename is given, it defaults to the name of the host machine +If no file name is given, it defaults to the name of the host machine suffixed with @code{-slow.log}. If a filename is given, but doesn't contain a path, the file is written in the data directory. @@ -23512,8 +23536,8 @@ can become a difficult task. You can pipe the slow query log through the @code{mysqldumpslow} command to get a summary of the queries which appear in the log. -If you use @code{--log-long-format} also, then queries that do not -use indexes are logged as well. @xref{Command-line options}. +You are using @code{--log-long-format} then also queries that are not +using indexes are printed. @xref{Command-line options}. @node Log file maintenance, , Slow query log, Log Files @@ -23523,19 +23547,22 @@ use indexes are logged as well. @xref{Command-line options}. @cindex maintaining, log files @cindex log files, maintaining -MySQL has many log files which makes it easy to see what is going on. -@xref{Log Files}. One must, however, occasionally clean up -after @code{MySQL} to ensure that the logs don't take up too much disk -space by either removing or backing up old log files and then telling MySQL -to start logging to new files. @xref{Backup}. +The MySQL Server can create a number of different log files, which make +it easy to see what is going on. @xref{Log Files}. One must however +regularly clean up these files, to ensure that the logs don't take up +too much disk space. -On a Linux (@code{Redhat}) installation you can use the +When using MySQL with log files, you will, from time to time, +want to remove/backup old log files and tell MySQL to start +logging on new files. @xref{Backup}. + +On a Linux (@code{Redhat}) installation, you can use the @code{mysql-log-rotate} script for this. If you installed MySQL -from an RPM distribution the script should have been installed -automatically. @strong{Note}: you should be careful with this if you are -using the logs for replication. +from an RPM distribution, the script should have been installed +automatically. Note that you should be careful with this if you are using +the log for replication! -On other systems you must install a short script yourself that you can +On other systems you must install a short script yourself that you start from @code{cron} to handle log files. You can force MySQL to start using new log files by using @@ -24203,7 +24230,7 @@ ignore, use the directive multiple times, once for each database. You should not use this directive if you are using cross table updates and you don't want these update to be replicated. -The main reason for this behavior is that it's hard from the command +The main reason for this behaviour is that it's hard from the command alone know if a query should be replicated or not; For example if you are using multi-table-delete or multi-table-update commands in MySQL 4.x that goes across multiple databases. It's also very fast to just check @@ -24294,10 +24321,16 @@ summary of commands: @item @strong{Command} @tab @strong{Description} @item @code{SLAVE START} - @tab Starts the slave thread. (Slave) + @tab Starts the slave thread. +As of MySQL 4.0.2, you can add @code{IO_THREAD} or @code{SQL_THREAD} +options to the statement to start the I/O thread or the SQL thread. +The I/O thread reads queries from the master server and stores them in the +relay log. The SQL thread reads the relay log and executes the queries. +(Slave) @item @code{SLAVE STOP} - @tab Stops the slave thread. (Slave) + @tab Stops the slave thread. Like @code{SLAVE START}, this statement +may be used with @code{IO_THREAD} and @code{SQL_THREAD} options. (Slave) @item @code{SET SQL_LOG_BIN=0} @tab Disables update logging if the user has the @code{SUPER} privilege. @@ -31225,7 +31258,7 @@ mysql> SELECT IF(STRCMP('test','test1'),'no','yes'); If @code{expr2} or @code{expr3} is explicitely @code{NULL} then the result type of the @code{IF()} function is the type of the not -@code{NULL} column. (This behavior is new in MySQL 4.0.3). +@code{NULL} column. (This behaviour is new in MySQL 4.0.3). @code{expr1} is evaluated as an integer value, which means that if you are testing floating-point or string values, you should do so using a comparison @@ -35001,6 +35034,7 @@ DELAYED} when you are really sure you need it! UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2, ...] [WHERE where_definition] + [ORDER BY ...] [LIMIT #] @end example @@ -36226,10 +36260,8 @@ mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT, This will create a @code{MyISAM} table with three columns, a, b, and c. Notice that the columns from the @code{SELECT} statement are appended to -the right side of the table, not overlapped onto it. -Still, the column from the @code{SELECT} will overlap the column from -the @code{CREATE} clause if they both have the same name. Take the following -examples: +the right side of the table, not overlapped onto it. Take the following +example: @example mysql> SELECT * FROM foo; @@ -36250,18 +36282,6 @@ mysql> SELECT * FROM bar; | NULL | 1 | +------+---+ 1 row in set (0.00 sec) - -mysql> CREATE TABLE foobar (n FLOAT(3,2), m INT) SELECT n FROM foo; -Query OK, 1 row affected (0.02 sec) -Records: 1 Duplicates: 0 Warnings: 0 - -mysql> SELECT * FROM foobar; -+------+------+ -| n | m | -+------+------+ -| 1.00 | NULL | -+------+------+ -1 row in set (0.00 sec) @end example For each row in table @code{foo}, a row is inserted in @code{bar} with @@ -36615,7 +36635,7 @@ deleted due to duplication of unique key values. The @code{FOREIGN KEY}, @code{CHECK}, and @code{REFERENCES} clauses don't actually do anything, except for InnoDB type tables which support @code{ADD CONSTRAINT FOREIGN KEY (...) REFERENCES ... (...)}. -Note that InnoDB does not allow a constraint @code{symbol} or @code{index_name} +Note that InnoDB does not allow an @code{index_name} to be specified. @xref{InnoDB}. The syntax for other table types is provided only for compatibility, to make it easier to port code from other SQL servers and to run applications @@ -39268,7 +39288,7 @@ constraints to guard the integrity of your data. The syntax of a foreign key constraint definition in InnoDB: @example -FOREIGN KEY (index_col_name, ...) +[CONSTRAINT symbol] FOREIGN KEY (index_col_name, ...) REFERENCES table_name (index_col_name, ...) [ON DELETE CASCADE | ON DELETE SET NULL] @end example @@ -39327,7 +39347,7 @@ Starting from version 3.23.50 InnoDB allows you to add a new foreign key constraint to a table through @example ALTER TABLE yourtablename - ADD CONSTRAINT FOREIGN KEY (...) REFERENCES anothertablename(...) +ADD [CONSTRAINT symbol] FOREIGN KEY (...) REFERENCES anothertablename(...) @end example Remember to create the required indexes first, though. @@ -50833,8 +50853,10 @@ each individual 4.0.x release. @appendixsubsec Changes in release 4.0.5 @itemize @item -Give error if one has more than 2 ^ 32 rows in a MyISAM MERGE file and one -has not compiled MySQL with @code{-DBIG_TABLES}. +Small fix in @code{mysqld_safe} for some shells. +@item +Give error if a @code{MyISAM} @code{MERGE} table has more than 2 ^ 32 rows and +MySQL was not compiled with with @code{-DBIG_TABLES}. @item Fixed some @code{ORDER BY ... DESC} problems with InnoDB. @item @@ -50854,7 +50876,7 @@ Fixed bug where @code{GRANT}/@code{REVOKE} failed if hostname was given in not matching case. @item Don't give warning in @code{LOAD DATA INFILE} when setting a -@code{timestamp} to a string of '0'. +@code{timestamp} to a string value of @code{'0'}. @item Fixed bug in @code{myisamchk -R} mode. @item @@ -50927,7 +50949,7 @@ output in @code{SHOW GRANTS}. Fixed that @code{mysqld --help} reports correct values for @code{--datadir} and @code{--bind-address}. @item -Fixed that one can drop UDFs that didn't exist when mysqld was started. +Fixed that one can drop UDFs that didn't exist when @code{mysqld} was started. @item Fixed core dump problem with @code{SHOW VARIABLES} on some 64 bit systems (like Solaris sparc). @@ -51009,7 +51031,7 @@ that can be used as data values in queries. Changed variable @code{DELAY_KEY_WRITE} to an enum to allow one set @code{DELAY_KEY_WRITE} for all tables without taking down the server. @item -Changed behavior of @code{IF(condition,column,NULL)} so that it returns +Changed behaviour of @code{IF(condition,column,NULL)} so that it returns the value of the column type. @item Made @code{safe_mysqld} a symlink to @code{mysqld_safe} in binary distribution. @@ -51281,6 +51303,9 @@ Fixed bug in truncation operator for boolean full-text search. Allow value of @code{--user=#} option for @code{mysqld} to be specified as a numeric user ID. @item +Fixed a bug where @code{SQL_CALC_ROWS} returned an incorrect value when used +with one table and @code{ORDER BY} and with @code{InnoDB} tables. +@item Fixed that @code{SELECT 0 LIMIT 0} doesn't hang thread. @item Fixed some problems with @code{USE/IGNORE INDEX} when using From 76ab191d750cca3702a50f97619a13b135d95705 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 12:55:54 +1000 Subject: [PATCH 05/11] Sync wth 3.23 changelog. --- Docs/manual.texi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/manual.texi b/Docs/manual.texi index 57b91920b36..dfdbddcaae7 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -51692,6 +51692,8 @@ not yet 100% confident in this code. @appendixsubsec Changes in release 3.23.53 @itemize @bullet @item +Small fix in @code{mysqld_safe} for some shells. +@item Fixed that @code{SHOW STATUS} doesn't reset @code{Delayed_insert_threads}. @item Fixed core dump bug when using the @code{BINARY} cast on a @code{NULL} value. From f42287866540903c6aa95d969a53bd6b20452594 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 13:04:39 +1000 Subject: [PATCH 06/11] Update reserved words list (4.1) --- Docs/manual.texi | 185 +++++++++++++++++++++++++---------------------- 1 file changed, 97 insertions(+), 88 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index dfdbddcaae7..b846ae1871d 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -28984,7 +28984,7 @@ A few are reserved because MySQL needs them and is @c START_OF_RESERVED_WORDS -@c Reserved word list updated Tue Jul 23 20:41:20 2002 by monty. +@c Reserved word list updated Tue Oct 8 13:03:34 2002 by arjen. @c To regenerate, use Support/update-reserved-words.pl. @multitable @columnfractions .33 .33 .34 @@ -29006,38 +29006,41 @@ A few are reserved because MySQL needs them and is @item @code{BINARY} @tab @code{BLOB} @tab @code{BOTH} -@item @code{BY} +@item @code{BTREE} + @tab @code{BY} @tab @code{CASCADE} - @tab @code{CASE} -@item @code{CHANGE} +@item @code{CASE} + @tab @code{CHANGE} @tab @code{CHAR} - @tab @code{CHARACTER} -@item @code{COLUMN} - @tab @code{COLUMNS} +@item @code{CHARACTER} + @tab @code{COLLATE} + @tab @code{COLUMN} +@item @code{COLUMNS} @tab @code{CONSTRAINT} -@item @code{CREATE} - @tab @code{CROSS} + @tab @code{CREATE} +@item @code{CROSS} @tab @code{CURRENT_DATE} -@item @code{CURRENT_TIME} - @tab @code{CURRENT_TIMESTAMP} + @tab @code{CURRENT_TIME} +@item @code{CURRENT_TIMESTAMP} @tab @code{DATABASE} -@item @code{DATABASES} - @tab @code{DAY_HOUR} + @tab @code{DATABASES} +@item @code{DAY_HOUR} @tab @code{DAY_MINUTE} -@item @code{DAY_SECOND} - @tab @code{DEC} + @tab @code{DAY_SECOND} +@item @code{DEC} @tab @code{DECIMAL} -@item @code{DEFAULT} - @tab @code{DELAYED} + @tab @code{DEFAULT} +@item @code{DELAYED} @tab @code{DELETE} -@item @code{DESC} - @tab @code{DESCRIBE} + @tab @code{DESC} +@item @code{DESCRIBE} @tab @code{DISTINCT} -@item @code{DISTINCTROW} - @tab @code{DOUBLE} + @tab @code{DISTINCTROW} +@item @code{DOUBLE} @tab @code{DROP} -@item @code{ELSE} - @tab @code{ENCLOSED} + @tab @code{ELSE} +@item @code{ENCLOSED} + @tab @code{ERRORS} @tab @code{ESCAPED} @item @code{EXISTS} @tab @code{EXPLAIN} @@ -29048,83 +29051,86 @@ A few are reserved because MySQL needs them and is @item @code{FROM} @tab @code{FULLTEXT} @tab @code{FUNCTION} -@item @code{GRANT} +@item @code{GEOMETRY} + @tab @code{GRANT} @tab @code{GROUP} +@item @code{HASH} @tab @code{HAVING} -@item @code{HIGH_PRIORITY} - @tab @code{HOUR_MINUTE} + @tab @code{HIGH_PRIORITY} +@item @code{HOUR_MINUTE} @tab @code{HOUR_SECOND} -@item @code{IF} - @tab @code{IGNORE} + @tab @code{IF} +@item @code{IGNORE} @tab @code{IN} -@item @code{INDEX} - @tab @code{INFILE} + @tab @code{INDEX} +@item @code{INFILE} @tab @code{INNER} -@item @code{INNODB} - @tab @code{INSERT} + @tab @code{INNODB} +@item @code{INSERT} @tab @code{INT} -@item @code{INTEGER} - @tab @code{INTERVAL} + @tab @code{INTEGER} +@item @code{INTERVAL} @tab @code{INTO} -@item @code{IS} - @tab @code{JOIN} + @tab @code{IS} +@item @code{JOIN} @tab @code{KEY} -@item @code{KEYS} - @tab @code{KILL} + @tab @code{KEYS} +@item @code{KILL} @tab @code{LEADING} -@item @code{LEFT} - @tab @code{LIKE} + @tab @code{LEFT} +@item @code{LIKE} @tab @code{LIMIT} -@item @code{LINES} - @tab @code{LOAD} + @tab @code{LINES} +@item @code{LOAD} @tab @code{LOCK} -@item @code{LONG} - @tab @code{LONGBLOB} + @tab @code{LONG} +@item @code{LONGBLOB} @tab @code{LONGTEXT} -@item @code{LOW_PRIORITY} - @tab @code{MASTER_SERVER_ID} + @tab @code{LOW_PRIORITY} +@item @code{MASTER_SERVER_ID} @tab @code{MATCH} -@item @code{MEDIUMBLOB} - @tab @code{MEDIUMINT} + @tab @code{MEDIUMBLOB} +@item @code{MEDIUMINT} @tab @code{MEDIUMTEXT} -@item @code{MIDDLEINT} - @tab @code{MINUTE_SECOND} + @tab @code{MIDDLEINT} +@item @code{MINUTE_SECOND} @tab @code{MRG_MYISAM} -@item @code{NATURAL} - @tab @code{NOT} + @tab @code{NATURAL} +@item @code{NOT} @tab @code{NULL} -@item @code{NUMERIC} - @tab @code{ON} + @tab @code{NUMERIC} +@item @code{ON} @tab @code{OPTIMIZE} -@item @code{OPTION} - @tab @code{OPTIONALLY} + @tab @code{OPTION} +@item @code{OPTIONALLY} @tab @code{OR} -@item @code{ORDER} - @tab @code{OUTER} + @tab @code{ORDER} +@item @code{OUTER} @tab @code{OUTFILE} -@item @code{PARTIAL} @tab @code{PRECISION} - @tab @code{PRIMARY} -@item @code{PRIVILEGES} +@item @code{PRIMARY} + @tab @code{PRIVILEGES} @tab @code{PROCEDURE} - @tab @code{PURGE} -@item @code{READ} +@item @code{PURGE} + @tab @code{READ} @tab @code{REAL} - @tab @code{REFERENCES} -@item @code{REGEXP} +@item @code{REFERENCES} + @tab @code{REGEXP} @tab @code{RENAME} - @tab @code{REPLACE} -@item @code{REQUIRE} +@item @code{REPLACE} + @tab @code{REQUIRE} @tab @code{RESTRICT} - @tab @code{RETURNS} -@item @code{REVOKE} +@item @code{RETURNS} + @tab @code{REVOKE} @tab @code{RIGHT} - @tab @code{RLIKE} -@item @code{SELECT} - @tab @code{SET} +@item @code{RLIKE} + @tab @code{RTREE} + @tab @code{SELECT} +@item @code{SET} @tab @code{SHOW} -@item @code{SMALLINT} - @tab @code{SONAME} + @tab @code{SMALLINT} +@item @code{SONAME} + @tab @code{SPATIAL} @tab @code{SQL_BIG_RESULT} @item @code{SQL_CALC_FOUND_ROWS} @tab @code{SQL_SMALL_RESULT} @@ -29141,26 +29147,29 @@ A few are reserved because MySQL needs them and is @item @code{TINYTEXT} @tab @code{TO} @tab @code{TRAILING} -@item @code{UNION} +@item @code{TYPES} + @tab @code{UNION} @tab @code{UNIQUE} - @tab @code{UNLOCK} -@item @code{UNSIGNED} +@item @code{UNLOCK} + @tab @code{UNSIGNED} @tab @code{UPDATE} - @tab @code{USAGE} -@item @code{USE} +@item @code{USAGE} + @tab @code{USE} @tab @code{USER_RESOURCES} - @tab @code{USING} -@item @code{VALUES} +@item @code{USING} + @tab @code{VALUES} @tab @code{VARBINARY} - @tab @code{VARCHAR} -@item @code{VARYING} - @tab @code{WHEN} +@item @code{VARCHAR} + @tab @code{VARYING} + @tab @code{WARNINGS} +@item @code{WHEN} @tab @code{WHERE} -@item @code{WITH} - @tab @code{WRITE} + @tab @code{WITH} +@item @code{WRITE} @tab @code{XOR} -@item @code{YEAR_MONTH} - @tab @code{ZEROFILL} + @tab @code{YEAR_MONTH} +@item @code{ZEROFILL} + @tab @tab @end multitable From e1390e23311c454835e3d7999c0da1d71fd5da70 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 15:13:36 +1000 Subject: [PATCH 07/11] Fixup. --- Docs/manual.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index b846ae1871d..d3495892d4d 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -51701,7 +51701,7 @@ not yet 100% confident in this code. @appendixsubsec Changes in release 3.23.53 @itemize @bullet @item -Small fix in @code{mysqld_safe} for some shells. +Small fix in @code{safe_mysqld} for some shells. @item Fixed that @code{SHOW STATUS} doesn't reset @code{Delayed_insert_threads}. @item From 956c993f64ca673bb8085d21164e22d110aea3c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 15:54:51 +0500 Subject: [PATCH 08/11] test case for auto_increment for HEAP --- mysql-test/r/heap_auto_increment.result | 41 +++++++++++++++++++++++++ mysql-test/t/heap_auto_increment.test | 30 ++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 mysql-test/r/heap_auto_increment.result create mode 100644 mysql-test/t/heap_auto_increment.test diff --git a/mysql-test/r/heap_auto_increment.result b/mysql-test/r/heap_auto_increment.result new file mode 100644 index 00000000000..9a5ed57d741 --- /dev/null +++ b/mysql-test/r/heap_auto_increment.result @@ -0,0 +1,41 @@ +drop table if exists t1; +create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3; +insert into t1 values (1,1),(NULL,3),(NULL,4); +delete from t1 where a=4; +insert into t1 values (NULL,5),(NULL,6); +select * from t1; +a b +1 1 +3 3 +5 5 +6 6 +delete from t1 where a=6; +replace t1 values (3,1); +ALTER TABLE t1 add c int; +replace t1 values (3,3,3); +insert into t1 values (NULL,7,7); +update t1 set a=8,b=b+1,c=c+1 where a=7; +insert into t1 values (NULL,9,9); +select * from t1; +a b c +1 1 NULL +3 3 3 +5 5 NULL +8 8 8 +9 9 9 +drop table t1; +create table t1 ( +skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY, +sval char(20) +) type=heap; +insert into t1 values (NULL, "hello"); +insert into t1 values (NULL, "hey"); +select * from t1; +skey sval +1 hello +2 hey +select _rowid,t1._rowid,skey,sval from t1; +_rowid _rowid skey sval +1 1 1 hello +2 2 2 hey +drop table t1; diff --git a/mysql-test/t/heap_auto_increment.test b/mysql-test/t/heap_auto_increment.test new file mode 100644 index 00000000000..8a0d19d9183 --- /dev/null +++ b/mysql-test/t/heap_auto_increment.test @@ -0,0 +1,30 @@ +# +# Test of auto_increment; The test for BDB tables is in bdb.test +# + +drop table if exists t1; +create table t1 (a int not null auto_increment,b int, primary key (a)) type=heap auto_increment=3; +insert into t1 values (1,1),(NULL,3),(NULL,4); +delete from t1 where a=4; +insert into t1 values (NULL,5),(NULL,6); +select * from t1; +delete from t1 where a=6; +#show table status like "t1"; +replace t1 values (3,1); +ALTER TABLE t1 add c int; +replace t1 values (3,3,3); +insert into t1 values (NULL,7,7); +update t1 set a=8,b=b+1,c=c+1 where a=7; +insert into t1 values (NULL,9,9); +select * from t1; +drop table t1; + +create table t1 ( + skey tinyint unsigned NOT NULL auto_increment PRIMARY KEY, + sval char(20) +) type=heap; +insert into t1 values (NULL, "hello"); +insert into t1 values (NULL, "hey"); +select * from t1; +select _rowid,t1._rowid,skey,sval from t1; +drop table t1; From e8e3f7728fbe66f75b328a56a48059552b0bea15 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 14:50:12 +0300 Subject: [PATCH 09/11] fixed couple of bugs in field/reference name resolution fixed error handling in subselect fix_field mysql-test/r/subselect.result: test of name resolution mysql-test/t/subselect.test: test of name resolution sql/item.cc: fixed couple of bugs in field/reference name resolution. sql/item_subselect.cc: fixed error handling sql/mysql_priv.h: fixed couple of bugs in field/reference name resolution. sql/sql_base.cc: fixed couple of bugs in field/reference name resolution. sql/sql_select.cc: new find_item_in_list interface --- mysql-test/r/subselect.result | 4 +- mysql-test/t/subselect.test | 6 ++- sql/item.cc | 43 +++++++++++++----- sql/item_subselect.cc | 3 +- sql/mysql_priv.h | 7 ++- sql/sql_base.cc | 85 +++++++++++++++++++++++++++++------ sql/sql_select.cc | 4 +- 7 files changed, 121 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ec5a12cdfc8..2618741a520 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -131,6 +131,8 @@ patient_uq clinic_uq 1 1 1 2 2 2 +select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); +Column: 'a' in field list is ambiguous drop table if exists t1,t2,t3; CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); @@ -159,4 +161,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); Subselect returns more than 1 record -drop table if exists inscrit; +drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 00d58c218aa..c34332d6d90 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -53,6 +53,10 @@ insert into clinic values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta" insert into attend values (1,1),(1,2),(2,2),(1,3); select * from attend where exists (select * from clinic where uq = clinic_uq); +# not unique fields +-- error 1052 +select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); + # different tipes & group functions drop table if exists t1,t2,t3; @@ -81,4 +85,4 @@ INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); -- error 1240 SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); -drop table if exists inscrit; \ No newline at end of file +drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; \ No newline at end of file diff --git a/sql/item.cc b/sql/item.cc index f1e25fb4d97..6da53b98657 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) if (!field) // If field is not checked { Field *tmp; - if (!(tmp=find_field_in_tables(thd, this, tables, 0))) + if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field) { /* We can't find table field in table list of current select, @@ -445,14 +445,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) */ SELECT_LEX *last= 0; for (SELECT_LEX *sl= thd->lex.select->outer_select(); - sl && !tmp; + sl; sl= sl->outer_select()) - tmp=find_field_in_tables(thd, this, - (TABLE_LIST*)(last= sl)->table_list.first, - 0); + if ((tmp= find_field_in_tables(thd, this, + (TABLE_LIST*) + (last= sl)->table_list.first, + 0)) != not_found_field) + break; if (!tmp) + return -1; + else if (tmp == not_found_field) { - // Call to produce appropriate error message + // call to return error code find_field_in_tables(thd, this, tables, 1); return -1; } @@ -478,7 +482,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) tbl->shared= 1; } } - } + } + else if (!tmp) + return -1; + set_field(tmp); } else if (thd && thd->set_query_id && field->query_id != thd->query_id) @@ -786,7 +793,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if (!ref) { - if (!(ref= find_item_in_list(this, thd->lex.select->item_list, 0))) + if ((ref= find_item_in_list(this, thd->lex.select->item_list, + REPORT_EXCEPT_NOT_FOUND)) == + not_found_item) { /* We can't find table field in table list of current select, @@ -795,17 +804,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) of view rules. For example if both tables (outer & current) have field 'field' it is not mistake to refer to this field without mention of table name, but if we join tables in one list it will - cause error ER_NON_UNIQ_ERROR in find_field_in_tables. + cause error ER_NON_UNIQ_ERROR in find_item_in_list. */ SELECT_LEX *last=0; for (SELECT_LEX *sl= thd->lex.select->outer_select(); - sl && !ref; + sl; sl= sl->outer_select()) - ref= find_item_in_list(this, (last= sl)->item_list, 0); + if((ref= find_item_in_list(this, (last= sl)->item_list, + REPORT_EXCEPT_NOT_FOUND)) != + not_found_item) + break; + if (!ref) + { + return 1; + } + else if (ref == not_found_item) { // Call to report error - find_item_in_list(this, thd->lex.select->item_list, 1); + find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS); return 1; } else @@ -831,6 +848,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) } } } + else if (!ref) + return 1; max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7e0b2e201ec..e8ee6a780ea 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -83,7 +83,8 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; } int res= engine->prepare(); - fix_length_and_dec(); + if (!res) + fix_length_and_dec(); return res; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 8e691c8f96c..b74a2da5f6d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -456,6 +456,7 @@ bool wait_for_tables(THD *thd); bool table_is_used(TABLE *table, bool wait_for_name_lock); bool drop_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name); +extern const Field *not_found_field; Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables, bool report_error); Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, @@ -545,7 +546,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, int *error); -Item ** find_item_in_list(Item *item, List &items, bool report_error); +enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, + IGNORE_ERRORS}; +extern const Item **not_found_item; +Item ** find_item_in_list(Item *item, List &items, + find_item_error_report_type report_error); bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator *it); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8deae314484..78774b376b1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1781,9 +1781,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, return field; } +// Special Field pointer for find_field_in_tables returning +const Field *not_found_field= (Field*) 0x1; +/* + Find field in table list. + + SYNOPSIS + find_field_in_tables() + thd - pointer to current thread structure + item - field item that should be found + tables - tables for scaning + report_error - if FALSE then do not report error if item not found and + return not_found_field; + + RETURN VALUES + 0 - field is not found or field is not unique, error message is + reported + not_found_field - function was called with report_error == FALSE and + field if not found, no error message reported + found field +*/ Field * -find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, +find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables, bool report_error) { Field *found=0; @@ -1829,13 +1849,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); table_name=buff; } - my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name, - thd->where); + if (report_error) + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + table_name, thd->where); + else + return (Field*) not_found_field; } else if (report_error) my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), item->full_name(),thd->where); + else + return (Field*) not_found_field; return (Field*) 0; } bool allow_rowid= tables && !tables->next; // Only one table @@ -1850,11 +1875,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, return (Field*) 0; if (found) { - if (!report_error) // Returns first found + if (!thd->where) // Returns first found break; - if (report_error) - my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), - name,thd->where); + my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), + name,thd->where); return (Field*) 0; } found=field; @@ -1865,11 +1889,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables, if (report_error) my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), item->full_name(), thd->where); + else + return (Field*) not_found_field; return (Field*) 0; } +// Special Item pointer for find_item_in_list returning +const Item **not_found_item= (const Item**) 0x1; + +/* + Find Item in list of items (find_field_in_tables analog) + + SYNOPSIS + find_item_in_list() + find - item to find + items - list of items + report_error + REPORT_ALL_ERRORS - report errors, return 0 if error + REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0 + IGNORE_ERRORS - do not report errors, return 0 if error + + RETURN VALUES + 0 - item is not found or item is not unique, error message is + reported + not_found_item - function was called with report_error == + REPORT_EXCEPT_NOT_FOUND and item if not found, no error + message reported + found field + +*/ + Item ** -find_item_in_list(Item *find, List &items, bool report_error) +find_item_in_list(Item *find, List &items, + find_item_error_report_type report_error) { List_iterator li(items); Item **found=0,*item; @@ -1894,7 +1946,7 @@ find_item_in_list(Item *find, List &items, bool report_error) { if ((*found)->eq(item,0)) continue; // Same field twice (Access?) - if (report_error) + if (report_error != IGNORE_ERRORS) my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0), find->full_name(), current_thd->where); return (Item**) 0; @@ -1917,10 +1969,17 @@ find_item_in_list(Item *find, List &items, bool report_error) break; } } - if (!found && report_error) - my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), - find->full_name(), current_thd->where); - return found; + if (found) + return found; + else if (report_error != REPORT_EXCEPT_NOT_FOUND) + { + if (report_error == REPORT_ALL_ERRORS) + my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), + find->full_name(), current_thd->where); + return (Item **) 0; + } + else + return (Item **) not_found_item; } /**************************************************************************** diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 35703e57d82..09d41e2891b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6487,7 +6487,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List &fields, order->in_field_list=1; return 0; } - Item **item=find_item_in_list(*order->item, fields, 0); + Item **item= find_item_in_list(*order->item, fields, IGNORE_ERRORS); if (item) { order->item=item; // use it @@ -6587,7 +6587,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, thd->set_query_id=1; // Not really needed, but... for (; new_field ; new_field= new_field->next) { - if ((item= find_item_in_list(*new_field->item, fields, 0))) + if ((item= find_item_in_list(*new_field->item, fields, IGNORE_ERRORS))) new_field->item=item; /* Change to shared Item */ else { From 58dc03066c8b8c38cdfa47e1f3c99ee002551b4f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 15:34:39 +0300 Subject: [PATCH 10/11] removed compiler warnings --- sql/item.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 6da53b98657..a0cb6f46f06 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -795,7 +795,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if ((ref= find_item_in_list(this, thd->lex.select->item_list, REPORT_EXCEPT_NOT_FOUND)) == - not_found_item) + (Item **)not_found_item) { /* We can't find table field in table list of current select, @@ -812,14 +812,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) sl= sl->outer_select()) if((ref= find_item_in_list(this, (last= sl)->item_list, REPORT_EXCEPT_NOT_FOUND)) != - not_found_item) + (Item **)not_found_item) break; if (!ref) { return 1; } - else if (ref == not_found_item) + else if (ref == (Item **)not_found_item) { // Call to report error find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS); From ac97cce4617a52d100cb2b5fa6c6c972c3510702 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Oct 2002 23:49:59 +0300 Subject: [PATCH 11/11] removed 'this' pointer from initialization list of constructors --- sql/item_subselect.cc | 29 ++++++++++++++++++----------- sql/item_subselect.h | 11 +++++++++-- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e8ee6a780ea..2d08b9cb6b5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -32,11 +32,22 @@ SUBSELECT TODO: #include "mysql_priv.h" #include "sql_select.h" -Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, - select_subselect *result): +Item_subselect::Item_subselect(): Item(), engine_owner(1), value_assigned(0) { - DBUG_ENTER("Item_subselect::Item_subselect"); + assign_null(); + /* + item value is NULL if select_subselect not changed this value + (i.e. some rows will be found returned) + */ + null_value= 1; +} + +void Item_subselect::init(THD *thd, st_select_lex *select_lex, + select_subselect *result) +{ + + DBUG_ENTER("Item_subselect::init"); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); if (select_lex->next_select()) @@ -45,12 +56,6 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, else engine= new subselect_single_select_engine(thd, select_lex, result, this); - assign_null(); - /* - item value is NULL if select_subselect not changed this value - (i.e. some rows will be found returned) - */ - null_value= 1; DBUG_VOID_RETURN; } @@ -100,8 +105,9 @@ inline table_map Item_subselect::used_tables() const Item_singleval_subselect::Item_singleval_subselect(THD *thd, st_select_lex *select_lex): - Item_subselect(thd, select_lex, new select_singleval_subselect(this)) + Item_subselect() { + init(thd, select_lex, new select_singleval_subselect(this)); max_columns= 1; maybe_null= 1; } @@ -149,8 +155,9 @@ String *Item_singleval_subselect::val_str (String *str) Item_exists_subselect::Item_exists_subselect(THD *thd, st_select_lex *select_lex): - Item_subselect(thd, select_lex, new select_exists_subselect(this)) + Item_subselect() { + init(thd, select_lex, new select_exists_subselect(this)); max_columns= UINT_MAX; null_value= 0; //can't be NULL maybe_null= 0; //can't be NULL diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 92839eb0e5f..5d070871b49 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -39,8 +39,7 @@ protected: uint max_columns; public: - Item_subselect(THD *thd, st_select_lex *select_lex, - select_subselect* result); + Item_subselect(); Item_subselect(Item_subselect *item) { null_value= item->null_value; @@ -50,6 +49,14 @@ public: engine_owner= 0; name= item->name; } + + /* + We need this method, because some compilers do not allow 'this' + pointer in constructor initialization list, but we need pass pointer + to subselect Item class to select_subselect classes constructor. + */ + void init (THD *thd, st_select_lex *select_lex, select_subselect *result); + ~Item_subselect(); virtual void assign_null() {