From 5d90d9406eb23052916482d4b4f76631a507cfe9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 1 Dec 2003 17:19:10 +0400 Subject: [PATCH 001/157] SCRUM WL#1246 (Query cache in embedded library) libmysqld/Makefile.am: New files added to the project libmysqld/lib_sql.cc: added initialization of 'newborn' fields: catalog, catalog_length, def_length sql/sql_cache.cc: Code added to provide query-cache in embedded library query_cache_insert isn't called during the query execution in embedded library. So we call it in query_cache_end_of_result. Parameter of query_cache_end_of_result changed to get access to the recordset sql/sql_cache.h: function's parameter changed sql/sql_parse.cc: we don't need these anymore --- libmysqld/Makefile.am | 4 +- libmysqld/emb_qcache.cc | 430 ++++++++++++++++++++++++++++++++++++++++ libmysqld/emb_qcache.h | 61 ++++++ libmysqld/lib_sql.cc | 9 + sql/sql_cache.cc | 41 +++- sql/sql_cache.h | 4 +- sql/sql_parse.cc | 6 +- 7 files changed, 535 insertions(+), 20 deletions(-) create mode 100644 libmysqld/emb_qcache.cc create mode 100644 libmysqld/emb_qcache.h diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 95cbd4ec826..e51fb5e315e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -33,10 +33,10 @@ INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \ noinst_LIBRARIES = libmysqld_int.a pkglib_LIBRARIES = libmysqld.a SUBDIRS = . examples -libmysqld_sources= libmysqld.c lib_sql.cc +libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c -noinst_HEADERS = embedded_priv.h +noinst_HEADERS = embedded_priv.h emb_qcache.h sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \ diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc new file mode 100644 index 00000000000..0374ab58784 --- /dev/null +++ b/libmysqld/emb_qcache.cc @@ -0,0 +1,430 @@ +/* Copyright (C) 2000-2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysql_priv.h" +#ifdef HAVE_QUERY_CACHE +#include +#include "emb_qcache.h" + +void Querycache_stream::store_char(char c) +{ + if (data_end == cur_data) + use_next_block(); + *(cur_data++)= c; +#ifndef DBUG_OFF + stored_size++; +#endif +} + +void Querycache_stream::store_short(ushort s) +{ +#ifndef DBUG_OFF + stored_size+= 2; +#endif + if (data_end - cur_data > 1) + { + int2store(cur_data, s); + cur_data+= 2; + return; + } + if (data_end == cur_data) + { + use_next_block(); + int2store(cur_data, s); + cur_data+= 2; + return; + } + *cur_data= ((byte *)(&s))[0]; + use_next_block(); + *(cur_data++)= ((byte *)(&s))[1]; +} + +void Querycache_stream::store_int(uint i) +{ +#ifndef DBUG_OFF + stored_size+= 4; +#endif + size_t rest_len= data_end - cur_data; + if (rest_len > 3) + { + int4store(cur_data, i); + cur_data+= 4; + return; + } + if (!rest_len) + { + use_next_block(); + int4store(cur_data, i); + cur_data+= 4; + return; + } + memcpy(cur_data, &i, rest_len); + use_next_block(); + memcpy(cur_data, ((byte*)&i)+rest_len, 4-rest_len); + cur_data+= 4-rest_len; +} + +void Querycache_stream::store_ll(ulonglong ll) +{ +#ifndef DBUG_OFF + stored_size+= 8; +#endif + size_t rest_len= data_end - cur_data; + if (rest_len > 7) + { + int8store(cur_data, ll); + cur_data+= 8; + return; + } + if (!rest_len) + { + use_next_block(); + int8store(cur_data, ll); + cur_data+= 8; + return; + } + memcpy(cur_data, &ll, rest_len); + use_next_block(); + memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len); + cur_data+= 8-rest_len; +} + +void Querycache_stream::store_str_only(const char *str, uint str_len) +{ +#ifndef DBUG_OFF + stored_size+= str_len; +#endif + do + { + size_t rest_len= data_end - cur_data; + if (rest_len > str_len) + { + memcpy(cur_data, str, str_len); + cur_data+= str_len; + return; + } + memcpy(cur_data, str, rest_len); + use_next_block(); + str_len-= rest_len; + str+= rest_len; + } while(str_len); +} + +void Querycache_stream::store_str(const char *str, uint str_len) +{ + store_int(str_len); + store_str_only(str, str_len); +} + +void Querycache_stream::store_safe_str(const char *str, uint str_len) +{ + if (str) + { + store_int(str_len+1); + store_str_only(str, str_len); + } + else + store_int(0); +} + +char Querycache_stream::load_char() +{ + if (cur_data == data_end) + use_next_block(); + return *(cur_data++); +} + +ushort Querycache_stream::load_short() +{ + ushort result; + if (data_end-cur_data > 1) + { + result= uint2korr(cur_data); + cur_data+= 2; + return result; + } + if (data_end == cur_data) + { + use_next_block(); + result= uint2korr(cur_data); + cur_data+= 2; + return result; + } + ((byte*)&result)[0]= *cur_data; + use_next_block(); + ((byte*)&result)[1]= *(cur_data++); + return result; +} + +uint Querycache_stream::load_int() +{ + int result; + size_t rest_len= data_end - cur_data; + if (rest_len > 3) + { + result= uint4korr(cur_data); + cur_data+= 4; + return result; + } + if (!rest_len) + { + use_next_block(); + result= uint4korr(cur_data); + cur_data+= 4; + return result; + } + memcpy(&result, cur_data, rest_len); + use_next_block(); + memcpy(((byte*)&result)+rest_len, cur_data, 4-rest_len); + cur_data+= 4-rest_len; + return result; +} + +ulonglong Querycache_stream::load_ll() +{ + ulonglong result; + size_t rest_len= data_end - cur_data; + if (rest_len > 7) + { + result= uint8korr(cur_data); + cur_data+= 8; + return result; + } + if (!rest_len) + { + use_next_block(); + result= uint8korr(cur_data); + cur_data+= 8; + return result; + } + memcpy(&result, cur_data, rest_len); + use_next_block(); + memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len); + cur_data+= 8-rest_len; + return result; +} + +void Querycache_stream::load_str_only(char *buffer, uint str_len) +{ + do + { + size_t rest_len= data_end - cur_data; + if (rest_len > str_len) + { + memcpy(buffer, cur_data, str_len); + cur_data+= str_len; + buffer+= str_len; + break; + } + memcpy(buffer, cur_data, rest_len); + use_next_block(); + str_len-= rest_len; + buffer+= rest_len; + } while(str_len); + *buffer= 0; +} + +char *Querycache_stream::load_str(MEM_ROOT *alloc, uint *str_len) +{ + char *result; + *str_len= load_int(); + if (!(result= alloc_root(alloc, *str_len + 1))) + return 0; + load_str_only(result, *str_len); + return result; +} + +int Querycache_stream::load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len) +{ + if (!(*str_len= load_int())) + { + *str= NULL; + return 0; + } + (*str_len)--; + if (!(*str= alloc_root(alloc, *str_len + 1))) + return 1; + load_str_only(*str, *str_len); + return 0; +} + +int Querycache_stream::load_column(MEM_ROOT *alloc, char** column) +{ + int len; + if (!(len = load_int())) + { + *column= NULL; + return 0; + } + len--; + if (!(*column= (char *)alloc_root(alloc, len + 4 + 1))) + return 1; + int4store(*column, len); + (*column)+= 4; + load_str_only(*column, len); + return 1; +} + +uint emb_count_querycache_size(THD *thd) +{ + uint result; + MYSQL *mysql= thd->mysql; + MYSQL_FIELD *field= mysql->fields; + MYSQL_FIELD *field_end= field + mysql->field_count; + + *thd->data->prev_ptr= NULL; // this marks the last record + MYSQL_ROWS *cur_row= thd->data->data; + + result= 4+8 + (42 + 4*thd->data->rows)*mysql->field_count; + + for(; field < field_end; field++) + { + result+= field->name_length + field->table_length + + field->org_name_length + field->org_table_length + field->db_length + + field->catalog_length; + if (field->def) + result+= field->def_length; + } + + for (; cur_row; cur_row=cur_row->next) + { + MYSQL_ROW col= cur_row->data; + MYSQL_ROW col_end= col + mysql->field_count; + for (; col < col_end; col++) + if (*col) + result+= *(uint *)((*col) - sizeof(uint)); + } + return result; +} + +void emb_store_querycache_result(Querycache_stream *dst, THD *thd) +{ + MYSQL *mysql= thd->mysql; + MYSQL_FIELD *field= mysql->fields; + MYSQL_FIELD *field_end= field + mysql->field_count; + + *thd->data->prev_ptr= NULL; // this marks the last record + MYSQL_ROWS *cur_row= thd->data->data; + + dst->store_int((uint)mysql->field_count); + dst->store_ll((uint)thd->data->rows); + + for(; field < field_end; field++) + { + dst->store_int((uint)field->length); + dst->store_int((uint)field->max_length); + dst->store_char((char)field->type); + dst->store_short((ushort)field->flags); + dst->store_short((ushort)field->charsetnr); + dst->store_char((char)field->decimals); + dst->store_str(field->name, field->name_length); + dst->store_str(field->table, field->table_length); + dst->store_str(field->org_name, field->org_name_length); + dst->store_str(field->org_table, field->org_table_length); + dst->store_str(field->db, field->db_length); + dst->store_str(field->catalog, field->catalog_length); + + dst->store_safe_str(field->def, field->def_length); + } + + for (; cur_row; cur_row=cur_row->next) + { + MYSQL_ROW col= cur_row->data; + MYSQL_ROW col_end= col + mysql->field_count; + for (; col < col_end; col++) + { + uint len= *col ? *(uint *)((*col) - sizeof(uint)) : 0; + dst->store_safe_str(*col, len); + } + } + DBUG_ASSERT(emb_count_querycache_size(thd) == dst->stored_size); +} + +int emb_load_querycache_result(THD *thd, Querycache_stream *src) +{ + MYSQL *mysql= thd->mysql; + MYSQL_DATA *data; + MYSQL_FIELD *field; + MYSQL_FIELD *field_end; + MEM_ROOT *f_alloc= &mysql->field_alloc; + MYSQL_ROWS *row, *end_row; + MYSQL_ROWS **prev_row; + ulonglong rows; + MYSQL_ROW columns; + + mysql->field_count= src->load_int(); + rows= src->load_ll(); + + if (!(field= (MYSQL_FIELD *) + alloc_root(&mysql->field_alloc,mysql->field_count*sizeof(MYSQL_FIELD)))) + goto err; + mysql->fields= field; + for(field_end= field+mysql->field_count; field < field_end; field++) + { + field->length= src->load_int(); + field->max_length= (unsigned int)src->load_int(); + field->type= (enum enum_field_types)src->load_char(); + field->flags= (unsigned int)src->load_short(); + field->charsetnr= (unsigned int)src->load_short(); + field->decimals= (unsigned int)src->load_char(); + + if (!(field->name= src->load_str(f_alloc, &field->name_length)) || + !(field->table= src->load_str(f_alloc,&field->table_length)) || + !(field->org_name= src->load_str(f_alloc, &field->org_name_length)) || + !(field->org_table= src->load_str(f_alloc, &field->org_table_length))|| + !(field->db= src->load_str(f_alloc, &field->db_length)) || + !(field->catalog= src->load_str(f_alloc, &field->catalog_length)) || + src->load_safe_str(f_alloc, &field->def, &field->def_length)) + goto err; + } + + if (!rows) + return 0; + if (!(data= (MYSQL_DATA*)my_malloc(sizeof(MYSQL_DATA), + MYF(MY_WME | MY_ZEROFILL)))) + goto err; + thd->data= data; + init_alloc_root(&data->alloc, 8192,0); + row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS) + + rows * (mysql->field_count+1)*sizeof(char*)); + end_row= row + rows; + columns= (MYSQL_ROW)end_row; + + data->rows= rows; + data->fields= mysql->field_count; + data->data= row; + + for (prev_row= &row->next; row < end_row; prev_row= &row->next, row++) + { + *prev_row= row; + row->data= columns; + MYSQL_ROW col_end= columns + mysql->field_count; + uint len; + for (; columns < col_end; columns++) + src->load_column(&data->alloc, columns); + + *(columns++)= NULL; + } + *prev_row= NULL; + data->prev_ptr= prev_row; + + return 0; +err: + return 1; +} + +#endif /*HAVE_QUERY_CACHE*/ + diff --git a/libmysqld/emb_qcache.h b/libmysqld/emb_qcache.h new file mode 100644 index 00000000000..32ce19847ff --- /dev/null +++ b/libmysqld/emb_qcache.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +class Querycache_stream +{ + byte *cur_data; + byte *data_end; + Query_cache_block *block; + uint headers_len; +public: +#ifndef DBUG_OFF + uint stored_size; +#endif + Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) : + block(ini_block), headers_len(ini_headers_len) + { + use_next_block(); +#ifndef DBUG_OFF + stored_size= 0; +#endif + } + void use_next_block() + { + cur_data= ((byte*)block)+headers_len; + data_end= cur_data + (block->used-headers_len); + } + + void store_char(char c); + void store_short(ushort s); + void store_int(uint i); + void store_ll(ulonglong ll); + void store_str_only(const char *str, uint str_len); + void store_str(const char *str, uint str_len); + void store_safe_str(const char *str, uint str_len); + + char load_char(); + ushort load_short(); + uint load_int(); + ulonglong load_ll(); + void load_str_only(char *buffer, uint str_len); + char *load_str(MEM_ROOT *alloc, uint *str_len); + int load_safe_str(MEM_ROOT *alloc, char **str, uint *str_len); + int load_column(MEM_ROOT *alloc, char **column); +}; + +uint emb_count_querycache_size(THD *thd); +int emb_load_querycache_result(THD *thd, Querycache_stream *src); +void emb_store_querycache_result(Querycache_stream *dst, THD* thd); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index d4cb916a89c..4e003b1d450 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -573,6 +573,9 @@ bool Protocol::send_fields(List *list, uint flag) client_field->org_name_length= strlen(client_field->org_name); client_field->org_table_length= strlen(client_field->org_table); client_field->charsetnr= server_field.charsetnr; + + client_field->catalog= strdup_root(field_alloc, "std"); + client_field->catalog_length= 3; if (INTERNAL_NUM_FIELD(client_field)) client_field->flags|= NUM_FLAG; @@ -583,9 +586,15 @@ bool Protocol::send_fields(List *list, uint flag) String tmp(buff, sizeof(buff), default_charset_info), *res; if (!(res=item->val_str(&tmp))) + { client_field->def= strdup_root(field_alloc, ""); + client_field->def_length= 0; + } else + { client_field->def= strdup_root(field_alloc, tmp.ptr()); + client_field->def_length= tmp.length(); + } } else client_field->def=0; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 396764cd532..3c77d72947f 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -308,6 +308,10 @@ TODO list: #include "../myisammrg/myrg_def.h" #endif +#ifdef EMBEDDED_LIBRARY +#include "emb_qcache.h" +#endif + #if defined(EXTRA_DEBUG) && !defined(DBUG_OFF) #define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \ pthread_mutex_lock(M);} @@ -646,20 +650,24 @@ void query_cache_abort(NET *net) } -void query_cache_end_of_result(NET *net) +void query_cache_end_of_result(THD *thd) { DBUG_ENTER("query_cache_end_of_result"); +#ifdef EMBEDDED_LIBRARY + query_cache_insert(&thd->net, (byte*)thd, + emb_count_querycache_size(thd)); +#endif #ifndef DBUG_OFF // Check if we have called query_cache.wreck() (which disables the cache) if (query_cache.query_cache_size == 0) DBUG_VOID_RETURN; #endif - if (net->query_cache_query != 0) // Quick check on unlocked structure + if (thd->net.query_cache_query != 0) // Quick check on unlocked structure { STRUCT_LOCK(&query_cache.structure_guard_mutex); Query_cache_block *query_block = ((Query_cache_block*) - net->query_cache_query); + thd->net.query_cache_query); if (query_block) { DUMP(&query_cache); @@ -691,7 +699,7 @@ void query_cache_end_of_result(NET *net) // Cache was flushed or resized and query was deleted => do nothing STRUCT_UNLOCK(&query_cache.structure_guard_mutex); } - net->query_cache_query=0; + thd->net.query_cache_query=0; DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); } DBUG_VOID_RETURN; @@ -1052,23 +1060,29 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) /* Send cached result to client */ +#ifndef EMBEDDED_LIBRARY do { DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)", - result_block->length, result_block->used, - result_block->headers_len()+ - ALIGN_SIZE(sizeof(Query_cache_result)))); - + result_block->length, result_block->used, + result_block->headers_len()+ + ALIGN_SIZE(sizeof(Query_cache_result)))); + Query_cache_result *result = result_block->result(); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ if (net_real_write(&thd->net, result->data(), result_block->used - result_block->headers_len() - ALIGN_SIZE(sizeof(Query_cache_result)))) break; // Client aborted -#endif result_block = result_block->next; } while (result_block != first_result_block); +#else + { + Querycache_stream qs(result_block, result_block->headers_len() + + ALIGN_SIZE(sizeof(Query_cache_result))); + emb_load_querycache_result(thd, &qs); + } +#endif /*!EMBEDDED_LIBRARY*/ thd->limit_found_rows = query->found_rows(); @@ -1784,18 +1798,23 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, Query_cache_block *block = *result_block; uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_result))); +#ifndef EMBEDDED_LIBRARY // Now fill list of blocks that created by allocate_data_chain do { block->type = type; ulong length = block->used - headers_len; DBUG_PRINT("qcache", ("write %lu byte in block 0x%lx",length, - (ulong)block)); + (ulong)block)); memcpy((void*)(((byte*) block)+headers_len), (void*) rest, length); rest += length; block = block->next; type = Query_cache_block::RES_CONT; } while (block != *result_block); +#else + Querycache_stream qs(*result_block, headers_len); + emb_store_querycache_result(&qs, (THD*)data); +#endif /*!EMBEDDED_LIBRARY*/ } else { diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 68e69ab523f..ac4f465bf79 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -392,7 +392,7 @@ protected: void destroy(); friend void query_cache_insert(NET *net, const char *packet, ulong length); - friend void query_cache_end_of_result(NET *net); + friend void query_cache_end_of_result(THD *thd); friend void query_cache_abort(NET *net); /* @@ -416,7 +416,7 @@ protected: extern Query_cache query_cache; extern TYPELIB query_cache_type_typelib; -void query_cache_end_of_result(NET *net); +void query_cache_end_of_result(THD *thd); void query_cache_abort(NET *net); #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c50bfc43862..cc4fe60580c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3886,9 +3886,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) else { mysql_execute_command(thd); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ - query_cache_end_of_result(&thd->net); -#endif + query_cache_end_of_result(thd); } } } @@ -3896,9 +3894,7 @@ mysql_parse(THD *thd, char *inBuf, uint length) { DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); -#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ query_cache_abort(&thd->net); -#endif } thd->proc_info="freeing items"; free_items(thd->free_list); /* Free strings used by items */ From e91d1f79001a70b24163c961d142de8bb08e4b38 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 1 Dec 2003 12:56:29 -0600 Subject: [PATCH 002/157] Fix typos. --- support-files/my-huge.cnf.sh | 4 ++-- support-files/my-innodb-heavy-4G.cnf.sh | 4 ++-- support-files/my-large.cnf.sh | 4 ++-- support-files/my-medium.cnf.sh | 4 ++-- support-files/my-small.cnf.sh | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index 18e926b1400..ba92856df0e 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -10,8 +10,8 @@ # ~/.my.cnf to set user-specific options. # # One can in this file use all long options that the program supports. -# If you want to know which options a program support, run the program -# with --help option. +# If you want to know which options a program supports, run the program +# with the --help option. # The following options will be passed to all MySQL clients [client] diff --git a/support-files/my-innodb-heavy-4G.cnf.sh b/support-files/my-innodb-heavy-4G.cnf.sh index ed2c2ce9dfd..9c772269749 100644 --- a/support-files/my-innodb-heavy-4G.cnf.sh +++ b/support-files/my-innodb-heavy-4G.cnf.sh @@ -317,7 +317,7 @@ key_buffer_size = 32M read_buffer_size = 2M # When reading rows in sorted order after a sort, the rows are read -# through this buffer to avoid a disk seeks. You can improve ORDER BY +# through this buffer to avoid disk seeks. You can improve ORDER BY # performance a lot, if set this to a high value. # Allocated per thread, when needed. read_rnd_buffer_size = 16M @@ -331,7 +331,7 @@ read_rnd_buffer_size = 16M bulk_insert_buffer_size = 64M # This buffer is allocated when MySQL needs to rebuild the index in -# REPAIR, OPTIMZE, ALTER table statements as well as in LOAD DATA INFILE +# REPAIR, OPTIMIZE, ALTER table statements as well as in LOAD DATA INFILE # into an empty table. It is allocated per thread so be careful with # large settings. myisam_sort_buffer_size = 128M diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 2b92dc61053..ba865a5bfd0 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -10,8 +10,8 @@ # ~/.my.cnf to set user-specific options. # # One can in this file use all long options that the program supports. -# If you want to know which options a program support, run the program -# with --help option. +# If you want to know which options a program supports, run the program +# with the --help option. # The following options will be passed to all MySQL clients [client] diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index 601ffc503c0..d4ae0061a95 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -11,8 +11,8 @@ # ~/.my.cnf to set user-specific options. # # One can in this file use all long options that the program supports. -# If you want to know which options a program support, run the program -# with --help option. +# If you want to know which options a program supports, run the program +# with the --help option. # The following options will be passed to all MySQL clients [client] diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh index 3c4cafa688f..ca26a10a397 100644 --- a/support-files/my-small.cnf.sh +++ b/support-files/my-small.cnf.sh @@ -11,8 +11,8 @@ # ~/.my.cnf to set user-specific options. # # One can in this file use all long options that the program supports. -# If you want to know which options a program support, run the program -# with --help option. +# If you want to know which options a program supports, run the program +# with the --help option. # The following options will be passed to all MySQL clients [client] From 4eb6fd537b98eabf02b61d4a7979414bf735f784 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 4 Dec 2003 23:57:10 +0200 Subject: [PATCH 003/157] fixed length of current database name if it is dropped (BUG#1986) mysql-test/r/query_cache.result: test of BUG#1986 mysql-test/t/query_cache.test: test of BUG#1986 sql/sql_db.cc: as far as we remove db name we should remove its length --- mysql-test/r/query_cache.result | 8 ++++++++ mysql-test/t/query_cache.test | 13 +++++++++++++ sql/sql_db.cc | 5 +++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index e668b9031cc..54a72fe58c2 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -809,4 +809,12 @@ show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 4 DROP TABLE t1; +CREATE TABLE t1 (a int(1)); +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +SELECT * FROM test.t1; +a +USE test; +DROP TABLE t1; SET GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 14cbf4c906d..a7f28bfb5b6 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -585,4 +585,17 @@ show status like "Qcache_queries_in_cache"; # Keep things tidy # DROP TABLE t1; + +# +# DROP current database test +# +CREATE TABLE t1 (a int(1)); +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +SELECT * FROM test.t1; +USE test; +DROP TABLE t1; + + SET GLOBAL query_cache_size=0; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index c61e6800cfa..6aff95641ba 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -409,7 +409,7 @@ exit: when the slave is replicating a DROP DATABASE: - garbage characters in the error message: "Error 'Can't drop database 'test2'; database doesn't exist' on query - 'h4zIΏ'" + 'h4zI©'" - segfault - hang in "free(vio)" (yes!) in the I/O or SQL slave threads (so slave server hangs at shutdown etc). @@ -418,7 +418,8 @@ exit: { if (!(thd->slave_thread)) /* a slave thread will free it itself */ x_free(thd->db); - thd->db= 0; + thd->db= 0; + thd->db_length= 0; } exit2: VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); From fd28d1be71d3b1fc76f09e9bcc942061cb0c52a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 11:04:58 +0400 Subject: [PATCH 004/157] Fix for #2046 Just didn't notice that the mysql_connect function was implemeted in libmysqld.c. Implementation removed. libmysqld/libmysqld.c: supefluous code deleted --- libmysqld/libmysqld.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 59c18368279..b893b8c30fe 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -81,28 +81,6 @@ static void end_server(MYSQL *mysql) DBUG_VOID_RETURN; } -/************************************************************************** -** Connect to sql server -** If host == 0 then use localhost -**************************************************************************/ - -MYSQL * STDCALL -mysql_connect(MYSQL *mysql,const char *host, - const char *user, const char *passwd) -{ - MYSQL *res; - mysql=mysql_init(mysql); /* Make it thread safe */ - { - DBUG_ENTER("mysql_connect"); - if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0))) - { - if (mysql->free_me) - my_free((gptr) mysql,MYF(0)); - } - DBUG_RETURN(res); - } -} - static inline int mysql_init_charset(MYSQL *mysql) { char charset_name_buff[16], *charset_name; From fc75518a78af9dfb68baac2cbf279983fe54b492 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Dec 2003 22:46:14 +0200 Subject: [PATCH 005/157] fixed unlocking tables during subquery execution (BUG#2048) mysql-test/r/subselect_innodb.result: bug 2048 test mysql-test/t/subselect_innodb.test: bug 2048 test sql/item_subselect.cc: do not unlock tables for subqueries sql/sql_derived.cc: derived table tables can be unlocked sql/sql_lex.h: new interface to pass additional options sql/sql_union.cc: new interface to pass additional options do not unlock tables for UNION --- mysql-test/r/subselect_innodb.result | 20 ++++++++++++++++++++ mysql-test/t/subselect_innodb.test | 24 +++++++++++++++++++++++- sql/item_subselect.cc | 5 +++-- sql/sql_derived.cc | 2 +- sql/sql_lex.h | 2 +- sql/sql_union.cc | 7 ++++--- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 2f5b92fd05d..83ff5209e58 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -63,3 +63,23 @@ processor_id (SELECT y.yod_id FROM t1 p2, t2 y WHERE p2.processor_id = p1.proces 2 1 3 1 drop table t1,t2,t3; +CREATE TABLE t1 ( +id int(11) NOT NULL default '0', +b int(11) default NULL, +c char(3) default NULL, +PRIMARY KEY (id), +KEY t2i1 (b) +) TYPE=innodb DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL'); +CREATE TABLE t2 ( +id int(11) NOT NULL default '0', +b int(11) default NULL, +c char(3) default NULL, +PRIMARY KEY (id), +KEY t2i (b) +) TYPE=innodb DEFAULT CHARSET=latin1; +INSERT INTO t2 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL'); +select (select max(id) from t2 where b=1 group by b) as x,b from t1 where b=1; +x b +2 1 +drop table t1,t2; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index 5e274ecbd5c..360bedf8972 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -67,4 +67,26 @@ INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t3 VALUES (1,1),(2,2),(3,3); INSERT INTO t2 VALUES (1,1),(2,2),(3,3); SELECT distinct p1.processor_id, (SELECT y.yod_id FROM t1 p2, t2 y WHERE p2.processor_id = p1.processor_id and p2.processor_id = y.processor_id) FROM t1 p1; -drop table t1,t2,t3; \ No newline at end of file +drop table t1,t2,t3; + +# +# innodb locking +# +CREATE TABLE t1 ( + id int(11) NOT NULL default '0', + b int(11) default NULL, + c char(3) default NULL, + PRIMARY KEY (id), + KEY t2i1 (b) +) TYPE=innodb DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL'); +CREATE TABLE t2 ( + id int(11) NOT NULL default '0', + b int(11) default NULL, + c char(3) default NULL, + PRIMARY KEY (id), + KEY t2i (b) +) TYPE=innodb DEFAULT CHARSET=latin1; +INSERT INTO t2 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL'); +select (select max(id) from t2 where b=1 group by b) as x,b from t1 where b=1; +drop table t1,t2; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7b401b50d4c..04458a7961a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -906,7 +906,8 @@ int subselect_single_select_engine::prepare() { if (prepared) return 0; - join= new JOIN(thd, select_lex->item_list, select_lex->options, result); + join= new JOIN(thd, select_lex->item_list, + select_lex->options | SELECT_NO_UNLOCK, result); if (!join || !result) { thd->fatal_error(); //out of memory @@ -933,7 +934,7 @@ int subselect_single_select_engine::prepare() int subselect_union_engine::prepare() { - return unit->prepare(thd, result); + return unit->prepare(thd, result, SELECT_NO_UNLOCK); } int subselect_uniquesubquery_engine::prepare() diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e8f1c5d87de..10d2254969a 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -114,7 +114,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, DBUG_RETURN(1); // out of memory // st_select_lex_unit::prepare correctly work for single select - if ((res= unit->prepare(thd, derived_result))) + if ((res= unit->prepare(thd, derived_result, 0))) goto exit; /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 15da6ca57a3..d8344403097 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -351,7 +351,7 @@ public: void exclude_tree(); /* UNION methods */ - int prepare(THD *thd, select_result *result); + int prepare(THD *thd, select_result *result, ulong additional_options); int exec(); int cleanup(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f2470a59944..435354cb4ad 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -29,7 +29,7 @@ int mysql_union(THD *thd, LEX *lex, select_result *result, { DBUG_ENTER("mysql_union"); int res= 0; - if (!(res= unit->prepare(thd, result))) + if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK))) res= unit->exec(); res|= unit->cleanup(); DBUG_RETURN(res); @@ -106,7 +106,8 @@ bool select_union::flush() } -int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result) +int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, + ulong additional_options) { SELECT_LEX *lex_select_save= thd_arg->lex.current_select; SELECT_LEX *sl, *first_select; @@ -146,7 +147,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result) for (;sl; sl= sl->next_select()) { JOIN *join= new JOIN(thd_arg, sl->item_list, - sl->options | thd_arg->options | SELECT_NO_UNLOCK, + sl->options | thd_arg->options | additional_options, tmp_result); thd_arg->lex.current_select= sl; offset_limit_cnt= sl->offset_limit; From 7572bf7a19435f6f8b28dbdbc50bc31365645536 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 13 Dec 2003 17:33:50 -0800 Subject: [PATCH 006/157] mysqld.cc: Resolution of a relative path for character sets dir. sql/mysqld.cc: Resolution of a relative path for character sets dir. --- sql/mysqld.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 805e6860f65..a0eb255f52b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5772,8 +5772,9 @@ static void fix_paths(void) { strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff, CHARSET_DIR, NullS); - charsets_dir=mysql_charsets_dir; } + (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff); + charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) exit(1); From 2fe005174f3fb867399f31a637c4c3967cf8a401 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 21 Dec 2003 22:26:45 +0300 Subject: [PATCH 007/157] THD::init_for_queries() pushed back: see comments to the method why sql/sql_class.h: THD::init_for_queries() pushed back: see comments to the method why Cleanup --- sql/slave.cc | 1 + sql/sql_class.cc | 23 +++++++++++++++++------ sql/sql_class.h | 11 ++++++++++- sql/sql_parse.cc | 2 ++ 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index d2a7d397fa7..8af38624df6 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3111,6 +3111,7 @@ slave_begin: sql_print_error("Failed during slave thread initialization"); goto err; } + thd->init_for_queries(); rli->sql_thd= thd; thd->temporary_tables = rli->save_temporary_tables; // restore temp tables pthread_mutex_lock(&LOCK_thread_count); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 606ecdbecbb..12f0cc4ca72 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -144,9 +144,6 @@ THD::THD():user_time(0), is_fatal_error(0), *scramble= '\0'; init(); - init_sql_alloc(&mem_root, // must be after init() - variables.query_alloc_block_size, - variables.query_prealloc_size); /* Initialize sub structures */ bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root)); bzero((char*) &warn_root,sizeof(warn_root)); @@ -182,9 +179,6 @@ THD::THD():user_time(0), is_fatal_error(0), transaction.trans_log.end_of_file= max_binlog_cache_size; } #endif - init_sql_alloc(&transaction.mem_root, - variables.trans_alloc_block_size, - variables.trans_prealloc_size); /* We need good random number initialization for new thread Just coping global one will not work @@ -227,6 +221,23 @@ void THD::init(void) } +/* + Init THD for query processing. + This has to be called once before we call mysql_parse. + See also comments in sql_class.h. +*/ + +void THD::init_for_queries() +{ + init_sql_alloc(&mem_root, + variables.query_alloc_block_size, + variables.query_prealloc_size); + init_sql_alloc(&transaction.mem_root, + variables.trans_alloc_block_size, + variables.trans_prealloc_size); +} + + /* Do what's needed when one invokes change user diff --git a/sql/sql_class.h b/sql/sql_class.h index d663521b296..1451218f42b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -405,7 +405,6 @@ struct system_variables void free_tmp_table(THD *thd, TABLE *entry); -class Prepared_statement; /* State of a single command executed against this connection. @@ -760,6 +759,16 @@ public: ~THD(); void init(void); + /* + Initialize memory roots necessary for query processing and (!) + pre-allocate memory for it. We can't do that in THD constructor because + there are use cases (acl_init, delayed inserts, watcher threads, + killing mysqld) where it's vital to not allocate excessive and not used + memory. Note, that we still don't return error from init_for_queries(): + if preallocation fails, we should notice that at the first call to + alloc_root. + */ + void init_for_queries(); void change_user(void); void cleanup(void); bool store_globals(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6d975de421f..678d0890136 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -974,6 +974,7 @@ pthread_handler_decl(handle_one_connection,arg) thd->proc_info=0; thd->set_time(); + thd->init_for_queries(); while (!net->error && net->vio != 0 && !thd->killed) { if (do_command(thd)) @@ -1054,6 +1055,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME)); buff= (char*) thd->net.buff; + thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { uint length=(uint) strlen(buff); From 5c9aacb157af7a8e0c31c8580bebc77ed45b125f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 21 Dec 2003 21:18:59 +0100 Subject: [PATCH 008/157] typo fixed --- sql/sql_acl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 01820917ce9..282a9afa038 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -52,7 +52,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, return (byte*) entry->key; } -#define IP_ADDR_STRLEN +#define IP_ADDR_STRLEN (3+1+3+1+3+1+3) #define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; From f2ddb590e381bfe669e99884a298436a52eddafc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Dec 2003 15:57:34 +0300 Subject: [PATCH 009/157] Names of all client methods (static functions inside client.c) now uniform: cli_ + member name. --- sql-common/client.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 14b45942e15..08b39d2ca58 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1403,15 +1403,15 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) before calling mysql_real_connect ! */ -static my_bool cli_mysql_read_query_result(MYSQL *mysql); -static MYSQL_RES *cli_mysql_use_result(MYSQL *mysql); +static my_bool cli_read_query_result(MYSQL *mysql); +static MYSQL_RES *cli_use_result(MYSQL *mysql); static MYSQL_METHODS client_methods= { - cli_mysql_read_query_result, + cli_read_query_result, cli_advanced_command, cli_read_rows, - cli_mysql_use_result, + cli_use_result, cli_fetch_lengths #ifndef MYSQL_SERVER ,cli_list_fields, @@ -2022,7 +2022,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, goto error; if (mysql->fields) { - if (!(res= cli_mysql_use_result(mysql))) + if (!(res= cli_use_result(mysql))) goto error; mysql_free_result(res); } @@ -2240,13 +2240,13 @@ void STDCALL mysql_close(MYSQL *mysql) DBUG_VOID_RETURN; } -static my_bool cli_mysql_read_query_result(MYSQL *mysql) +static my_bool cli_read_query_result(MYSQL *mysql) { uchar *pos; ulong field_count; MYSQL_DATA *fields; ulong length; - DBUG_ENTER("cli_mysql_read_query_result"); + DBUG_ENTER("cli_read_query_result"); /* Read from the connection which we actually used, which @@ -2419,10 +2419,10 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) have to wait for the client (and will not wait more than 30 sec/packet). **************************************************************************/ -static MYSQL_RES * cli_mysql_use_result(MYSQL *mysql) +static MYSQL_RES * cli_use_result(MYSQL *mysql) { MYSQL_RES *result; - DBUG_ENTER("cli_mysql_use_result"); + DBUG_ENTER("cli_use_result"); mysql = mysql->last_used_con; From 509d5cf39108724e3bd16264b2867a54c4ae6d3a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Dec 2003 19:00:51 +0400 Subject: [PATCH 010/157] Fix & test for the bug #2182: lpad returns incorrect result. mysql-test/r/func_str.result: Test for the bug #2182: lpad returns incorrect result mysql-test/t/func_str.test: Test for the bug #2182: lpad returns incorrect result sql/item_strfunc.cc: Fix for the bug #2182: lpad returns incorrect result --- mysql-test/r/func_str.result | 3 +++ mysql-test/t/func_str.test | 6 ++++++ sql/item_strfunc.cc | 5 ++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c74feccfb7f..f08ae1b1efd 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -605,3 +605,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select high_priority md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,(_latin1'HE' collate _latin1'BINARY') AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate _latin1'latin1_bin'),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substr_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")` +SELECT lpad(12345, 5, "#"); +lpad(12345, 5, "#") +12345 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ad7b9b21b51..155ed459d1f 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -346,3 +346,9 @@ DROP TABLE t1; select substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', -2); explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'mood' sounds like 'mud', aes_decrypt(aes_encrypt('abc','1'),'1'),concat('*',space(5),'*'), reverse('abc'), rpad('a',4,'1'), lpad('a',4,'1'), concat_ws(',','',NULL,'a'),make_set(255,_latin2'a',_latin2'b',_latin2'c'),elt(2,1),locate("a","b",2),format(130,10),char(0),conv(130,16,10),hex(130),binary 'HE', export_set(255,_latin2'y',_latin2'n',_latin2' '),FIELD('b' COLLATE latin1_bin,'A','B'),FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'),collation(conv(130,16,10)), coercibility(conv(130,16,10)),length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),concat('monty',' was here ','again'),length('hello'),char(ascii('h')),ord('h'),quote(1/0),crc32("123"),replace('aaaa','a','b'),insert('txs',2,1,'hi'),left(_latin2'a',1),right(_latin2'a',1),lcase(_latin2'a'),ucase(_latin2'a'),SUBSTR('abcdefg',3,2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),trim(_latin2' a '),ltrim(_latin2' a '),rtrim(_latin2' a '), decode(encode(repeat("a",100000),"monty"),"monty"); + +# +# Bug #2182 +# + +SELECT lpad(12345, 5, "#"); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 3cb03d7ea49..2df81f97be0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2022,9 +2022,8 @@ String *Item_func_lpad::val_str(String *str) { uint32 res_char_length,pad_char_length; ulong count= (long) args[1]->val_int(), byte_count; - String a1,a3; - String *res= args[0]->val_str(&a1); - String *pad= args[2]->val_str(&a3); + String *res= args[0]->val_str(&tmp_value); + String *pad= args[2]->val_str(&lpad_str); if (!res || args[1]->null_value || !pad) goto err; From 85938910d53fe236fa7591ebeb19ebc258298fbe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Dec 2003 13:08:16 -0600 Subject: [PATCH 011/157] Minor comment edits. --- libmysql/libmysql.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 728454a50fb..783082c6b03 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1589,7 +1589,7 @@ static my_bool my_realloc_str(NET *net, ulong length) ********************************************************************/ /* - Read the prepare statement results .. + Read the prepared statement results .. NOTE This is only called for connection to servers that supports @@ -1815,7 +1815,7 @@ static void store_param_type(NET *net, uint type) /**************************************************************************** Functions to store parameter data from a prepared statement. - All functions has the following characteristics: + All functions have the following characteristics: SYNOPSIS store_param_xxx() @@ -1997,7 +1997,7 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param) /* - Send the prepare query to server for execution + Send the prepared query to server for execution */ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length) @@ -2087,7 +2087,7 @@ int cli_stmt_execute(MYSQL_STMT *stmt) } /* - Execute the prepare query + Execute the prepared query */ int STDCALL mysql_execute(MYSQL_STMT *stmt) @@ -2332,7 +2332,7 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number, /**************************************************************************** Functions to fetch data to application buffers - All functions has the following characteristics: + All functions have the following characteristics: SYNOPSIS fetch_result_xxx() @@ -3059,12 +3059,12 @@ no_data: /* - Fetch datat for one specified column data + Fetch data for one specified column data SYNOPSIS mysql_fetch_column() stmt Prepared statement handler - bind Where date should be placed. Should be filled in as + bind Where data should be placed. Should be filled in as when calling mysql_bind_param() column Column to fetch (first column is 0) ulong offset Offset in result data (to fetch blob in pieces) @@ -3491,8 +3491,8 @@ my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode) *********************************************************************/ /* - Returns if there are any more query results exists to be read using - mysql_next_result() + Returns true/false to indicate whether any more query results exist + to be read using mysql_next_result() */ my_bool STDCALL mysql_more_results(MYSQL *mysql) From 923af04fc1598cdbbe006b2995dfba5fd5de2ff8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Dec 2003 15:38:19 +0300 Subject: [PATCH 012/157] short patch for bug #2184 'Prepared statements in embedded library was broken with recent changes' (attempt 2). Adding Statement_core is better because: - set_statement() code is shorter and you don't need to modify it when adding new members to Statement_core - a bit faster (you don't have virtual call and don't free_root() twice) Do that short patch instead in hope that set_statement() will be sooner or later removed entirely sql/sql_class.cc: short patch for bug #2184 'Prepared statements in embedded library was broken with recent changes' sql/sql_class.h: short patch for bug #2184 'Prepared statements in embedded library was broken with recent changes' --- sql/sql_class.cc | 2 ++ sql/sql_class.h | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 12f0cc4ca72..60220ffc889 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -336,6 +336,8 @@ THD::~THD() #ifndef DBUG_OFF dbug_sentry = THD_SENTRY_GONE; #endif + /* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */ + init_alloc_root(&stmt_backup.mem_root, 0, 0); DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index c1cd65edf76..5390e8a4ac4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -582,8 +582,7 @@ public: Statement_map stmt_map; /* keeps THD state while it is used for active statement - Note, that double free_root() is safe, so we don't need to do any - special cleanup for it in THD destructor. + Note: we perform special cleanup for it in THD destructor. */ Statement stmt_backup; /* From 7136e3866ca001f636e9288c51c61f8759f1eab5 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Dec 2003 17:17:45 +0400 Subject: [PATCH 013/157] Fix for #2184 (Prepared statements if embedded library broken) There was an error with same function/class member names sql/sql_prepare.cc: Name scope specified --- sql/sql_prepare.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a513e445db9..5d6ab165641 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1193,7 +1193,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg) #ifndef EMBEDDED_LIBRARY setup_params= insert_params; // not fully qualified query #else - setup_params_data= setup_params_data; + setup_params_data= ::setup_params_data; #endif } From 02531752eb4930c0568996a00d16483325f81206 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 23 Dec 2003 18:24:33 +0400 Subject: [PATCH 014/157] Fix for #2181 (mysql_execute crashed instead of returning error on embedded server) We didn't perform the check for the error for embedded server libmysql/libmysql.c: error checking moved to the mysql_execute level --- libmysql/libmysql.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 728454a50fb..9d084879fc8 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2035,14 +2035,6 @@ int cli_stmt_execute(MYSQL_STMT *stmt) uint null_count; my_bool result; -#ifdef CHECK_EXTRA_ARGUMENTS - if (!stmt->param_buffers) - { - /* Parameters exists, but no bound buffers */ - set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND, unknown_sqlstate); - DBUG_RETURN(1); - } -#endif net_clear(net); /* Sets net->write_pos */ /* Reserve place for null-marker bytes */ null_count= (stmt->param_count+7) /8; @@ -2099,6 +2091,14 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt) set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); DBUG_RETURN(1); } +#ifdef CHECK_EXTRA_ARGUMENTS + if (stmt->param_count && !stmt->param_buffers) + { + /* Parameters exists, but no bound buffers */ + set_stmt_error(stmt, CR_NOT_ALL_PARAMS_BOUND, unknown_sqlstate); + DBUG_RETURN(1); + } +#endif if ((*stmt->mysql->methods->stmt_execute)(stmt)) DBUG_RETURN(1); From b72efef6f8eccdb7e47bac298668f31086853657 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Dec 2003 16:04:25 +0400 Subject: [PATCH 015/157] install_test_db.sh: install-test-db did not substiture the path to charsets file, so tests failed with non-default collation incompiled, for example --with-collation=latin1_german1_ci mysqld.cc: better error messaging sql/mysqld.cc: better error messaging mysql-test/install_test_db.sh: install-test-db did not substiture the path to charsets file, so tests failed with non-default collation incompiled, for example --with-collation=latin1_german1_ci --- mysql-test/install_test_db.sh | 2 +- sql/mysqld.cc | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index d8bdd91c59f..11ed1bb312c 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -66,7 +66,7 @@ if [ x$BINARY_DIST = x1 ] ; then basedir=.. else basedir=. -EXTRA_ARG="--language=../sql/share/english/" +EXTRA_ARG="--language=../sql/share/english/ --character-sets-dir=../sql/share/charsets/" fi mysqld_boot=" $execdir/mysqld --no-defaults --bootstrap --skip-grant-tables \ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bf57f9fb8f4..e81113f6111 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2148,8 +2148,12 @@ static int init_common_variables(const char *conf_file_name, int argc, { CHARSET_INFO *default_collation; default_collation= get_charset_by_name(default_collation_name, MYF(0)); - if (!default_collation || !my_charset_same(default_charset_info, - default_collation)) + if (!default_collation) + { + sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name); + return 1; + } + if (!my_charset_same(default_charset_info, default_collation)) { sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH), default_collation_name, From 56f484056355118e8ae5f5f22a45b3e3a64db885 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Dec 2003 16:04:26 +0400 Subject: [PATCH 016/157] charset.c: he mysqld server crashes if issued a command select convert(...) with a non-compiled character set: mysys/charset.c: he mysqld server crashes if issued a command select convert(...) with a non-compiled character set: --- mysys/charset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/charset.c b/mysys/charset.c index 1fe926a51d6..f8c8237c88b 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -539,8 +539,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) { strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); my_read_charset_file(buf,flags); - cs= (cs->state & MY_CS_LOADED) ? cs : NULL; } + cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; pthread_mutex_unlock(&THR_LOCK_charset); return cs; } From 4bff43a7244cedb45f99c812596a6527d3808c43 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Dec 2003 16:59:48 +0400 Subject: [PATCH 017/157] "like" did not work in some cases with character set big5 --- mysql-test/include/have_big5.inc | 4 ++++ mysql-test/r/ctype_big5.result | 10 ++++++++++ mysql-test/r/have_big5.require | 2 ++ mysql-test/t/ctype_big5.test | 18 ++++++++++++++++++ strings/ctype-big5.c | 2 +- 5 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 mysql-test/include/have_big5.inc create mode 100644 mysql-test/r/ctype_big5.result create mode 100644 mysql-test/r/have_big5.require create mode 100644 mysql-test/t/ctype_big5.test diff --git a/mysql-test/include/have_big5.inc b/mysql-test/include/have_big5.inc new file mode 100644 index 00000000000..790e8085e1a --- /dev/null +++ b/mysql-test/include/have_big5.inc @@ -0,0 +1,4 @@ +-- require r/have_big5.require +disable_query_log; +show collation like "big5_chinese_ci"; +enable_query_log; diff --git a/mysql-test/r/ctype_big5.result b/mysql-test/r/ctype_big5.result new file mode 100644 index 00000000000..44fad0cd96a --- /dev/null +++ b/mysql-test/r/ctype_big5.result @@ -0,0 +1,10 @@ +drop table if exists t1; +SET NAMES big5; +CREATE TABLE t1 (c CHAR(10) CHARACTER SET big5, KEY(c)); +INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa'); +SELECT * FROM t1 WHERE c LIKE 'aaa%'; +c +aaa +aaaa +aaaaa +DROP TABLE t1; diff --git a/mysql-test/r/have_big5.require b/mysql-test/r/have_big5.require new file mode 100644 index 00000000000..74aacf74b62 --- /dev/null +++ b/mysql-test/r/have_big5.require @@ -0,0 +1,2 @@ +Collation Charset Id Default Compiled Sortlen +big5_chinese_ci big5 1 Yes Yes 1 diff --git a/mysql-test/t/ctype_big5.test b/mysql-test/t/ctype_big5.test new file mode 100644 index 00000000000..9bf1808636e --- /dev/null +++ b/mysql-test/t/ctype_big5.test @@ -0,0 +1,18 @@ +-- source include/have_big5.inc + +# +# Tests with the big5 character set +# +--disable_warnings +drop table if exists t1; +--enable_warnings + +SET NAMES big5; + +# +# Bug 1883: LIKE did not work in some cases with a key. +# +CREATE TABLE t1 (c CHAR(10) CHARACTER SET big5, KEY(c)); +INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa'); +SELECT * FROM t1 WHERE c LIKE 'aaa%'; +DROP TABLE t1; diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 85f066c4eba..c5ddc167d0d 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -377,7 +377,7 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)), *min_length= (uint) (min_str-min_org); *max_length= res_length; do { - *min_str++ = '\0'; /* Because if key compression */ + *min_str++ = ' '; /* Because if key compression */ *max_str++ = max_sort_char; } while (min_str != min_end); return 0; From 229cc612776f757de6822eb97eb4e9a97226e760 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Dec 2003 17:58:06 +0400 Subject: [PATCH 018/157] sql_parse.cc: Fix for the bug 1175: Usernames will not converted to utf8 during connect sql/sql_parse.cc: Fix for the bug 1175: Usernames will not converted to utf8 during connect --- sql/sql_parse.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 678d0890136..465d840e2b8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -834,6 +834,7 @@ static int check_connection(THD *thd) char *passwd= strend(user)+1; char *db= passwd; char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 /* Old clients send null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty @@ -854,6 +855,14 @@ static int check_connection(THD *thd) db= db_buff; } + if (user) + { + user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1, + system_charset_info, user, strlen(user), + thd->charset())]= '\0'; + user= user_buff; + } + if (thd->user) x_free(thd->user); if (!(thd->user= my_strdup(user, MYF(0)))) From 8fac0f4d2753277928a5bb4c2a5fc5a5a8becc64 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Dec 2003 17:42:17 +0400 Subject: [PATCH 019/157] Bug 2202: CAST from binary to char still returns a binary string --- mysql-test/r/cast.result | 15 +++++++++++++++ mysql-test/t/cast.test | 13 +++++++++++++ sql/item_timefunc.cc | 2 ++ sql/sql_string.cc | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index acca50b45dd..24d33e79411 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -101,6 +101,21 @@ t1 CREATE TABLE `t1` ( `c5` char(2) character set utf8 NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 (a binary(10), b char(10) character set koi8r); +insert into t1 values (_binary'ΤΕΣΤ',_binary'ΤΕΣΤ'); +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +a b cast(a as char character set cp1251) cast(b as binary) +ΤΕΣΤ ΤΕΣΤ ΤΕΣΤ ΤΕΣΤ +set names koi8r; +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +a b cast(a as char character set cp1251) cast(b as binary) +ΤΕΣΤ ΤΕΣΤ ζευζ ΤΕΣΤ +set names cp1251; +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +a b cast(a as char character set cp1251) cast(b as binary) +ΤΕΣΤ ςερς ΤΕΣΤ ΤΕΣΤ +drop table t1; +set names binary; select cast("2001-1-1" as date) = "2001-01-01"; cast("2001-1-1" as date) = "2001-01-01" 1 diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index dd17904effb..cb5f10515bd 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -64,6 +64,19 @@ select * from t1; show create table t1; drop table t1; +# +# Bug 2202 +# CAST from BINARY to non-BINARY and from non-BINARY to BINARY +# +create table t1 (a binary(10), b char(10) character set koi8r); +insert into t1 values (_binary'ΤΕΣΤ',_binary'ΤΕΣΤ'); +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +set names koi8r; +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +set names cp1251; +select a,b,cast(a as char character set cp1251),cast(b as binary) from t1; +drop table t1; +set names binary; # # The following should be fixed in 4.1 diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 9799c5814c4..ed5b9ecc0db 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1848,6 +1848,8 @@ String *Item_char_typecast::val_str(String *str) } res= str; } + + res->set_charset(cast_cs); /* Cut the tail if cast with length diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 61070f07266..89f48607969 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -235,7 +235,7 @@ bool String::copy(const char *str, uint32 arg_length, { if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) { - return copy(str, arg_length, &my_charset_bin); + return copy(str, arg_length, to_cs); } uint32 new_length= to_cs->mbmaxlen*arg_length; if (alloc(new_length)) From 398f7b77002db5759dac2f9b858549f08926d72e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Dec 2003 17:46:30 +0400 Subject: [PATCH 020/157] languages.html: new file --- sql/share/charsets/languages.html | 257 ++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 sql/share/charsets/languages.html diff --git a/sql/share/charsets/languages.html b/sql/share/charsets/languages.html new file mode 100644 index 00000000000..6d1a8aafc5c --- /dev/null +++ b/sql/share/charsets/languages.html @@ -0,0 +1,257 @@ +#!/bin/sh +#
+(
+echo "DROP TABLE lang;"
+echo "CREATE TABLE lang (lang varchar(128), letters text character set utf8);"
+(
+grep -v "^#" << END
+#
+Greenlandic	ÁÂÃÊÍÎÔÚÛáâãêíîôúûĨĩĸŨũ
+#Use of these letters was abolished in a spelling reform in 1973:
+#Greenlandic	ÅÆØåæø
+#Characters not found in the UCS:
+#	K LATIN CAPITAL LETTER KRA
+#############################################################
+#Basque	ÑÜñüŔŕ
+#Characters not found in the UCS:
+#	D LATIN CAPITAL LETTER D WITH MACRON
+#	d LATIN SMALL LETTER D WITH MACRON
+#	L LATIN CAPITAL LETTER L WITH MACRON
+#	l LATIN SMALL LETTER L WITH MACRON
+#	T LATIN CAPITAL LETTER T WITH MACRON
+#	t LATIN SMALL LETTER T WITH MACRON
+#############################################################
+#Maltese	#ÀÁÂÈÉÊÌÍÎÒÓÔÙÚÛ#àáâèéêìíîòÓôùúû#ĊċĠġĦħŻżʼ
+#BosnianCyr	ЂЈЉЊЋЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшђјљњћџ
+#Scots	A
+#Scots1	ƷȜȝʒ
+###########################################
+#### Hiragana 3040-309F
+Hiragana	ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん
+Hiragana1	ゔ゙゚
+Hiragana2	゛゜ゝゞ
+#### Katakana 30A0-30FF
+Katakana	ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶ
+Katakana1	ヷヸヹヺ
+Katakana2	・ーヽヾ
+############################################
+Albanian	ÂÇËâçë
+Bosnian	ĆćČčĐ𩹮ž
+Breton	ÂÊÑÙÜâêñùü
+Catalan	ÀÇÈÉÍÏÒÓÚÜàçèéíïòóúü
+#Catalan1	·Ŀŀ
+Croatian	ĆćČčĐ𩹮ž
+CroatianLig	DZDzdzDŽDždžLJLjljNJNjnj
+Czech	ÁÉÍÓÚÝáéíóúýČčĎďĚěŇňŘřŠšŤťŮůŽž
+Danish	ÁÄÅÆÉÓÖØÜáäåæéóöøü
+Dutch	ÀÂÄÆÇÈÉÊËÎÏÑÒÓÔÖÙÚÛÜàâäæçèéêëîïñòóôöùúûü
+Esperanto	ĈĉĜĝĤĥĴĵŜŝŬŭ
+Estonian	ÄÕÖÜäõöüŠšŽž
+Faroese	ÅÆÐÓÖØÚÝåæðóöøúý
+Finnish	ÄÅÖÜäåöü
+#Finnish1	ŠšŽž
+French(limited)	ÀÂÆÇÈÉÊËÎÏÑÔÙÛàâæçèéêëîïñôùûÿ
+French	ŒœŸ
+German	ÄÖÜßäöü
+Hungarian	ÁÉÍÓÖÚÜáéíóöúüŐőŰű
+Icelandic	ÁÆÉÍÐÓÖÚÝÞáæéíðóöúýþ
+Italian	ÀÈÉÌÍÏÒÓÙÚàèéìíïòóùú
+#Latin	A
+Latvian	ĀāČčĒēĢģĪīĶķĻļŅņŠšŪūŽž
+Lithuanian	ĄąČčĖėĘęĮįŠšŪūŲųŽž
+Norwegian	ÅÆØåæø
+Polish	ÓóĄąĆćĘꣳŃńŚśŹźŻż
+Portuguese	ÀÁÂÃÇÉÊÍÓÔÕÚÜàáâãçéêíóôõúü
+#http://en.wikipedia.org/wiki/Special_Romanian_Unicode_characters
+Romanian	ÂÎâîĂăȘșȚț
+Romanian(ErrorST)	ÂÎâîĂ㪺Ţţ
+Slovak	ÁÄÉÍÓÔÚÝáäéíóôúýČčĎďĹ弾ŇňŔ੹ŤťŽž
+Slovene	ČčŠšŽž
+Sorbian-Lower	ĆćČčĚ죳ŃńŘřŚśŠšŹźŽž
+Sorbian-Upper	ÓóĆćČčĚ죳ŃńŘřŠšŽž
+Spanish	ÁÉÍÑÓÚÜáéíñóúü
+Swedish	ÄÅÖäåö
+Turkish	ÂÇÖÛÜâçöûüĞğİı
+Welsh	ÀÁÂÄÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÝàáâäèéêëìíîïòóôöùúûüýÿŴŵŶŷŸẀẁẂẃẄẅỲỳ
+##################################
+Belarusian	ЁІЎАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяёіў
+Bulgarian	АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя
+Bulgarian1	ЀҭѐѝѢѣѪѫ
+Macedonian	ЃЅЈЉЊЌЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшѓѕјљњќџ
+Russian	ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё
+RussianOLD	ІіѢѣѲѳѴѵ
+Serbian	ЂЈЉЊЋЏАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШабвгдежзиклмнопрстуфхцчшђјљњћџ
+Ukrainian	ЄІЇАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЭЮЯабвгдежзийклмнопрстуфхцчшщьэюяєіїҐґ
+##################################
+Armenian	ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՑՒՓՔՕՖ՛՜՝՞՟աբգդեֆ։
+#Armenian1	՚֊
+#Characters not found in the UCS:
+#	ARMENIAN ETERNITY SIGN
+#
+GeorgianOld	ႠႡႢႣႤႥႦႧႨႩႪႫႬႭႮႯႰႱႲႳႴႵႶႷႸႹႺႻႼႽႾႿჀჁჂჃჄჅ
+Georgian	აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰ
+GeorgianArc	ჱჲჳჴჵჶ
+GeorgianPunc	჻
+#
+GreekExt1	΄΅Ά·ΈΉΊ»Ό½ΎΏΐ
+Greek	ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψω
+GreekExt2	ΪΫάέήίΰϊϋόύώ
+GreekExt4	ς
+#
+Hebrew	אבגדהוזחטיךכלםמןנסעףפץצקרשת
+##################################
+#Abaza
+#Abkhaz
+#Adyghe
+#Agul *
+#(Aisor)
+#Akhvakh *
+#(?lvdalska)
+#(Andi) *
+#(Aragonese)
+#Archi *
+#Arumanian
+#(Arvanite)
+#Asturian
+#Avar
+#Azerbaijani
+#(Bagulal) *
+#Balkar
+#Bashkir
+#Basque			!
+#Bats *
+#Bezhta *
+#(Botlikh) *
+#Budukh *
+#(Chamalal)
+#Chechen
+#Chuvash
+#Cornish		!
+#(Corsican)
+#Dargwa
+#Erzya
+#(Franco-Proven?al)
+#(Frisian, East)
+#(Frisian, North)
+#Frisian, West
+#Friulian
+#Gagauz
+#Gaelic, Irish		!
+#Gaelic, Manx		!
+#Gaelic, Scottish	!
+#Galician		!
+#(German, Low)		!
+#(German, Swiss)	!
+#Godoberi *
+#(Hinukh) *
+#(Hunzib) *
+#Ingrian
+#Ingush
+#Istro-Romanian
+#(Judeo-Georgian)
+#(Judeo-Kurdish)
+#(Judeo-Tati)
+#Kabardian
+#Kalmyk
+#Karachay
+#(Karaim)
+#(Karata) *
+#Karelian
+#Kashubian
+#Kazakh
+#Khinalug
+#(Khvarshi) *
+#(Kirmanji)
+#Komi
+#Komi-Permyak
+#(Kryts)
+#Kumyk
+#(Kurdish)
+#(Ladin)
+#(Ladino)
+#Lak
+#Laz
+#Lezgian
+#Livonian
+#(Ludian)
+#Luxemburgish		!
+#Mari, Hill
+#Mari, Meadow
+#Megleno-Romanian
+#(Mingrelian)
+#Moksha
+#Moldavian
+#Nenets, Tundra
+#Nogai
+#Occitan
+#Old Church Slavonic
+#(Olonets)
+#Ossetian
+#(Romani)
+#Romansch
+#(Rusyn)
+#Rutul
+#Sami, Inari
+#Sami, Kildin
+#Sami, Lule
+#Sami, Northern
+#Sami, Skolt
+#Sami, Southern
+#(Sami, Ter) *
+#(Sami, Ume) *
+#(Sardinian) *
+#Scots			!
+#Svan
+#Tabasaran
+#(Talysh)
+#Tatar, Crimean
+#Tatar, Kazan
+#Tati
+#(Tindi) *
+#(Tsakonian) *
+#Tsakhur *
+#(Tsez) *
+#(Turkish, Crimean)
+#Ubykh *
+#Udi
+#Udmurt
+#(V?mhusm?l)
+#Vepsian
+#Votic
+#(Walloon)
+#(Yiddish) 
+################################
+#      4	Gaelic-new-orthography
+#      4	Frisian
+#      3	Rhaeto-Romanic
+#      2	S&AACUTEmi-with-restrictions
+#      1	Rhjaeto-Romanic
+#      1	Gaelic-old-and-new-orthographies
+END
+) | 
+
+while read a b
+do
+  c=`echo $b | replace "&#x" "" ";" ""`
+  printf "INSERT INTO lang VALUES ('$a',_ucs2 X'$c');\n"
+done
+) | mysql -f test
+
+#mysql test << END
+#SELECT * FROM lang WHERE CONVERT(letters USING latin1) NOT LIKE _binary'%?%';
+#SELECT * FROM lang WHERE CONVERT(letters USING latin2) NOT LIKE _binary'%?%';
+#END
+
+
+
+list="big5 dec8 cp850 hp8 koi8r latin1 latin2 swe7 ascii ujis sjis hebrew euckr koi8u gb2312 greek cp1250 gbk latin5 armscii8 cp866 keybcs2 macce macroman cp852 latin7 cp1251 cp1256 cp1257 geostd8"
+
+for p in $list
+do
+echo "-----------------"
+echo $p:
+mysql  -sss test << END
+SELECT lang FROM lang WHERE CONVERT(letters USING $p) NOT LIKE _binary'%?%' ORDER BY lang;
+END
+done
+

From 17e54cf40702918c5f9b932a2416619ad88e12e7 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 25 Dec 2003 18:50:22 +0400
Subject: [PATCH 021/157] Fix for the bug #2198: SELECT INTO OUTFILE (with
 Sub-Select) Problem. Proper Item_cache::setup() method. Code cleanup.
 (discussed with sanja)

sql/item.cc:
  code cleanup
sql/item.h:
  fix for the bug #2198: SELECT INTO OUTFILE (with Sub-Select) Problem.
  proper Item_cache::setup() method
  code cleanup
sql/item_subselect.cc:
  fix for the bug #2198: SELECT INTO OUTFILE (with Sub-Select) Problem.
  proper Item_cache::setup() method
  code cleanup
---
 sql/item.cc           |  3 ---
 sql/item.h            | 16 +++++++++-------
 sql/item_subselect.cc | 15 ++++++---------
 3 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/sql/item.cc b/sql/item.cc
index 417f05680cf..37240700c68 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1867,7 +1867,6 @@ void Item_cache_int::store(Item *item)
 {
   value= item->val_int_result();
   null_value= item->null_value;
-  collation.set(item->collation);
 }
 
 
@@ -1875,7 +1874,6 @@ void Item_cache_real::store(Item *item)
 {
   value= item->val_result();
   null_value= item->null_value;
-  collation.set(item->collation);
 }
 
 
@@ -1898,7 +1896,6 @@ void Item_cache_str::store(Item *item)
     value_buff.copy(*value);
     value= &value_buff;
   }
-  collation.set(item->collation);
 }
 
 
diff --git a/sql/item.h b/sql/item.h
index 5def1e2b710..5917a0dc95e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -878,13 +878,15 @@ public:
   void set_used_tables(table_map map) { used_table_map= map; }
 
   virtual bool allocate(uint i) { return 0; };
-  virtual bool setup(Item *item) { example= item;  return 0; };
-  virtual void store(Item *)= 0;
-  void set_len_n_dec(uint32 max_len, uint8 dec)
+  virtual bool setup(Item *item)
   {
-    max_length= max_len;
-    decimals= dec;
-  }
+    example= item;
+    max_length= item->max_length;
+    decimals= item->decimals;
+    collation.set(item->collation);
+    return 0;
+  };
+  virtual void store(Item *)= 0;
   enum Type type() const { return CACHE_ITEM; }
   static Item_cache* get_cache(Item_result type);
   table_map used_tables() const { return used_table_map; }
@@ -909,7 +911,7 @@ class Item_cache_real: public Item_cache
   double value;
 public:
   Item_cache_real(): Item_cache() {}
-  
+
   void store(Item *item);
   double val() { return value; }
   longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 43775e1c96c..cb729041f22 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -301,8 +301,6 @@ void Item_singlerow_subselect::fix_length_and_dec()
   if ((max_columns= engine->cols()) == 1)
   {
     engine->fix_length_and_dec(row= &value);
-    if (!(value= Item_cache::get_cache(engine->type())))
-      return;
   }
   else
   {
@@ -955,13 +953,9 @@ static Item_result set_row(List &item_list, Item *item,
     res_type= sel_item->result_type();
     item->decimals= sel_item->decimals;
     *maybe_null= sel_item->maybe_null;
-    if (row)
-    {
-      if (!(row[i]= Item_cache::get_cache(res_type)))
-	return STRING_RESULT; // we should return something
-      row[i]->set_len_n_dec(sel_item->max_length, sel_item->decimals);
-      row[i]->collation.set(sel_item->collation);
-    }
+    if (!(row[i]= Item_cache::get_cache(res_type)))
+      return STRING_RESULT; // we should return something
+    row[i]->setup(sel_item);
   }
   if (item_list.elements > 1)
     res_type= ROW_RESULT;
@@ -982,7 +976,10 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
   DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
 
   if (unit->first_select()->item_list.elements == 1)
+  {
     res_type= set_row(unit->types, item, row, &maybe_null);
+    item->collation.set(row[0]->collation);
+  }
   else
   {
     bool fake= 0;

From e52ae56f3322cf114400cdc6b601040f80909549 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 25 Dec 2003 19:07:44 +0400
Subject: [PATCH 022/157] dump_map.c:   new file

---
 strings/dump_map.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)
 create mode 100644 strings/dump_map.c

diff --git a/strings/dump_map.c b/strings/dump_map.c
new file mode 100644
index 00000000000..f999160d0d4
--- /dev/null
+++ b/strings/dump_map.c
@@ -0,0 +1,72 @@
+#include 
+#include 
+
+static void print_short_array(unsigned short *a)
+{
+  int i;
+  printf("{\n");
+  for (i=0; i<=0xFF; i++)
+  {
+    printf("0x%04X%s%s",(int)a[i],i<0xFF?",":"",(i+1) % 8 ? "" :"\n");
+  }
+  printf("};\n");
+  
+}
+
+
+
+int main(void)
+{
+  char str[160];
+  unsigned short touni[256];
+  unsigned short fromuni[65536];
+  unsigned short fromstat[256];
+  int i;
+  
+  bzero((void*)touni,sizeof(touni));
+  bzero((void*)fromuni,sizeof(fromuni));
+  bzero((void*)fromstat,sizeof(fromstat));
+  
+  while (fgets(str,sizeof(str),stdin))
+  {
+    unsigned int c,u;
+    
+    if ((str[0]=='#') || (2!=sscanf(str,"%x%x",&c,&u)))
+      continue;
+    if (c>0xFF || u>0xFFFF)
+      continue;
+    
+    touni[c]= u;
+    fromuni[u]= c;
+  }
+  
+  printf("unsigned short cs_to_uni[256]=");
+  print_short_array(touni);
+  
+  for (i=0;i<=0xFF;i++)
+  {
+    fromstat[touni[i]>>8]++;
+  }
+  
+  for (i=0;i<=256;i++)
+  {
+    if (fromstat[i])
+    { 
+      printf("unsigned char pl%02X[256]=",i);
+      print_short_array(fromuni+i*256);
+    }
+  }
+  
+  printf("unsigned short *uni_to_cs[256]={\n");
+  for (i=0;i<=255;i++)
+  {
+    if (fromstat[i])
+      printf("pl%02X",i);
+    else
+      printf("NULL");
+    printf("%s%s",i<255?",":"",((i+1) % 8) ? "":"\n");
+  }
+  printf("};\n");
+  
+  return 0;
+}

From d55382369eb639417dd01a62ff4867f9213f10ce Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 25 Dec 2003 20:11:01 +0400
Subject: [PATCH 023/157] Bug 1552: TIS620 to Unicode and Unicode to TIS620
 conversion check.

---
 mysql-test/include/have_tis620.inc |   4 +
 mysql-test/r/ctype_tis620.result   | 113 ++++++++++++++++
 mysql-test/r/have_tis620.require   |   2 +
 mysql-test/t/ctype_tis620.test     |  64 +++++++++
 strings/ctype-tis620.c             | 203 ++++++++++++++++++++++++++++-
 5 files changed, 384 insertions(+), 2 deletions(-)
 create mode 100644 mysql-test/include/have_tis620.inc
 create mode 100644 mysql-test/r/ctype_tis620.result
 create mode 100644 mysql-test/r/have_tis620.require
 create mode 100644 mysql-test/t/ctype_tis620.test

diff --git a/mysql-test/include/have_tis620.inc b/mysql-test/include/have_tis620.inc
new file mode 100644
index 00000000000..c1e775681b0
--- /dev/null
+++ b/mysql-test/include/have_tis620.inc
@@ -0,0 +1,4 @@
+-- require r/have_tis620.require
+disable_query_log;
+show collation like "tis620_thai_ci";
+enable_query_log;
diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result
new file mode 100644
index 00000000000..10164cd07ef
--- /dev/null
+++ b/mysql-test/r/ctype_tis620.result
@@ -0,0 +1,113 @@
+drop table if exists t1;
+SET @pl0= _tis620 0x000102030405060708090A0B0C0D0E0F;
+SET @pl1= _tis620 0x101112131415161718191A1B1C1D1E1F;
+SET @pl2= _tis620 0x202122232425262728292A2B2C2D2E2F;
+SET @pl3= _tis620 0x303132333435363738393A3B3C3D3E3F;
+SET @pl4= _tis620 0x404142434445464748494A4B4C4D4E4F;
+SET @pl5= _tis620 0x505152535455565758595A5B5C5D5E5F;
+SET @pl6= _tis620 0x606162636465666768696A6B6C6D6E6F;
+SET @pl7= _tis620 0x707172737475767778797A7B7C7D7E7F;
+SET @pl8= _tis620 0x808182838485868788898A8B8C8D8E8F;
+SET @pl9= _tis620 0x909192939495969798999A9B9C9D9E9F;
+SET @plA= _tis620 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAF;
+SET @plB= _tis620 0xB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF;
+SET @plC= _tis620 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF;
+SET @plD= _tis620 0xD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF;
+SET @plE= _tis620 0xE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF;
+SET @plF= _tis620 0xF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF;
+SELECT hex(@u0:=convert(@pl0 using utf8));
+hex(@u0:=convert(@pl0 using utf8))
+000102030405060708090A0B0C0D0E0F
+SELECT hex(@u1:=convert(@pl1 using utf8));
+hex(@u1:=convert(@pl1 using utf8))
+101112131415161718191A1B1C1D1E1F
+SELECT hex(@u2:=convert(@pl2 using utf8));
+hex(@u2:=convert(@pl2 using utf8))
+202122232425262728292A2B2C2D2E2F
+SELECT hex(@u3:=convert(@pl3 using utf8));
+hex(@u3:=convert(@pl3 using utf8))
+303132333435363738393A3B3C3D3E3F
+SELECT hex(@u4:=convert(@pl4 using utf8));
+hex(@u4:=convert(@pl4 using utf8))
+404142434445464748494A4B4C4D4E4F
+SELECT hex(@u5:=convert(@pl5 using utf8));
+hex(@u5:=convert(@pl5 using utf8))
+505152535455565758595A5B5C5D5E5F
+SELECT hex(@u6:=convert(@pl6 using utf8));
+hex(@u6:=convert(@pl6 using utf8))
+606162636465666768696A6B6C6D6E6F
+SELECT hex(@u7:=convert(@pl7 using utf8));
+hex(@u7:=convert(@pl7 using utf8))
+707172737475767778797A7B7C7D7E7F
+SELECT hex(@u8:=convert(@pl8 using utf8));
+hex(@u8:=convert(@pl8 using utf8))
+C280C281C282C283C284C285C286C287C288C289C28AC28BC28CC28DC28EC28F
+SELECT hex(@u9:=convert(@pl9 using utf8));
+hex(@u9:=convert(@pl9 using utf8))
+C290C291C292C293C294C295C296C297C298C299C29AC29BC29CC29DC29EC29F
+SELECT hex(@uA:=convert(@plA using utf8));
+hex(@uA:=convert(@plA using utf8))
+EFBFBDE0B881E0B882E0B883E0B884E0B885E0B886E0B887E0B888E0B889E0B88AE0B88BE0B88CE0B88DE0B88EE0B88F
+SELECT hex(@uB:=convert(@plB using utf8));
+hex(@uB:=convert(@plB using utf8))
+E0B890E0B891E0B892E0B893E0B894E0B895E0B896E0B897E0B898E0B899E0B89AE0B89BE0B89CE0B89DE0B89EE0B89F
+SELECT hex(@uC:=convert(@plC using utf8));
+hex(@uC:=convert(@plC using utf8))
+E0B8A0E0B8A1E0B8A2E0B8A3E0B8A4E0B8A5E0B8A6E0B8A7E0B8A8E0B8A9E0B8AAE0B8ABE0B8ACE0B8ADE0B8AEE0B8AF
+SELECT hex(@uD:=convert(@plD using utf8));
+hex(@uD:=convert(@plD using utf8))
+E0B8B0E0B8B1E0B8B2E0B8B3E0B8B4E0B8B5E0B8B6E0B8B7E0B8B8E0B8B9E0B8BAEFBFBDEFBFBDEFBFBDEFBFBDE0B8BF
+SELECT hex(@uE:=convert(@plE using utf8));
+hex(@uE:=convert(@plE using utf8))
+E0B980E0B981E0B982E0B983E0B984E0B985E0B986E0B987E0B988E0B989E0B98AE0B98BE0B98CE0B98DE0B98EE0B98F
+SELECT hex(@uF:=convert(@plF using utf8));
+hex(@uF:=convert(@plF using utf8))
+E0B990E0B991E0B992E0B993E0B994E0B995E0B996E0B997E0B998E0B999E0B99AE0B99BEFBFBDEFBFBDEFBFBDEFBFBD
+SELECT hex(convert(@u0 USING tis620));
+hex(convert(@u0 USING tis620))
+000102030405060708090A0B0C0D0E0F
+SELECT hex(convert(@u1 USING tis620));
+hex(convert(@u1 USING tis620))
+101112131415161718191A1B1C1D1E1F
+SELECT hex(convert(@u2 USING tis620));
+hex(convert(@u2 USING tis620))
+202122232425262728292A2B2C2D2E2F
+SELECT hex(convert(@u3 USING tis620));
+hex(convert(@u3 USING tis620))
+303132333435363738393A3B3C3D3E3F
+SELECT hex(convert(@u4 USING tis620));
+hex(convert(@u4 USING tis620))
+404142434445464748494A4B4C4D4E4F
+SELECT hex(convert(@u5 USING tis620));
+hex(convert(@u5 USING tis620))
+505152535455565758595A5B5C5D5E5F
+SELECT hex(convert(@u6 USING tis620));
+hex(convert(@u6 USING tis620))
+606162636465666768696A6B6C6D6E6F
+SELECT hex(convert(@u7 USING tis620));
+hex(convert(@u7 USING tis620))
+707172737475767778797A7B7C7D7E7F
+SELECT hex(convert(@u8 USING tis620));
+hex(convert(@u8 USING tis620))
+808182838485868788898A8B8C8D8E8F
+SELECT hex(convert(@u9 USING tis620));
+hex(convert(@u9 USING tis620))
+909192939495969798999A9B9C9D9E9F
+SELECT hex(convert(@uA USING tis620));
+hex(convert(@uA USING tis620))
+FFA1A2A3A4A5A6A7A8A9AAABACADAEAF
+SELECT hex(convert(@uB USING tis620));
+hex(convert(@uB USING tis620))
+B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF
+SELECT hex(convert(@uC USING tis620));
+hex(convert(@uC USING tis620))
+C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
+SELECT hex(convert(@uD USING tis620));
+hex(convert(@uD USING tis620))
+D0D1D2D3D4D5D6D7D8D9DAFFFFFFFFDF
+SELECT hex(convert(@uE USING tis620));
+hex(convert(@uE USING tis620))
+E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
+SELECT hex(convert(@uF USING tis620));
+hex(convert(@uF USING tis620))
+F0F1F2F3F4F5F6F7F8F9FAFBFFFFFFFF
diff --git a/mysql-test/r/have_tis620.require b/mysql-test/r/have_tis620.require
new file mode 100644
index 00000000000..a1bf93ac491
--- /dev/null
+++ b/mysql-test/r/have_tis620.require
@@ -0,0 +1,2 @@
+Collation	Charset	Id	Default	Compiled	Sortlen
+tis620_thai_ci	tis620	18	Yes	Yes	4
diff --git a/mysql-test/t/ctype_tis620.test b/mysql-test/t/ctype_tis620.test
new file mode 100644
index 00000000000..82c660dfea0
--- /dev/null
+++ b/mysql-test/t/ctype_tis620.test
@@ -0,0 +1,64 @@
+-- source include/have_tis620.inc
+
+#
+# Tests with the big5 character set
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Bug 1552: tis620 <-> unicode conversion crashed
+# Check tis620 -> utf8 -> tis620 round trip conversion
+#
+
+SET @pl0= _tis620 0x000102030405060708090A0B0C0D0E0F;
+SET @pl1= _tis620 0x101112131415161718191A1B1C1D1E1F;
+SET @pl2= _tis620 0x202122232425262728292A2B2C2D2E2F;
+SET @pl3= _tis620 0x303132333435363738393A3B3C3D3E3F;
+SET @pl4= _tis620 0x404142434445464748494A4B4C4D4E4F;
+SET @pl5= _tis620 0x505152535455565758595A5B5C5D5E5F;
+SET @pl6= _tis620 0x606162636465666768696A6B6C6D6E6F;
+SET @pl7= _tis620 0x707172737475767778797A7B7C7D7E7F;
+SET @pl8= _tis620 0x808182838485868788898A8B8C8D8E8F;
+SET @pl9= _tis620 0x909192939495969798999A9B9C9D9E9F;
+SET @plA= _tis620 0xA0A1A2A3A4A5A6A7A8A9AAABACADAEAF;
+SET @plB= _tis620 0xB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF;
+SET @plC= _tis620 0xC0C1C2C3C4C5C6C7C8C9CACBCCCDCECF;
+SET @plD= _tis620 0xD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF;
+SET @plE= _tis620 0xE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF;
+SET @plF= _tis620 0xF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF;
+
+SELECT hex(@u0:=convert(@pl0 using utf8));
+SELECT hex(@u1:=convert(@pl1 using utf8));
+SELECT hex(@u2:=convert(@pl2 using utf8));
+SELECT hex(@u3:=convert(@pl3 using utf8));
+SELECT hex(@u4:=convert(@pl4 using utf8));
+SELECT hex(@u5:=convert(@pl5 using utf8));
+SELECT hex(@u6:=convert(@pl6 using utf8));
+SELECT hex(@u7:=convert(@pl7 using utf8));
+SELECT hex(@u8:=convert(@pl8 using utf8));
+SELECT hex(@u9:=convert(@pl9 using utf8));
+SELECT hex(@uA:=convert(@plA using utf8));
+SELECT hex(@uB:=convert(@plB using utf8));
+SELECT hex(@uC:=convert(@plC using utf8));
+SELECT hex(@uD:=convert(@plD using utf8));
+SELECT hex(@uE:=convert(@plE using utf8));
+SELECT hex(@uF:=convert(@plF using utf8));
+
+SELECT hex(convert(@u0 USING tis620));
+SELECT hex(convert(@u1 USING tis620));
+SELECT hex(convert(@u2 USING tis620));
+SELECT hex(convert(@u3 USING tis620));
+SELECT hex(convert(@u4 USING tis620));
+SELECT hex(convert(@u5 USING tis620));
+SELECT hex(convert(@u6 USING tis620));
+SELECT hex(convert(@u7 USING tis620));
+SELECT hex(convert(@u8 USING tis620));
+SELECT hex(convert(@u9 USING tis620));
+SELECT hex(convert(@uA USING tis620));
+SELECT hex(convert(@uB USING tis620));
+SELECT hex(convert(@uC USING tis620));
+SELECT hex(convert(@uD USING tis620));
+SELECT hex(convert(@uE USING tis620));
+SELECT hex(convert(@uF USING tis620));
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index a2edc33b3d2..92b2eeb25e0 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -701,6 +701,205 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
 }
 #endif /* NOT_NEEDED */
 
+static unsigned short cs_to_uni[256]={
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
+0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
+0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
+0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
+0xFFFD,0x0E01,0x0E02,0x0E03,0x0E04,0x0E05,0x0E06,0x0E07,
+0x0E08,0x0E09,0x0E0A,0x0E0B,0x0E0C,0x0E0D,0x0E0E,0x0E0F,
+0x0E10,0x0E11,0x0E12,0x0E13,0x0E14,0x0E15,0x0E16,0x0E17,
+0x0E18,0x0E19,0x0E1A,0x0E1B,0x0E1C,0x0E1D,0x0E1E,0x0E1F,
+0x0E20,0x0E21,0x0E22,0x0E23,0x0E24,0x0E25,0x0E26,0x0E27,
+0x0E28,0x0E29,0x0E2A,0x0E2B,0x0E2C,0x0E2D,0x0E2E,0x0E2F,
+0x0E30,0x0E31,0x0E32,0x0E33,0x0E34,0x0E35,0x0E36,0x0E37,
+0x0E38,0x0E39,0x0E3A,0xFFFD,0xFFFD,0xFFFD,0xFFFD,0x0E3F,
+0x0E40,0x0E41,0x0E42,0x0E43,0x0E44,0x0E45,0x0E46,0x0E47,
+0x0E48,0x0E49,0x0E4A,0x0E4B,0x0E4C,0x0E4D,0x0E4E,0x0E4F,
+0x0E50,0x0E51,0x0E52,0x0E53,0x0E54,0x0E55,0x0E56,0x0E57,
+0x0E58,0x0E59,0x0E5A,0x0E5B,0xFFFD,0xFFFD,0xFFFD,0xFFFD
+};
+static unsigned char pl00[256]={
+0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
+0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,
+0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
+0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,
+0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
+0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
+0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
+0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
+0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
+0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
+0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
+0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
+0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
+0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
+0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
+0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,
+0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
+0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
+0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
+0x0098,0x0099,0x009A,0x009B,0x009C,0x009D,0x009E,0x009F,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
+};
+static unsigned char pl0E[256]={
+0x0000,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,
+0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF,
+0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,
+0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF,
+0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,
+0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF,
+0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,
+0x00D8,0x00D9,0x00DA,0x0000,0x0000,0x0000,0x0000,0x00DF,
+0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,
+0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF,
+0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,
+0x00F8,0x00F9,0x00FA,0x00FB,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
+};
+static unsigned char plFF[256]={
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+0x0000,0x0000,0x0000,0x0000,0x0000,0x00FF,0x0000,0x0000
+};
+static unsigned char *uni_to_cs[256]={
+pl00,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,pl0E,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+NULL,NULL,NULL,NULL,NULL,NULL,NULL,plFF
+};
+
+
+static
+int my_mb_wc_tis620(CHARSET_INFO *cs,my_wc_t *wc,
+		  const unsigned char *str,
+		  const unsigned char *end __attribute__((unused)))
+{
+  if (str >= end)
+    return MY_CS_TOOFEW(0);
+  
+  *wc=cs_to_uni[*str];
+  return (!wc[0] && str[0]) ? MY_CS_ILSEQ : 1;
+}
+
+static
+int my_wc_mb_tis620(CHARSET_INFO *cs,my_wc_t wc,
+		  unsigned char *str,
+		  unsigned char *end __attribute__((unused)))
+{
+  unsigned char *pl;
+  
+  if (str >= end)
+    return MY_CS_TOOSMALL;
+  
+  pl= uni_to_cs[(wc>>8) & 0xFF];
+  str[0]= pl ? pl[wc & 0xFF] : '\0';
+  return (!str[0] && wc) ? MY_CS_ILUNI : 1;
+}
+
 
 static MY_COLLATION_HANDLER my_collation_ci_handler =
 {
@@ -721,8 +920,8 @@ static MY_CHARSET_HANDLER my_charset_handler=
     my_numchars_8bit,
     my_charpos_8bit,
     my_lengthsp_8bit,
-    my_mb_wc_8bit,	/* mb_wc     */
-    my_wc_mb_8bit,	/* wc_mb     */
+    my_mb_wc_tis620,	/* mb_wc     */
+    my_wc_mb_tis620,	/* wc_mb     */
     my_caseup_str_8bit,
     my_casedn_str_8bit,
     my_caseup_8bit,

From 3f4d396dc33a68252f8db838d14192186f4ce342 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 26 Dec 2003 12:32:02 +0200
Subject: [PATCH 024/157] Fixed bug in table level privilege GRANT handling.
 (Bug #2178) Portability fixes

mysql-test/r/rpl_until.result:
  Portability fix
mysql-test/t/rpl_until.test:
  Portability fix
sql/slave.cc:
  Write UNTIL position to logs (for debugging)
sql/slave.h:
  Write UNTIL position to logs (for debugging)
sql/sql_acl.cc:
  Fixed bug in table level privilege GRANT handling. (Bug #2178)
---
 mysql-test/r/rpl_until.result | 2 +-
 mysql-test/t/rpl_until.test   | 6 +++---
 sql/slave.cc                  | 2 +-
 sql/slave.h                   | 5 +++++
 sql/sql_acl.cc                | 2 +-
 5 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index c179351551d..82b1ed233ec 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -31,7 +31,7 @@ n
 4
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	332	master-bin.000001	Yes	No							0		0	244	649	Master	master-bin.000001	244	No						#
+#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	#	master-bin.000001	Yes	No							0		0	244	#	Master	master-bin.000001	244	No						#
 start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
 select * from t1;
 n
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index 9bc4ea4e7b1..4508fbea194 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -29,7 +29,7 @@ sleep 2;
 # here table should be still not deleted
 select * from t1;
 --replace_result $MASTER_MYPORT MASTER_MYPORT
---replace_column 1 # 33 #
+--replace_column 1 # 9 # 23 # 33 #
 show slave status;
 
 # this should fail right after start
@@ -59,9 +59,9 @@ stop slave;
 
 # this should stop immideately
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
-sleep 2;
+--real-sleep 2;
 # here the sql slave thread should be stopped
---replace_result $MASTER_MYPORT MASTER_MYPORT
+--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
 --replace_column 1 # 9 # 23 # 33 #
 show slave status;
 
diff --git a/sql/slave.cc b/sql/slave.cc
index d2a7d397fa7..36d8975a127 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2682,7 +2682,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
       rli->is_until_satisfied()) 
   {
     sql_print_error("Slave SQL thread stopped because it reached its"
-                    " UNTIL position");
+                    " UNTIL position %ld", (long) rli->until_pos());
     /* 
       Setting abort_slave flag because we do not want additional message about
       error in query execution to be printed.
diff --git a/sql/slave.h b/sql/slave.h
index e42b93a47ef..d92c44dd2ba 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -324,6 +324,11 @@ typedef struct st_relay_log_info
 
   /* Check if UNTIL condition is satisfied. See slave.cc for more. */
   bool is_until_satisfied();
+  inline ulonglong until_pos()
+  {
+    return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
+	    group_relay_log_pos);
+  }
 } RELAY_LOG_INFO;
 
 
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 01820917ce9..3f70cc1323b 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2543,7 +2543,7 @@ my_bool grant_init(THD *org_thd)
   do
   {
     GRANT_TABLE *mem_check;
-    if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || mem_check->ok())
+    if (!(mem_check=new GRANT_TABLE(t_table,c_table)) || !mem_check->ok())
     {
       /* This could only happen if we are out memory */
       grant_option= FALSE;			/* purecov: deadcode */

From 64d039833ec84669fa0d2154264f100f41db0fd2 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 29 Dec 2003 18:45:13 +0400
Subject: [PATCH 025/157] logging_ok:   Logging to logging@openlogging.org
 accepted item_strfunc.cc:   Bug wich appeared in ctype_tis620 is fixed

sql/item_strfunc.cc:
  Bug wich appeared in ctype_tis620 is fixed
BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
---
 BitKeeper/etc/logging_ok | 1 +
 sql/item_strfunc.cc      | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index db4ad62f23b..785ea13b492 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -15,6 +15,7 @@ arjen@george.bitbike.com
 bar@bar.intranet.mysql.r18.ru
 bar@bar.mysql.r18.ru
 bar@bar.udmsearch.izhnet.ru
+bar@deer.(none)
 bar@gw.udmsearch.izhnet.ru
 bell@laptop.sanja.is.com.ua
 bell@sanja.is.com.ua
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 3cb03d7ea49..fdacc4ec536 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2104,8 +2104,8 @@ String *Item_func_conv_charset::val_str(String *str)
     null_value=1;
     return 0;
   }
-  null_value= str->copy(arg->ptr(),arg->length(),arg->charset(),conv_charset);
-  return null_value ? 0 : str;
+  null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),conv_charset);
+  return null_value ? 0 : &str_value;
 }
 
 void Item_func_conv_charset::fix_length_and_dec()

From c7b62fcde712852f0797bad7aba9e731b441a1fe Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 29 Dec 2003 19:58:18 +0400
Subject: [PATCH 026/157] latin1.xml, Index.xml:   Modern Spanish collation

sql/share/charsets/Index.xml:
  Modern Spanish collation
sql/share/charsets/latin1.xml:
  Modern Spanish collation
---
 sql/share/charsets/Index.xml  |  3 ++-
 sql/share/charsets/latin1.xml | 21 +++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index 3661784325c..f21e03de8b2 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -1,6 +1,6 @@
 
 
-
+
 
 
 This file lists all of the available character sets.
@@ -100,6 +100,7 @@ To make maintaining easier please:
   
   
   
+  
   
     binary
     compiled
diff --git a/sql/share/charsets/latin1.xml b/sql/share/charsets/latin1.xml
index 9e11be39ad6..178fd07e7f6 100644
--- a/sql/share/charsets/latin1.xml
+++ b/sql/share/charsets/latin1.xml
@@ -209,6 +209,27 @@
 
 
 
+
+
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+ 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+ 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+ 40 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
+ 8F 91 93 95 98 9A A4 A6 A8 AA AF B3 B4 B5 B6 B7
+ B8 41 51 53 57 5B 65 67 69 6B 75 77 79 7B 7D 81
+ 8F 91 93 95 98 9A A4 A6 A8 AA AF B9 BA BB BC BF
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
+ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
+ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
+ 41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B
+ 57 7F 81 81 81 81 81 BD 81 9A 9A 9A 9A AA B1 97
+ 41 41 41 41 41 41 41 53 5B 5B 5B 5B 6B 6B 6B 6B
+ 57 7F 81 81 81 81 81 BE 81 9A 9A 9A 9A AA B1 AA
+
+
+
 
 
 

From a4be3840a37dcb24530f895f7a46080fed570874 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 30 Dec 2003 13:30:21 +0400
Subject: [PATCH 027/157] Fix for the bug #2235: mysqldump --compatible doesn't
 work correctly.

---
 client/mysqldump.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/client/mysqldump.c b/client/mysqldump.c
index 018cd43ce87..f0dfefbf0ca 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -830,7 +830,7 @@ static uint getTableStructure(char *table, char* db)
 	char *end;
 	uint i;
 
-	sprintf(buff, "/*!41000 SET @@sql_mode=\"");
+	sprintf(buff, "/*!40100 SET @@sql_mode=\"");
 	end= strend(buff);
 	for (i= 0; opt_compatible_mode; opt_compatible_mode>>= 1, i++)
 	{

From 367ded9f71c7209c851e212ecedc538ca810d8da Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 30 Dec 2003 14:08:19 +0400
Subject: [PATCH 028/157] Fix for prepared statements Here i added
 Item_*::cleanup() functions, removed a lot of ~Item_*'s, added code to
 restore order_list and group_list

sql/item.cc:
  cleanups methods implemented
  Item_ref constructors changed
sql/item.h:
  cleanups declared
  Item_ref constructors changed
  some ~Item_* deleted
sql/item_cmpfunc.cc:
  new Item_ref format
sql/item_cmpfunc.h:
  saving/restoring of the original arguments added to
  eq and equal functions
sql/item_func.cc:
  New Item_ref format
sql/item_func.h:
  destructors removed/changed to 'cleanup()'
sql/item_row.cc:
  New Item_ref format
sql/item_row.h:
  ~Item_row -> cleanup()
sql/item_strfunc.cc:
  new Item_ref format
sql/item_strfunc.h:
  destructors removed
sql/item_subselect.cc:
  Item_subselect implementation,
  new Item_ref() format
sql/item_subselect.h:
  cleanups for subselects declared
sql/item_sum.cc:
  cleanups implementations
sql/item_sum.h:
  cleanups declarations
  destructors removed
sql/mysql_priv.h:
  free_items, cleanup_items exported
sql/sql_prepare.cc:
  cleanup_items, free_items calls added
  stmt->query_id= thd->query_id restored
  cleanup procedures for group_list and order_list added
sql/sql_yacc.yy:
  New Item_ref() format
---
 sql/item.cc           | 18 +++++++++++++++++-
 sql/item.h            | 35 ++++++++++++++++++++++-------------
 sql/item_cmpfunc.cc   |  3 +--
 sql/item_cmpfunc.h    | 15 +++++++++------
 sql/item_func.cc      |  2 +-
 sql/item_func.h       | 10 +---------
 sql/item_row.cc       |  2 +-
 sql/item_row.h        |  6 +++++-
 sql/item_strfunc.cc   |  5 +++--
 sql/item_strfunc.h    |  2 --
 sql/item_subselect.cc | 17 +++++++++++++++--
 sql/item_subselect.h  | 10 ++++++++++
 sql/item_sum.cc       | 26 ++++++++++++++++++++------
 sql/item_sum.h        | 17 ++++++++---------
 sql/mysql_priv.h      |  5 +++++
 sql/sql_prepare.cc    | 20 +++++++++++++-------
 sql/sql_yacc.yy       | 10 +++++-----
 17 files changed, 136 insertions(+), 67 deletions(-)

diff --git a/sql/item.cc b/sql/item.cc
index 417f05680cf..e364f095a70 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -920,6 +920,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 
 	Item_ref *rf;
 	*ref= rf= new Item_ref(last->ref_pointer_array + counter,
+			       ref,
 			       (char *)table_name,
 			       (char *)field_name);
 	if (!rf)
@@ -936,7 +937,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 	if (last->having_fix_field)
 	{
 	  Item_ref *rf;
-	  *ref= rf= new Item_ref((where->db[0]?where->db:0), 
+	  *ref= rf= new Item_ref(ref, this,
+				 (where->db[0]?where->db:0), 
 				 (char *)where->alias,
 				 (char *)field_name);
 	  if (!rf)
@@ -962,6 +964,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
   return 0;
 }
 
+void Item_field::cleanup()
+{
+  Item_ident::cleanup();
+  field= 0;
+  result_field= 0;
+}
 
 void Item::init_make_field(Send_field *tmp_field,
 			   enum enum_field_types field_type)
@@ -1601,6 +1609,14 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
 }
 
 
+void Item_ref::cleanup()
+{
+  Item_ident::cleanup();
+  if (hook_ptr)
+    *hook_ptr= orig_item;
+}
+
+
 void Item_ref::print(String *str)
 {
   if (ref && *ref)
diff --git a/sql/item.h b/sql/item.h
index 5def1e2b710..e1318224498 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -290,6 +290,7 @@ public:
   bool get_time(TIME *ltime);
   bool is_null() { return field->is_null(); }
   Item *get_tmp_table_item(THD *thd);
+  void cleanup();
   friend class Item_default_value;
   friend class Item_insert_value;
 };
@@ -498,7 +499,6 @@ public:
     set_name(name_par,0,cs);
     decimals=NOT_FIXED_DEC;
   }
-  ~Item_string() {}
   enum Type type() const { return STRING_ITEM; }
   double val()
   { 
@@ -565,7 +565,6 @@ class Item_varbinary :public Item
 {
 public:
   Item_varbinary(const char *str,uint str_length);
-  ~Item_varbinary() {}
   enum Type type() const { return VARBIN_ITEM; }
   double val() { return (double) Item_varbinary::val_int(); }
   longlong val_int();
@@ -602,20 +601,25 @@ public:
 class Item_ref :public Item_ident
 {
 public:
-  Field *result_field;				/* Save result here */
+  Field *result_field;			 /* Save result here */
   Item **ref;
-  Item_ref(const char *db_par, const char *table_name_par,
-	   const char *field_name_par)
-    :Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
-  Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
-    :Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
+  Item **hook_ptr;                       /* These two to restore  */
+  Item *orig_item;                       /* things in 'cleanup()' */
+  Item_ref(Item **hook, Item *original,const char *db_par,
+	   const char *table_name_par, const char *field_name_par)
+    :Item_ident(db_par,table_name_par,field_name_par),ref(0), hook_ptr(hook),
+    orig_item(original) {}
+  Item_ref(Item **item, Item **hook, 
+	   const char *table_name_par, const char *field_name_par)
+    :Item_ident(NullS,table_name_par,field_name_par),
+    ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {}
   // Constructor need to process subselect with temporary tables (see Item)
-  Item_ref(THD *thd, Item_ref &item)
-    :Item_ident(thd, item), ref(item.ref) {}
+  Item_ref(THD *thd, Item_ref &item, Item **hook)
+    :Item_ident(thd, item), ref(item.ref), 
+    hook_ptr(hook), orig_item(hook ? *hook : 0) {}
   enum Type type() const		{ return REF_ITEM; }
   bool eq(const Item *item, bool binary_cmp) const
   { return ref && (*ref)->eq(item, binary_cmp); }
-  ~Item_ref() { if (ref && (*ref) && (*ref) != this) delete *ref; }
   double val()
   {
     double tmp=(*ref)->val_result();
@@ -660,6 +664,7 @@ public:
   }
   Item *real_item() { return *ref; }
   void print(String *str);
+  void cleanup();
 };
 
 class Item_in_subselect;
@@ -670,7 +675,7 @@ protected:
 public:
   Item_ref_null_helper(Item_in_subselect* master, Item **item,
 		       const char *table_name_par, const char *field_name_par):
-    Item_ref(item, table_name_par, field_name_par), owner(master) {}
+    Item_ref(item, NULL, table_name_par, field_name_par), owner(master) {}
   double val();
   longlong val_int();
   String* val_str(String* s);
@@ -734,7 +739,6 @@ public:
     name=item->name;
     cached_field_type= item->field_type();
   }
-  ~Item_copy_string() { delete item; }
   enum Type type() const { return COPY_STR_ITEM; }
   enum Item_result result_type () const { return STRING_RESULT; }
   enum_field_types field_type() const { return cached_field_type; }
@@ -982,6 +986,11 @@ public:
   bool check_cols(uint c);
   bool null_inside();
   void bring_value();
+  void cleanup()
+  {
+    Item_cache::cleanup();
+    values= 0;
+  }
 };
 
 
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a79ef21e97a..4b270c6aad0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -496,7 +496,6 @@ longlong Item_func_eq::val_int()
   return value == 0 ? 1 : 0;
 }
 
-
 /* Same as Item_func_eq, but NULL = NULL */
 
 void Item_func_equal::fix_length_and_dec()
@@ -1754,7 +1753,7 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List &fields)
       uint el= fields.elements;
       fields.push_front(item);
       ref_pointer_array[el]= item;
-      li.replace(new Item_ref(ref_pointer_array + el, 0, item->name));
+      li.replace(new Item_ref(ref_pointer_array + el, li.ref(), 0, item->name));
     }
     item->update_used_tables();
     used_tables_cache|=item->used_tables();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 541bc47557d..50c5449c1ec 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -197,11 +197,19 @@ public:
 
 class Item_bool_rowready_func2 :public Item_bool_func2
 {
+  Item *orig_a, *orig_b; /* propagate_const can change parameters */
 public:
-  Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b)
+  Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b),
+    orig_a(a), orig_b(b)
   {
     allowed_arg_cols= a->cols();
   }
+  void cleanup()
+  {
+    Item_bool_func2::cleanup();
+    tmp_arg[0]= orig_a;
+    tmp_arg[1]= orig_b;
+  }
 };
 
 class Item_func_not :public Item_bool_func
@@ -705,10 +713,6 @@ class Item_func_in :public Item_int_func
   }
   longlong val_int();
   void fix_length_and_dec();
-  ~Item_func_in()
-  {
-    cleanup(); /* This is not called by Item::~Item() */
-  }
   void cleanup()
   {
     delete array;
@@ -888,7 +892,6 @@ public:
   Item_cond(THD *thd, Item_cond &item);
   Item_cond(List &nlist)
     :Item_bool_func(), list(nlist), abort_on_null(0) {}
-  ~Item_cond() { list.delete_elements(); }
   bool add(Item *item) { return list.push_back(item); }
   bool fix_fields(THD *, struct st_table_list *, Item **ref);
 
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a251be402ce..33c443ac1c5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -252,7 +252,7 @@ void Item_func::split_sum_func(Item **ref_pointer_array, List &fields)
       uint el= fields.elements;
       fields.push_front(item);
       ref_pointer_array[el]= item;
-      *arg= new Item_ref(ref_pointer_array + el, 0, item->name);
+      *arg= new Item_ref(ref_pointer_array + el, arg, 0, item->name);
     }
   }
 }
diff --git a/sql/item_func.h b/sql/item_func.h
index ac67b5a4065..634880db7ad 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -107,7 +107,6 @@ public:
   Item_func(List &list);
   // Constructor used for Item_cond_and/or (see Item comment)
   Item_func(THD *thd, Item_func &item);
-  ~Item_func() {} /* Nothing to do; Items are freed automaticly */
   bool fix_fields(THD *,struct st_table_list *, Item **ref);
   table_map used_tables() const;
   table_map not_null_tables() const;
@@ -755,7 +754,6 @@ public:
   Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {}
   Item_udf_func(udf_func *udf_arg, List &list)
     :Item_func(list), udf(udf_arg) {}
-  ~Item_udf_func() {}
   const char *func_name() const { return udf.name(); }
   bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
   {
@@ -776,7 +774,6 @@ class Item_func_udf_float :public Item_udf_func
   Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
   Item_func_udf_float(udf_func *udf_arg, List &list)
     :Item_udf_func(udf_arg,list) {}
-  ~Item_func_udf_float() {}
   longlong val_int() { return (longlong) Item_func_udf_float::val(); }
   double val();
   String *val_str(String *str);
@@ -790,7 +787,6 @@ public:
   Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
   Item_func_udf_int(udf_func *udf_arg, List &list)
     :Item_udf_func(udf_arg,list) {}
-  ~Item_func_udf_int() {}
   longlong val_int();
   double val() { return (double) Item_func_udf_int::val_int(); }
   String *val_str(String *str);
@@ -805,7 +801,6 @@ public:
   Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
   Item_func_udf_str(udf_func *udf_arg, List &list)
     :Item_udf_func(udf_arg,list) {}
-  ~Item_func_udf_str() {}
   String *val_str(String *);
   double val()
   {
@@ -830,7 +825,6 @@ class Item_func_udf_float :public Item_real_func
  public:
   Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
   Item_func_udf_float(udf_func *udf_arg, List &list) :Item_real_func(list) {}
-  ~Item_func_udf_float() {}
   double val() { return 0.0; }
 };
 
@@ -840,7 +834,6 @@ class Item_func_udf_int :public Item_int_func
 public:
   Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
   Item_func_udf_int(udf_func *udf_arg, List &list) :Item_int_func(list) {}
-  ~Item_func_udf_int() {}
   longlong val_int() { return 0; }
 };
 
@@ -850,7 +843,6 @@ class Item_func_udf_str :public Item_func
 public:
   Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
   Item_func_udf_str(udf_func *udf_arg, List &list)  :Item_func(list) {}
-  ~Item_func_udf_str() {}
   String *val_str(String *) { null_value=1; return 0; }
   double val() { null_value=1; return 0.0; }
   longlong val_int() { null_value=1; return 0; }
@@ -997,7 +989,7 @@ public:
 
   Item_func_match(List &a, uint b): Item_real_func(a), key(0), flags(b),
        join_key(0), ft_handler(0), table(0), master(0), concat(0) { }
-  ~Item_func_match()
+  void cleanup()
   {
     if (!master && ft_handler)
     {
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 89b38c8a753..7f847bd1d4e 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -91,7 +91,7 @@ void Item_row::split_sum_func(Item **ref_pointer_array, List &fields)
       uint el= fields.elements;
       fields.push_front(*arg);
       ref_pointer_array[el]= *arg;
-      *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
+      *arg= new Item_ref(ref_pointer_array + el, arg, 0, (*arg)->name);
     }
   }
 }
diff --git a/sql/item_row.h b/sql/item_row.h
index a09bd1a2c31..1b792f981fd 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -34,10 +34,14 @@ public:
     with_null(0)
   {}
 
-  ~Item_row()
+  void cleanup()
   {
     if (array_holder && items)
+    {
       sql_element_free(items);
+      items= 0;
+      array_holder= 0;
+    }
   }
 
   enum Type type() const { return ROW_ITEM; };
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 3cb03d7ea49..b4580c79f9c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -616,7 +616,8 @@ void Item_func_concat_ws::split_sum_func(Item **ref_pointer_array,
     uint el= fields.elements;
     fields.push_front(separator);
     ref_pointer_array[el]= separator;
-    separator= new Item_ref(ref_pointer_array + el, 0, separator->name);
+    separator= new Item_ref(ref_pointer_array + el,
+			    &separator, 0, separator->name);
   }
   Item_str_func::split_sum_func(ref_pointer_array, fields);
 }
@@ -1709,7 +1710,7 @@ void Item_func_make_set::split_sum_func(Item **ref_pointer_array,
     uint el= fields.elements;
     fields.push_front(item);
     ref_pointer_array[el]= item;
-    item= new Item_ref(ref_pointer_array + el, 0, item->name);
+    item= new Item_ref(ref_pointer_array + el, &item, 0, item->name);
   }
   Item_str_func::split_sum_func(ref_pointer_array, fields);
 }
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 40b00cdd488..fd0afb19726 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -95,7 +95,6 @@ class Item_func_concat_ws :public Item_str_func
 public:
   Item_func_concat_ws(Item *a,List &list) 
     :Item_str_func(list),separator(a) {}
-  ~Item_func_concat_ws() { delete separator; }
   String *val_str(String *);
   void fix_length_and_dec();
   void update_used_tables();
@@ -409,7 +408,6 @@ class Item_func_make_set :public Item_str_func
 
 public:
   Item_func_make_set(Item *a,List &list) :Item_str_func(list),item(a) {}
-  ~Item_func_make_set() { delete item; }
   String *val_str(String *str);
   bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
   {
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 43775e1c96c..e0d9bcf3bd6 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -63,6 +63,11 @@ void Item_subselect::init(st_select_lex *select_lex,
   DBUG_VOID_RETURN;
 }
 
+void Item_subselect::cleanup()
+{
+  Item_result_field::cleanup();
+  engine->cleanup(); 
+}
 
 Item_subselect::~Item_subselect()
 {
@@ -641,7 +646,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
       As far as  Item_ref_in_optimizer do not substitude itself on fix_fields
       we can use same item for all selects.
     */
-    expr= new Item_ref((Item**)optimizer->get_cache(), 
+    expr= new Item_ref((Item**)optimizer->get_cache(),
+		       NULL,
 		       (char *)"",
 		       (char *)in_left_expr_name);
 
@@ -791,7 +797,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
 					 (char *) "");
     func=
       eq_creator.create(new Item_ref((*optimizer->get_cache())->
-				     addr(i), 
+				     addr(i),
+				     NULL,
 				     (char *)"",
 				     (char *)in_left_expr_name),
 			func);
@@ -889,6 +896,12 @@ subselect_single_select_engine(st_select_lex *select,
   this->select_lex= select_lex;
 }
 
+void subselect_single_select_engine::cleanup()
+{
+  prepared= 0;
+  optimized= 0;
+  executed= 0;
+}
 
 subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
 					       select_subselect *result_arg,
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 8444dc7bf66..dc3d07540da 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -69,6 +69,7 @@ public:
 		     select_subselect *result);
 
   ~Item_subselect();
+  void cleanup();
   virtual void reset() 
   {
     null_value= 1;
@@ -199,6 +200,13 @@ public:
      
   {}
 
+  void cleanup()
+  {
+    Item_exists_subselect::cleanup();
+    abort_on_null= 0;
+    transformed= 0;
+    upper_not= 0;
+  }
   subs_type substype() { return IN_SUBS; }
   void reset() 
   {
@@ -261,6 +269,7 @@ public:
     maybe_null= 0;
   }
   virtual ~subselect_engine() {}; // to satisfy compiler
+  virtual void cleanup() {}
   
   // set_thd should be called before prepare()
   void set_thd(THD *thd_arg) { thd= thd_arg; }
@@ -290,6 +299,7 @@ public:
   subselect_single_select_engine(st_select_lex *select,
 				 select_subselect *result,
 				 Item_subselect *item);
+  void cleanup();
   int prepare();
   void fix_length_and_dec(Item_cache** row);
   int exec();
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index f187650515a..84d00ce8732 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1082,8 +1082,9 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
 }
 
 
-Item_sum_count_distinct::~Item_sum_count_distinct()
+void Item_sum_count_distinct::cleanup()
 {
+  Item_sum_int::cleanup();
   /*
     Free table and tree if they belong to this item (if item have not pointer
     to original item from which was made copy => it own its objects )
@@ -1095,6 +1096,7 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
     delete tmp_table_param;
     if (use_tree)
       delete_tree(tree);
+    table= 0;
   }
 }
 
@@ -1661,6 +1663,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
 }
 
 
+void Item_func_group_concat::cleanup()
+{
+  /*
+    Free table and tree if they belong to this item (if item have not pointer
+    to original item from which was made copy => it own its objects )
+  */
+  if (!original)
+  {
+    THD *thd= current_thd;
+    if (table)
+      free_tmp_table(thd, table);
+    delete tmp_table_param;
+    if (tree_mode)
+      delete_tree(tree); 
+  }
+}
+
 Item_func_group_concat::~Item_func_group_concat()
 {
   /*
@@ -1676,11 +1695,6 @@ Item_func_group_concat::~Item_func_group_concat()
       sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
       warning->set_msg(thd, warn_buff);
     }
-    if (table)
-      free_tmp_table(thd, table);
-    delete tmp_table_param;
-    if (tree_mode)
-      delete_tree(tree); 
   }
 }
 
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 8065218df97..dd180d42011 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -58,7 +58,11 @@ public:
   Item_sum(List &list);
   //Copy constructor, need to perform subselects with temporary tables
   Item_sum(THD *thd, Item_sum &item);
-  ~Item_sum() { result_field=0; }
+  void cleanup()
+  {
+    Item_result_field::cleanup();
+    result_field=0;
+  }
 
   enum Type type() const { return SUM_FUNC_ITEM; }
   virtual enum Sumfunctype sum_func () const=0;
@@ -235,7 +239,7 @@ class Item_sum_count_distinct :public Item_sum_int
      rec_offset(item.rec_offset), use_tree(item.use_tree),
      always_null(item.always_null)
   {}
-  ~Item_sum_count_distinct();
+  void cleanup();
 
   table_map used_tables() const { return used_table_cache; }
   enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
@@ -523,7 +527,6 @@ public:
   { quick_group=0;}
   Item_udf_sum(THD *thd, Item_udf_sum &item)
     :Item_sum(thd, item), udf(item.udf) {}
-  ~Item_udf_sum() {}
   const char *func_name() const { return udf.name(); }
   bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
   {
@@ -548,7 +551,6 @@ class Item_sum_udf_float :public Item_udf_sum
     :Item_udf_sum(udf_arg,list) {}
   Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
     :Item_udf_sum(thd, item) {}
-  ~Item_sum_udf_float() {}
   longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
   double val();
   String *val_str(String*str);
@@ -565,7 +567,6 @@ public:
     :Item_udf_sum(udf_arg,list) {}
   Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
     :Item_udf_sum(thd, item) {}
-  ~Item_sum_udf_int() {}
   longlong val_int();
   double val() { return (double) Item_sum_udf_int::val_int(); }
   String *val_str(String*str);
@@ -583,7 +584,6 @@ public:
     :Item_udf_sum(udf_arg,list) {}
   Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
     :Item_udf_sum(thd, item) {}
-  ~Item_sum_udf_str() {}
   String *val_str(String *);
   double val()
   {
@@ -612,7 +612,6 @@ class Item_sum_udf_float :public Item_sum_num
   Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_sum_num() {}
   Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
     :Item_sum_num(thd, item) {}
-  ~Item_sum_udf_float() {}
   enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
   double val() { return 0.0; }
   void clear() {}
@@ -628,7 +627,6 @@ public:
   Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_sum_num() {}
   Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
     :Item_sum_num(thd, item) {}
-  ~Item_sum_udf_int() {}
   enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
   longlong val_int() { return 0; }
   double val() { return 0; }
@@ -645,7 +643,6 @@ public:
   Item_sum_udf_str(udf_func *udf_arg, List &list)  :Item_sum_num() {}
   Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
     :Item_sum_num(thd, item) {}
-  ~Item_sum_udf_str() {}
   String *val_str(String *) { null_value=1; return 0; }
   double val() { null_value=1; return 0.0; }
   longlong val_int() { null_value=1; return 0; }
@@ -734,6 +731,8 @@ class Item_func_group_concat : public Item_sum
      quick_group= item.quick_group;
     };
   ~Item_func_group_concat();
+  void cleanup();
+
   enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
   const char *func_name() const { return "group_concat"; }
   enum Type type() const { return SUM_FUNC_ITEM; }  
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 15a99385285..d5a521dffe7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -759,6 +759,11 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
 uint check_word(TYPELIB *lib, const char *val, const char *end,
 		const char **end_of_word);
 
+/* sql_parse.cc */
+void free_items(Item *item);
+void cleanup_items(Item *item);
+
+
 /*
   External variables
 */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5d6ab165641..dd5825f27ac 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -756,7 +756,9 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
     JOIN *join= new JOIN(thd, fields, select_options, result);
     thd->used_tables= 0;	// Updated by setup_fields  
 
-    if (join->prepare(&select_lex->ref_pointer_array, tables, 
+//    if (join->prepare(&select_lex->ref_pointer_array, tables, 
+    if (join->prepare(&select_lex->ref_pointer_array,
+		      (TABLE_LIST*)select_lex->table_list.first,
                       wild_num, conds, og_num, order, group, having, proc, 
                       select_lex, unit))
       DBUG_RETURN(1);
@@ -925,6 +927,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
     sl->prep_where= sl->where;
   }
 
+  cleanup_items(thd->free_list);
   stmt->set_statement(thd);
   thd->set_statement(&thd->stmt_backup);
 
@@ -975,14 +978,10 @@ void mysql_stmt_execute(THD *thd, char *packet)
     DBUG_VOID_RETURN;
   }
 
-  /*
-    XXX: while thd->query_id is incremented for each command, stmt->query_id
-    holds query_id of prepare stage. Keeping old query_id seems to be more
-    natural, but differs from the way prepared statements work in 4.1:
-  */ 
-  /* stmt->query_id= thd->query_id; */
+  stmt->query_id= thd->query_id;
   thd->stmt_backup.set_statement(thd);
   thd->set_statement(stmt);
+  thd->free_list= 0;
 
   /*
     To make sure that all runtime data is stored in its own memory root and 
@@ -1006,6 +1005,11 @@ void mysql_stmt_execute(THD *thd, char *packet)
     if (sl->prep_where)
       sl->where= sl->prep_where->copy_andor_structure(thd);
     DBUG_ASSERT(sl->join == 0);
+    ORDER *order;
+    for (order=(ORDER *)sl->group_list.first ; order ; order=order->next)
+      order->item= (Item **)(order+1);
+    for (order=(ORDER *)sl->order_list.first ; order ; order=order->next)
+      order->item= (Item **)(order+1);
   }
 
   /*
@@ -1042,6 +1046,8 @@ void mysql_stmt_execute(THD *thd, char *packet)
   if (!(specialflag & SPECIAL_NO_PRIOR))
     my_pthread_setprio(pthread_self(), WAIT_PRIOR);
 
+  free_items(thd->free_list);
+  cleanup_items(stmt->free_list);
   free_root(&thd->mem_root, MYF(0));
   thd->set_statement(&thd->stmt_backup);
   DBUG_VOID_RETURN;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 310d8a41be2..5fee5ab13a7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4486,7 +4486,7 @@ simple_ident:
 	  $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
               (Item*) new Item_field(NullS,NullS,$1.str) :
-	      (Item*) new Item_ref(NullS,NullS,$1.str);
+	      (Item*) new Item_ref(0,0, NullS,NullS,$1.str);
 	}
 	| ident '.' ident
 	{
@@ -4502,7 +4502,7 @@ simple_ident:
 	  $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
 	      (Item*) new Item_field(NullS,$1.str,$3.str) :
-	      (Item*) new Item_ref(NullS,$1.str,$3.str);
+	      (Item*) new Item_ref(0,0,NullS,$1.str,$3.str);
 	}
 	| '.' ident '.' ident
 	{
@@ -4518,7 +4518,7 @@ simple_ident:
 	  $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
 	       sel->get_in_sum_expr() > 0) ?
 	      (Item*) new Item_field(NullS,$2.str,$4.str) :
-              (Item*) new Item_ref(NullS,$2.str,$4.str);
+              (Item*) new Item_ref(0,0,NullS,$2.str,$4.str);
 	}
 	| ident '.' ident '.' ident
 	{
@@ -4536,8 +4536,8 @@ simple_ident:
 	      (Item*) new Item_field((YYTHD->client_capabilities &
 				      CLIENT_NO_SCHEMA ? NullS : $1.str),
 				     $3.str, $5.str) :
-	      (Item*) new Item_ref((YYTHD->client_capabilities &
-				    CLIENT_NO_SCHEMA ? NullS : $1.str),
+	      (Item*) new Item_ref(0,0,(YYTHD->client_capabilities &
+				        CLIENT_NO_SCHEMA ? NullS : $1.str),
                                    $3.str, $5.str);
 	};
 

From 8b4e00ffb7dbb1bcec6619d577d46090d9f94cce Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 30 Dec 2003 17:58:39 +0200
Subject: [PATCH 029/157] Fixed Bug#1472,  mysql \h output out of order.

---
 client/mysql.cc | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index d2bed5519bf..e3945e8aa2f 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -227,11 +227,12 @@ typedef struct {
 } COMMANDS;
 
 static COMMANDS commands[] = {
-  { "help",   'h', com_help,   1, "Display this help." },
   { "?",      '?', com_help,   1, "Synonym for `help'." },
   { "clear",  'c', com_clear,  0, "Clear command."},
   { "connect",'r', com_connect,1,
     "Reconnect to the server. Optional arguments are db and host." },
+  { "delimiter", 'd', com_delimiter,    1,
+    "Set query delimiter. " },
 #ifdef USE_POPEN
   { "edit",   'e', com_edit,   0, "Edit command with $EDITOR."},
 #endif
@@ -239,6 +240,7 @@ static COMMANDS commands[] = {
     "Send command to mysql server, display result vertically."},
   { "exit",   'q', com_quit,   0, "Exit mysql. Same as quit."},
   { "go",     'g', com_go,     0, "Send command to mysql server." },
+  { "help",   'h', com_help,   1, "Display this help." },
 #ifdef USE_POPEN
   { "nopager",'n', com_nopager,0, "Disable pager, print to stdout." },
 #endif
@@ -261,8 +263,6 @@ static COMMANDS commands[] = {
     "Set outfile [to_outfile]. Append everything into given outfile." },
   { "use",    'u', com_use,    1,
     "Use another database. Takes database name as argument." },
-  { "delimiter", 'd', com_delimiter,    1,
-    "Set query delimiter. " },
   /* Get bash-like expansion for some commands */
   { "create table",     0, 0, 0, ""},
   { "create database",  0, 0, 0, ""},
@@ -1577,8 +1577,8 @@ static int
 com_help(String *buffer __attribute__((unused)),
 	 char *line __attribute__((unused)))
 {
-  reg1 int i;
-  char * help_arg= strchr(line,' ');
+  reg1 int i, j;
+  char * help_arg= strchr(line,' '), buff[32], *end;
 
   if (help_arg)
     return com_server_help(buffer,line,help_arg+1);
@@ -1591,8 +1591,11 @@ com_help(String *buffer __attribute__((unused)),
     put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
   for (i = 0; commands[i].name; i++)
   {
+    end= strmov(buff, commands[i].name);
+    for (j= strlen(commands[i].name); j < 10; j++)
+      end= strmov(end, " ");
     if (commands[i].func)
-      tee_fprintf(stdout, "%s\t(\\%c)\t%s\n", commands[i].name,
+      tee_fprintf(stdout, "%s(\\%c) %s\n", buff,
 		  commands[i].cmd_char, commands[i].doc);
   }
   if (connected && mysql_get_server_version(&mysql) >= 40100)

From 92fdbe5e0359576d9cb61d9662677cdf52405aed Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 31 Dec 2003 19:01:03 +0400
Subject: [PATCH 030/157] #2244  	User variables collation conflict is
 not detected

---
 mysql-test/r/user_var.result | 42 ++++++++++++++++++++++++++++++++++++
 mysql-test/t/user_var.test   | 28 ++++++++++++++++++++++++
 sql/item_func.cc             |  6 +++++-
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index fc3dc4eddcd..a9351d2f1fb 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -120,3 +120,45 @@ select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i;
 1	3	2	0
 3	6	3	0
 drop table t1;
+set @a=_latin2'test';
+select charset(@a),collation(@a),coercibility(@a);
+charset(@a)	collation(@a)	coercibility(@a)
+latin2	latin2_general_ci	3
+select @a=_latin2'TEST';
+@a=_latin2'TEST'
+1
+select @a=_latin2'TEST' collate latin2_bin;
+@a=_latin2'TEST' collate latin2_bin
+0
+set @a=_latin2'test' collate latin2_general_ci;
+select charset(@a),collation(@a),coercibility(@a);
+charset(@a)	collation(@a)	coercibility(@a)
+latin2	latin2_general_ci	0
+select @a=_latin2'TEST';
+@a=_latin2'TEST'
+1
+select @a=_latin2'TEST' collate latin2_bin;
+ERROR HY000: Illegal mix of collations (latin2_general_ci,EXPLICIT) and (latin2_bin,EXPLICIT) for operation '='
+select charset(@a:=_latin2'test');
+charset(@a:=_latin2'test')
+latin2
+select collation(@a:=_latin2'test');
+collation(@a:=_latin2'test')
+latin2_general_ci
+select coercibility(@a:=_latin2'test');
+coercibility(@a:=_latin2'test')
+3
+select collation(@a:=_latin2'test' collate latin2_bin);
+collation(@a:=_latin2'test' collate latin2_bin)
+latin2_bin
+select coercibility(@a:=_latin2'test' collate latin2_bin);
+coercibility(@a:=_latin2'test' collate latin2_bin)
+0
+select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
+(@a:=_latin2'test' collate latin2_bin) = _latin2'TEST'
+0
+select charset(@a),collation(@a),coercibility(@a);
+charset(@a)	collation(@a)	coercibility(@a)
+latin2	latin2_bin	0
+select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
+ERROR HY000: Illegal mix of collations (latin2_bin,EXPLICIT) and (latin2_general_ci,EXPLICIT) for operation '='
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 39742d20c7c..32ed6fe33db 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -71,3 +71,31 @@ select @a:=0; select @a, @a:=@a+count(*), count(*), @a from t1 group by i;
 select @a:=0; select @a+0, @a:=@a+0+count(*), count(*), @a+0 from t1 group by i;
 drop table t1;
 
+#
+# Bug #2244: User variables didn't copy collation and derivation
+# attributes from values they were initialized to.
+#
+
+set @a=_latin2'test';
+select charset(@a),collation(@a),coercibility(@a);
+select @a=_latin2'TEST';
+select @a=_latin2'TEST' collate latin2_bin;
+
+set @a=_latin2'test' collate latin2_general_ci;
+select charset(@a),collation(@a),coercibility(@a);
+select @a=_latin2'TEST';
+--error 1266
+select @a=_latin2'TEST' collate latin2_bin;
+
+#
+# Check the same invoking Item_set_user_var
+#
+select charset(@a:=_latin2'test');
+select collation(@a:=_latin2'test');
+select coercibility(@a:=_latin2'test');
+select collation(@a:=_latin2'test' collate latin2_bin);
+select coercibility(@a:=_latin2'test' collate latin2_bin);
+select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST';
+select charset(@a),collation(@a),coercibility(@a);
+--error 1266
+select (@a:=_latin2'test' collate latin2_bin) = _latin2'TEST' collate latin2_general_ci;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a251be402ce..5af64ca0be4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2163,6 +2163,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
      is different from query_id).
   */
   entry->update_query_id= thd->query_id;
+  entry->collation.set(args[0]->collation);
   cached_result_type= args[0]->result_type();
   return 0;
 }
@@ -2174,6 +2175,7 @@ Item_func_set_user_var::fix_length_and_dec()
   maybe_null=args[0]->maybe_null;
   max_length=args[0]->max_length;
   decimals=args[0]->decimals;
+  collation.set(args[0]->collation);
 }
 
 
@@ -2488,7 +2490,9 @@ void Item_func_get_user_var::fix_length_and_dec()
 
   if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
     null_value= 1;
-
+  else
+    collation.set(var_entry->collation);
+  
   if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
     return;
 

From 3940368293134f3fcce418c8533143ab6f4581ec Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 1 Jan 2004 01:51:36 +0200
Subject: [PATCH 031/157] row0purge.c:   Fix bug: if purge of a table was not
 possible because its .ibd file was missing, trx->dict_operation_lock_mode was
 left to a wrong value, causing an assertion failure

innobase/row/row0purge.c:
  Fix bug: if purge of a table was not possible because its .ibd file was missing, trx->dict_operation_lock_mode was left to a wrong value, causing an assertion failure
---
 innobase/row/row0purge.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index a455722f15a..d5895f20461 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -534,6 +534,8 @@ row_purge_parse_undo_rec(
 
 		node->table = NULL;
 
+		row_mysql_unfreeze_data_dictionary(trx);
+
 		return(FALSE);
 	}
 

From 63f15064a48e4a3fbd5a15bda39d70ee5254a6ac Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 2 Jan 2004 16:21:58 +0200
Subject: [PATCH 032/157] log0recv.h, log0recv.c:   Merge a log replay change
 required by ibbackup

innobase/log/log0recv.c:
  Merge a log replay change required by ibbackup
innobase/include/log0recv.h:
  Merge a log replay change required by ibbackup
---
 innobase/include/log0recv.h |  2 ++
 innobase/log/log0recv.c     | 24 ++++++++++++++++--------
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index 5991960e8ae..c972c3ce977 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -15,6 +15,8 @@ Created 9/20/1997 Heikki Tuuri
 #include "hash0hash.h"
 #include "log0log.h"
 
+extern ibool	recv_replay_file_ops;
+
 /***********************************************************************
 Reads the checkpoint info needed in hot backup. */
 
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index b01474753bd..01679a374b0 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -34,6 +34,11 @@ Created 9/20/1997 Heikki Tuuri
 #include "dict0boot.h"
 #include "fil0fil.h"
 
+/* This is set to FALSE if the backup was originally taken with the
+ibbackup --include regexp option: then we do not want to create tables in
+directories which were not included */
+ibool	recv_replay_file_ops	= TRUE;
+
 /* Log records are stored in the hash table in chunks at most of this size;
 this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */
 #define RECV_DATA_BLOCK_SIZE	(MEM_MAX_ALLOC_IN_BUF - sizeof(recv_data_t))
@@ -1974,18 +1979,21 @@ loop:
 					     || type == MLOG_FILE_RENAME
 					     || type == MLOG_FILE_DELETE)) {
 #ifdef UNIV_HOTBACKUP
-			/* In ibbackup --apply-log, replay an .ibd file
-			operation, if possible; note that
-			fil_path_to_mysql_datadir is set in ibbackup to
-			point to the datadir we should use there */
+			if (recv_replay_file_ops) {
+
+				/* In ibbackup --apply-log, replay an .ibd file
+				operation, if possible; note that
+				fil_path_to_mysql_datadir is set in ibbackup to
+				point to the datadir we should use there */
 			
-			if (NULL == fil_op_log_parse_or_replay(body, end_ptr,
-							type, TRUE, space)) {
-				fprintf(stderr,
+				if (NULL == fil_op_log_parse_or_replay(body,
+						end_ptr, type, TRUE, space)) {
+					fprintf(stderr,
 "InnoDB: Error: file op log record of type %lu space %lu not complete in\n"
 "InnoDB: the replay phase. Path %s\n", (ulint)type, space, (char*)(body + 2));
 
-				ut_a(0);
+					ut_a(0);
+				}
 			}
 #endif
 			/* In normal mysqld crash recovery we do not try to

From b21d8b0eff5b2da2f4b565ab630549ede52ed28a Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 3 Jan 2004 00:12:07 +0200
Subject: [PATCH 033/157] removed droping field->query_id for reinitialization
 tables for subquery. (BUG#2089)

mysql-test/r/subselect_innodb.result:
  correct results
sql/mysql_priv.h:
  new parameter for setup_tables()
sql/sql_base.cc:
  new parameter for setup_tables() added to avoid dropping query_id of fields during reinitialization subquery
sql/sql_class.cc:
  layout fixed
sql/sql_help.cc:
  new parameter for setup_tables()
sql/sql_insert.cc:
  new parameter for setup_tables()
sql/sql_lex.cc:
  removed incorrect code
sql/sql_load.cc:
  new parameter for setup_tables()
sql/sql_olap.cc:
  new parameter for setup_tables()
sql/sql_prepare.cc:
  new parameter for setup_tables()
sql/sql_select.cc:
  new parameter for setup_tables()
sql/sql_update.cc:
  new parameter for setup_tables()
---
 mysql-test/r/subselect_innodb.result | 17 +++++++++++++++--
 sql/mysql_priv.h                     |  2 +-
 sql/sql_base.cc                      | 27 ++++++++++++++++++++-------
 sql/sql_class.cc                     |  2 +-
 sql/sql_help.cc                      |  2 +-
 sql/sql_insert.cc                    |  4 ++--
 sql/sql_lex.cc                       |  5 -----
 sql/sql_load.cc                      |  2 +-
 sql/sql_olap.cc                      |  2 +-
 sql/sql_prepare.cc                   |  2 +-
 sql/sql_select.cc                    |  4 ++--
 sql/sql_update.cc                    |  2 +-
 12 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index 6729916f1c8..972cbdda38f 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -60,6 +60,19 @@ INSERT INTO t2 VALUES (1,1),(2,2),(3,3);
 SELECT distinct p1.processor_id, (SELECT y.yod_id FROM t1 p2, t2 y WHERE p2.processor_id = p1.processor_id and p2.processor_id = y.processor_id) FROM t1 p1;
 processor_id	(SELECT y.yod_id FROM t1 p2, t2 y WHERE p2.processor_id = p1.processor_id and p2.processor_id = y.processor_id)
 1	1
-2	1
-3	1
+2	2
+3	3
 drop table t1,t2,t3;
+create table t1 (id int not null, value char(255), primary key(id)) engine=innodb;
+create table t2 (id int not null, value char(255)) engine=innodb;
+insert into t1 values (1,'a'),(2,'b');
+insert into t2 values (1,'z'),(2,'x');
+select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
+id	value	(select t1.value from t1 where t1.id=t2.id)
+1	z	a
+2	x	b
+select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
+id	value	(select t1.value from t1 where t1.id=t2.id)
+1	z	a
+2	x	b
+drop table t1,t2;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 15a99385285..bba30964a31 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -664,7 +664,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
 bool insert_fields(THD *thd,TABLE_LIST *tables,
 		   const char *db_name, const char *table_name,
 		   List_iterator *it);
-bool setup_tables(TABLE_LIST *tables);
+bool setup_tables(TABLE_LIST *tables, my_bool reinit);
 int setup_wild(THD *thd, TABLE_LIST *tables, List &fields,
 	       List *sum_func_list, uint wild_num);
 int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index d7984213fd6..3125c392751 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2039,15 +2039,28 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
 
 
 /*
-  Remap table numbers if INSERT ... SELECT
-  Check also that the 'used keys' and 'ignored keys' exists and set up the
-  table structure accordingly
+  prepare tables
 
-  This has to be called for all tables that are used by items, as otherwise
-  table->map is not set and all Item_field will be regarded as const items.
+  SYNOPSIS
+    setup_tables()
+    tables - tables list
+    reinit - true if called for table reinitialization before
+             subquery reexecuting
+
+   RETURN
+     0	ok;  In this case *map will includes the choosed index
+     1	error
+
+   NOTE
+     Remap table numbers if INSERT ... SELECT
+     Check also that the 'used keys' and 'ignored keys' exists and set up the
+     table structure accordingly
+
+     This has to be called for all tables that are used by items, as otherwise
+     table->map is not set and all Item_field will be regarded as const items.
 */
 
-bool setup_tables(TABLE_LIST *tables)
+bool setup_tables(TABLE_LIST *tables, my_bool reinit)
 {
   DBUG_ENTER("setup_tables");
   uint tablenr=0;
@@ -2074,7 +2087,7 @@ bool setup_tables(TABLE_LIST *tables)
       table->keys_in_use_for_query.subtract(map);
     }
     table->used_keys.intersect(table->keys_in_use_for_query);
-    if (table_list->shared  || table->clear_query_id)
+    if ((table_list->shared  || table->clear_query_id) && !reinit)
     {
       table->clear_query_id= 0;
       /* Clear query_id that may have been set by previous select */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 60220ffc889..2c75c3c5a22 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1037,7 +1037,7 @@ bool select_singlerow_subselect::send_data(List &items)
   Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
   if (it->assigned())
   {
-      my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0));
+    my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0));
     DBUG_RETURN(1);
   }
   if (unit->offset_limit_cnt)
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index c40133c04a8..a5b7c691ae1 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -686,7 +686,7 @@ int mysqld_help(THD *thd, const char *mask)
     goto end;
   }
   /* Init tables and fields to be usable from items */
-  setup_tables(tables);
+  setup_tables(tables, 0);
   memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); 
   if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
   {
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e23e62fb714..c2f3e737daf 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -84,7 +84,7 @@ check_insert_fields(THD *thd,TABLE *table,List &fields,
     table_list.grant=table->grant;
 
     thd->dupp_field=0;
-    if (setup_tables(&table_list) ||
+    if (setup_tables(&table_list, 0) ||
 	setup_fields(thd, 0, &table_list,fields,1,0,0))
       return -1;
     if (thd->dupp_field)
@@ -204,7 +204,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
   }
 
   if (check_insert_fields(thd,table,fields,*values,1) ||
-      setup_tables(insert_table_list) ||
+      setup_tables(insert_table_list, 0) ||
       setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
       (duplic == DUP_UPDATE &&
        (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index de0d6ade618..efb0ce92ad0 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1222,11 +1222,6 @@ void st_select_lex::mark_as_dependent(SELECT_LEX *last)
       s->uncacheable|= UNCACHEABLE_DEPENDENT;
       SELECT_LEX_UNIT *munit= s->master_unit();
       munit->uncacheable|= UNCACHEABLE_DEPENDENT;
-      //Tables will be reopened many times
-      for (TABLE_LIST *tbl= s->get_table_list();
-	   tbl;
-	   tbl= tbl->next)
-	tbl->shared= 1;
     }
 }
 
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 0c35e99ed08..175791ef31e 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -123,7 +123,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
   else
   {						// Part field list
     thd->dupp_field=0;
-    if (setup_tables(table_list) ||
+    if (setup_tables(table_list, 0) ||
 	setup_fields(thd, 0, table_list, fields, 1, 0, 0))
       DBUG_RETURN(-1);
     if (thd->dupp_field)
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index ef7bf013be8..1d16771c1a4 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -164,7 +164,7 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
   List	all_fields(select_lex->item_list);
 
 
-  if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
+  if (setup_tables((TABLE_LIST *)select_lex->table_list.first, 0) ||
       setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
 		   select_lex->item_list, 1, &all_fields,1) ||
       setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5d6ab165641..0a565c00ba7 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -679,7 +679,7 @@ static bool mysql_test_upd_fields(Prepared_statement *stmt,
 #endif
   if (open_and_lock_tables(thd, table_list))
     DBUG_RETURN(1);
-  if (setup_tables(table_list) ||
+  if (setup_tables(table_list, 0) ||
       setup_fields(thd, 0, table_list, fields, 1, 0, 0) || 
       setup_conds(thd, table_list, &conds) || thd->net.report_error)      
     DBUG_RETURN(1);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a1f6abfd53a..fe5b8885810 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -301,7 +301,7 @@ JOIN::prepare(Item ***rref_pointer_array,
 
   /* Check that all tables, fields, conds and order are ok */
 
-  if (setup_tables(tables_list) ||
+  if (setup_tables(tables_list, 0) ||
       setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
       select_lex->setup_ref_array(thd, og_num) ||
       setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
@@ -1015,7 +1015,7 @@ JOIN::reinit()
   if (unit->select_limit_cnt == HA_POS_ERROR)
     select_lex->options&= ~OPTION_FOUND_ROWS;
   
-  if (setup_tables(tables_list))
+  if (setup_tables(tables_list, 1))
     DBUG_RETURN(1);
   
   /* Reset of sum functions */
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index cdea32ad3f6..9fc8d482bfa 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -95,7 +95,7 @@ int mysql_update(THD *thd,
   tables.table= table;
   tables.alias= table_list->alias;
 
-  if (setup_tables(update_table_list) ||
+  if (setup_tables(update_table_list, 0) ||
       setup_conds(thd,update_table_list,&conds) ||
       thd->lex->select_lex.setup_ref_array(thd, order_num) ||
       setup_order(thd, thd->lex->select_lex.ref_pointer_array,

From fbf563e86a219d02fa9bae0c8fb52c34c60bacbe Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 4 Jan 2004 23:44:33 +0200
Subject: [PATCH 034/157] allow UPDATE and DELETE stetements with tables
 derived from subquery if they are not updated (BUG#2117) allow delete table
 by alias in multi-delete statement

include/mysqld_error.h:
  new error message about non-updateable table
mysql-test/r/derived.result:
  test of multi-update and multi-delete
mysql-test/t/derived.test:
  test of multi-update and multi-delete
sql/share/czech/errmsg.txt:
  new error message about non-updateable table
sql/share/danish/errmsg.txt:
  new error message about non-updateable table
sql/share/dutch/errmsg.txt:
  new error message about non-updateable table
sql/share/english/errmsg.txt:
  new error message about non-updateable table
sql/share/estonian/errmsg.txt:
  new error message about non-updateable table
sql/share/french/errmsg.txt:
  new error message about non-updateable table
sql/share/german/errmsg.txt:
  new error message about non-updateable table
sql/share/greek/errmsg.txt:
  new error message about non-updateable table
sql/share/hungarian/errmsg.txt:
  new error message about non-updateable table
sql/share/italian/errmsg.txt:
  new error message about non-updateable table
sql/share/japanese/errmsg.txt:
  new error message about non-updateable table
sql/share/korean/errmsg.txt:
  new error message about non-updateable table
sql/share/norwegian-ny/errmsg.txt:
  new error message about non-updateable table
sql/share/norwegian/errmsg.txt:
  new error message about non-updateable table
sql/share/polish/errmsg.txt:
  new error message about non-updateable table
sql/share/portuguese/errmsg.txt:
  new error message about non-updateable table
sql/share/romanian/errmsg.txt:
  new error message about non-updateable table
sql/share/russian/errmsg.txt:
  new error message about non-updateable table
sql/share/serbian/errmsg.txt:
  new error message about non-updateable table
sql/share/slovak/errmsg.txt:
  new error message about non-updateable table
sql/share/spanish/errmsg.txt:
  new error message about non-updateable table
sql/share/swedish/errmsg.txt:
  new error message about non-updateable table
sql/share/ukrainian/errmsg.txt:
  new error message about non-updateable table
sql/sql_parse.cc:
  allow delete table by alias
  separate error message for try to delete derived table
sql/sql_update.cc:
  test "is updated table derived?"
sql/sql_yacc.yy:
  error message in case of try to update derived table
---
 include/mysqld_error.h            |  3 ++-
 mysql-test/r/derived.result       | 27 +++++++++++++++++++++-
 mysql-test/t/derived.test         | 21 +++++++++++++++++-
 sql/share/czech/errmsg.txt        |  1 +
 sql/share/danish/errmsg.txt       |  1 +
 sql/share/dutch/errmsg.txt        |  1 +
 sql/share/english/errmsg.txt      |  1 +
 sql/share/estonian/errmsg.txt     |  1 +
 sql/share/french/errmsg.txt       |  1 +
 sql/share/german/errmsg.txt       |  1 +
 sql/share/greek/errmsg.txt        |  1 +
 sql/share/hungarian/errmsg.txt    |  1 +
 sql/share/italian/errmsg.txt      |  1 +
 sql/share/japanese/errmsg.txt     |  1 +
 sql/share/korean/errmsg.txt       |  1 +
 sql/share/norwegian-ny/errmsg.txt |  1 +
 sql/share/norwegian/errmsg.txt    |  1 +
 sql/share/polish/errmsg.txt       |  1 +
 sql/share/portuguese/errmsg.txt   |  1 +
 sql/share/romanian/errmsg.txt     |  1 +
 sql/share/russian/errmsg.txt      |  1 +
 sql/share/serbian/errmsg.txt      |  1 +
 sql/share/slovak/errmsg.txt       |  1 +
 sql/share/spanish/errmsg.txt      |  1 +
 sql/share/swedish/errmsg.txt      |  1 +
 sql/share/ukrainian/errmsg.txt    |  1 +
 sql/sql_parse.cc                  | 21 +++++++++++++++---
 sql/sql_update.cc                 | 37 ++++++++++++++++++++++++++++++-
 sql/sql_yacc.yy                   | 14 ++++++------
 29 files changed, 132 insertions(+), 14 deletions(-)

diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 6a484d0419c..179a2f823d7 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -303,4 +303,5 @@
 #define ER_WARN_HOSTNAME_WONT_WORK 1284
 #define ER_UNKNOWN_STORAGE_ENGINE 1285
 #define ER_WARN_DEPRECATED_SYNTAX 1286
-#define ER_ERROR_MESSAGES 287
+#define ER_NON_UPDATABLE_TABLE 1287
+#define ER_ERROR_MESSAGES 288
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index bb268cd1094..f311b56f519 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -209,7 +209,7 @@ ERROR 42000: You have an error in your SQL syntax.  Check the manual that corres
 create table t1 (a int);
 insert into t1 values (1),(2),(3);
 update (select * from t1) as t1 set a = 5;
-ERROR 42000: You have an error in your SQL syntax.  Check the manual that corresponds to your MySQL server version for the right syntax to use
+ERROR HY000: The target table t1 of the UPDATE is not updatable.
 delete from (select * from t1);
 ERROR 42000: You have an error in your SQL syntax.  Check the manual that corresponds to your MySQL server version for the right syntax to use near '(select * from t1)' at line 1
 insert into  (select * from t1) values (5);
@@ -245,3 +245,28 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	
 3	UNION	t1	ALL	NULL	NULL	NULL	NULL	2	
 drop table t1;
+CREATE TABLE `t1` (
+`N` int(11) unsigned NOT NULL default '0',
+`M` tinyint(1) default '0',
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+Warnings:
+Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
+UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
+select * from t1;
+N	M
+1	2
+1	2
+1	2
+2	2
+2	2
+3	0
+UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
+ERROR HY000: The target table P2 of the UPDATE is not updatable.
+delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+select * from t1;
+N	M
+3	0
+delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+ERROR HY000: The target table P2 of the DELETE is not updatable.
+drop table t1;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index caf673d95c1..77e76d16772 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -115,7 +115,7 @@ select mail_id,  if(folder.f_description!='', folder.f_description, folder.f_nam
 #
 create table t1 (a int);
 insert into t1 values (1),(2),(3);
--- error 1149
+-- error 1287
 update (select * from t1) as t1 set a = 5;
 -- error 1064
 delete from (select * from t1);
@@ -138,3 +138,22 @@ insert into t1 values (1),(2);
 select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
 explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
 drop table t1;
+
+
+#
+# multi-update & multi-delete with derived tables
+#
+CREATE TABLE `t1` (
+  `N` int(11) unsigned NOT NULL default '0',
+  `M` tinyint(1) default '0',
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
+UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
+select * from t1;
+-- error 1287
+UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
+delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+select * from t1;
+-- error 1287
+delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+drop table t1;
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 85606a060e7..cf5f573774b 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -299,3 +299,4 @@ character-set=latin2
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index d005150cb89..2a42570ded3 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 3fd44f9ec69..53463c31d02 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -301,3 +301,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index afce57a9a74..71c8c8f1559 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index dcdc74f5ab8..fecf0cde7be 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -295,3 +295,4 @@ character-set=latin7
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 94922ca40f4..afc1879a526 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 74f50289d86..56e263bc64e 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -302,3 +302,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 5813717f57a..1596b1adbab 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -290,3 +290,4 @@ character-set=greek
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 77ce0b8d4d2..bcd17fca7cc 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin2
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 204e1f980cc..22a09ac1a1b 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index af22a2eb49a..b76fa5d8f6d 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -292,3 +292,4 @@ character-set=ujis
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 6e348736698..482bc91852c 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -290,3 +290,4 @@ character-set=euckr
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 248d88bd1c9..a442a5879b8 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 9055b84f5e9..47660e29676 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index ec9f3782b08..7f81facf6f5 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin2
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index ffb70632bd4..8ddd281b346 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
 "MySQL foi inicializado em modo --skip-name-resolve. Vocκ necesita reincializα-lo sem esta opηγo para este grant funcionar",
 "Motor de tabela desconhecido '%s'",
 "'%s' ι desatualizado. Use '%s' em seu lugar.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index e3640fb7a7a..2235871738c 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin2
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 5224f19b001..76fc04f42e4 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=koi8r
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"τΑΒΜΙΓΑ %-.100s Χ %s ΞΕ ΝΟΦΕΤ ΙΪΝΕΞΡΤΣΡ.",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 904c8f0c8b9..a61c6a25ccc 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -285,3 +285,4 @@ character-set=cp1250
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index c7e543a5497..36437930095 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -298,3 +298,4 @@ character-set=latin2
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 845a7da36eb..8e61ce6a62f 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 9da0a511ddb..9c13347cc3c 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The target table %-.100s of the %s is not updatable.",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 7186e0550b2..b5d5f74ef77 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -295,3 +295,4 @@ character-set=koi8u
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"τΑΒΜΙΓΡ %-.100s Υ %s ΞΕ ΝΟΦΕ ΟΞΟΧΜΐΧΑΤΙΣΨ.",
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 465d840e2b8..4310f69d2a7 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2663,15 +2663,30 @@ mysql_execute_command(THD *thd)
       table_count++;
       /* All tables in aux_tables must be found in FROM PART */
       TABLE_LIST *walk;
-      for (walk=(TABLE_LIST*) tables ; walk ; walk=walk->next)
+      for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
       {
-	if (!strcmp(auxi->real_name,walk->real_name) &&
+	if ((!strcmp(auxi->real_name,walk->real_name) ||
+	     !strcmp(auxi->real_name,walk->alias)) &&
 	    !strcmp(walk->db,auxi->db))
 	  break;
       }
       if (!walk)
       {
-	net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
+	if (lex->derived_tables)
+	{
+	  // are we trying to delete derived table?
+	  for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
+	  {
+	    if (!strcmp(auxi->real_name,walk->alias) &&
+		walk->derived)
+	    {
+	      net_printf(thd, ER_NON_UPDATABLE_TABLE,
+			 auxi->real_name, "DELETE");
+	      goto error;
+	    }
+	  }
+	}
+	net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
 	goto error;
       }
       walk->lock_type= auxi->lock_type;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index cdea32ad3f6..87421c482d5 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -434,13 +434,36 @@ int mysql_multi_update(THD *thd,
   fix_tables_pointers(thd->lex->all_selects_list);
 
   select_lex->select_limit= HA_POS_ERROR;
+
+  table_map item_tables= 0, derived_tables= 0;
+  if (thd->lex->derived_tables)
+  {
+    // Assign table map values to check updatability of derived tables
+    uint tablenr=0;
+    for (TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
+	 table_list;
+	 table_list= table_list->next, tablenr++)
+    {
+      table_list->table->map= (table_map) 1 << tablenr;
+    }
+  }
   if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
     DBUG_RETURN(-1);
+  if (thd->lex->derived_tables)
+  {
+    // Find tables used in items
+    List_iterator_fast it(*fields);
+    Item *item;
+    while ((item= it++))
+    {
+      item_tables|= item->used_tables();
+    }
+  }
 
   /*
     Count tables and setup timestamp handling
   */
-  for (tl= select_lex->get_table_list() ; tl ; tl=tl->next)
+  for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
   {
     TABLE *table= tl->table;
     if (table->timestamp_field)
@@ -450,6 +473,18 @@ int mysql_multi_update(THD *thd,
       if (table->timestamp_field->query_id != thd->query_id)
 	table->time_stamp= table->timestamp_field->offset() +1;
     }
+    if (tl->derived)
+      derived_tables|= table->map;
+  }
+  if (thd->lex->derived_tables && (item_tables & derived_tables))
+  {
+    // find derived table which cause error
+    for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
+    {
+      if (tl->derived && (item_tables & tl->table->map))
+	my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
+			MYF(0), tl->alias, "UPDATE");
+    }
   }
 
   if (!(result=new multi_update(thd, table_list, fields, values,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 310d8a41be2..41fb93891fb 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3155,13 +3155,6 @@ join_table:
         | '(' SELECT_SYM select_derived ')' opt_table_alias
 	{
 	  LEX *lex=Lex;
-	  if (lex->sql_command == SQLCOM_UPDATE &&
-	      &lex->select_lex == lex->current_select->outer_select())
-	  {
-	    send_error(lex->thd, ER_SYNTAX_ERROR);
-	    YYABORT;
-	  }
-
 	  SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
 	  lex->current_select= unit->outer_select();
 	  if (!($$= lex->current_select->
@@ -3838,6 +3831,13 @@ update:
 	  Select->set_lock_for_tables($3);
           if (lex->select_lex.table_list.elements > 1)
             lex->sql_command= SQLCOM_UPDATE_MULTI;
+	  else if (lex->select_lex.get_table_list()->derived)
+	  {
+	    /* it is single table update and it is update of derived table */
+	    net_printf(lex->thd, ER_NON_UPDATABLE_TABLE,
+		       lex->select_lex.get_table_list()->alias, "UPDATE");
+	    YYABORT;
+	  }
 	}
 	;
 

From d4a7fa95eef5f9463c3fbe405ff1ae3416e3168a Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 5 Jan 2004 21:45:14 +0200
Subject: [PATCH 035/157] Fixed Bug#2205.

---
 client/mysql.cc | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index e3945e8aa2f..2ce0d769924 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -2436,8 +2436,9 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
 static int
 com_use(String *buffer __attribute__((unused)), char *line)
 {
-  char *tmp;
-  char buff[256];
+  char *tmp, buff[FN_REFLEN + 1];
+  MYSQL_RES *res;
+  MYSQL_ROW row;
 
   bzero(buff, sizeof(buff));
   strmov(buff, line);
@@ -2447,6 +2448,31 @@ com_use(String *buffer __attribute__((unused)), char *line)
     put_info("USE must be followed by a database name", INFO_ERROR);
     return 0;
   }
+
+  /* 
+     We need to recheck the current database, because it may change
+     under our feet, for example if DROP DATABASE or RENAME DATABASE
+     (latter one not yet available by the time the comment was written)
+  */
+  current_db= 0; // Let's reset current_db, assume it's gone
+  /* 
+     We don't care about in case of an error below because current_db
+     was just set to 0.
+  */
+  if (!mysql_query(&mysql, "SELECT DATABASE()") &&
+      (res= mysql_use_result(&mysql)))
+  {
+    row= mysql_fetch_row(res);
+    if (row[0] &&
+	(!current_db || cmp_database(charset_info, current_db, row[0])))
+    {
+      my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+      current_db= my_strdup(row[0], MYF(MY_WME));
+    }
+    (void) mysql_fetch_row(res);		// Read eof
+    mysql_free_result(res);
+  }
+    
   if (!current_db || cmp_database(charset_info, current_db, tmp))
   {
     if (one_database)

From 0d770c43db695281fe24c1da18cb12216b30a542 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 6 Jan 2004 13:10:57 +0200
Subject: [PATCH 036/157] srv0start.c:   Add comment that the insert buffer
 format changed between 4.0 and 4.1.1, but the undo log format did not

innobase/srv/srv0start.c:
  Add comment that the insert buffer format changed between 4.0 and 4.1.1, but the undo log format did not
---
 innobase/srv/srv0start.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 5fe66f515bc..9dd270b6e15 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1603,6 +1603,19 @@ NetWare. */
 	fflush(stderr);
 
 	if (trx_doublewrite_must_reset_space_ids) {
+		/* Actually, we did not change the undo log format between
+		4.0 and 4.1.1, and we would not need to run purge to
+		completion. Note also that the purge algorithm in 4.1.1
+		can process the the history list again even after a full
+		purge, because our algorithm does not cut the end of the
+		history list in all cases so that it would become empty
+		after a full purge. That mean that we may purge 4.0 type
+		undo log even after this phase.
+		
+		The insert buffer record format changed between 4.0 and
+		4.1.1. It is essential that the insert buffer is emptied
+		here! */
+
 		fprintf(stderr,
 "InnoDB: You are upgrading to an InnoDB version which allows multiple\n"
 "InnoDB: tablespaces. Wait that purge and insert buffer merge run to\n"

From 5e55cd5d0feba9e276ddc8bc4c2e225f714b3290 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 6 Jan 2004 13:13:04 +0200
Subject: [PATCH 037/157] As far as we cut off derived table branch, we have to
 close JOINs (BUG#2141) (test case is absend because it is multi-thread and
 very big)

sql/sql_derived.cc:
  As far as we cut off this branch, we have to close JOINs
---
 sql/sql_derived.cc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index e8f1c5d87de..ab3ef8da21a 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -198,7 +198,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
 	  }
 	}
 	else
+	{
 	  unit->exclude_tree();
+	  unit->cleanup();
+	}
 	org_table_list->db= (char *)"";
 	  // Force read of table stats in the optimizer
 	table->file->info(HA_STATUS_VARIABLE);

From 079b4819a4a08cdf4e54eac802037efeb1e7f772 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 6 Jan 2004 20:03:06 +0200
Subject: [PATCH 038/157] srv0start.c:   More instructions about a downgrade
 4.1.1 -> 4.0.18

innobase/srv/srv0start.c:
  More instructions about a downgrade 4.1.1 -> 4.0.18
---
 innobase/srv/srv0start.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 9dd270b6e15..d7a14b8a9ec 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1638,8 +1638,9 @@ NetWare. */
 
 		fprintf(stderr,
 "InnoDB: You have now successfully upgraded to the multiple tablespaces\n"
-"InnoDB: format. You should not downgrade again to an earlier version of\n"
-"InnoDB: InnoDB!\n");
+"InnoDB: format. You should NOT DOWNGRADE again to an earlier version of\n"
+"InnoDB: InnoDB! But if you absolutely need to downgrade, see section 4.6 of\n"
+"InnoDB: http://www.innodb.com/ibman.php for instructions.\n");
 	}
 
 	if (srv_force_recovery == 0) {

From fae79aeca552593a830cb95e77ecb32a012faf70 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 7 Jan 2004 14:45:04 +0400
Subject: [PATCH 039/157] SCRUM WL#1246 (Query cache in embedded library) Small
 fix - code removed that prevents using query cache in embedded library

include/mysql_embed.h:
  Now we have the query_cache in embedded library
---
 include/mysql_embed.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/mysql_embed.h b/include/mysql_embed.h
index df358e29872..7a169d4133e 100644
--- a/include/mysql_embed.h
+++ b/include/mysql_embed.h
@@ -32,6 +32,4 @@
 #undef  MYSQL_SERVER_SUFFIX
 #define MYSQL_SERVER_SUFFIX "-embedded"
 
-#undef HAVE_QUERY_CACHE				/* Cache dosn't work yet */
-
 #endif /* EMBEDDED_LIBRARY */

From 902c361910cdec368c5baec1be6079978a46f1a8 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 7 Jan 2004 16:41:09 +0400
Subject: [PATCH 040/157] SCRUM WL#1246 (Query cache in embedded library) Some
 fixes after testing

libmysqld/emb_qcache.cc:
  code added to check if the recordset has no rows
sql/sql_cache.cc:
  this code should not work if the query isn't cacheable
---
 libmysqld/emb_qcache.cc | 32 ++++++++++++++++++++++++--------
 sql/sql_cache.cc        |  8 ++++----
 2 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc
index 0374ab58784..4dac154ab80 100644
--- a/libmysqld/emb_qcache.cc
+++ b/libmysqld/emb_qcache.cc
@@ -284,11 +284,18 @@ uint emb_count_querycache_size(THD *thd)
   MYSQL *mysql= thd->mysql;
   MYSQL_FIELD *field= mysql->fields;
   MYSQL_FIELD *field_end= field + mysql->field_count;
+  MYSQL_ROWS *cur_row=NULL;
+  my_ulonglong n_rows=0;
   
-  *thd->data->prev_ptr= NULL; // this marks the last record
-  MYSQL_ROWS *cur_row= thd->data->data;
-
-  result= 4+8 + (42 + 4*thd->data->rows)*mysql->field_count;
+  if (!field)
+    return 0;
+  if (thd->data)
+  {
+    *thd->data->prev_ptr= NULL; // this marks the last record
+    cur_row= thd->data->data;
+    n_rows= thd->data->rows;
+  }
+  result= 4+8 + (42 + 4*n_rows)*mysql->field_count;
 
   for(; field < field_end; field++)
   {
@@ -315,12 +322,21 @@ void emb_store_querycache_result(Querycache_stream *dst, THD *thd)
   MYSQL *mysql= thd->mysql;
   MYSQL_FIELD *field= mysql->fields;
   MYSQL_FIELD *field_end= field + mysql->field_count;
-  
-  *thd->data->prev_ptr= NULL; // this marks the last record
-  MYSQL_ROWS *cur_row= thd->data->data;
+  MYSQL_ROWS *cur_row= NULL;
+  my_ulonglong n_rows= 0;
+
+  if (!field)
+    return;
+
+  if (thd->data)
+  {
+    *thd->data->prev_ptr= NULL; // this marks the last record
+    cur_row= thd->data->data;
+    n_rows= thd->data->rows;
+  }
 
   dst->store_int((uint)mysql->field_count);
-  dst->store_ll((uint)thd->data->rows);
+  dst->store_ll((uint)n_rows);
 
   for(; field < field_end; field++)
   {
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index aad8d0a5d2c..7c31281c926 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -653,10 +653,6 @@ void query_cache_abort(NET *net)
 void query_cache_end_of_result(THD *thd)
 {
   DBUG_ENTER("query_cache_end_of_result");
-#ifdef EMBEDDED_LIBRARY
-    query_cache_insert(&thd->net, (byte*)thd, 
-		       emb_count_querycache_size(thd));
-#endif
 
 #ifndef DBUG_OFF
   // Check if we have called query_cache.wreck() (which disables the cache)
@@ -665,6 +661,10 @@ void query_cache_end_of_result(THD *thd)
 
   if (thd->net.query_cache_query != 0)	// Quick check on unlocked structure
   {
+#ifdef EMBEDDED_LIBRARY
+    query_cache_insert(&thd->net, (byte*)thd, 
+		       emb_count_querycache_size(thd));
+#endif
     STRUCT_LOCK(&query_cache.structure_guard_mutex);
     Query_cache_block *query_block = ((Query_cache_block*)
 				      thd->net.query_cache_query);

From 582886a3e971df2766411cdfe57c8a09f3c2e6b6 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 7 Jan 2004 21:30:15 +0400
Subject: [PATCH 041/157] Fix for 1224 (USER() CURRENT_USER() functions in
 embedded library) Now we return user@host for USER() in embedded library
 CURRENT_USER returns empty string if library compiled with
 NO_EMBEDDED_ACCESS_CHECKS

libmysqld/embedded_priv.h:
  function's declarations trimmed
libmysqld/lib_sql.cc:
  user/host names handling added
libmysqld/libmysqld.c:
  user/host names handling added
sql/sql_class.cc:
  we shouldn't free user/host names in embedded library
---
 libmysqld/embedded_priv.h |  9 +++++----
 libmysqld/lib_sql.cc      | 22 ++++++++++++++++++----
 libmysqld/libmysqld.c     | 17 +++++++----------
 sql/sql_class.cc          |  4 +++-
 4 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h
index 673531c0c14..1608f4ed4ad 100644
--- a/libmysqld/embedded_priv.h
+++ b/libmysqld/embedded_priv.h
@@ -23,9 +23,10 @@
 #include 
 
 C_MODE_START
-extern void lib_connection_phase(NET *net, int phase);
-extern void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
-extern void *create_embedded_thd(int client_flag, char *db);
-extern MYSQL_METHODS embedded_methods;
+void lib_connection_phase(NET *net, int phase);
+void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db);
+void *create_embedded_thd(int client_flag, char *db);
+int check_embedded_connection(MYSQL *mysql);
 void free_old_query(MYSQL *mysql);
+extern MYSQL_METHODS embedded_methods;
 C_MODE_END
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 5f478fc8041..2d451d6cecd 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -478,7 +478,17 @@ void *create_embedded_thd(int client_flag, char *db)
   return thd;
 }
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+int check_embedded_connection(MYSQL *mysql)
+{
+  THD *thd= (THD*)mysql->thd;
+  thd->host= (char*)my_localhost;
+  thd->host_or_ip= thd->host;
+  thd->user= mysql->user;
+  return 0;
+}
+
+#else
 int check_embedded_connection(MYSQL *mysql)
 {
   THD *thd= (THD*)mysql->thd;
@@ -486,9 +496,13 @@ int check_embedded_connection(MYSQL *mysql)
   char scramble_buff[SCRAMBLE_LENGTH];
   int passwd_len;
 
-  thd->host= mysql->options.client_ip ?
-    mysql->options.client_ip : (char*)my_localhost;
-  thd->ip= thd->host;
+  if (mysql->options.client_ip)
+  {
+    thd->host= mysql->options.client_ip;
+    thd->ip= thd->host;
+  }
+  else
+    thd->host= (char*)my_localhost;
   thd->host_or_ip= thd->host;
 
   if (acl_check_host(thd->host,thd->ip))
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 69fdf14eca4..95f745aef5f 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -124,17 +124,14 @@ static inline int mysql_init_charset(MYSQL *mysql)
   return 0;
 }
 
-int check_embedded_connection(MYSQL *mysql);
-
 MYSQL * STDCALL
 mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
 		   const char *passwd, const char *db,
 		   uint port, const char *unix_socket,ulong client_flag)
 {
   char *db_name;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
   char name_buff[USERNAME_LENGTH];
-#endif
+
   DBUG_ENTER("mysql_real_connect");
   DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
 		      host ? host : "(Null)",
@@ -165,10 +162,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
   if (!db || !db[0])
     db=mysql->options.db;
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
   if (!user || !user[0])
     user=mysql->options.user;
 
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
   if (!passwd)
   {
     passwd=mysql->options.password;
@@ -177,16 +174,18 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
       passwd=getenv("MYSQL_PWD");		/* get it from environment */
 #endif
   }
+  mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
+#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
   if (!user || !user[0])
   {
     read_user_name(name_buff);
-    if (!name_buff[0])
+    if (name_buff[0])
       user= name_buff;
   }
 
+  if (!user)
+    user= "";
   mysql->user=my_strdup(user,MYF(0));
-  mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
-#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
 
   port=0;
   unix_socket=0;
@@ -196,10 +195,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
 
   init_embedded_mysql(mysql, client_flag, db_name);
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
   if (check_embedded_connection(mysql))
     goto error;
-#endif
 
   if (mysql_init_charset(mysql))
     goto error;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 60220ffc889..89b812eb205 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -323,12 +323,14 @@ THD::~THD()
 #endif
 
   DBUG_PRINT("info", ("freeing host"));
+#ifndef EMBEDDED_LIBRARY
   if (host != my_localhost)			// If not pointer to constant
     safeFree(host);
   if (user != delayed_user)
     safeFree(user);
-  safeFree(db);
   safeFree(ip);
+#endif
+  safeFree(db);
   free_root(&warn_root,MYF(0));
   free_root(&transaction.mem_root,MYF(0));
   mysys_var=0;					// Safety (shouldn't be needed)

From b321b7c00d5f41c47e652e0ae56489730309ee57 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 8 Jan 2004 18:56:21 +0200
Subject: [PATCH 042/157] row0mysql.c:   Fix typo

innobase/row/row0mysql.c:
  Fix typo
---
 innobase/row/row0mysql.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index d5472219d09..cf7a3efcdfc 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1447,7 +1447,7 @@ row_create_table_for_mysql(
 			fprintf(stderr, 
      "  InnoDB: Error: table %s already exists in InnoDB internal\n"
      "InnoDB: data dictionary. Have you deleted the .frm file\n"
-     "InnoDB: and not used DROPT ABLE? Have you used DROP DATABASE\n"
+     "InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
      "InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n"
      "InnoDB: See the Restrictions section of the InnoDB manual.\n",
 				 table->name);

From d84ee4d503783a174346393436e7a8ecc7b941bd Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 9 Jan 2004 22:28:29 +0200
Subject: [PATCH 043/157] null.result, null.test:    Fix for a bug #2219,
 regarding a bad cast to integer from NULL item_func.h:   Fix for a bug #2219,
 regarding a bad cast to integer from NULL sql_parse.cc:   A fix for a bug
 #2207, with mysql server haning on option setting

sql/sql_parse.cc:
  A fix for a bug #2207, with mysql server haning on option setting
sql/item_func.h:
  Fix for a bug #2219, regarding a bad cast to integer from NULL
mysql-test/t/null.test:
   Fix for a bug #2219, regarding a bad cast to integer from NULL
mysql-test/r/null.result:
   Fix for a bug #2219, regarding a bad cast to integer from NULL
---
 mysql-test/r/null.result | 3 +++
 mysql-test/t/null.test   | 1 +
 sql/item_func.h          | 8 ++++----
 sql/sql_parse.cc         | 2 ++
 4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index c4af221e117..aa56bce6453 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -153,3 +153,6 @@ explain select * from t1 where a between 2 and 3 or b is null;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	idx	idx	4	NULL	2	Using where
 drop table t1;
+select cast(NULL as signed);
+cast(NULL as signed)
+NULL
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index c11ed78253b..9f3b6646e7f 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -97,3 +97,4 @@ insert into t1 values
 explain select * from t1 where a between 2 and 3;
 explain select * from t1 where a between 2 and 3 or b is null;
 drop table t1;
+select cast(NULL as signed);
diff --git a/sql/item_func.h b/sql/item_func.h
index ac67b5a4065..33a4357d26c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -212,8 +212,8 @@ class Item_func_signed :public Item_int_func
 {
 public:
   Item_func_signed(Item *a) :Item_int_func(a) {}
-  double val() { return args[0]->val(); }
-  longlong val_int() { return args[0]->val_int(); }
+  double val() {  null_value=args[0]->null_value; return args[0]->val(); }
+  longlong val_int() {  null_value=args[0]->null_value; return args[0]->val_int(); }
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=0; }
   void print(String *str);
@@ -224,8 +224,8 @@ class Item_func_unsigned :public Item_int_func
 {
 public:
   Item_func_unsigned(Item *a) :Item_int_func(a) {}
-  double val() { return args[0]->val(); }
-  longlong val_int() { return args[0]->val_int(); }
+  double val() { null_value=args[0]->null_value; return args[0]->val(); }
+  longlong val_int() { null_value=args[0]->null_value; return args[0]->val_int(); }
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=1; }
   void print(String *str);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 465d840e2b8..3f36b48f5e6 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1624,9 +1624,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
     switch (command) {
     case MYSQL_OPTION_MULTI_STATEMENTS_ON:
       thd->client_capabilities|= CLIENT_MULTI_STATEMENTS;
+      send_eof(thd);
       break;
     case MYSQL_OPTION_MULTI_STATEMENTS_OFF:
       thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS;
+      send_eof(thd);
       break;
     default:
       send_error(thd, ER_UNKNOWN_COM_ERROR);

From 24f8054460a574660730024690786b877afccfd3 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 11 Jan 2004 18:15:19 +0100
Subject: [PATCH 044/157] Detect unexpected return codes of mysqltest in
 mysql-test-run. This way, a crash of mysqltest will be visible in the test
 logs (output of mysql-test-run).

mysql-test/mysql-test-run.sh:
  by design mysqltest returns 0 or 1 or 2 (see the exit()s and the return()
  of main()). So any greater code is a crash, I guess.
  On build and on my machine, 139 is segfault and 134 is assertion failure.
---
 mysql-test/mysql-test-run.sh | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 265ff036998..3f7efd3d6bc 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -603,7 +603,7 @@ error () {
 error_is () {
     $ECHO "Errors are (from $TIMEFILE) :"
     $CAT < $TIMEFILE
-    $ECHO "(the last line(s) may be the ones that caused the die() in mysqltest)"
+    $ECHO "(the last lines may be the most important ones)"
 }
 
 prefix_to_8() {
@@ -1309,6 +1309,9 @@ run_testcase ()
         skip_inc
 	$ECHO "$RES$RES_SPACE [ skipped ]"
       else
+        if [ $res -gt 2 ]; then
+          $ECHO "mysqltest returned unexpected code $res, it has probably crashed" >> $TIMEFILE
+        fi
 	total_inc
         fail_inc
 	$ECHO "$RES$RES_SPACE [ fail ]"

From 6c8045d4698240bc20639c4f9631735bbed90fea Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 12 Jan 2004 14:31:04 +0400
Subject: [PATCH 045/157] charset.c:   Fixed: client crashed when there are no
 Index.xml file.

mysys/charset.c:
  Fixed: client crashed when there are no Index.xml file.
---
 mysys/charset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mysys/charset.c b/mysys/charset.c
index f8c8237c88b..b911f29627c 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -540,7 +540,7 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
      strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
      my_read_charset_file(buf,flags);
   }
-  cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
+  cs= (cs && cs->state & MY_CS_AVAILABLE) ? cs : NULL;
   pthread_mutex_unlock(&THR_LOCK_charset);
   return cs;
 }

From 5b8b45f19f144b5dd02879ca25572fab0db6e7be Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 12 Jan 2004 17:43:39 +0100
Subject: [PATCH 046/157] checking 2nd level of FT index destroyed
 info->lastkey and CHECK TABLE erroneously treated table as corrupted bug#2190

---
 myisam/mi_check.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index a55929805fa..5687e7d48e3 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -551,7 +551,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
 		     ha_checksum *key_checksum, uint level)
 {
   int flag;
-  uint used_length,comp_flag,nod_flag,key_length,not_used;
+  uint used_length,comp_flag,nod_flag,key_length=0,not_used;
   uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
   my_off_t next_page,record;
   char llbuff[22];
@@ -586,6 +586,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
   }
   for ( ;; )
   {
+    memcpy((char*) info->lastkey,(char*) key,key_length);
+    info->lastkey_length=key_length;
     if (nod_flag)
     {
       next_page=_mi_kpos(nod_flag,keypos);
@@ -629,8 +631,6 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
     }
     (*key_checksum)+= mi_byte_checksum((byte*) key,
 				       key_length- info->s->rec_reflength);
-    memcpy((char*) info->lastkey,(char*) key,key_length);
-    info->lastkey_length=key_length;
     record= _mi_dpos(info,0,key+key_length);
     if (keyinfo->flag & HA_FULLTEXT) /* special handling for ft2 */
     {
@@ -658,7 +658,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
       DBUG_PRINT("test",("page: %s  record: %s  filelength: %s",
 			 llstr(page,llbuff),llstr(record,llbuff2),
 			 llstr(info->state->data_file_length,llbuff3)));
-      DBUG_DUMP("key",(byte*) info->lastkey,key_length);
+      DBUG_DUMP("key",(byte*) key,key_length);
       DBUG_DUMP("new_in_page",(char*) old_keypos,(uint) (keypos-old_keypos));
       goto err;
     }

From e90eb6f43ed987a9f69b8215bb123396ec9394aa Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 12 Jan 2004 21:05:41 +0100
Subject: [PATCH 047/157] Fix for BUG#2333 "ALTER DATABASE on inexistent
 database hangs the client": mysql_alter_db() now returns -1 in case of error,
 so that mysql_execute_command() calls send_error().

sql/sql_db.cc:
  In case of error, return -1 so that mysql_execute_command()
  understands that it must send_error().
  The double (( at the left of 'error' in the 'if' are to avoid a compiler warning.
---
 sql/sql_db.cc | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 70b1d1d0d3a..08f9ace529d 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -270,11 +270,8 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
   VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
 
   // do not alter database if another thread is holding read lock
-  if (wait_if_global_read_lock(thd,0))
-  {
-    error= -1;
+  if ((error=wait_if_global_read_lock(thd,0)))
     goto exit2;
-  }
 
   /* Check directory */
   (void)sprintf(path,"%s/%s/%s", mysql_data_home, db, MY_DB_OPT_FILE);
@@ -307,7 +304,7 @@ exit:
   start_waiting_global_read_lock(thd);
 exit2:
   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
-  DBUG_RETURN(error);
+  DBUG_RETURN(error ? -1 : 0); /* -1 to delegate send_error() */
 }
 
 

From ea854327159c22dc811c9b64131918c694f49ae6 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 04:05:38 +0200
Subject: [PATCH 048/157] row0sel.c:   If MySQL tries to do SELECT from an
 InnoDB table, but has set no table locks at all in ::external_lock(), print a
 descriptive error message and assert; some subquery bugs were of this type

innobase/row/row0sel.c:
  If MySQL tries to do SELECT from an InnoDB table, but has set no table locks at all in ::external_lock(), print a descriptive error message and assert; some subquery bugs were of this type
---
 innobase/row/row0sel.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 2215e3feff8..a13aaa47af2 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2758,6 +2758,7 @@ row_search_for_mysql(
 	ulint		cnt				= 0;
 	ulint		next_offs;
 	mtr_t		mtr;
+	char		err_buf[1000];
 	
 	ut_ad(index && pcur && search_tuple);
 	ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -2773,6 +2774,17 @@ row_search_for_mysql(
 		ut_a(0);
 	}
 
+	if (trx->n_mysql_tables_in_use == 0) {
+	
+		trx_print(err_buf, trx);
+
+		fprintf(stderr,
+"InnoDB: Error: MySQL is trying to perform a SELECT\n"
+"InnoDB: but it has not locked any tables in ::external_lock()!\n%s\n",
+			err_buf);
+		ut_a(0);
+	}
+
 /*	printf("Match mode %lu\n search tuple ", match_mode);
 	dtuple_print(search_tuple);
 	
@@ -3072,6 +3084,16 @@ shortcut_fails_too_big_rec:
 	if (!prebuilt->sql_stat_start) {
 		/* No need to set an intention lock or assign a read view */
 
+		if (trx->read_view == NULL
+		    && prebuilt->select_lock_type == LOCK_NONE) {
+			trx_print(err_buf, trx);
+
+			fprintf(stderr,
+"InnoDB: Error: MySQL is trying to perform a consistent read\n"
+"InnoDB: but the read view is not assigned!\n%s\n", err_buf);
+			
+			ut_a(0);
+		}
 	} else if (prebuilt->select_lock_type == LOCK_NONE) {
 		/* This is a consistent read */	
 		/* Assign a read view for the query */

From 79a4b2cd49b87da5dd327cd04242deda7188205f Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 04:10:20 +0200
Subject: [PATCH 049/157] row0sel.c:   Improve previous push: save 1000 bytes
 of thread stack in non-error cases

innobase/row/row0sel.c:
  Improve previous push: save 1000 bytes of thread stack in non-error cases
---
 innobase/row/row0sel.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index a13aaa47af2..5a5da3ba59a 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2758,7 +2758,6 @@ row_search_for_mysql(
 	ulint		cnt				= 0;
 	ulint		next_offs;
 	mtr_t		mtr;
-	char		err_buf[1000];
 	
 	ut_ad(index && pcur && search_tuple);
 	ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -2775,7 +2774,8 @@ row_search_for_mysql(
 	}
 
 	if (trx->n_mysql_tables_in_use == 0) {
-	
+		char	err_buf[1000];
+
 		trx_print(err_buf, trx);
 
 		fprintf(stderr,
@@ -3086,6 +3086,8 @@ shortcut_fails_too_big_rec:
 
 		if (trx->read_view == NULL
 		    && prebuilt->select_lock_type == LOCK_NONE) {
+			char	err_buf[1000];
+
 			trx_print(err_buf, trx);
 
 			fprintf(stderr,

From 491ab7f72e37ae16531567c21df4be11e9f6a0db Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 01:10:21 -0100
Subject: [PATCH 050/157] Minor Novell supplied changes for 4.1 (inside netware
 directory)

netware/init_db.sql:
  Add new tables for 4.1
netware/libmysql.imp:
  Comment out simple_command
---
 netware/init_db.sql  | 4 ++++
 netware/libmysql.imp | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/netware/init_db.sql b/netware/init_db.sql
index 4613e5c0274..063c1815eb1 100644
--- a/netware/init_db.sql
+++ b/netware/init_db.sql
@@ -24,3 +24,7 @@ CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64)
 
 CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges';
 
+CREATE TABLE help_topic (help_topic_id int unsigned NOT NULL, name varchar(64) NOT NULL, help_category_id smallint unsigned NOT NULL, description text NOT NULL, example text NOT NULL, url varchar(128) NOT NULL, primary key (help_topic_id), unique index (name))comment='help topics';
+CREATE TABLE help_category (help_category_id smallint unsigned NOT NULL, name varchar(64) NOT NULL, parent_category_id smallint unsigned null, url varchar(128) NOT NULL, primary key (help_category_id), unique index (name)) comment='help categories';
+CREATE TABLE help_keyword (help_keyword_id int unsigned NOT NULL, name varchar(64) NOT NULL, primary key  (help_keyword_id), unique index (name)) comment='help keywords';
+CREATE TABLE help_relation (help_topic_id int unsigned NOT NULL references help_topic, help_keyword_id  int unsigned NOT NULL references help_keyword, primary key (help_keyword_id, help_topic_id)) comment='keyword-topic relation';
diff --git a/netware/libmysql.imp b/netware/libmysql.imp
index 75fcc8d1a99..977fb1b0b1f 100644
--- a/netware/libmysql.imp
+++ b/netware/libmysql.imp
@@ -77,7 +77,7 @@ mysql_thread_init,
 mysql_thread_safe,
 mysql_use_result,
 net_safe_read,
-simple_command,
+#simple_command,
 mysql_connect,
 mysql_create_db,
 mysql_drop_db,

From 21e2c72bfbdccfdb0f72c6cbb61d7987bb7bb576 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 16:18:37 +0400
Subject: [PATCH 051/157] a fix (bug #2361: ALTER TABLE ... DROP PRIMARY KEY
 drops a non-primary key).

---
 mysql-test/r/alter_table.result | 9 +++++++++
 mysql-test/t/alter_table.test   | 9 +++++++++
 sql/sql_table.cc                | 8 +++++---
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 7ec12c1b021..33af0b30d1c 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -412,3 +412,12 @@ t1	0	PRIMARY	1	Host	A	NULL	NULL	NULL		BTREE
 t1	0	PRIMARY	2	User	A	0	NULL	NULL		BTREE	
 t1	1	Host	1	Host	A	NULL	NULL	NULL		BTREE	disabled
 DROP TABLE t1;
+CREATE TABLE t1 (a int UNIQUE);
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) default NULL,
+  UNIQUE KEY `a` (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index eab4fd7f5f0..71991973105 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -244,3 +244,12 @@ LOCK TABLES t1 WRITE;
 ALTER TABLE t1 DISABLE KEYS;
 SHOW INDEX FROM t1;
 DROP TABLE t1;
+
+#
+# Bug 2361
+#
+
+CREATE TABLE t1 (a int UNIQUE);
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ecd5f9ccb66..be42de34899 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2242,13 +2242,15 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   KEY *key_info=table->key_info;
   for (uint i=0 ; i < table->keys ; i++,key_info++)
   {
-    if (drop_primary && (key_info->flags & HA_NOSAME))
+    char *key_name= key_info->name;
+
+    if (drop_primary && !my_strcasecmp(system_charset_info, key_name,
+                                       "PRIMARY"))
     {
-      drop_primary=0;
+      drop_primary= 0;
       continue;
     }
 
-    char *key_name=key_info->name;
     Alter_drop *drop;
     drop_it.rewind();
     while ((drop=drop_it++))

From bf7e46938b8c79f5f9279adb671b7ab56f694435 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 17:27:21 +0400
Subject: [PATCH 052/157] item_strfunc.cc:   Unnesessary code was removed.
 Comment was added.

sql/item_strfunc.cc:
  Unnesessary code was removed. Comment was added.
---
 sql/item_strfunc.cc | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index fdacc4ec536..528345beb77 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -975,8 +975,13 @@ String *Item_func_right::val_str(String *str)
   if (res->length() <= (uint) length)
     return res; /* purecov: inspected */
 
+  /*
+    As far "res" contains at least "length" bytes
+    (according to the above condition and return),
+    the below statement is safe. res->numchars() can 
+    never return a value less than "length".
+  */
   uint start=res->numchars()-(uint) length;
-  if (start<=0) return res;
   start=res->charpos(start);
   tmp_value.set(*res,start,res->length()-start);
   return &tmp_value;

From 9dfada0cba36d75fc3dc49cecefc8c3f9b5114d2 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 17:13:03 +0200
Subject: [PATCH 053/157] srv0start.c, srv0srv.c:   If UNIV_SYNC_DEBUG was
 switched on, the error monitor thread could reserve a mutex BEFORE the sync
 debug system was initialized, and that caused a sync debug assertion in
 startup: move the 2 sec. sleep to a safer place; note that this is only
 heuristics, and in theory it can assert still

innobase/srv/srv0srv.c:
  If UNIV_SYNC_DEBUG was switched on, the error monitor thread could reserve a mutex BEFORE the sync debug system was initialized, and that caused a sync debug assertion in startup: move the 2 sec. sleep to a safer place; note that this is only heuristics, and in theory it can assert still
innobase/srv/srv0start.c:
  If UNIV_SYNC_DEBUG was switched on, the error monitor thread could reserve a mutex BEFORE the sync debug system was initialized, and that caused a sync debug assertion in startup: move the 2 sec. sleep to a safer place; note that this is only heuristics, and in theory it can assert still
---
 innobase/srv/srv0srv.c   |  4 ++--
 innobase/srv/srv0start.c | 11 ++++++-----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 027d7c8fb6e..d2368c5341f 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -2739,8 +2739,6 @@ loop:
 
 	cnt++;
 
-	os_thread_sleep(2000000);
-
 	/* Try to track a strange bug reported by Harald Fuchs and others,
 	where the lsn seems to decrease at times */
 
@@ -2782,6 +2780,8 @@ loop:
 	fflush(stderr);
 	fflush(stdout);
 
+	os_thread_sleep(2000000);
+
 	if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
 
 		goto loop;
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index d7a14b8a9ec..e6fdc95fad0 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1512,12 +1512,13 @@ NetWare. */
 	srv_is_being_started = FALSE;
 
 #ifdef UNIV_DEBUG
-        /* Wait a while so that creates threads have time to suspend themselves
-	before we switch sync debugging on; otherwise a thread may execute
-	mutex_enter() before the checks are on, and mutex_exit() after the
-	checks are on. */
+        /* Wait a while so that the created threads have time to suspend
+	themselves before we switch sync debugging on; otherwise a thread may
+	execute mutex_enter() before the checks are on, and mutex_exit() after
+	the checks are on, which will cause an assertion failure in sync
+	debug. */
 
-        os_thread_sleep(2000000);
+        os_thread_sleep(3000000);
 #endif
 	sync_order_checks_on = TRUE;
 

From 38a87d0eea0559101c683907db267d5cc1c7ef04 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 13 Jan 2004 19:55:37 +0100
Subject: [PATCH 054/157]  - link the mysql client RPM against libreadline
 instead of libedit    (BUG 2289)

support-files/mysql.spec.sh:
   - link the mysql client against libreadline instead of libedit (BUG 2289)
---
 support-files/mysql.spec.sh | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 5a9fbf64b1c..1ee88096def 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -220,7 +220,8 @@ sh -c  "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \
             --includedir=%{_includedir} \
             --mandir=%{_mandir} \
 	    --enable-thread-safe-client \
-	    --with-comment=\"Official MySQL RPM\";
+	    --with-comment=\"Official MySQL RPM\" \
+	    --with-readline ;
 	    # Add this for more debugging support
 	    # --with-debug
 	    # Add this for MyISAM RAID support:
@@ -574,6 +575,10 @@ fi
 # The spec file changelog only includes changes made to the spec file
 # itself
 %changelog 
+* Tue Jan 13 2004 Lenz Grimmer 
+
+- link the mysql client against libreadline instead of libedit (BUG 2289)
+
 * Fri Dec 13 2003 Lenz Grimmer 
 
 - fixed file permissions (BUG 1672)

From 7eea262321ed50eba83fa3369c9071f48a1e4757 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 04:58:37 +0200
Subject: [PATCH 055/157] - Added missing documentation to some mysql.cc
 options. - Fixed Bug#2346 - Fixed Bug#2378 - Fixed bug in pager (no Bug#ID
 (?)) - Added support for new special situations option type, GET_DISABLED.  
 See handling of --debug in mysql.cc. compiled wihtout debugging, as an  
 example.

client/mysql.cc:
  - Added missing documentation to some options.
  - Fixed a bug in pager (no Bug#ID found (?)), but reported on internals list
    with subject "[PATCH] Fix pager problems in mysql client"
  - Fixed Bug#2346, "unique prefix is enough" option behaviour can be confusing with --debug
include/my_getopt.h:
  Added new option type, GET_DISABLED.
include/mysys_err.h:
  New exit code for my_getopt.
mysys/my_getopt.c:
  - Added handling for GET_DISABLED option type (Fix for Bug#2346)
  - Fixed Bug#2378, "Problem with option abbreviation"
---
 client/mysql.cc     | 72 +++++++++++++++++++++++++++++++--------------
 include/my_getopt.h |  7 +++--
 include/mysys_err.h |  1 +
 mysys/my_getopt.c   | 29 ++++++++++++++++--
 4 files changed, 81 insertions(+), 28 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index 2ce0d769924..46e15ebbbd3 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -44,7 +44,7 @@
 #include 
 #endif
 
-const char *VER= "14.3";
+const char *VER= "14.4";
 
 /* Don't try to make a nice table if the data is too big */
 #define MAX_COLUMN_LENGTH	     1024
@@ -134,7 +134,8 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
 	       vertical=0, line_numbers=1, column_names=1,opt_html=0,
                opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
 	       tty_password= 0, opt_nobeep=0, opt_reconnect=1,
-	       default_charset_used= 0, opt_secure_auth= 0;
+	       default_charset_used= 0, opt_secure_auth= 0,
+               default_pager_set= 0;
 static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
 static my_string opt_mysql_unix_port=0;
 static int connect_flag=CLIENT_INTERACTIVE;
@@ -331,8 +332,11 @@ int main(int argc,char *argv[])
   strmov(pager, "stdout");	// the default, if --pager wasn't given
   {
     char *tmp=getenv("PAGER");
-    if (tmp)
-      strmov(default_pager,tmp);
+    if (tmp && strlen(tmp))
+    {
+      default_pager_set= 1;
+      strmov(default_pager, tmp);
+    }
   }
   if (!isatty(0) || !isatty(1))
   {
@@ -467,6 +471,8 @@ static struct my_option my_long_options[] =
 {
   {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
    0, 0, 0, 0, 0},
+  {"help", 'I', "Synonym for -?", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+   0, 0, 0, 0, 0},
   {"auto-rehash", OPT_AUTO_REHASH,
    "Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash.",
    (gptr*) &rehash, (gptr*) &rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
@@ -484,8 +490,12 @@ static struct my_option my_long_options[] =
   {"compress", 'C', "Use compression in server/client protocol.",
    (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
    0, 0, 0},
-#ifndef DBUG_OFF
-  {"debug", '#', "Output debug log.", (gptr*) &default_dbug_option,
+#ifdef DBUG_OFF
+  {"debug", '#', "This is a non-debug version. Catch this and exit",
+   (gptr*) &default_dbug_option,
+   (gptr*) &default_dbug_option, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#else
+  {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
    (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"database", 'D', "Database to use.", (gptr*) ¤t_db,
@@ -608,19 +618,27 @@ static struct my_option my_long_options[] =
    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
-  {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (gptr*) &opt_connect_timeout,
+  {"connect_timeout", OPT_CONNECT_TIMEOUT,
+   "Number of seconds before connection timeout.",
+   (gptr*) &opt_connect_timeout,
    (gptr*) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0,
    0, 1},
-  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
+  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
+   "Max packet length to send to, or receive from server",
    (gptr*) &max_allowed_packet, (gptr*) &max_allowed_packet, 0, GET_ULONG,
    REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L,
    MALLOC_OVERHEAD, 1024, 0},
-  {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
+  {"net_buffer_length", OPT_NET_BUFFER_LENGTH,
+   "Buffer for TCP/IP and socket communication",
    (gptr*) &net_buffer_length, (gptr*) &net_buffer_length, 0, GET_ULONG,
    REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0},
-  {"select_limit", OPT_SELECT_LIMIT, "", (gptr*) &select_limit,
+  {"select_limit", OPT_SELECT_LIMIT,
+   "Automatic limit for SELECT when using --safe-updates",
+   (gptr*) &select_limit,
    (gptr*) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ~0L, 0, 1, 0},
-  {"max_join_size", OPT_MAX_JOIN_SIZE, "", (gptr*) &max_join_size,
+  {"max_join_size", OPT_MAX_JOIN_SIZE,
+   "Automatic limit for rows in a join when using --safe-updates",
+   (gptr*) &max_join_size,
    (gptr*) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ~0L, 0, 1,
    0},
   {"secure-auth", OPT_SECURE_AUTH, "Refuse client connecting to server if it"
@@ -689,11 +707,16 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
     else
     {
       opt_nopager= 0;
-      if (argument)
+      if (argument && strlen(argument))
+      {
+	default_pager_set= 1;
 	strmov(pager, argument);
-      else
+	strmov(default_pager, pager);
+      }
+      else if (default_pager_set)
 	strmov(pager, default_pager);
-      strmov(default_pager, pager);
+      else
+	opt_nopager= 1;
     }
     break;
   case OPT_NOPAGER:
@@ -814,6 +837,7 @@ static int get_options(int argc, char **argv)
     strmov(default_pager, "stdout");
     strmov(pager, "stdout");
     opt_nopager= 1;
+    default_pager_set= 0;
     opt_outfile= 0;
     opt_reconnect= 0;
     connect_flag= 0; /* Not in interactive mode */
@@ -2163,12 +2187,17 @@ com_pager(String *buffer, char *line __attribute__((unused)))
 
   if (status.batch)
     return 0;
-  /* Skip space from file name */
-  while (my_isspace(charset_info,*line))
+  /* Skip spaces in front of the pager command */
+  while (my_isspace(charset_info, *line))
     line++;
-  if (!(param= strchr(line, ' '))) // if pager was not given, use the default
+  /* Skip the pager command */
+  param= strchr(line, ' ');
+  /* Skip the spaces between the command and the argument */
+  while (param && my_isspace(charset_info, *param))
+    param++;
+  if (!param || !strlen(param)) // if pager was not given, use the default
   {
-    if (!default_pager[0])
+    if (!default_pager_set)
     {
       tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
       opt_nopager=1;
@@ -2180,9 +2209,7 @@ com_pager(String *buffer, char *line __attribute__((unused)))
   }
   else
   {
-    while (my_isspace(charset_info,*param))
-      param++;
-    end=strmake(pager_name, param, sizeof(pager_name)-1);
+    end= strmake(pager_name, param, sizeof(pager_name)-1);
     while (end > pager_name && (my_isspace(charset_info,end[-1]) || 
                                 my_iscntrl(charset_info,end[-1])))
       end--;
@@ -2191,7 +2218,7 @@ com_pager(String *buffer, char *line __attribute__((unused)))
     strmov(default_pager, pager_name);
   }
   opt_nopager=0;
-  tee_fprintf(stdout, "PAGER set to %s\n", pager);
+  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
   return 0;
 }
 
@@ -2202,6 +2229,7 @@ com_nopager(String *buffer __attribute__((unused)),
 {
   strmov(pager, "stdout");
   opt_nopager=1;
+  PAGER= stdout;
   tee_fprintf(stdout, "PAGER set to stdout\n");
   return 0;
 }
diff --git a/include/my_getopt.h b/include/my_getopt.h
index 148238f8d1b..5f4025efa0e 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -17,11 +17,12 @@
 C_MODE_START
 
 enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG,
-			GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC
+			GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC,
+			GET_DISABLED
                       };
 
-#define GET_ASK_ADDR	128
-#define GET_TYPE_MASK	127
+#define GET_ASK_ADDR	 128
+#define GET_TYPE_MASK	 127
 
 enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
 
diff --git a/include/mysys_err.h b/include/mysys_err.h
index 0ee89e91ee4..230be5f4720 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -68,6 +68,7 @@ extern const char * NEAR globerrs[];	/* my_error_messages is here */
 #define EXIT_UNKNOWN_SUFFIX		9
 #define EXIT_NO_PTR_TO_VARIABLE		10
 #define EXIT_CANNOT_CONNECT_TO_SERVICE	11
+#define EXIT_OPTION_DISABLED            12
 
 
 #ifdef	__cplusplus
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 76f8f6bf852..b278eaa36e1 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -285,6 +285,19 @@ int handle_options(int *argc, char ***argv,
 	    return EXIT_AMBIGUOUS_OPTION;
 	  }
 	}
+	if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
+	{
+	  if (my_getopt_print_errors)
+	    fprintf(stderr,
+		    "%s: %s: Option '%s' used, but is disabled\n", my_progname,
+		    option_is_loose ? "WARNING" : "ERROR", opt_str);
+	  if (option_is_loose)
+	  {
+	    (*argc)--;
+	    continue;
+	  }
+	  return EXIT_OPTION_DISABLED;
+	}
 	if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
 	{
 	  if (my_getopt_print_errors)
@@ -358,6 +371,14 @@ int handle_options(int *argc, char ***argv,
 	    {
 	      /* Option recognized. Find next what to do with it */
 	      opt_found= 1;
+	      if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
+	      {
+		if (my_getopt_print_errors)
+		  fprintf(stderr,
+			  "%s: ERROR: Option '-%c' used, but is disabled\n",
+			  my_progname, optp->id);
+		return EXIT_OPTION_DISABLED;
+	      }
 	      if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
 		  optp->arg_type == NO_ARG)
 	      {
@@ -550,7 +571,7 @@ static int findopt(char *optpat, uint length,
 		   const struct my_option **opt_res,
 		   char **ffname)
 {
-  int count;
+  uint count;
   struct my_option *opt= (struct my_option *) *opt_res;
 
   for (count= 0; opt->name; opt++)
@@ -562,7 +583,8 @@ static int findopt(char *optpat, uint length,
 	*ffname= (char *) opt->name;	/* We only need to know one prev */
       if (!opt->name[length])		/* Exact match */
 	return 1;
-      count++;
+      if (!count || strcmp(*ffname, opt->name)) /* Don't count synonyms */
+	count++;
     }
   }
   return count;
@@ -882,7 +904,8 @@ void my_print_variables(const struct my_option *options)
 	longlong2str(*((ulonglong*) value), buff, 10);
 	printf("%s\n", buff);
 	break;
-      default: /* dummy default to avoid compiler warnings */
+      default:
+	printf("(Disabled)\n");
 	break;
       }
     }

From c6863b04e0dc05114dcd3b63361e1f114612b121 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 14:02:51 +0400
Subject: [PATCH 056/157] item_strfunc.cc:   Comment typo fix   ,

sql/item_strfunc.cc:
  Comment typo fix
  ,
---
 sql/item_strfunc.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 528345beb77..45b2b7455f9 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -979,7 +979,7 @@ String *Item_func_right::val_str(String *str)
     As far "res" contains at least "length" bytes
     (according to the above condition and return),
     the below statement is safe. res->numchars() can 
-    never return a value less than "length".
+    never return a value more than "length".
   */
   uint start=res->numchars()-(uint) length;
   start=res->charpos(start);

From cbc748899635d8a564fc2c3cce9eee04edc1cd73 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 11:52:25 +0100
Subject: [PATCH 057/157] bugs #2280, #2281 - show create table should always
 return a valid sql statement

---
 sql/sql_show.cc | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 52f7e6cb9ed..ab761ad761d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -997,6 +997,19 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
   DBUG_RETURN(0);
 }
 
+/* possible TODO: call find_keyword() from sql_lex.cc here */
+static bool require_quotes(const char *name, uint length)
+{
+  uint i, d, c;
+  for (i=0; iident_map[c])
+      return 1;
+  }
+  return 0;
+}
 
 void
 append_identifier(THD *thd, String *packet, const char *name, uint length)
@@ -1007,7 +1020,8 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
   else
     qtype= '`';
 
-  if (thd->options & OPTION_QUOTE_SHOW_CREATE)
+  if ((thd->options & OPTION_QUOTE_SHOW_CREATE) ||
+      require_quotes(name, length))
   {
     packet->append(&qtype, 1);
     packet->append(name, length, system_charset_info);

From fd7d543adc6ee48e6dd79e6da6f3656b5dc13501 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 12:29:30 +0100
Subject: [PATCH 058/157] show create tests

---
 mysql-test/r/show_check.result | 25 +++++++++++++++++++++----
 mysql-test/t/show_check.test   |  9 +++++++--
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index f39fa3e7576..290f916ae72 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -88,20 +88,37 @@ drop table t2;
 create table t1 (
 test_set set( 'val1', 'val2', 'val3' ) not null default '',
 name char(20) default 'O''Brien' comment 'O''Brien as default',
-c int not null comment 'int column'
-  ) comment = 'it\'s a table' ;
-show create table t1 ;
+c int not null comment 'int column',
+`c-b` int comment 'name with a space',
+`space ` int comment 'name with a space',
+) comment = 'it\'s a table' ;
+show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `test_set` set('val1','val2','val3') NOT NULL default '',
   `name` char(20) default 'O''Brien' COMMENT 'O''Brien as default',
-  `c` int(11) NOT NULL default '0' COMMENT 'int column'
+  `c` int(11) NOT NULL default '0' COMMENT 'int column',
+  `c-b` int(11) default NULL COMMENT 'name with a space',
+  `space ` int(11) default NULL COMMENT 'name with a space'
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
+set sql_quote_show_create=0;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE t1 (
+  test_set set('val1','val2','val3') NOT NULL default '',
+  name char(20) default 'O''Brien' COMMENT 'O''Brien as default',
+  c int(11) NOT NULL default '0' COMMENT 'int column',
+  `c-b` int(11) default NULL COMMENT 'name with a space',
+  `space ` int(11) default NULL COMMENT 'name with a space'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='it''s a table'
+set sql_quote_show_create=1;
 show full columns from t1;
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
 test_set	set('val1','val2','val3')	latin1_swedish_ci					select,insert,update,references	
 name	char(20)	latin1_swedish_ci	YES		O'Brien		select,insert,update,references	O'Brien as default
 c	int(11)	NULL			0		select,insert,update,references	int column
+c-b	int(11)	NULL	YES		NULL		select,insert,update,references	name with a space
+space 	int(11)	NULL	YES		NULL		select,insert,update,references	name with a space
 drop table t1;
 create table t1 (a int not null, unique aa (a));
 show create table t1;
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 4ab39e3ccbc..d262f02c978 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -53,9 +53,14 @@ drop table t2;
 create table t1 (
   test_set set( 'val1', 'val2', 'val3' ) not null default '',
   name char(20) default 'O''Brien' comment 'O''Brien as default',
-  c int not null comment 'int column'
+  c int not null comment 'int column',
+  `c-b` int comment 'name with a space',
+  `space ` int comment 'name with a space',
   ) comment = 'it\'s a table' ;
-show create table t1 ;
+show create table t1;
+set sql_quote_show_create=0;
+show create table t1;
+set sql_quote_show_create=1;
 show full columns from t1;
 drop table t1;
 

From 13cf5e6b0ae32d25d4f6d13928ce5766ba0e2f50 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 16:01:55 +0400
Subject: [PATCH 059/157] fix for the 2361 bug: ALTER TABLE ... DROP PRIMARY
 KEY drops a non-primary key "PRIMARY" has been replaced by primary_key_name.

sql/mysql_priv.h:
  "PRIMARY" replaced by primary_key_name.
sql/sql_help.cc:
  "PRIMARY" replaced by primary_key_name.
sql/sql_select.cc:
  "PRIMARY" replaced by primary_key_name.
sql/sql_show.cc:
  "PRIMARY" replaced by primary_key_name.
sql/sql_table.cc:
  fix for the 2361 bug: ALTER TABLE ... DROP PRIMARY KEY drops a non-primary key
  "PRIMARY" replaced by primary_key_name.
sql/table.cc:
  "PRIMARY" replaced by primary_key_name.
---
 sql/mysql_priv.h  | 1 +
 sql/sql_help.cc   | 4 ++--
 sql/sql_select.cc | 8 ++++----
 sql/sql_show.cc   | 2 +-
 sql/sql_table.cc  | 8 ++++----
 sql/table.cc      | 4 ++--
 6 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 15a99385285..a277e06301b 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -38,6 +38,7 @@ typedef ulong key_part_map;           /* Used for finding key parts */
 /* useful constants */
 extern const key_map key_map_empty;
 extern const key_map key_map_full;
+extern const char *primary_key_name;
 
 #include "mysql_com.h"
 #include 
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index c40133c04a8..d5516fe3337 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -274,9 +274,9 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
 
   DBUG_ENTER("get_topics_for_keyword");
   
-  if ((iindex_topic= find_type((char*) "PRIMARY",
+  if ((iindex_topic= find_type((char*) primary_key_name,
 			       &topics->keynames, 1+2)-1)<0 ||
-      (iindex_relations= find_type((char*) "PRIMARY",
+      (iindex_relations= find_type((char*) primary_key_name,
 				   &relations->keynames, 1+2)-1)<0)
   {
     send_error(thd,ER_CORRUPT_HELP_DB);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a1f6abfd53a..1b03a70c43d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9130,16 +9130,16 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
   {
     res= mysql_explain_select(thd, sl,
 			      (((&thd->lex->select_lex)==sl)?
-			       ((thd->lex->all_selects_list != sl)?"PRIMARY":
-				"SIMPLE"):
+			       ((thd->lex->all_selects_list != sl) ? 
+				primary_key_name : "SIMPLE"):
 			       ((sl == first)?
 				((sl->linkage == DERIVED_TABLE_TYPE) ?
 				 "DERIVED":
-				((sl->uncacheable & UNCACHEABLE_DEPENDENT)?
+				((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
 				 "DEPENDENT SUBQUERY":
 				 (sl->uncacheable?"UNCACHEABLE SUBQUERY":
 				   "SUBQUERY"))):
-				((sl->uncacheable & UNCACHEABLE_DEPENDENT)?
+				((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
 				 "DEPENDENT UNION":
 				 sl->uncacheable?"UNCACHEABLE UNION":
 				  "UNION"))),
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 52f7e6cb9ed..984d57fc354 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1167,7 +1167,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
     bool found_primary=0;
     packet->append(",\n  ", 4);
 
-    if (i == primary_key && !strcmp(key_info->name,"PRIMARY"))
+    if (i == primary_key && !strcmp(key_info->name, primary_key_name))
     {
       found_primary=1;
       packet->append("PRIMARY ", 8);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index be42de34899..413fb77d929 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -29,7 +29,7 @@
 #include 
 #endif
 
-static const char *primary_key_name="PRIMARY";
+const char *primary_key_name= "PRIMARY";
 
 static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
 static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
@@ -2244,8 +2244,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   {
     char *key_name= key_info->name;
 
-    if (drop_primary && !my_strcasecmp(system_charset_info, key_name,
-                                       "PRIMARY"))
+    if (drop_primary && (key_info-> flags & HA_NOSAME) &&
+	!my_strcasecmp(system_charset_info, key_name, primary_key_name))
     {
       drop_primary= 0;
       continue;
@@ -2305,7 +2305,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
       key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
                                  (key_info->flags & HA_NOSAME ?
 				 (!my_strcasecmp(system_charset_info,
-                                                 key_name, "PRIMARY") ?
+                                                 key_name, primary_key_name) ?
 				  Key::PRIMARY  : Key::UNIQUE) :
 				  (key_info->flags & HA_FULLTEXT ?
 				   Key::FULLTEXT : Key::MULTIPLE)),
diff --git a/sql/table.cc b/sql/table.cc
index 912c133e571..1127349db20 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -481,8 +481,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
   /* Fix key->name and key_part->field */
   if (key_parts)
   {
-    uint primary_key=(uint) (find_type((char*) "PRIMARY",&outparam->keynames,
-				       3)-1);
+    uint primary_key=(uint) (find_type((char*) primary_key_name,
+				       &outparam->keynames, 3) - 1);
     uint ha_option=outparam->file->table_flags();
     keyinfo=outparam->key_info;
     key_part=keyinfo->key_part;

From 6eaa5c3a66adc7cbe152a8791b3ad560c3a936f5 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 15:15:42 +0200
Subject: [PATCH 060/157] assigned correct lex->current_select for derived
 tables (BUG#2349) moved LIMIT initialialization, because it is need only for
 single select derived table

mysql-test/r/derived.result:
  test suite for BUG#2349
mysql-test/t/derived.test:
  test suite for BUG#2349
sql/sql_derived.cc:
  assigned correct lex->current_select (BUG#2349)
  moved LIMIT initialialization, because it is need only for single select
---
 mysql-test/r/derived.result | 28 ++++++++++++++++++++++++++++
 mysql-test/t/derived.test   | 26 ++++++++++++++++++++++++++
 sql/sql_derived.cc          | 19 +++++++++++--------
 3 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index bb268cd1094..9b5aa9123a4 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -245,3 +245,31 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	
 3	UNION	t1	ALL	NULL	NULL	NULL	NULL	2	
 drop table t1;
+CREATE TABLE t1 (
+OBJECTID int(11) NOT NULL default '0',
+SORTORDER int(11) NOT NULL auto_increment,
+KEY t1_SortIndex (SORTORDER),
+KEY t1_IdIndex (OBJECTID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+Warnings:
+Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+CREATE TABLE t2 (
+ID int(11) default NULL,
+PARID int(11) default NULL,
+UNIQUE KEY t2_ID_IDX (ID),
+KEY t2_PARID_IDX (PARID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+Warnings:
+Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+INSERT INTO t2 VALUES (1000,0),(1001,0),(1002,0),(1003,0),(1008,1),(1009,1),(1010,1),(1011,1),(1016,2);
+CREATE TABLE t3 (
+ID int(11) default NULL,
+DATA decimal(10,2) default NULL,
+UNIQUE KEY t3_ID_IDX (ID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+Warnings:
+Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
+select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
+497	ID	NULL
+drop table t1, t2, t3;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index caf673d95c1..bb61dab6d74 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -138,3 +138,29 @@ insert into t1 values (1),(2);
 select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
 explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
 drop table t1;
+
+
+#
+# correct lex->current_select
+#
+CREATE TABLE t1 (
+  OBJECTID int(11) NOT NULL default '0',
+  SORTORDER int(11) NOT NULL auto_increment,
+  KEY t1_SortIndex (SORTORDER),
+  KEY t1_IdIndex (OBJECTID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+CREATE TABLE t2 (
+  ID int(11) default NULL,
+  PARID int(11) default NULL,
+  UNIQUE KEY t2_ID_IDX (ID),
+  KEY t2_PARID_IDX (PARID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t2 VALUES (1000,0),(1001,0),(1002,0),(1003,0),(1008,1),(1009,1),(1010,1),(1011,1),(1016,2);
+CREATE TABLE t3 (
+  ID int(11) default NULL,
+  DATA decimal(10,2) default NULL,
+  UNIQUE KEY t3_ID_IDX (ID)
+) TYPE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
+select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
+drop table t1, t2, t3;
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index e8f1c5d87de..8c0fcb7f4c3 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -146,17 +146,19 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
     }
     derived_result->set_table(table);
 
-    unit->offset_limit_cnt= first_select->offset_limit;
-    unit->select_limit_cnt= first_select->select_limit+
-      first_select->offset_limit;
-    if (unit->select_limit_cnt < first_select->select_limit)
-      unit->select_limit_cnt= HA_POS_ERROR;
-    if (unit->select_limit_cnt == HA_POS_ERROR)
-      first_select->options&= ~OPTION_FOUND_ROWS;
-
     if (is_union)
       res= mysql_union(thd, lex, derived_result, unit);
     else
+    {
+      unit->offset_limit_cnt= first_select->offset_limit;
+      unit->select_limit_cnt= first_select->select_limit+
+	first_select->offset_limit;
+      if (unit->select_limit_cnt < first_select->select_limit)
+	unit->select_limit_cnt= HA_POS_ERROR;
+      if (unit->select_limit_cnt == HA_POS_ERROR)
+	first_select->options&= ~OPTION_FOUND_ROWS;
+
+      lex->current_select= first_select;
       res= mysql_select(thd, &first_select->ref_pointer_array, 
 			(TABLE_LIST*) first_select->table_list.first,
 			first_select->with_wild,
@@ -169,6 +171,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
 			(first_select->options | thd->options |
 			 SELECT_NO_UNLOCK),
 			derived_result, unit, first_select);
+    }
 
     if (!res)
     {

From 502a9efbcf4e4d9a4db314fcf305e8cedabd18c4 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 17:26:30 +0400
Subject: [PATCH 061/157] item_strfunc.cc:   We don't need to copy if start is
 0, we can return the original value.

sql/item_strfunc.cc:
  We don't need to copy if start is 0, we can return the original value.
---
 sql/item_strfunc.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 45b2b7455f9..f810afa3cfa 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -982,6 +982,8 @@ String *Item_func_right::val_str(String *str)
     never return a value more than "length".
   */
   uint start=res->numchars()-(uint) length;
+  if (!start)
+    return res;
   start=res->charpos(start);
   tmp_value.set(*res,start,res->length()-start);
   return &tmp_value;

From e9322b891adb41b78d907072776bdd365e6fd54c Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 16:42:08 +0100
Subject: [PATCH 062/157] compilation error fixed

---
 client/mysql.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index 46e15ebbbd3..59872a83506 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -492,8 +492,7 @@ static struct my_option my_long_options[] =
    0, 0, 0},
 #ifdef DBUG_OFF
   {"debug", '#', "This is a non-debug version. Catch this and exit",
-   (gptr*) &default_dbug_option,
-   (gptr*) &default_dbug_option, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+   0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
 #else
   {"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
    (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},

From 4d53f9961c54ae4e186050a0aa8272a216b7e877 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 14 Jan 2004 17:48:38 +0200
Subject: [PATCH 063/157] Fixed a non-debug version compilation error and
 warning.

---
 client/mysql.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index 46e15ebbbd3..010233b5b6e 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -174,9 +174,7 @@ static CHARSET_INFO *charset_info= &my_charset_latin1;
 			   
 #include "sslopt-vars.h"
 
-#ifndef DBUG_OFF
 const char *default_dbug_option="d:t:o,/tmp/mysql.trace";
-#endif
 
 void tee_fprintf(FILE *file, const char *fmt, ...);
 void tee_fputs(const char *s, FILE *file);
@@ -1559,7 +1557,7 @@ static int com_server_help(String *buffer __attribute__((unused)),
       init_pager();
       char last_char;
       
-      int num_name, num_cat;
+      int num_name= 0, num_cat= 0;
       LINT_INIT(num_name);
       LINT_INIT(num_cat);
 

From f9bec44af107fec1ececea47a76f085b5af87464 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 04:00:21 +0200
Subject: [PATCH 064/157] Added handling for ; comment character as there was
 for #. Bug#2080

---
 mysys/default.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mysys/default.c b/mysys/default.c
index 3a751eb4e29..d9099a9e505 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -461,7 +461,7 @@ static char *remove_end_comment(char *ptr)
       else if (quote == *ptr)
 	quote= 0;
     }
-    if (!quote && *ptr == '#') /* We are not inside a comment */
+    if (!quote && (*ptr == '#' || *ptr == ';')) // We are not inside a comment
     {
       *ptr= 0;
       return ptr;

From 3ad098661aa69f7f6be36cd0c54ee44ee21cbe74 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 04:26:57 +0200
Subject: [PATCH 065/157] Fixed Bug#2281, --quote is now enabled by default.
 Can be disabled with --disable-quote

Added --compatible=ansi mode.

Fixed a non-reported bug in compatible mode; there was a check for
/*!41000 */ at this part of the code, while it obviously should have been
/*!40100 */. So the mysqldump compatiple mode made for 4.0.1 will not work
until 4.10 or later server is released :P Fixed into 4.0.2.


client/mysqldump.c:
  Fixed Bug#2281, --quote is now enabled by default. Can be disabled
  with --disable-quote

  Added --compatible=ansi mode.

  Changed sapdb into maxdb, as this change has been made to server too.

  Fixed a non-reported bug in compatible mode; there was a check for
  /*!41000 */ at this part of the code, while it obviously should have been
  /*!40100 */. So the mysqldump compatiple mode made for 4.1.0 will not work
  until 4.10.0 or later server is released :P Fixed into 4.1.2.
---
 client/mysqldump.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/client/mysqldump.c b/client/mysqldump.c
index 018cd43ce87..921ffbaab5b 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -37,7 +37,7 @@
 ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
 */
 
-#define DUMP_VERSION "10.4"
+#define DUMP_VERSION "10.5"
 
 #include 
 #include 
@@ -107,7 +107,8 @@ static CHARSET_INFO *charset_info= &my_charset_latin1;
 const char *compatible_mode_names[]=
 {
   "MYSQL323", "MYSQL40", "POSTGRESQL", "ORACLE", "MSSQL", "DB2",
-  "SAPDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
+  "MAXDB", "NO_KEY_OPTIONS", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS",
+  "ANSI",
   NullS
 };
 TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
@@ -136,7 +137,7 @@ static struct my_option my_long_options[] =
    "Directory where character sets are.", (gptr*) &charsets_dir,
    (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"compatible", OPT_COMPATIBLE,
-   "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: mysql323, mysql40, postgresql, oracle, mssql, db2, sapdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.",
+   "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.",
    (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag,
@@ -239,7 +240,7 @@ static struct my_option my_long_options[] =
   {"quick", 'q', "Don't buffer query, dump directly to stdout.",
    (gptr*) &quick, (gptr*) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
   {"quote-names",'Q', "Quote table and column names with backticks (`).",
-   (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+   (gptr*) &opt_quoted, (gptr*) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
    0, 0},
   {"result-file", 'r',
    "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).",
@@ -830,7 +831,7 @@ static uint getTableStructure(char *table, char* db)
 	char *end;
 	uint i;
 
-	sprintf(buff, "/*!41000 SET @@sql_mode=\"");
+	sprintf(buff, "/*!40100 SET @@sql_mode=\"");
 	end= strend(buff);
 	for (i= 0; opt_compatible_mode; opt_compatible_mode>>= 1, i++)
 	{

From 484cf319c541e3fe49b667dff41099df30a0f947 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 06:48:31 +0200
Subject: [PATCH 066/157] Fixed Bug#2123, mysqld segmentation faulted when it
 tried to open a file that already existed. The problem was that
 end_io_cache() was called even if init_io_cache() was not. This affected both
 OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was
 freed, sometimes mysqld core dumped.

Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.

On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.

After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.

Regards,
Jani


mysys/mf_iocache.c:
  Fixed a bug in comment.
---
 mysys/mf_iocache.c |  4 +--
 sql/sql_class.cc   | 77 +++++++++++++++++++---------------------------
 2 files changed, 34 insertions(+), 47 deletions(-)

diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index b5c80d9482f..1dd3108e151 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1175,8 +1175,8 @@ int _flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
     info		IO_CACHE Handle to free
 
   NOTES
-    It's currently safe to call this if one has called io_cache_init()
-    on the 'info' object, even if io_cache_init() failed.
+    It's currently safe to call this if one has called init_io_cache()
+    on the 'info' object, even if init_io_cache() failed.
     This function is also safe to call twice with the same handle.
 
   RETURN
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 89b812eb205..696744953dc 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -695,39 +695,53 @@ select_export::~select_export()
   thd->sent_row_count=row_count;
 }
 
-int
-select_export::prepare(List &list, SELECT_LEX_UNIT *u)
+
+static int create_file(THD *thd, char *path, sql_exchange *exchange,
+		       File *file, IO_CACHE *cache)
 {
-  char path[FN_REFLEN];
-  uint option=4;
-  bool blob_flag=0;
-  unit= u;
+  uint option= 4;
+
 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
-  option|=1;					// Force use of db directory
+  option|= 1;					// Force use of db directory
 #endif
-  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
-    strmake(path,exchange->file_name,FN_REFLEN-1);
-  (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "",
+  (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "",
 		   option);
-  if (!access(path,F_OK))
+  if (!access(path, F_OK))
   {
     my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
     return 1;
   }
   /* Create the file world readable */
-  if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
+  if ((*file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
     return 1;
 #ifdef HAVE_FCHMOD
-  (void) fchmod(file,0666);			// Because of umask()
+  (void) fchmod(*file, 0666);			// Because of umask()
 #else
-  (void) chmod(path,0666);
+  (void) chmod(path, 0666);
 #endif
-  if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME)))
+  if (init_io_cache(cache, *file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
   {
-    my_close(file,MYF(0));
-    file= -1;
+    my_close(*file, MYF(0));
+    my_delete(path, MYF(0));  // Delete file on error, it was just created 
+    *file= -1;
+    end_io_cache(cache);
     return 1;
   }
+  return 0;
+}
+
+
+int
+select_export::prepare(List &list, SELECT_LEX_UNIT *u)
+{
+  char path[FN_REFLEN];
+  bool blob_flag=0;
+  unit= u;
+  if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
+    strmake(path,exchange->file_name,FN_REFLEN-1);
+
+  if (create_file(thd, path, exchange, &file, &cache))
+    return 1;
   /* Check if there is any blobs in data */
   {
     List_iterator_fast li(list);
@@ -901,7 +915,6 @@ err:
 void select_export::send_error(uint errcode, const char *err)
 {
   ::send_error(thd,errcode,err);
-  (void) end_io_cache(&cache);
   (void) my_close(file,MYF(0));
   file= -1;
 }
@@ -938,33 +951,9 @@ int
 select_dump::prepare(List &list __attribute__((unused)),
 		     SELECT_LEX_UNIT *u)
 {
-  uint option=4;
   unit= u;
-#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
-  option|=1;					// Force use of db directory
-#endif
-  (void) fn_format(path,exchange->file_name, thd->db ? thd->db : "", "",
-		   option);
-  if (!access(path,F_OK))
-  {
-    my_error(ER_FILE_EXISTS_ERROR,MYF(0),exchange->file_name);
+  if (create_file(thd, path, exchange, &file, &cache))
     return 1;
-  }
-  /* Create the file world readable */
-  if ((file=my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
-    return 1;
-#ifdef HAVE_FCHMOD
-  (void) fchmod(file,0666);			// Because of umask()
-#else
-  (void) chmod(path,0666);
-#endif
-  if (init_io_cache(&cache,file,0L,WRITE_CACHE,0L,1,MYF(MY_WME)))
-  {
-    my_close(file,MYF(0));
-    my_delete(path,MYF(0));
-    file= -1;
-    return 1;
-  }
   return 0;
 }
 
@@ -1011,9 +1000,7 @@ err:
 void select_dump::send_error(uint errcode,const char *err)
 {
   ::send_error(thd,errcode,err);
-  (void) end_io_cache(&cache);
   (void) my_close(file,MYF(0));
-  (void) my_delete(path,MYF(0));		// Delete file on error
   file= -1;
 }
 

From 4239d4b24f281f9f5c2d21a622b616ac711f9f2e Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 12:12:55 +0400
Subject: [PATCH 067/157] item_strfunc.cc:   Unnesessary copying was fixed

sql/item_strfunc.cc:
  Unnesessary copying was fixed
---
 sql/item_strfunc.cc | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index f810afa3cfa..3b67fd371a4 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -975,16 +975,10 @@ String *Item_func_right::val_str(String *str)
   if (res->length() <= (uint) length)
     return res; /* purecov: inspected */
 
-  /*
-    As far "res" contains at least "length" bytes
-    (according to the above condition and return),
-    the below statement is safe. res->numchars() can 
-    never return a value more than "length".
-  */
-  uint start=res->numchars()-(uint) length;
-  if (!start)
+  uint start=res->numchars();
+  if (start <= (uint) length)
     return res;
-  start=res->charpos(start);
+  start=res->charpos(start - (uint) length);
   tmp_value.set(*res,start,res->length()-start);
   return &tmp_value;
 }

From fd427c063da5d5b3843120ad76f02cfd823c8d22 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 13:27:20 +0400
Subject: [PATCH 068/157] Fic for Bug 2367: INSERT() behaviour is different for
 different charsets.

---
 mysql-test/r/ctype_ucs.result  | 6 ++++++
 mysql-test/r/ctype_utf8.result | 6 ++++++
 mysql-test/t/ctype_ucs.test    | 7 ++++++-
 mysql-test/t/ctype_utf8.test   | 6 ++++++
 strings/ctype-mb.c             | 2 +-
 5 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 2f6dc0c23ca..58761526150 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -173,6 +173,12 @@ SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630061005F';
 word
 cat
 DROP TABLE t1;
+select insert(_ucs2 0x006100620063,10,2,_ucs2 0x006400650066);
+insert(_ucs2 0x006100620063,10,2,_ucs2 0x006400650066)
+abc
+select insert(_ucs2 0x006100620063,1,2,_ucs2 0x006400650066);
+insert(_ucs2 0x006100620063,1,2,_ucs2 0x006400650066)
+defc
 SET NAMES latin1;
 CREATE TABLE t1 (
 word VARCHAR(64),
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 1aef43cd570..16c65619878 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -62,3 +62,9 @@ select 'A' like 'a' collate utf8_bin;
 select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%');
 _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%')
 1
+select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
+insert('txs',2,1,'hi')	insert('is ',4,0,'a')	insert('txxxxt',2,4,'es')
+this	is a	test
+select insert("aa",100,1,"b"),insert("aa",1,3,"b");
+insert("aa",100,1,"b")	insert("aa",1,3,"b")
+aa	b
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 90b423cd1e0..7eec58563b3 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -93,6 +93,12 @@ SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630025';
 SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630061005F';
 DROP TABLE t1;
 
+#
+# Check that INSERT works fine. 
+# This invokes charpos() function.
+select insert(_ucs2 0x006100620063,10,2,_ucs2 0x006400650066);
+select insert(_ucs2 0x006100620063,1,2,_ucs2 0x006400650066);
+
 ######################################################
 
 #
@@ -191,4 +197,3 @@ DROP TABLE t1;
 # END OF Bug 1264 test
 #
 ########################################################
-
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 54d934b66db..5c924e82729 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -35,3 +35,9 @@ select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%');
 #
 #select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD091,_utf8 '%');
 #
+
+#
+# Bug 2367: INSERT() behaviour is different for different charsets.
+#
+select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
+select insert("aa",100,1,"b"),insert("aa",1,3,"b");
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 271c56b8a0a..b5e8c4598a0 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -271,7 +271,7 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
     b+= (mblen= my_ismbchar(cs,b,e)) ? mblen : 1;
     pos--;
   }
-  return b-b0;
+  return pos ? e+2-b0 : b-b0;
 }
 
 uint my_instr_mb(CHARSET_INFO *cs,

From 5dcab209c2ff1fa64b9aaffb38a622ac841dab39 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 15:58:06 +0400
Subject: [PATCH 069/157] field.cc:   http://bugs.mysql.com/bug.php?id=2218  
 updating utf-8 text field generate nonsense chars   Fix for the above bug.

sql/field.cc:
  http://bugs.mysql.com/bug.php?id=2218
  updating utf-8 text field generate nonsense chars
  Fix for the above bug.
---
 sql/field.cc | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sql/field.cc b/sql/field.cc
index a9029b893e3..5602231dd9b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4567,17 +4567,19 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
   }
   else
   {
+    bool was_conversion;
     char buff[80];
     String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
     /* Convert character set if nesessary */
-    if (use_conversion(cs, field_charset))
+    if ((was_conversion= use_conversion(cs, field_charset)))
     { 
       tmpstr.copy(from, length, cs, field_charset);
       from= tmpstr.ptr();
       length=  tmpstr.length();
     }
     Field_blob::store_length(length);
-    if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
+    if (was_conversion || table->copy_blobs || length <= MAX_FIELD_WIDTH)
     {						// Must make a copy
       if (from != value.ptr())			// For valgrind
       {

From d372811cb2375b33aa2e1302604ec1722f7a8e7d Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 16:10:44 +0400
Subject: [PATCH 070/157] I forgot to add the test in the previous commit :(
 Blame me!

---
 mysql-test/r/ctype_recoding.result |  6 ++++++
 mysql-test/t/ctype_recoding.test   | 10 ++++++++++
 2 files changed, 16 insertions(+)

diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 571c89ef467..7209c86bb31 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -19,6 +19,12 @@ SELECT HEX(a) FROM t2;
 HEX(a)
 D0BFD180D0BED0B1D0B0
 DROP TABLE t1, t2;
+CREATE TABLE t1 (description text character set cp1250 NOT NULL);
+INSERT INTO t1 (description) VALUES (_latin2'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde');
+SELECT description FROM t1;
+description
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde
+DROP TABLE t1;
 CREATE TABLE t1 (a TEXT CHARACTER SET cp1251) SELECT _koi8r'ΠΟΒΑ' AS a;
 CREATE TABLE t2 (a TEXT CHARACTER SET utf8);
 SHOW CREATE TABLE t1;
diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test
index 0b901009041..40349da8aa9 100644
--- a/mysql-test/t/ctype_recoding.test
+++ b/mysql-test/t/ctype_recoding.test
@@ -14,6 +14,15 @@ INSERT t2 SELECT * FROM t1;
 SELECT HEX(a) FROM t2;
 DROP TABLE t1, t2;
 
+
+#
+# Check that long strings conversion does not fail (bug#2218)
+#
+CREATE TABLE t1 (description text character set cp1250 NOT NULL);
+INSERT INTO t1 (description) VALUES (_latin2'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde');
+SELECT description FROM t1;
+DROP TABLE t1;
+
 # same with TEXT
 CREATE TABLE t1 (a TEXT CHARACTER SET cp1251) SELECT _koi8r'ΠΟΒΑ' AS a;
 CREATE TABLE t2 (a TEXT CHARACTER SET utf8);
@@ -62,3 +71,4 @@ SET NAMES koi8r;
 SELECT hex('ΤΕΣΤ');
 SET character_set_connection=cp1251;
 SELECT hex('ΤΕΣΤ');
+

From 758f4da316eb38b9c80ba34c27f86c04ebf7ad53 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 13:32:12 +0100
Subject: [PATCH 071/157]  - no C++ comments in .c files, please...

---
 mysys/default.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mysys/default.c b/mysys/default.c
index d9099a9e505..81e1fd06374 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -461,7 +461,8 @@ static char *remove_end_comment(char *ptr)
       else if (quote == *ptr)
 	quote= 0;
     }
-    if (!quote && (*ptr == '#' || *ptr == ';')) // We are not inside a comment
+    /* We are not inside a comment */
+    if (!quote && (*ptr == '#' || *ptr == ';'))
     {
       *ptr= 0;
       return ptr;

From 070647206ac2ce7c5d0c39eca8a4f89e636d2891 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 17:07:29 +0400
Subject: [PATCH 072/157] charset.c:   http://bugs.mysql.com/bug.php?id=2386  
 Index.xml file larger than 1024*16   Fix for the above bug.

mysys/charset.c:
  http://bugs.mysql.com/bug.php?id=2386
  Index.xml file larger than 1024*16
  Fix for the above bug.
---
 mysys/charset.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/mysys/charset.c b/mysys/charset.c
index b911f29627c..5e9e3c3fcaa 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -357,7 +357,7 @@ static int add_collation(CHARSET_INFO *cs)
 }
 
 
-#define MAX_BUF 1024*16
+#define MY_MAX_ALLOWED_BUF 1024*1024
 #define MY_CHARSET_INDEX "Index.xml"
 
 const char *charsets_dir= NULL;
@@ -369,16 +369,19 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
   char *buf;
   int  fd;
   uint len;
+  MY_STAT stat_info;
   
-  if (!(buf= (char *)my_malloc(MAX_BUF,myflags)))
-    return FALSE;
+  if (!my_stat(filename, &stat_info, MYF(MY_WME)) ||
+       ((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) ||
+       !(buf= (char *)my_malloc(len,myflags)))
+    return TRUE;
   
   if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
   {
     my_free(buf,myflags);
     return TRUE;
   }
-  len=read(fd,buf,MAX_BUF);
+  len=read(fd,buf,len);
   my_close(fd,myflags);
   
   if (my_parse_charset_xml(buf,len,add_collation))

From 235f1a4d60968bd9083780d13e249aad9fe7120c Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 15 Jan 2004 21:06:22 +0400
Subject: [PATCH 073/157] SCRUM: WL#1163 (Making spatial code optional) Pack of
 changes to do in sql/ code.

sql/field.cc:
  Spatial code #ifdef-ed
sql/field.h:
  Spatial code #ifdef-ed
sql/item_create.cc:
  Spatial code #ifdef-ed
sql/item_create.h:
  Spatial code #ifdef-ed
sql/item_geofunc.cc:
  Spatial code #ifdef-ed
sql/item_geofunc.h:
  Spatial code #ifdef-ed
  GEOM_NEW implementation
sql/lex.h:
  Code was significally modified to support optional group
  of functions
sql/lex_symbol.h:
  SYM_GROUP structure presented
sql/sql_table.cc:
  Spatial code #ifdef-ed
sql/sql_yacc.yy:
  Several modifications to make spatial code optional
sql/table.cc:
  Spatial code #ifdef-ed
sql/unireg.cc:
  Spatial code #ifdef-ed
---
 sql/field.cc        |   10 +-
 sql/field.h         |    7 +-
 sql/item_create.cc  |    2 +
 sql/item_create.h   |    4 +
 sql/item_geofunc.cc |    4 +
 sql/item_geofunc.h  |   11 +
 sql/lex.h           | 1283 ++++++++++++++++++++++---------------------
 sql/lex_symbol.h    |    6 +
 sql/sql_table.cc    |   29 +-
 sql/sql_yacc.yy     |  289 ++++++----
 sql/table.cc        |    5 +
 sql/unireg.cc       |    5 +
 12 files changed, 919 insertions(+), 736 deletions(-)

diff --git a/sql/field.cc b/sql/field.cc
index a9029b893e3..6d6218dc60a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4470,7 +4470,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
   :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
 	     null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
 	     table_arg, cs),
-   geom_flag(true), packlength(blob_pack_length)
+   packlength(blob_pack_length)
 {
   flags|= BLOB_FLAG;
   if (table)
@@ -4705,6 +4705,7 @@ void Field_blob::get_key_image(char *buff,uint length,
   uint32 blob_length= get_length(ptr);
   char *blob;
 
+#ifdef HAVE_SPATIAL
   if (type == itMBR)
   {
     if (!blob_length)
@@ -4721,6 +4722,7 @@ void Field_blob::get_key_image(char *buff,uint length,
     float8store(buff+24, mbr.ymax);
     return;
   }
+#endif /*HAVE_SPATIAL*/
 
   if ((uint32) length > blob_length)
   {
@@ -4930,6 +4932,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
   return (max_length > 255 ? 2 : 1)+max_length;
 }
 
+#ifdef HAVE_SPATIAL
 
 void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
 			       imagetype type)
@@ -5013,6 +5016,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
   return 0;
 }
 
+#endif /*HAVE_SPATIAL*/
 
 /****************************************************************************
 ** enum type.
@@ -5488,10 +5492,12 @@ Field *make_field(char *ptr, uint32 field_length,
 				      f_packtype(pack_flag),
 				      field_length);
 
+#ifdef HAVE_SPATIAL
     if (f_is_geom(pack_flag))
       return new Field_geom(ptr,null_pos,null_bit,
 			    unireg_check, field_name, table,
 			    pack_length, geom_type);
+#endif
     if (f_is_blob(pack_flag))
       return new Field_blob(ptr,null_pos,null_bit,
 			    unireg_check, field_name, table,
@@ -5651,10 +5657,12 @@ create_field::create_field(Field *old_field,Field *orig_field)
       def=new Item_string(pos,tmp.length(), charset);
     }
   }
+#ifdef HAVE_SPATIAL
   if (sql_type == FIELD_TYPE_GEOMETRY)
   {
     geom_type= ((Field_geom*)old_field)->geom_type;
   }
+#endif
 }
 
 
diff --git a/sql/field.h b/sql/field.h
index e3b4bf29fb8..9a12fd48e54 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -913,7 +913,6 @@ public:
 
 
 class Field_blob :public Field_str {
-  bool geom_flag;
 protected:
   uint packlength;
   String value;				// For temporaries
@@ -926,7 +925,7 @@ public:
 	     struct st_table *table_arg, CHARSET_INFO *cs)
     :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
 	       NONE, field_name_arg, table_arg, cs),
-    geom_flag(true), packlength(4)
+    packlength(4)
   {
     flags|= BLOB_FLAG;
   }
@@ -1001,7 +1000,7 @@ public:
   field_cast_enum field_cast_type() { return FIELD_CAST_BLOB; }
 };
 
-
+#ifdef HAVE_SPATIAL
 class Field_geom :public Field_blob {
 public:
   enum geometry_type geom_type;
@@ -1029,7 +1028,7 @@ public:
   void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
   field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; }
 };
-
+#endif /*HAVE_SPATIAL*/
 
 class Field_enum :public Field_str {
 protected:
diff --git a/sql/item_create.cc b/sql/item_create.cc
index f61b87ebe88..4ed8182305d 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -487,6 +487,7 @@ Item *create_func_quote(Item* a)
   return new Item_func_quote(a);
 }
 
+#ifdef HAVE_SPATIAL
 Item *create_func_as_wkt(Item *a)
 {
   return new Item_func_as_wkt(a);
@@ -646,6 +647,7 @@ Item *create_func_point(Item *a, Item *b)
 {
   return new Item_func_point(a, b);
 }
+#endif /*HAVE_SPATIAL*/
 
 Item *create_func_crc32(Item* a)
 {
diff --git a/sql/item_create.h b/sql/item_create.h
index 083868d87a6..773fdffbaf2 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -99,6 +99,8 @@ Item *create_func_is_free_lock(Item* a);
 Item *create_func_is_used_lock(Item* a);
 Item *create_func_quote(Item* a);
 
+#ifdef HAVE_SPATIAL
+
 Item *create_func_geometry_from_text(Item *a);
 Item *create_func_as_wkt(Item *a);
 Item *create_func_as_wkb(Item *a);
@@ -138,6 +140,8 @@ Item *create_func_numgeometries(Item *a);
 
 Item *create_func_point(Item *a, Item *b);
 
+#endif /*HAVE_SPATIAL*/
+
 Item *create_func_compress(Item *a);
 Item *create_func_uncompress(Item *a);
 Item *create_func_uncompressed_length(Item *a);
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 5ac87a25e67..671c4ed6de4 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -17,6 +17,8 @@
 
 /* This file defines all spatial functions */
 
+#ifdef HAVE_SPATIAL
+
 #ifdef __GNUC__
 #pragma implementation				// gcc: Class implementation
 #endif
@@ -651,3 +653,5 @@ longlong Item_func_srid::val_int()
   uint32 res= uint4korr(swkb->ptr());
   return (longlong) res;
 }
+
+#endif /*HAVE_SPATIAL*/
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index f6f00ed2bab..545052807ec 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -17,6 +17,8 @@
 
 /* This file defines all spatial functions */
 
+#ifdef HAVE_SPATIAL
+
 #ifdef __GNUC__
 #pragma interface			/* gcc class implementation */
 #endif
@@ -338,3 +340,12 @@ public:
   const char *func_name() const { return "srid"; }
   void fix_length_and_dec() { max_length= 10; }
 };
+
+#define GEOM_NEW(obj_constructor) new obj_constructor
+
+#else /*HAVE_SPATIAL*/
+
+#define GEOM_NEW(obj_constructor) NULL
+
+#endif
+
diff --git a/sql/lex.h b/sql/lex.h
index 6e69df6f96c..78a22fad153 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -20,13 +20,24 @@
 #include "lex_symbol.h"
 
 /* We don't want to include sql_yacc.h into gen_lex_hash */
+static SYM_GROUP sym_group_common= {"", ""};
+static SYM_GROUP sym_group_geom= {"Spatial extentions", "HAVE_SPATIAL"};
 
 #ifdef NO_YACC_SYMBOLS
-#define SYM(A) 0
-#define CREATE_FUNC(A) 0
+#define SYM_OR_NULL(A) 0
 #else
-#define SYM(A) A
-#define CREATE_FUNC(A) (void*) (A)
+#define SYM_OR_NULL(A) A
+#endif
+
+#define SYM(A) SYM_OR_NULL(A),0,0,&sym_group_common
+#define F_SYM(A) SYM_OR_NULL(A)
+
+#define CREATE_FUNC(A) (void *)(SYM_OR_NULL(A)), &sym_group_common
+
+#ifdef HAVE_GEOM
+#define CREATE_FUNC_GEOM(A) (void *)(SYM_OR_NULL(A)), &sym_group_geom
+#else
+#define CREATE_FUNC_GEOM(A) 0, &sym_group_geom
 #endif
 
 /*
@@ -36,639 +47,641 @@
 */
 
 static SYMBOL symbols[] = {
-  { "&&",		SYM(AND),0,0},
-  { "<",		SYM(LT),0,0},
-  { "<=",		SYM(LE),0,0},
-  { "<>",		SYM(NE),0,0},
-  { "!=",		SYM(NE),0,0},
-  { "=",		SYM(EQ),0,0},
-  { ">",		SYM(GT_SYM),0,0},
-  { ">=",		SYM(GE),0,0},
-  { "<<",		SYM(SHIFT_LEFT),0,0},
-  { ">>",		SYM(SHIFT_RIGHT),0,0},
-  { "<=>",		SYM(EQUAL_SYM),0,0},
-  { "ACTION",		SYM(ACTION),0,0},
-  { "ADD",		SYM(ADD),0,0},
-  { "AFTER",		SYM(AFTER_SYM),0,0},
-  { "AGAINST",          SYM(AGAINST),0,0},
-  { "AGGREGATE",	SYM(AGGREGATE_SYM),0,0},
-  { "ALL",		SYM(ALL),0,0},
-  { "ALTER",		SYM(ALTER),0,0},
-  { "ANALYZE",		SYM(ANALYZE_SYM),0,0},
-  { "AND",		SYM(AND),0,0},
-  { "ANY",              SYM(ANY_SYM),0,0},
-  { "AS",		SYM(AS),0,0},
-  { "ASC",		SYM(ASC),0,0},
-  { "ASCII",		SYM(ASCII_SYM),0,0},
-  { "AUTO_INCREMENT",	SYM(AUTO_INC),0,0},
-  { "AVG",		SYM(AVG_SYM),0,0},
-  { "AVG_ROW_LENGTH",	SYM(AVG_ROW_LENGTH),0,0},
-  { "BACKUP",	        SYM(BACKUP_SYM),0,0},
-  { "BDB",              SYM(BERKELEY_DB_SYM),0,0},
-  { "BEFORE",	        SYM(BEFORE_SYM),0,0},
-  { "BEGIN",	        SYM(BEGIN_SYM),0,0},
-  { "BERKELEYDB",       SYM(BERKELEY_DB_SYM),0,0},
-  { "BETWEEN",		SYM(BETWEEN_SYM),0,0},
-  { "BIGINT",		SYM(BIGINT),0,0},
-  { "BINARY",		SYM(BINARY),0,0},
-  { "BINLOG",		SYM(BINLOG_SYM),0,0},
-  { "BIT",		SYM(BIT_SYM),0,0},
-  { "BLOB",		SYM(BLOB_SYM),0,0},
-  { "BOOL",		SYM(BOOL_SYM),0,0},
-  { "BOOLEAN",		SYM(BOOLEAN_SYM),0,0},
-  { "BOTH",		SYM(BOTH),0,0},
-  { "BTREE",		SYM(BTREE_SYM),0,0},
-  { "BY",		SYM(BY),0,0},
-  { "BYTE",		SYM(BYTE_SYM), 0, 0},
-  { "CACHE",		SYM(CACHE_SYM),0,0},
-  { "CASCADE",		SYM(CASCADE),0,0},
-  { "CASE",		SYM(CASE_SYM),0,0},
-  { "CHANGE",		SYM(CHANGE),0,0},
-  { "CHANGED",		SYM(CHANGED),0,0},
-  { "CHAR",		SYM(CHAR_SYM),0,0},
-  { "CHARACTER",	SYM(CHAR_SYM),0,0},
-  { "CHARSET",		SYM(CHARSET),0,0},
-  { "CHECK",		SYM(CHECK_SYM),0,0},
-  { "CHECKSUM",		SYM(CHECKSUM_SYM),0,0},
-  { "CIPHER",		SYM(CIPHER_SYM),0,0},
-  { "CLIENT",		SYM(CLIENT_SYM),0,0},
-  { "CLOSE",		SYM(CLOSE_SYM),0,0},
-  { "COLLATE",		SYM(COLLATE_SYM),0,0},
-  { "COLLATION",	SYM(COLLATION_SYM),0,0},
-  { "COLUMN",		SYM(COLUMN_SYM),0,0},
-  { "COLUMNS",		SYM(COLUMNS),0,0},
-  { "COMMENT",		SYM(COMMENT_SYM),0,0},
-  { "COMMIT",		SYM(COMMIT_SYM),0,0},
-  { "COMMITTED",	SYM(COMMITTED_SYM),0,0},
-  { "COMPRESSED",	SYM(COMPRESSED_SYM),0,0},
-  { "CONCURRENT",	SYM(CONCURRENT),0,0},
-  { "CONSTRAINT",	SYM(CONSTRAINT),0,0},
-  { "CREATE",		SYM(CREATE),0,0},
-  { "CROSS",		SYM(CROSS),0,0},
-  { "CUBE",		SYM(CUBE_SYM),0,0},
-  { "CURRENT_DATE",	SYM(CURDATE),0,0},
-  { "CURRENT_TIME",	SYM(CURTIME),0,0},
-  { "CURRENT_TIMESTAMP", SYM(NOW_SYM),0,0},
-  { "DATA",		SYM(DATA_SYM),0,0},
-  { "DATABASE",		SYM(DATABASE),0,0},
-  { "DATABASES",	SYM(DATABASES),0,0},
-  { "DATE",		SYM(DATE_SYM),0,0},
-  { "DATETIME",		SYM(DATETIME),0,0},
-  { "DAY",		SYM(DAY_SYM),0,0},
-  { "DAY_HOUR",		SYM(DAY_HOUR_SYM),0,0},
-  { "DAY_MICROSECOND",	SYM(DAY_MICROSECOND_SYM),0,0},
-  { "DAY_MINUTE",	SYM(DAY_MINUTE_SYM),0,0},
-  { "DAY_SECOND",	SYM(DAY_SECOND_SYM),0,0},
-  { "DEC",		SYM(DECIMAL_SYM),0,0},
-  { "DECIMAL",		SYM(DECIMAL_SYM),0,0},
-  { "DEFAULT",		SYM(DEFAULT),0,0},
-  { "DELAYED",		SYM(DELAYED_SYM),0,0},
-  { "DELAY_KEY_WRITE",	SYM(DELAY_KEY_WRITE_SYM),0,0},
-  { "DELETE",		SYM(DELETE_SYM),0,0},
-  { "DESC",		SYM(DESC),0,0},
-  { "DESCRIBE",		SYM(DESCRIBE),0,0},
-  { "DES_KEY_FILE",	SYM(DES_KEY_FILE),0,0},
-  { "DIRECTORY",	SYM(DIRECTORY_SYM),0,0},
-  { "DISABLE",		SYM(DISABLE_SYM),0,0},
-  { "DISCARD",		SYM(DISCARD),0,0},
-  { "DISTINCT",		SYM(DISTINCT),0,0},
-  { "DISTINCTROW",	SYM(DISTINCT),0,0},	/* Access likes this */
-  { "DIV",		SYM(DIV_SYM),0,0},
-  { "DO",		SYM(DO_SYM),0,0},
-  { "DOUBLE",		SYM(DOUBLE_SYM),0,0},
-  { "DROP",		SYM(DROP),0,0},
-  { "DUAL",		SYM(DUAL_SYM),0,0},
-  { "DUMPFILE",		SYM(DUMPFILE),0,0},
-  { "DUPLICATE",	SYM(DUPLICATE_SYM),0,0},
-  { "DYNAMIC",		SYM(DYNAMIC_SYM),0,0},
-  { "ELSE",             SYM(ELSE),0,0},
-  { "ENABLE",		SYM(ENABLE_SYM),0,0},
-  { "ENCLOSED",		SYM(ENCLOSED),0,0},
-  { "END",		SYM(END),0,0},
-  { "ENGINE",		SYM(ENGINE_SYM),0,0},
-  { "ENGINES",		SYM(ENGINES_SYM),0,0},
-  { "ENUM",		SYM(ENUM),0,0},
-  { "ERRORS",		SYM(ERRORS),0,0},
-  { "ESCAPE",		SYM(ESCAPE_SYM),0,0},
-  { "ESCAPED",		SYM(ESCAPED),0,0},
-  { "EVENTS",		SYM(EVENTS_SYM),0,0},
-  { "EXECUTE",		SYM(EXECUTE_SYM),0,0},
-  { "EXISTS",		SYM(EXISTS),0,0},
-  { "EXPANSION",	SYM(EXPANSION_SYM),0,0},
-  { "EXPLAIN",		SYM(DESCRIBE),0,0},
-  { "EXTENDED",		SYM(EXTENDED_SYM),0,0},
-  { "FALSE",		SYM(FALSE_SYM),0,0},
-  { "FAST",		SYM(FAST_SYM),0,0},
-  { "FIELDS",		SYM(COLUMNS),0,0},
-  { "FILE",		SYM(FILE_SYM),0,0},
-  { "FIRST",		SYM(FIRST_SYM),0,0},
-  { "FIXED",		SYM(FIXED_SYM),0,0},
-  { "FLOAT",		SYM(FLOAT_SYM),0,0},
-  { "FLOAT4",		SYM(FLOAT_SYM),0,0},
-  { "FLOAT8",		SYM(DOUBLE_SYM),0,0},
-  { "FLUSH",		SYM(FLUSH_SYM),0,0},
-  { "FOR",		SYM(FOR_SYM),0,0},
-  { "FORCE",		SYM(FORCE_SYM),0,0},
-  { "FOREIGN",		SYM(FOREIGN),0,0},
-  { "FROM",		SYM(FROM),0,0},
-  { "FULL",		SYM(FULL),0,0},
-  { "FULLTEXT",		SYM(FULLTEXT_SYM),0,0},
-  { "FUNCTION",		SYM(UDF_SYM),0,0},
-  { "GEOMETRY",		SYM(GEOMETRY_SYM),0,0},
-  { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION),0,0},
-  { "GET_FORMAT",       SYM(GET_FORMAT),0,0},
-  { "GLOBAL",		SYM(GLOBAL_SYM),0,0},
-  { "GRANT",		SYM(GRANT),0,0},
-  { "GRANTS",	        SYM(GRANTS),0,0},
-  { "GROUP",		SYM(GROUP),0,0},
-  { "HANDLER",		SYM(HANDLER_SYM),0,0},
-  { "HASH",		SYM(HASH_SYM),0,0},
-  { "HAVING",		SYM(HAVING),0,0},
-  { "HELP",		SYM(HELP_SYM),0,0},
-  { "HIGH_PRIORITY",	SYM(HIGH_PRIORITY),0,0},
-  { "HOSTS",		SYM(HOSTS_SYM),0,0},
-  { "HOUR",		SYM(HOUR_SYM),0,0},
-  { "HOUR_MICROSECOND",	SYM(HOUR_MICROSECOND_SYM),0,0},
-  { "HOUR_MINUTE",	SYM(HOUR_MINUTE_SYM),0,0},
-  { "HOUR_SECOND",	SYM(HOUR_SECOND_SYM),0,0},
-  { "IDENTIFIED",	SYM(IDENTIFIED_SYM),0,0},
-  { "IF",		SYM(IF),0,0},
-  { "IGNORE",		SYM(IGNORE_SYM),0,0},
-  { "IMPORT",		SYM(IMPORT),0,0},
-  { "IN",		SYM(IN_SYM),0,0},
-  { "INDEX",		SYM(INDEX),0,0},
-  { "INDEXES",		SYM(INDEXES),0,0},
-  { "INFILE",		SYM(INFILE),0,0},
-  { "INNER",		SYM(INNER_SYM),0,0},
-  { "INNOBASE",		SYM(INNOBASE_SYM),0,0},
-  { "INNODB",		SYM(INNOBASE_SYM),0,0},
-  { "INSERT",		SYM(INSERT),0,0},
-  { "INSERT_METHOD",    SYM(INSERT_METHOD),0,0},
-  { "INT",		SYM(INT_SYM),0,0},
-  { "INT1",		SYM(TINYINT),0,0},
-  { "INT2",		SYM(SMALLINT),0,0},
-  { "INT3",		SYM(MEDIUMINT),0,0},
-  { "INT4",		SYM(INT_SYM),0,0},
-  { "INT8",		SYM(BIGINT),0,0},
-  { "INTEGER",		SYM(INT_SYM),0,0},
-  { "INTERVAL",		SYM(INTERVAL_SYM),0,0},
-  { "INTO",		SYM(INTO),0,0},
-  { "IO_THREAD",        SYM(RELAY_THREAD),0,0},
-  { "IS",		SYM(IS),0,0},
-  { "ISOLATION",	SYM(ISOLATION),0,0},
-  { "ISSUER",		SYM(ISSUER_SYM),0,0},
-  { "JOIN",		SYM(JOIN_SYM),0,0},
-  { "KEY",		SYM(KEY_SYM),0,0},
-  { "KEYS",		SYM(KEYS),0,0},
-  { "KILL",		SYM(KILL_SYM),0,0},
-  { "LAST",		SYM(LAST_SYM),0,0},
-  { "LEADING",		SYM(LEADING),0,0},
-  { "LEAVES",		SYM(LEAVES),0,0},
-  { "LEFT",		SYM(LEFT),0,0},
-  { "LEVEL",		SYM(LEVEL_SYM),0,0},
-  { "LIKE",		SYM(LIKE),0,0},
-  { "LIMIT",		SYM(LIMIT),0,0},
-  { "LINES",		SYM(LINES),0,0},
-  { "LINESTRING",	SYM(LINESTRING),0,0},
-  { "LOAD",		SYM(LOAD),0,0},
-  { "LOCAL",		SYM(LOCAL_SYM),0,0},
-  { "LOCALTIME",	SYM(NOW_SYM),0,0},
-  { "LOCALTIMESTAMP",	SYM(NOW_SYM),0,0},
-  { "LOCK",		SYM(LOCK_SYM),0,0},
-  { "LOCKS",		SYM(LOCKS_SYM),0,0},
-  { "LOGS",		SYM(LOGS_SYM),0,0},
-  { "LONG",		SYM(LONG_SYM),0,0},
-  { "LONGBLOB",		SYM(LONGBLOB),0,0},
-  { "LONGTEXT",		SYM(LONGTEXT),0,0},
-  { "LOW_PRIORITY",	SYM(LOW_PRIORITY),0,0},
-  { "MASTER",           SYM(MASTER_SYM),0,0},
-  { "MASTER_CONNECT_RETRY",           SYM(MASTER_CONNECT_RETRY_SYM),0,0},
-  { "MASTER_HOST",           SYM(MASTER_HOST_SYM),0,0},
-  { "MASTER_LOG_FILE",           SYM(MASTER_LOG_FILE_SYM),0,0},
-  { "MASTER_LOG_POS",           SYM(MASTER_LOG_POS_SYM),0,0},
-  { "MASTER_PASSWORD",           SYM(MASTER_PASSWORD_SYM),0,0},
-  { "MASTER_PORT",           SYM(MASTER_PORT_SYM),0,0},
-  { "MASTER_SERVER_ID",           SYM(MASTER_SERVER_ID_SYM),0,0},
-  { "MASTER_SSL",       SYM(MASTER_SSL_SYM),0,0},
-  { "MASTER_SSL_CA",    SYM(MASTER_SSL_CA_SYM),0,0},
-  { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM),0,0},
-  { "MASTER_SSL_CERT",  SYM(MASTER_SSL_CERT_SYM),0,0},
-  { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM),0,0},
-  { "MASTER_SSL_KEY",   SYM(MASTER_SSL_KEY_SYM),0,0},
-  { "MASTER_USER",           SYM(MASTER_USER_SYM),0,0},
-  { "MATCH",		SYM(MATCH),0,0},
-  { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR), 0,0},
-  { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR), 0,0},
-  { "MAX_ROWS",		SYM(MAX_ROWS),0,0},
-  { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR), 0,0},
-  { "MEDIUM",		SYM(MEDIUM_SYM),0,0},
-  { "MEDIUMBLOB",	SYM(MEDIUMBLOB),0,0},
-  { "MEDIUMINT",	SYM(MEDIUMINT),0,0},
-  { "MEDIUMTEXT",	SYM(MEDIUMTEXT),0,0},
-  { "MICROSECOND",	SYM(MICROSECOND_SYM),0,0},
-  { "MIDDLEINT",	SYM(MEDIUMINT),0,0},	/* For powerbuilder */
-  { "MINUTE",		SYM(MINUTE_SYM),0,0},
-  { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM),0,0},
-  { "MINUTE_SECOND",	SYM(MINUTE_SECOND_SYM),0,0},
-  { "MIN_ROWS",		SYM(MIN_ROWS),0,0},
-  { "MOD",		SYM(MOD_SYM),0,0},
-  { "MODE",		SYM(MODE_SYM),0,0},
-  { "MODIFY",		SYM(MODIFY_SYM),0,0},
-  { "MONTH",		SYM(MONTH_SYM),0,0},
-  { "MULTILINESTRING",	SYM(MULTILINESTRING),0,0},
-  { "MULTIPOINT",	SYM(MULTIPOINT),0,0},
-  { "MULTIPOLYGON",	SYM(MULTIPOLYGON),0,0},
-  { "NAMES",		SYM(NAMES_SYM),0,0},
-  { "NATIONAL",		SYM(NATIONAL_SYM),0,0},
-  { "NATURAL",		SYM(NATURAL),0,0},
-  { "NCHAR",		SYM(NCHAR_SYM),0,0},
-  { "NEW",              SYM(NEW_SYM),0,0},
-  { "NEXT",		SYM(NEXT_SYM),0,0},
-  { "NO",		SYM(NO_SYM),0,0},
-  { "NONE",		SYM(NONE_SYM),0,0},
-  { "NOT",		SYM(NOT),0,0},
-  { "NO_WRITE_TO_BINLOG",  SYM(NO_WRITE_TO_BINLOG),0,0},
-  { "NULL",		SYM(NULL_SYM),0,0},
-  { "NUMERIC",		SYM(NUMERIC_SYM),0,0},
-  { "NVARCHAR",		SYM(NVARCHAR_SYM),0,0},
-  { "OFFSET",		SYM(OFFSET_SYM),0,0},
-  { "OLD_PASSWORD",	SYM(OLD_PASSWORD),0,0},
-  { "ON",		SYM(ON),0,0},
-  { "OPEN",		SYM(OPEN_SYM),0,0},
-  { "OPTIMIZE",		SYM(OPTIMIZE),0,0},
-  { "OPTION",		SYM(OPTION),0,0},
-  { "OPTIONALLY",	SYM(OPTIONALLY),0,0},
-  { "OR",		SYM(OR),0,0},
-  { "ORDER",		SYM(ORDER_SYM),0,0},
-  { "OUTER",		SYM(OUTER),0,0},
-  { "OUTFILE",		SYM(OUTFILE),0,0},
-  { "PACK_KEYS",	SYM(PACK_KEYS_SYM),0,0},
-  { "PARTIAL",		SYM(PARTIAL),0,0},
-  { "PASSWORD",		SYM(PASSWORD),0,0},
-  { "POINT",		SYM(POINT_SYM),0,0},
-  { "POLYGON",		SYM(POLYGON),0,0},
-  { "PRECISION",	SYM(PRECISION),0,0},
-  { "PREV",		SYM(PREV_SYM),0,0},
-  { "PRIMARY",		SYM(PRIMARY_SYM),0,0},
-  { "PRIVILEGES",	SYM(PRIVILEGES),0,0},
-  { "PROCEDURE",	SYM(PROCEDURE),0,0},
-  { "PROCESS"	,	SYM(PROCESS),0,0},
-  { "PROCESSLIST",	SYM(PROCESSLIST_SYM),0,0},
-  { "PURGE",		SYM(PURGE),0,0},
-  { "QUERY",		SYM(QUERY_SYM),0,0},
-  { "QUICK",	        SYM(QUICK),0,0},
-  { "RAID0",		SYM(RAID_0_SYM),0,0},
-  { "RAID_CHUNKS",	SYM(RAID_CHUNKS),0,0},
-  { "RAID_CHUNKSIZE",	SYM(RAID_CHUNKSIZE),0,0},
-  { "RAID_TYPE",	SYM(RAID_TYPE),0,0},
-  { "READ",		SYM(READ_SYM),0,0},
-  { "REAL",		SYM(REAL),0,0},
-  { "REFERENCES",	SYM(REFERENCES),0,0},
-  { "REGEXP",		SYM(REGEXP),0,0},
-  { "RELAY_LOG_FILE",   SYM(RELAY_LOG_FILE_SYM),0,0},
-  { "RELAY_LOG_POS",    SYM(RELAY_LOG_POS_SYM),0,0},
-  { "RELAY_THREAD",     SYM(RELAY_THREAD),0,0},
-  { "RELOAD",		SYM(RELOAD),0,0},
-  { "RENAME",		SYM(RENAME),0,0},
-  { "REPAIR",		SYM(REPAIR),0,0},
-  { "REPEATABLE",	SYM(REPEATABLE_SYM),0,0},
-  { "REPLACE",		SYM(REPLACE),0,0},
-  { "REPLICATION",	SYM(REPLICATION),0,0},
-  { "REQUIRE",	        SYM(REQUIRE_SYM),0,0},
-  { "RESET",		SYM(RESET_SYM),0,0},
-  { "RESTORE",		SYM(RESTORE_SYM),0,0},
-  { "RESTRICT",		SYM(RESTRICT),0,0},
-  { "RETURNS",		SYM(UDF_RETURNS_SYM),0,0},
-  { "REVOKE",		SYM(REVOKE),0,0},
-  { "RIGHT",		SYM(RIGHT),0,0},
-  { "RLIKE",		SYM(REGEXP),0,0},	/* Like in mSQL2 */
-  { "ROLLBACK",		SYM(ROLLBACK_SYM),0,0},
-  { "ROLLUP",		SYM(ROLLUP_SYM),0,0},
-  { "ROW",		SYM(ROW_SYM),0,0},
-  { "ROWS",		SYM(ROWS_SYM),0,0},
-  { "ROW_FORMAT",	SYM(ROW_FORMAT_SYM),0,0},
-  { "RTREE",		SYM(RTREE_SYM),0,0},
-  { "SAVEPOINT",	SYM(SAVEPOINT_SYM),0,0},
-  { "SECOND",		SYM(SECOND_SYM),0,0},
-  { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0},
-  { "SELECT",		SYM(SELECT_SYM),0,0},
-  { "SEPARATOR",	SYM(SEPARATOR_SYM),0,0},
-  { "SERIAL",		SYM(SERIAL_SYM),0,0},
-  { "SERIALIZABLE",	SYM(SERIALIZABLE_SYM),0,0},
-  { "SESSION",		SYM(SESSION_SYM),0,0},
-  { "SET",		SYM(SET),0,0},
-  { "SHARE",		SYM(SHARE_SYM),0,0},
-  { "SHOW",		SYM(SHOW),0,0},
-  { "SHUTDOWN",		SYM(SHUTDOWN),0,0},
-  { "SIGNED",		SYM(SIGNED_SYM),0,0},
-  { "SIMPLE",		SYM(SIMPLE_SYM),0,0},
-  { "SLAVE",            SYM(SLAVE),0,0},
-  { "SMALLINT",		SYM(SMALLINT),0,0},
-  { "SOME",             SYM(ANY_SYM),0,0},
-  { "SONAME",		SYM(UDF_SONAME_SYM),0,0},
-  { "SOUNDS",		SYM(SOUNDS_SYM),0,0},
-  { "SPATIAL",		SYM(SPATIAL_SYM),0,0},
-  { "SQL_BIG_RESULT",	SYM(SQL_BIG_RESULT),0,0},
-  { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT),0,0},
-  { "SQL_CACHE",        SYM(SQL_CACHE_SYM), 0, 0},
-  { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS),0,0},
-  { "SQL_NO_CACHE",	SYM(SQL_NO_CACHE_SYM), 0, 0},
-  { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
-  { "SQL_THREAD",	SYM(SQL_THREAD),0,0},
-  { "SSL",		SYM(SSL_SYM),0,0},
-  { "START",		SYM(START_SYM),0,0},
-  { "STARTING",		SYM(STARTING),0,0},
-  { "STATUS",		SYM(STATUS_SYM),0,0},
-  { "STOP",		SYM(STOP_SYM),0,0},
-  { "STORAGE",		SYM(STORAGE_SYM),0,0},
-  { "STRAIGHT_JOIN",	SYM(STRAIGHT_JOIN),0,0},
-  { "STRING",		SYM(STRING_SYM),0,0},
-  { "STRIPED",		SYM(RAID_STRIPED_SYM),0,0},
-  { "SUBJECT",		SYM(SUBJECT_SYM),0,0},
-  { "SUPER",		SYM(SUPER_SYM),0,0},
-  { "TABLE",		SYM(TABLE_SYM),0,0},
-  { "TABLES",		SYM(TABLES),0,0},
-  { "TABLESPACE",	SYM(TABLESPACE),0,0},
-  { "TEMPORARY",	SYM(TEMPORARY),0,0},
-  { "TERMINATED",	SYM(TERMINATED),0,0},
-  { "TEXT",		SYM(TEXT_SYM),0,0},
-  { "THEN",		SYM(THEN_SYM),0,0},
-  { "TIME",		SYM(TIME_SYM),0,0},
-  { "TIMESTAMP",	SYM(TIMESTAMP),0,0},
-  { "TINYBLOB",		SYM(TINYBLOB),0,0},
-  { "TINYINT",		SYM(TINYINT),0,0},
-  { "TINYTEXT",		SYM(TINYTEXT),0,0},
-  { "TO",		SYM(TO_SYM),0,0},
-  { "TRAILING",		SYM(TRAILING),0,0},
-  { "TRANSACTION",	SYM(TRANSACTION_SYM),0,0},
-  { "TRUE",		SYM(TRUE_SYM),0,0},
-  { "TRUNCATE",		SYM(TRUNCATE_SYM),0,0},
-  { "TYPE",		SYM(TYPE_SYM),0,0},
-  { "TYPES",		SYM(TYPES_SYM),0,0},
-  { "UNCOMMITTED",	SYM(UNCOMMITTED_SYM),0,0},
-  { "UNICODE",	        SYM(UNICODE_SYM),0,0},
-  { "UNION",	        SYM(UNION_SYM),0,0},
-  { "UNIQUE",		SYM(UNIQUE_SYM),0,0},
-  { "UNLOCK",		SYM(UNLOCK_SYM),0,0},
-  { "UNSIGNED",		SYM(UNSIGNED),0,0},
-  { "UNTIL",		SYM(UNTIL_SYM),0,0},
-  { "UPDATE",		SYM(UPDATE_SYM),0,0},
-  { "USAGE",		SYM(USAGE),0,0},
-  { "USE",		SYM(USE_SYM),0,0},
-  { "USER",		SYM(USER),0,0},
-  { "USER_RESOURCES",	SYM(RESOURCES),0,0},
-  { "USE_FRM",		SYM(USE_FRM),0,0},
-  { "USING",		SYM(USING),0,0},
-  { "UTC_DATE",         SYM(UTC_DATE_SYM),0,0},
-  { "UTC_TIME",         SYM(UTC_TIME_SYM),0,0},
-  { "UTC_TIMESTAMP",    SYM(UTC_TIMESTAMP_SYM),0,0},
-  { "VALUE",		SYM(VALUE_SYM),0,0},
-  { "VALUES",		SYM(VALUES),0,0},
-  { "VARBINARY",	SYM(VARBINARY),0,0},
-  { "VARCHAR",		SYM(VARCHAR),0,0},
-  { "VARCHARACTER",	SYM(VARCHAR),0,0},
-  { "VARIABLES",	SYM(VARIABLES),0,0},
-  { "VARYING",		SYM(VARYING),0,0},
-  { "WARNINGS",		SYM(WARNINGS),0,0},
-  { "WHEN",		SYM(WHEN_SYM),0,0},
-  { "WHERE",		SYM(WHERE),0,0},
-  { "WITH",		SYM(WITH),0,0},
-  { "WORK",		SYM(WORK_SYM),0,0},
-  { "WRITE",		SYM(WRITE_SYM),0,0},
-  { "X509",		SYM(X509_SYM),0,0},
-  { "XOR",		SYM(XOR),0,0},
-  { "YEAR",		SYM(YEAR_SYM),0,0},
-  { "YEAR_MONTH",	SYM(YEAR_MONTH_SYM),0,0},
-  { "ZEROFILL",		SYM(ZEROFILL),0,0},
-  { "||",		SYM(OR_OR_CONCAT),0,0}
+  { "&&",		SYM(AND)},
+  { "<",		SYM(LT)},
+  { "<=",		SYM(LE)},
+  { "<>",		SYM(NE)},
+  { "!=",		SYM(NE)},
+  { "=",		SYM(EQ)},
+  { ">",		SYM(GT_SYM)},
+  { ">=",		SYM(GE)},
+  { "<<",		SYM(SHIFT_LEFT)},
+  { ">>",		SYM(SHIFT_RIGHT)},
+  { "<=>",		SYM(EQUAL_SYM)},
+  { "ACTION",		SYM(ACTION)},
+  { "ADD",		SYM(ADD)},
+  { "AFTER",		SYM(AFTER_SYM)},
+  { "AGAINST",          SYM(AGAINST)},
+  { "AGGREGATE",	SYM(AGGREGATE_SYM)},
+  { "ALL",		SYM(ALL)},
+  { "ALTER",		SYM(ALTER)},
+  { "ANALYZE",		SYM(ANALYZE_SYM)},
+  { "AND",		SYM(AND)},
+  { "ANY",              SYM(ANY_SYM)},
+  { "AS",		SYM(AS)},
+  { "ASC",		SYM(ASC)},
+  { "ASCII",		SYM(ASCII_SYM)},
+  { "AUTO_INCREMENT",	SYM(AUTO_INC)},
+  { "AVG",		SYM(AVG_SYM)},
+  { "AVG_ROW_LENGTH",	SYM(AVG_ROW_LENGTH)},
+  { "BACKUP",	        SYM(BACKUP_SYM)},
+  { "BDB",              SYM(BERKELEY_DB_SYM)},
+  { "BEFORE",	        SYM(BEFORE_SYM)},
+  { "BEGIN",	        SYM(BEGIN_SYM)},
+  { "BERKELEYDB",       SYM(BERKELEY_DB_SYM)},
+  { "BETWEEN",		SYM(BETWEEN_SYM)},
+  { "BIGINT",		SYM(BIGINT)},
+  { "BINARY",		SYM(BINARY)},
+  { "BINLOG",		SYM(BINLOG_SYM)},
+  { "BIT",		SYM(BIT_SYM)},
+  { "BLOB",		SYM(BLOB_SYM)},
+  { "BOOL",		SYM(BOOL_SYM)},
+  { "BOOLEAN",		SYM(BOOLEAN_SYM)},
+  { "BOTH",		SYM(BOTH)},
+  { "BTREE",		SYM(BTREE_SYM)},
+  { "BY",		SYM(BY)},
+  { "BYTE",		SYM(BYTE_SYM)},
+  { "CACHE",		SYM(CACHE_SYM)},
+  { "CASCADE",		SYM(CASCADE)},
+  { "CASE",		SYM(CASE_SYM)},
+  { "CHANGE",		SYM(CHANGE)},
+  { "CHANGED",		SYM(CHANGED)},
+  { "CHAR",		SYM(CHAR_SYM)},
+  { "CHARACTER",	SYM(CHAR_SYM)},
+  { "CHARSET",		SYM(CHARSET)},
+  { "CHECK",		SYM(CHECK_SYM)},
+  { "CHECKSUM",		SYM(CHECKSUM_SYM)},
+  { "CIPHER",		SYM(CIPHER_SYM)},
+  { "CLIENT",		SYM(CLIENT_SYM)},
+  { "CLOSE",		SYM(CLOSE_SYM)},
+  { "COLLATE",		SYM(COLLATE_SYM)},
+  { "COLLATION",	SYM(COLLATION_SYM)},
+  { "COLUMN",		SYM(COLUMN_SYM)},
+  { "COLUMNS",		SYM(COLUMNS)},
+  { "COMMENT",		SYM(COMMENT_SYM)},
+  { "COMMIT",		SYM(COMMIT_SYM)},
+  { "COMMITTED",	SYM(COMMITTED_SYM)},
+  { "COMPRESSED",	SYM(COMPRESSED_SYM)},
+  { "CONCURRENT",	SYM(CONCURRENT)},
+  { "CONSTRAINT",	SYM(CONSTRAINT)},
+  { "CREATE",		SYM(CREATE)},
+  { "CROSS",		SYM(CROSS)},
+  { "CUBE",		SYM(CUBE_SYM)},
+  { "CURRENT_DATE",	SYM(CURDATE)},
+  { "CURRENT_TIME",	SYM(CURTIME)},
+  { "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
+  { "DATA",		SYM(DATA_SYM)},
+  { "DATABASE",		SYM(DATABASE)},
+  { "DATABASES",	SYM(DATABASES)},
+  { "DATE",		SYM(DATE_SYM)},
+  { "DATETIME",		SYM(DATETIME)},
+  { "DAY",		SYM(DAY_SYM)},
+  { "DAY_HOUR",		SYM(DAY_HOUR_SYM)},
+  { "DAY_MICROSECOND",	SYM(DAY_MICROSECOND_SYM)},
+  { "DAY_MINUTE",	SYM(DAY_MINUTE_SYM)},
+  { "DAY_SECOND",	SYM(DAY_SECOND_SYM)},
+  { "DEC",		SYM(DECIMAL_SYM)},
+  { "DECIMAL",		SYM(DECIMAL_SYM)},
+  { "DEFAULT",		SYM(DEFAULT)},
+  { "DELAYED",		SYM(DELAYED_SYM)},
+  { "DELAY_KEY_WRITE",	SYM(DELAY_KEY_WRITE_SYM)},
+  { "DELETE",		SYM(DELETE_SYM)},
+  { "DESC",		SYM(DESC)},
+  { "DESCRIBE",		SYM(DESCRIBE)},
+  { "DES_KEY_FILE",	SYM(DES_KEY_FILE)},
+  { "DIRECTORY",	SYM(DIRECTORY_SYM)},
+  { "DISABLE",		SYM(DISABLE_SYM)},
+  { "DISCARD",		SYM(DISCARD)},
+  { "DISTINCT",		SYM(DISTINCT)},
+  { "DISTINCTROW",	SYM(DISTINCT)},	/* Access likes this */
+  { "DIV",		SYM(DIV_SYM)},
+  { "DO",		SYM(DO_SYM)},
+  { "DOUBLE",		SYM(DOUBLE_SYM)},
+  { "DROP",		SYM(DROP)},
+  { "DUAL",		SYM(DUAL_SYM)},
+  { "DUMPFILE",		SYM(DUMPFILE)},
+  { "DUPLICATE",	SYM(DUPLICATE_SYM)},
+  { "DYNAMIC",		SYM(DYNAMIC_SYM)},
+  { "ELSE",             SYM(ELSE)},
+  { "ENABLE",		SYM(ENABLE_SYM)},
+  { "ENCLOSED",		SYM(ENCLOSED)},
+  { "END",		SYM(END)},
+  { "ENGINE",		SYM(ENGINE_SYM)},
+  { "ENGINES",		SYM(ENGINES_SYM)},
+  { "ENUM",		SYM(ENUM)},
+  { "ERRORS",		SYM(ERRORS)},
+  { "ESCAPE",		SYM(ESCAPE_SYM)},
+  { "ESCAPED",		SYM(ESCAPED)},
+  { "EVENTS",		SYM(EVENTS_SYM)},
+  { "EXECUTE",		SYM(EXECUTE_SYM)},
+  { "EXISTS",		SYM(EXISTS)},
+  { "EXPANSION",	SYM(EXPANSION_SYM)},
+  { "EXPLAIN",		SYM(DESCRIBE)},
+  { "EXTENDED",		SYM(EXTENDED_SYM)},
+  { "FALSE",		SYM(FALSE_SYM)},
+  { "FAST",		SYM(FAST_SYM)},
+  { "FIELDS",		SYM(COLUMNS)},
+  { "FILE",		SYM(FILE_SYM)},
+  { "FIRST",		SYM(FIRST_SYM)},
+  { "FIXED",		SYM(FIXED_SYM)},
+  { "FLOAT",		SYM(FLOAT_SYM)},
+  { "FLOAT4",		SYM(FLOAT_SYM)},
+  { "FLOAT8",		SYM(DOUBLE_SYM)},
+  { "FLUSH",		SYM(FLUSH_SYM)},
+  { "FOR",		SYM(FOR_SYM)},
+  { "FORCE",		SYM(FORCE_SYM)},
+  { "FOREIGN",		SYM(FOREIGN)},
+  { "FROM",		SYM(FROM)},
+  { "FULL",		SYM(FULL)},
+  { "FULLTEXT",		SYM(FULLTEXT_SYM)},
+  { "FUNCTION",		SYM(UDF_SYM)},
+  { "GEOMETRY",		SYM(GEOMETRY_SYM)},
+  { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
+  { "GET_FORMAT",       SYM(GET_FORMAT)},
+  { "GLOBAL",		SYM(GLOBAL_SYM)},
+  { "GRANT",		SYM(GRANT)},
+  { "GRANTS",	        SYM(GRANTS)},
+  { "GROUP",		SYM(GROUP)},
+  { "HANDLER",		SYM(HANDLER_SYM)},
+  { "HASH",		SYM(HASH_SYM)},
+  { "HAVING",		SYM(HAVING)},
+  { "HELP",		SYM(HELP_SYM)},
+  { "HIGH_PRIORITY",	SYM(HIGH_PRIORITY)},
+  { "HOSTS",		SYM(HOSTS_SYM)},
+  { "HOUR",		SYM(HOUR_SYM)},
+  { "HOUR_MICROSECOND",	SYM(HOUR_MICROSECOND_SYM)},
+  { "HOUR_MINUTE",	SYM(HOUR_MINUTE_SYM)},
+  { "HOUR_SECOND",	SYM(HOUR_SECOND_SYM)},
+  { "IDENTIFIED",	SYM(IDENTIFIED_SYM)},
+  { "IF",		SYM(IF)},
+  { "IGNORE",		SYM(IGNORE_SYM)},
+  { "IMPORT",		SYM(IMPORT)},
+  { "IN",		SYM(IN_SYM)},
+  { "INDEX",		SYM(INDEX)},
+  { "INDEXES",		SYM(INDEXES)},
+  { "INFILE",		SYM(INFILE)},
+  { "INNER",		SYM(INNER_SYM)},
+  { "INNOBASE",		SYM(INNOBASE_SYM)},
+  { "INNODB",		SYM(INNOBASE_SYM)},
+  { "INSERT",		SYM(INSERT)},
+  { "INSERT_METHOD",    SYM(INSERT_METHOD)},
+  { "INT",		SYM(INT_SYM)},
+  { "INT1",		SYM(TINYINT)},
+  { "INT2",		SYM(SMALLINT)},
+  { "INT3",		SYM(MEDIUMINT)},
+  { "INT4",		SYM(INT_SYM)},
+  { "INT8",		SYM(BIGINT)},
+  { "INTEGER",		SYM(INT_SYM)},
+  { "INTERVAL",		SYM(INTERVAL_SYM)},
+  { "INTO",		SYM(INTO)},
+  { "IO_THREAD",        SYM(RELAY_THREAD)},
+  { "IS",		SYM(IS)},
+  { "ISOLATION",	SYM(ISOLATION)},
+  { "ISSUER",		SYM(ISSUER_SYM)},
+  { "JOIN",		SYM(JOIN_SYM)},
+  { "KEY",		SYM(KEY_SYM)},
+  { "KEYS",		SYM(KEYS)},
+  { "KILL",		SYM(KILL_SYM)},
+  { "LAST",		SYM(LAST_SYM)},
+  { "LEADING",		SYM(LEADING)},
+  { "LEAVES",		SYM(LEAVES)},
+  { "LEFT",		SYM(LEFT)},
+  { "LEVEL",		SYM(LEVEL_SYM)},
+  { "LIKE",		SYM(LIKE)},
+  { "LIMIT",		SYM(LIMIT)},
+  { "LINES",		SYM(LINES)},
+  { "LINESTRING",	SYM(LINESTRING)},
+  { "LOAD",		SYM(LOAD)},
+  { "LOCAL",		SYM(LOCAL_SYM)},
+  { "LOCALTIME",	SYM(NOW_SYM)},
+  { "LOCALTIMESTAMP",	SYM(NOW_SYM)},
+  { "LOCK",		SYM(LOCK_SYM)},
+  { "LOCKS",		SYM(LOCKS_SYM)},
+  { "LOGS",		SYM(LOGS_SYM)},
+  { "LONG",		SYM(LONG_SYM)},
+  { "LONGBLOB",		SYM(LONGBLOB)},
+  { "LONGTEXT",		SYM(LONGTEXT)},
+  { "LOW_PRIORITY",	SYM(LOW_PRIORITY)},
+  { "MASTER",           SYM(MASTER_SYM)},
+  { "MASTER_CONNECT_RETRY",           SYM(MASTER_CONNECT_RETRY_SYM)},
+  { "MASTER_HOST",           SYM(MASTER_HOST_SYM)},
+  { "MASTER_LOG_FILE",           SYM(MASTER_LOG_FILE_SYM)},
+  { "MASTER_LOG_POS",           SYM(MASTER_LOG_POS_SYM)},
+  { "MASTER_PASSWORD",           SYM(MASTER_PASSWORD_SYM)},
+  { "MASTER_PORT",           SYM(MASTER_PORT_SYM)},
+  { "MASTER_SERVER_ID",           SYM(MASTER_SERVER_ID_SYM)},
+  { "MASTER_SSL",       SYM(MASTER_SSL_SYM)},
+  { "MASTER_SSL_CA",    SYM(MASTER_SSL_CA_SYM)},
+  { "MASTER_SSL_CAPATH",SYM(MASTER_SSL_CAPATH_SYM)},
+  { "MASTER_SSL_CERT",  SYM(MASTER_SSL_CERT_SYM)},
+  { "MASTER_SSL_CIPHER",SYM(MASTER_SSL_CIPHER_SYM)},
+  { "MASTER_SSL_KEY",   SYM(MASTER_SSL_KEY_SYM)},
+  { "MASTER_USER",           SYM(MASTER_USER_SYM)},
+  { "MATCH",		SYM(MATCH)},
+  { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)},
+  { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)},
+  { "MAX_ROWS",		SYM(MAX_ROWS)},
+  { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
+  { "MEDIUM",		SYM(MEDIUM_SYM)},
+  { "MEDIUMBLOB",	SYM(MEDIUMBLOB)},
+  { "MEDIUMINT",	SYM(MEDIUMINT)},
+  { "MEDIUMTEXT",	SYM(MEDIUMTEXT)},
+  { "MICROSECOND",	SYM(MICROSECOND_SYM)},
+  { "MIDDLEINT",	SYM(MEDIUMINT)},	/* For powerbuilder */
+  { "MINUTE",		SYM(MINUTE_SYM)},
+  { "MINUTE_MICROSECOND", SYM(MINUTE_MICROSECOND_SYM)},
+  { "MINUTE_SECOND",	SYM(MINUTE_SECOND_SYM)},
+  { "MIN_ROWS",		SYM(MIN_ROWS)},
+  { "MOD",		SYM(MOD_SYM)},
+  { "MODE",		SYM(MODE_SYM)},
+  { "MODIFY",		SYM(MODIFY_SYM)},
+  { "MONTH",		SYM(MONTH_SYM)},
+  { "MULTILINESTRING",	SYM(MULTILINESTRING)},
+  { "MULTIPOINT",	SYM(MULTIPOINT)},
+  { "MULTIPOLYGON",	SYM(MULTIPOLYGON)},
+  { "NAMES",		SYM(NAMES_SYM)},
+  { "NATIONAL",		SYM(NATIONAL_SYM)},
+  { "NATURAL",		SYM(NATURAL)},
+  { "NCHAR",		SYM(NCHAR_SYM)},
+  { "NEW",              SYM(NEW_SYM)},
+  { "NEXT",		SYM(NEXT_SYM)},
+  { "NO",		SYM(NO_SYM)},
+  { "NONE",		SYM(NONE_SYM)},
+  { "NOT",		SYM(NOT)},
+  { "NO_WRITE_TO_BINLOG",  SYM(NO_WRITE_TO_BINLOG)},
+  { "NULL",		SYM(NULL_SYM)},
+  { "NUMERIC",		SYM(NUMERIC_SYM)},
+  { "NVARCHAR",		SYM(NVARCHAR_SYM)},
+  { "OFFSET",		SYM(OFFSET_SYM)},
+  { "OLD_PASSWORD",	SYM(OLD_PASSWORD)},
+  { "ON",		SYM(ON)},
+  { "OPEN",		SYM(OPEN_SYM)},
+  { "OPTIMIZE",		SYM(OPTIMIZE)},
+  { "OPTION",		SYM(OPTION)},
+  { "OPTIONALLY",	SYM(OPTIONALLY)},
+  { "OR",		SYM(OR)},
+  { "ORDER",		SYM(ORDER_SYM)},
+  { "OUTER",		SYM(OUTER)},
+  { "OUTFILE",		SYM(OUTFILE)},
+  { "PACK_KEYS",	SYM(PACK_KEYS_SYM)},
+  { "PARTIAL",		SYM(PARTIAL)},
+  { "PASSWORD",		SYM(PASSWORD)},
+  { "POINT",		SYM(POINT_SYM)},
+  { "POLYGON",		SYM(POLYGON)},
+  { "PRECISION",	SYM(PRECISION)},
+  { "PREV",		SYM(PREV_SYM)},
+  { "PRIMARY",		SYM(PRIMARY_SYM)},
+  { "PRIVILEGES",	SYM(PRIVILEGES)},
+  { "PROCEDURE",	SYM(PROCEDURE)},
+  { "PROCESS"	,	SYM(PROCESS)},
+  { "PROCESSLIST",	SYM(PROCESSLIST_SYM)},
+  { "PURGE",		SYM(PURGE)},
+  { "QUERY",		SYM(QUERY_SYM)},
+  { "QUICK",	        SYM(QUICK)},
+  { "RAID0",		SYM(RAID_0_SYM)},
+  { "RAID_CHUNKS",	SYM(RAID_CHUNKS)},
+  { "RAID_CHUNKSIZE",	SYM(RAID_CHUNKSIZE)},
+  { "RAID_TYPE",	SYM(RAID_TYPE)},
+  { "READ",		SYM(READ_SYM)},
+  { "REAL",		SYM(REAL)},
+  { "REFERENCES",	SYM(REFERENCES)},
+  { "REGEXP",		SYM(REGEXP)},
+  { "RELAY_LOG_FILE",   SYM(RELAY_LOG_FILE_SYM)},
+  { "RELAY_LOG_POS",    SYM(RELAY_LOG_POS_SYM)},
+  { "RELAY_THREAD",     SYM(RELAY_THREAD)},
+  { "RELOAD",		SYM(RELOAD)},
+  { "RENAME",		SYM(RENAME)},
+  { "REPAIR",		SYM(REPAIR)},
+  { "REPEATABLE",	SYM(REPEATABLE_SYM)},
+  { "REPLACE",		SYM(REPLACE)},
+  { "REPLICATION",	SYM(REPLICATION)},
+  { "REQUIRE",	        SYM(REQUIRE_SYM)},
+  { "RESET",		SYM(RESET_SYM)},
+  { "RESTORE",		SYM(RESTORE_SYM)},
+  { "RESTRICT",		SYM(RESTRICT)},
+  { "RETURNS",		SYM(UDF_RETURNS_SYM)},
+  { "REVOKE",		SYM(REVOKE)},
+  { "RIGHT",		SYM(RIGHT)},
+  { "RLIKE",		SYM(REGEXP)},	/* Like in mSQL2 */
+  { "ROLLBACK",		SYM(ROLLBACK_SYM)},
+  { "ROLLUP",		SYM(ROLLUP_SYM)},
+  { "ROW",		SYM(ROW_SYM)},
+  { "ROWS",		SYM(ROWS_SYM)},
+  { "ROW_FORMAT",	SYM(ROW_FORMAT_SYM)},
+  { "RTREE",		SYM(RTREE_SYM)},
+  { "SAVEPOINT",	SYM(SAVEPOINT_SYM)},
+  { "SECOND",		SYM(SECOND_SYM)},
+  { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)},
+  { "SELECT",		SYM(SELECT_SYM)},
+  { "SEPARATOR",	SYM(SEPARATOR_SYM)},
+  { "SERIAL",		SYM(SERIAL_SYM)},
+  { "SERIALIZABLE",	SYM(SERIALIZABLE_SYM)},
+  { "SESSION",		SYM(SESSION_SYM)},
+  { "SET",		SYM(SET)},
+  { "SHARE",		SYM(SHARE_SYM)},
+  { "SHOW",		SYM(SHOW)},
+  { "SHUTDOWN",		SYM(SHUTDOWN)},
+  { "SIGNED",		SYM(SIGNED_SYM)},
+  { "SIMPLE",		SYM(SIMPLE_SYM)},
+  { "SLAVE",            SYM(SLAVE)},
+  { "SMALLINT",		SYM(SMALLINT)},
+  { "SOME",             SYM(ANY_SYM)},
+  { "SONAME",		SYM(UDF_SONAME_SYM)},
+  { "SOUNDS",		SYM(SOUNDS_SYM)},
+  { "SPATIAL",		SYM(SPATIAL_SYM)},
+  { "SQL_BIG_RESULT",	SYM(SQL_BIG_RESULT)},
+  { "SQL_BUFFER_RESULT", SYM(SQL_BUFFER_RESULT)},
+  { "SQL_CACHE",        SYM(SQL_CACHE_SYM)},
+  { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS)},
+  { "SQL_NO_CACHE",	SYM(SQL_NO_CACHE_SYM)},
+  { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)},
+  { "SQL_THREAD",	SYM(SQL_THREAD)},
+  { "SSL",		SYM(SSL_SYM)},
+  { "START",		SYM(START_SYM)},
+  { "STARTING",		SYM(STARTING)},
+  { "STATUS",		SYM(STATUS_SYM)},
+  { "STOP",		SYM(STOP_SYM)},
+  { "STORAGE",		SYM(STORAGE_SYM)},
+  { "STRAIGHT_JOIN",	SYM(STRAIGHT_JOIN)},
+  { "STRING",		SYM(STRING_SYM)},
+  { "STRIPED",		SYM(RAID_STRIPED_SYM)},
+  { "SUBJECT",		SYM(SUBJECT_SYM)},
+  { "SUPER",		SYM(SUPER_SYM)},
+  { "TABLE",		SYM(TABLE_SYM)},
+  { "TABLES",		SYM(TABLES)},
+  { "TABLESPACE",	SYM(TABLESPACE)},
+  { "TEMPORARY",	SYM(TEMPORARY)},
+  { "TERMINATED",	SYM(TERMINATED)},
+  { "TEXT",		SYM(TEXT_SYM)},
+  { "THEN",		SYM(THEN_SYM)},
+  { "TIME",		SYM(TIME_SYM)},
+  { "TIMESTAMP",	SYM(TIMESTAMP)},
+  { "TINYBLOB",		SYM(TINYBLOB)},
+  { "TINYINT",		SYM(TINYINT)},
+  { "TINYTEXT",		SYM(TINYTEXT)},
+  { "TO",		SYM(TO_SYM)},
+  { "TRAILING",		SYM(TRAILING)},
+  { "TRANSACTION",	SYM(TRANSACTION_SYM)},
+  { "TRUE",		SYM(TRUE_SYM)},
+  { "TRUNCATE",		SYM(TRUNCATE_SYM)},
+  { "TYPE",		SYM(TYPE_SYM)},
+  { "TYPES",		SYM(TYPES_SYM)},
+  { "UNCOMMITTED",	SYM(UNCOMMITTED_SYM)},
+  { "UNICODE",	        SYM(UNICODE_SYM)},
+  { "UNION",	        SYM(UNION_SYM)},
+  { "UNIQUE",		SYM(UNIQUE_SYM)},
+  { "UNLOCK",		SYM(UNLOCK_SYM)},
+  { "UNSIGNED",		SYM(UNSIGNED)},
+  { "UNTIL",		SYM(UNTIL_SYM)},
+  { "UPDATE",		SYM(UPDATE_SYM)},
+  { "USAGE",		SYM(USAGE)},
+  { "USE",		SYM(USE_SYM)},
+  { "USER",		SYM(USER)},
+  { "USER_RESOURCES",	SYM(RESOURCES)},
+  { "USE_FRM",		SYM(USE_FRM)},
+  { "USING",		SYM(USING)},
+  { "UTC_DATE",         SYM(UTC_DATE_SYM)},
+  { "UTC_TIME",         SYM(UTC_TIME_SYM)},
+  { "UTC_TIMESTAMP",    SYM(UTC_TIMESTAMP_SYM)},
+  { "VALUE",		SYM(VALUE_SYM)},
+  { "VALUES",		SYM(VALUES)},
+  { "VARBINARY",	SYM(VARBINARY)},
+  { "VARCHAR",		SYM(VARCHAR)},
+  { "VARCHARACTER",	SYM(VARCHAR)},
+  { "VARIABLES",	SYM(VARIABLES)},
+  { "VARYING",		SYM(VARYING)},
+  { "WARNINGS",		SYM(WARNINGS)},
+  { "WHEN",		SYM(WHEN_SYM)},
+  { "WHERE",		SYM(WHERE)},
+  { "WITH",		SYM(WITH)},
+  { "WORK",		SYM(WORK_SYM)},
+  { "WRITE",		SYM(WRITE_SYM)},
+  { "X509",		SYM(X509_SYM)},
+  { "XOR",		SYM(XOR)},
+  { "YEAR",		SYM(YEAR_SYM)},
+  { "YEAR_MONTH",	SYM(YEAR_MONTH_SYM)},
+  { "ZEROFILL",		SYM(ZEROFILL)},
+  { "||",		SYM(OR_OR_CONCAT)}
 };
 
 
 static SYMBOL sql_functions[] = {
-  { "ABS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
-  { "ACOS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
-  { "ADDDATE",		SYM(ADDDATE_SYM),0,0},
-  { "ADDTIME",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)},
-  { "AES_ENCRYPT",      SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
-  { "AES_DECRYPT",      SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
-  { "AREA",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_area)},
-  { "ASIN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
-  { "ASBINARY",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)},
-  { "ASTEXT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)},
-  { "ASWKB",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkb)},
-  { "ASWKT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_as_wkt)},
-  { "ATAN",		SYM(ATAN),0,0},
-  { "ATAN2",		SYM(ATAN),0,0},
-  { "BENCHMARK",	SYM(BENCHMARK_SYM),0,0},
-  { "BIN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bin)},
-  { "BIT_COUNT",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)},
-  { "BIT_OR",		SYM(BIT_OR),0,0},
-  { "BIT_AND",		SYM(BIT_AND),0,0},
-  { "BIT_XOR",		SYM(BIT_XOR),0,0},
-  { "CAST",		SYM(CAST_SYM),0,0},
-  { "CEIL",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
-  { "CEILING",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
-  { "CURRENT_USER",	SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
-  { "BIT_LENGTH",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
-  { "CENTROID",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)},
-  { "CHAR_LENGTH",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
-  { "CHARACTER_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
-  { "COALESCE",		SYM(COALESCE),0,0},
-  { "COERCIBILITY",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)},
-  { "COMPRESS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
-  { "CONCAT",		SYM(CONCAT),0,0},
-  { "CONCAT_WS",	SYM(CONCAT_WS),0,0},
-  { "CONNECTION_ID",	SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
-  { "CONTAINS",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
-  { "CONV",		SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
-  { "CONVERT",		SYM(CONVERT_SYM),0,0},
-  { "COUNT",		SYM(COUNT_SYM),0,0},
-  { "COS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
-  { "COT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
-  { "CRC32",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)},
-  { "CROSSES",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_crosses)},
-  { "CURDATE",		SYM(CURDATE),0,0},
-  { "CURTIME",		SYM(CURTIME),0,0},
-  { "DATE_ADD",		SYM(DATE_ADD_INTERVAL),0,0},
-  { "DATEDIFF",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)},
-  { "DATE_FORMAT",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)},
-  { "DATE_SUB",		SYM(DATE_SUB_INTERVAL),0,0},
-  { "DAYNAME",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)},
-  { "DAYOFMONTH",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofmonth)},
-  { "DAYOFWEEK",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofweek)},
-  { "DAYOFYEAR",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)},
-  { "DECODE",		SYM(DECODE_SYM),0,0},
-  { "DEGREES",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)},
-  { "DES_ENCRYPT",	SYM(DES_ENCRYPT_SYM),0,0},
-  { "DES_DECRYPT",	SYM(DES_DECRYPT_SYM),0,0},
-  { "DIMENSION",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dimension)},
-  { "DISJOINT",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)},
-  { "ELT",		SYM(ELT_FUNC),0,0},
-  { "ENCODE",		SYM(ENCODE_SYM),0,0},
-  { "ENCRYPT",		SYM(ENCRYPT),0,0},
-  { "ENDPOINT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_endpoint)},
-  { "ENVELOPE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_envelope)},
-  { "EQUALS",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)},
-  { "EXTERIORRING",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exteriorring)},
-  { "EXTRACT",		SYM(EXTRACT_SYM),0,0},
-  { "EXP",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)},
-  { "EXPORT_SET",	SYM(EXPORT_SET),0,0},
-  { "FIELD",		SYM(FIELD_FUNC),0,0},	/* For compability */
-  { "FIND_IN_SET",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)},
-  { "FLOOR",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)},
-  { "FORMAT",		SYM(FORMAT_SYM),0,0},
-  { "FOUND_ROWS",	SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)},
-  { "FROM_DAYS",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)},
-  { "FROM_UNIXTIME",	SYM(FROM_UNIXTIME),0,0},
-  { "GET_LOCK",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
-  { "GEOMETRYN",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_geometryn)},
-  { "GEOMETRYTYPE",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_geometry_type)},
-  { "GEOMCOLLFROMTEXT",	SYM(GEOMCOLLFROMTEXT),0,0},
-  { "GEOMCOLLFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT),0,0},
-  { "GEOMETRYCOLLECTIONFROMWKB",SYM(GEOMFROMWKB),0,0},
-  { "GEOMETRYFROMTEXT", SYM(GEOMFROMTEXT),0,0},
-  { "GEOMETRYFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "GEOMFROMTEXT",	SYM(GEOMFROMTEXT),0,0},
-  { "GEOMFROMWKB",	SYM(GEOMFROMWKB),0,0},
-    { "GLENGTH",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)},
-  { "GREATEST",		SYM(GREATEST_SYM),0,0},
-  { "GROUP_CONCAT",	SYM(GROUP_CONCAT_SYM),0,0},
-  { "GROUP_UNIQUE_USERS",	SYM(GROUP_UNIQUE_USERS),0,0},
-  { "HEX",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)},
-  { "IFNULL",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)},
-  { "INET_ATON",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)},
-  { "INET_NTOA",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)},
-  { "INSTR",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)},
-  { "INTERIORRINGN",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_interiorringn)},
-  { "INTERSECTS",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)},
-  { "ISCLOSED",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isclosed)},
-  { "ISEMPTY",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isempty)},
-  { "ISNULL",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)},
-  { "IS_FREE_LOCK",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)},
-  { "IS_USED_LOCK",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_used_lock)},
-  { "LAST_INSERT_ID",	SYM(LAST_INSERT_ID),0,0},
-  { "ISSIMPLE",         SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_issimple)},
-  { "LAST_DAY",         SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_last_day)},
-  { "LCASE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
-  { "LEAST",		SYM(LEAST_SYM),0,0},
-  { "LENGTH",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
-  { "LN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)},
-  { "LINEFROMTEXT",	SYM(LINEFROMTEXT),0,0},
-  { "LINEFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT),0,0},
-  { "LINESTRINGFROMWKB",SYM(GEOMFROMWKB),0,0},
-  { "LOAD_FILE",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)},
-  { "LOCATE",		SYM(LOCATE),0,0},
-  { "LOG",		SYM(LOG_SYM),0,0},
-  { "LOG2",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)},
-  { "LOG10",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)},
-  { "LOWER",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
-  { "LPAD",		SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
-  { "LTRIM",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
-  { "MAKE_SET",		SYM(MAKE_SET_SYM),0,0},
-  { "MAKEDATE",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)},
-  { "MAKETIME",		SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)},
-  { "MASTER_POS_WAIT",	SYM(MASTER_POS_WAIT),0,0},
-  { "MAX",		SYM(MAX_SYM),0,0},
-  { "MBRCONTAINS",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_contains)},
-  { "MBRDISJOINT",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_disjoint)},
-  { "MBREQUAL",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_equals)},
-  { "MBRINTERSECTS",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_intersects)},
-  { "MBROVERLAPS",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
-  { "MBRTOUCHES",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
-  { "MBRWITHIN",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
-  { "MD5",              SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
-  { "MID",		SYM(SUBSTRING),0,0},	/* unireg function */
-  { "MIN",		SYM(MIN_SYM),0,0},
-  { "MLINEFROMTEXT",	SYM(MLINEFROMTEXT),0,0},
-  { "MLINEFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "MPOINTFROMTEXT",	SYM(MPOINTFROMTEXT),0,0},
-  { "MPOINTFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "MPOLYFROMTEXT",	SYM(MPOLYFROMTEXT),0,0},
-  { "MPOLYFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "MONTHNAME",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)},
-  { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT),0,0},
-  { "MULTILINESTRINGFROMWKB",SYM(GEOMFROMWKB),0,0},
-  { "MULTIPOINTFROMTEXT",SYM(MPOINTFROMTEXT),0,0},
-  { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB),0,0},
-  { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT),0,0},
-  { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB),0,0},
-  { "NOW",		SYM(NOW_SYM),0,0},
-  { "NULLIF",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)},
-  { "NUMGEOMETRIES",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numgeometries)},
-  { "NUMINTERIORRINGS",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numinteriorring)},
-  { "NUMPOINTS",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
-  { "OCTET_LENGTH",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
-  { "OCT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
-  { "ORD",              SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
-  { "OVERLAPS",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
-  { "PERIOD_ADD",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
-  { "PERIOD_DIFF",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)},
-  { "PI",		SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)},
-  { "POINTFROMTEXT",	SYM(POINTFROMTEXT),0,0},
-  { "POINTFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "POINTN",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pointn)},
-  { "POLYFROMTEXT",	SYM(POLYFROMTEXT),0,0},
-  { "POLYFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "POLYGONFROMTEXT",	SYM(POLYFROMTEXT),0,0},
-  { "POLYGONFROMWKB",	SYM(GEOMFROMWKB),0,0},
-  { "POSITION",		SYM(POSITION_SYM),0,0},
-  { "POW",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
-  { "POWER",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
-  { "QUARTER",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
-  { "QUOTE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
-  { "RADIANS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
-  { "RAND",		SYM(RAND),0,0},
-  { "RELEASE_LOCK",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
-  { "REPEAT",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_repeat)},
-  { "REVERSE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)},
-  { "ROUND",		SYM(ROUND),0,0},
-  { "RPAD",		SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)},
-  { "RTRIM",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
-  { "SEC_TO_TIME",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
-  { "SESSION_USER",	SYM(USER),0,0},
-  { "SUBDATE",		SYM(SUBDATE_SYM),0,0},
-  { "SIGN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
-  { "SIN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
-  { "SHA",              SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
-  { "SHA1",             SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
-  { "SOUNDEX",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
-  { "SPACE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
-  { "SQRT",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
-  { "SRID",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_srid)},
-  { "STARTPOINT",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_startpoint)},
-  { "STD",		SYM(STD_SYM),0,0},
-  { "STDDEV",		SYM(STD_SYM),0,0},
-  { "STR_TO_DATE",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
-  { "STRCMP",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
-  { "SUBSTR",	  	SYM(SUBSTRING),0,0},
-  { "SUBSTRING",	SYM(SUBSTRING),0,0},
-  { "SUBSTRING_INDEX",	SYM(SUBSTRING_INDEX),0,0},
-  { "SUBTIME",          SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
-  { "SUM",		SYM(SUM_SYM),0,0},
-  { "SYSDATE",		SYM(NOW_SYM),0,0},
-  { "SYSTEM_USER",	SYM(USER),0,0},
-  { "TAN",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
-  { "TIME_FORMAT",	SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
-  { "TIME_TO_SEC",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
-  { "TIMEDIFF",         SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)},
-  { "TO_DAYS",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
-  { "TOUCHES",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_touches)},
-  { "TRIM",		SYM(TRIM),0,0},
-  { "UCASE",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
-  { "UNCOMPRESS",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)},
-  { "UNCOMPRESSED_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)},
-  { "UNIQUE_USERS",	SYM(UNIQUE_USERS),0,0},
-  { "UNIX_TIMESTAMP",	SYM(UNIX_TIMESTAMP),0,0},
-  { "UPPER",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
-  { "VARIANCE",		SYM(VARIANCE_SYM),0,0},
-  { "VERSION",		SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
-  { "WEEK",		SYM(WEEK_SYM),0,0},
-  { "WEEKDAY",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
-  { "WEEKOFYEAR",	SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
-  { "WITHIN",		SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_within)},
-  { "X",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_x)},
-  { "Y",		SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_y)},
-  { "YEARWEEK",		SYM(YEARWEEK),0,0}
+  { "ABS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
+#ifdef DUMMY
+  { "ACOS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
+  { "ADDDATE",		SYM(ADDDATE_SYM)},
+  { "ADDTIME",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)},
+  { "AES_ENCRYPT",      F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)},
+  { "AES_DECRYPT",      F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)},
+  { "AREA",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_area)},
+  { "ASIN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)},
+  { "ASBINARY",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)},
+  { "ASTEXT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)},
+  { "ASWKB",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)},
+  { "ASWKT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)},
+  { "ATAN",		SYM(ATAN)},
+  { "ATAN2",		SYM(ATAN)},
+  { "BENCHMARK",	SYM(BENCHMARK_SYM)},
+  { "BIN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bin)},
+  { "BIT_COUNT",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)},
+  { "BIT_OR",		SYM(BIT_OR)},
+  { "BIT_AND",		SYM(BIT_AND)},
+  { "BIT_XOR",		SYM(BIT_XOR)},
+  { "CAST",		SYM(CAST_SYM)},
+  { "CEIL",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
+  { "CEILING",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
+  { "CURRENT_USER",	F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
+  { "BIT_LENGTH",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
+  { "CENTROID",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)},
+  { "CHAR_LENGTH",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
+  { "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
+  { "COALESCE",		SYM(COALESCE)},
+  { "COERCIBILITY",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)},
+  { "COMPRESS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
+  { "CONCAT",		SYM(CONCAT)},
+  { "CONCAT_WS",	SYM(CONCAT_WS)},
+  { "CONNECTION_ID",	F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)},
+  { "CONTAINS",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)},
+  { "CONV",		F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)},
+  { "CONVERT",		SYM(CONVERT_SYM)},
+  { "COUNT",		SYM(COUNT_SYM)},
+  { "COS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)},
+  { "COT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)},
+  { "CRC32",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)},
+  { "CROSSES",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_crosses)},
+  { "CURDATE",		SYM(CURDATE)},
+  { "CURTIME",		SYM(CURTIME)},
+  { "DATE_ADD",		SYM(DATE_ADD_INTERVAL)},
+  { "DATEDIFF",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)},
+  { "DATE_FORMAT",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)},
+  { "DATE_SUB",		SYM(DATE_SUB_INTERVAL)},
+  { "DAYNAME",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)},
+  { "DAYOFMONTH",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofmonth)},
+  { "DAYOFWEEK",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofweek)},
+  { "DAYOFYEAR",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)},
+  { "DECODE",		SYM(DECODE_SYM)},
+  { "DEGREES",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)},
+  { "DES_ENCRYPT",	SYM(DES_ENCRYPT_SYM)},
+  { "DES_DECRYPT",	SYM(DES_DECRYPT_SYM)},
+  { "DIMENSION",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_dimension)},
+  { "DISJOINT",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)},
+  { "ELT",		SYM(ELT_FUNC)},
+  { "ENCODE",		SYM(ENCODE_SYM)},
+  { "ENCRYPT",		SYM(ENCRYPT)},
+  { "ENDPOINT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_endpoint)},
+  { "ENVELOPE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_envelope)},
+  { "EQUALS",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)},
+  { "EXTERIORRING",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_exteriorring)},
+  { "EXTRACT",		SYM(EXTRACT_SYM)},
+  { "EXP",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)},
+  { "EXPORT_SET",	SYM(EXPORT_SET)},
+  { "FIELD",		SYM(FIELD_FUNC)},	/* For compability */
+  { "FIND_IN_SET",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)},
+  { "FLOOR",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)},
+  { "FORMAT",		SYM(FORMAT_SYM)},
+  { "FOUND_ROWS",	F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)},
+  { "FROM_DAYS",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)},
+  { "FROM_UNIXTIME",	SYM(FROM_UNIXTIME)},
+  { "GET_LOCK",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
+  { "GEOMETRYN",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_geometryn)},
+  { "GEOMETRYTYPE",	SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_geometry_type)},
+  { "GEOMCOLLFROMTEXT",	SYM(GEOMCOLLFROMTEXT)},
+  { "GEOMCOLLFROMWKB",	SYM(GEOMFROMWKB)},
+  { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT)},
+  { "GEOMETRYCOLLECTIONFROMWKB",SYM(GEOMFROMWKB)},
+  { "GEOMETRYFROMTEXT", SYM(GEOMFROMTEXT)},
+  { "GEOMETRYFROMWKB",	SYM(GEOMFROMWKB)},
+  { "GEOMFROMTEXT",	SYM(GEOMFROMTEXT)},
+  { "GEOMFROMWKB",	SYM(GEOMFROMWKB)},
+  { "GLENGTH",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_glength)},
+  { "GREATEST",		SYM(GREATEST_SYM)},
+  { "GROUP_CONCAT",	SYM(GROUP_CONCAT_SYM)},
+  { "GROUP_UNIQUE_USERS",	SYM(GROUP_UNIQUE_USERS)},
+  { "HEX",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)},
+  { "IFNULL",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)},
+  { "INET_ATON",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)},
+  { "INET_NTOA",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)},
+  { "INSTR",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)},
+  { "INTERIORRINGN",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_interiorringn)},
+  { "INTERSECTS",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)},
+  { "ISCLOSED",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isclosed)},
+  { "ISEMPTY",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isempty)},
+  { "ISNULL",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)},
+  { "IS_FREE_LOCK",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)},
+  { "IS_USED_LOCK",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_used_lock)},
+  { "LAST_INSERT_ID",	SYM(LAST_INSERT_ID)},
+  { "ISSIMPLE",         F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_issimple)},
+  { "LAST_DAY",         F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_last_day)},
+  { "LCASE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
+  { "LEAST",		SYM(LEAST_SYM)},
+  { "LENGTH",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
+  { "LN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)},
+  { "LINEFROMTEXT",	SYM(LINEFROMTEXT)},
+  { "LINEFROMWKB",	SYM(GEOMFROMWKB)},
+  { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT)},
+  { "LINESTRINGFROMWKB",SYM(GEOMFROMWKB)},
+  { "LOAD_FILE",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)},
+  { "LOCATE",		SYM(LOCATE)},
+  { "LOG",		SYM(LOG_SYM)},
+  { "LOG2",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)},
+  { "LOG10",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)},
+  { "LOWER",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
+  { "LPAD",		F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
+  { "LTRIM",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
+  { "MAKE_SET",		SYM(MAKE_SET_SYM)},
+  { "MAKEDATE",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)},
+  { "MAKETIME",		F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)},
+  { "MASTER_POS_WAIT",	SYM(MASTER_POS_WAIT)},
+  { "MAX",		SYM(MAX_SYM)},
+  { "MBRCONTAINS",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)},
+  { "MBRDISJOINT",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)},
+  { "MBREQUAL",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)},
+  { "MBRINTERSECTS",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)},
+  { "MBROVERLAPS",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)},
+  { "MBRTOUCHES",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)},
+  { "MBRWITHIN",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)},
+  { "MD5",              F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
+  { "MID",		SYM(SUBSTRING)},	/* unireg function */
+  { "MIN",		SYM(MIN_SYM)},
+  { "MLINEFROMTEXT",	SYM(MLINEFROMTEXT)},
+  { "MLINEFROMWKB",	SYM(GEOMFROMWKB)},
+  { "MPOINTFROMTEXT",	SYM(MPOINTFROMTEXT)},
+  { "MPOINTFROMWKB",	SYM(GEOMFROMWKB)},
+  { "MPOLYFROMTEXT",	SYM(MPOLYFROMTEXT)},
+  { "MPOLYFROMWKB",	SYM(GEOMFROMWKB)},
+  { "MONTHNAME",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)},
+  { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT)},
+  { "MULTILINESTRINGFROMWKB",SYM(GEOMFROMWKB)},
+  { "MULTIPOINTFROMTEXT",SYM(MPOINTFROMTEXT)},
+  { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB)},
+  { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT)},
+  { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB)},
+  { "NOW",		SYM(NOW_SYM)},
+  { "NULLIF",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)},
+  { "NUMGEOMETRIES",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numgeometries)},
+  { "NUMINTERIORRINGS",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numinteriorring)},
+  { "NUMPOINTS",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numpoints)},
+  { "OCTET_LENGTH",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
+  { "OCT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
+  { "ORD",              F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
+  { "OVERLAPS",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)},
+  { "PERIOD_ADD",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
+  { "PERIOD_DIFF",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)},
+  { "PI",		F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)},
+  { "POINTFROMTEXT",	SYM(POINTFROMTEXT)},
+  { "POINTFROMWKB",	SYM(GEOMFROMWKB)},
+  { "POINTN",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_pointn)},
+  { "POLYFROMTEXT",	SYM(POLYFROMTEXT)},
+  { "POLYFROMWKB",	SYM(GEOMFROMWKB)},
+  { "POLYGONFROMTEXT",	SYM(POLYFROMTEXT)},
+  { "POLYGONFROMWKB",	SYM(GEOMFROMWKB)},
+  { "POSITION",		SYM(POSITION_SYM)},
+  { "POW",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
+  { "POWER",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)},
+  { "QUARTER",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quarter)},
+  { "QUOTE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)},
+  { "RADIANS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)},
+  { "RAND",		SYM(RAND)},
+  { "RELEASE_LOCK",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)},
+  { "REPEAT",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_repeat)},
+  { "REVERSE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)},
+  { "ROUND",		SYM(ROUND)},
+  { "RPAD",		F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)},
+  { "RTRIM",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)},
+  { "SEC_TO_TIME",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)},
+  { "SESSION_USER",	SYM(USER)},
+  { "SUBDATE",		SYM(SUBDATE_SYM)},
+  { "SIGN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)},
+  { "SIN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
+  { "SHA",              F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
+  { "SHA1",             F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
+  { "SOUNDEX",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
+  { "SPACE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
+  { "SQRT",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
+  { "SRID",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_srid)},
+  { "STARTPOINT",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_startpoint)},
+  { "STD",		SYM(STD_SYM)},
+  { "STDDEV",		SYM(STD_SYM)},
+  { "STR_TO_DATE",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
+  { "STRCMP",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
+  { "SUBSTR",	  	SYM(SUBSTRING)},
+  { "SUBSTRING",	SYM(SUBSTRING)},
+  { "SUBSTRING_INDEX",	SYM(SUBSTRING_INDEX)},
+#endif /*dummy*/
+  { "SUBTIME",          F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
+  { "SUM",		SYM(SUM_SYM)},
+  { "SYSDATE",		SYM(NOW_SYM)},
+  { "SYSTEM_USER",	SYM(USER)},
+  { "TAN",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
+  { "TIME_FORMAT",	F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
+  { "TIME_TO_SEC",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)},
+  { "TIMEDIFF",         F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)},
+  { "TO_DAYS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)},
+  { "TOUCHES",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)},
+  { "TRIM",		SYM(TRIM)},
+  { "UCASE",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
+  { "UNCOMPRESS",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)},
+  { "UNCOMPRESSED_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)},
+  { "UNIQUE_USERS",	SYM(UNIQUE_USERS)},
+  { "UNIX_TIMESTAMP",	SYM(UNIX_TIMESTAMP)},
+  { "UPPER",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
+  { "VARIANCE",		SYM(VARIANCE_SYM)},
+  { "VERSION",		F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
+  { "WEEK",		SYM(WEEK_SYM)},
+  { "WEEKDAY",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
+  { "WEEKOFYEAR",	F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)},
+  { "WITHIN",		F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)},
+  { "X",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_x)},
+  { "Y",		F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_y)},
+  { "YEARWEEK",		SYM(YEARWEEK)}
 };
diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h
index 9fff1751b1b..63d4f9d69c2 100644
--- a/sql/lex_symbol.h
+++ b/sql/lex_symbol.h
@@ -20,11 +20,17 @@
 #ifndef _lex_symbol_h
 #define _lex_symbol_h
 
+typedef struct st_sym_group {
+  const char *name;
+  const char *needed_define;
+} SYM_GROUP;
+
 typedef struct st_symbol {
   const char *name;
   uint	tok;
   uint length;
   void *create_func;
+  SYM_GROUP *group;
 } SYMBOL;
 
 typedef struct st_lex_symbol
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ecd5f9ccb66..127dc4c3474 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -510,6 +510,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       blob_columns++;
       break;
     case FIELD_TYPE_GEOMETRY:
+#ifdef HAVE_SPATIAL
       if (!(file->table_flags() & HA_HAS_GEOMETRY))
       {
 	my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
@@ -525,6 +526,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       sql_field->unireg_check=Field::BLOB_FIELD;
       blob_columns++;
       break;
+#else
+      my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
+		      "Spatial extentions", "HAVE_SPATIAL");
+      DBUG_RETURN(-1);
+#endif /*HAVE_SPATIAL*/
     case FIELD_TYPE_VAR_STRING:
     case FIELD_TYPE_STRING:
       sql_field->pack_flag=0;
@@ -658,8 +664,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
         key_info->flags = HA_FULLTEXT;
         break;
     case Key::SPATIAL:
+#ifdef HAVE_SPATIAL
         key_info->flags = HA_SPATIAL;
         break;
+#else
+	my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+			"Spatial extentions", "HAVE_SPATIAL");
+	DBUG_RETURN(-1);
+#endif
     case Key::FOREIGN_KEY:
       key_number--;				// Skip this key
       continue;
@@ -688,6 +700,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
        checking for proper key parts number:
     */
 
+#ifdef HAVE_SPATIAL
     /* TODO: Add proper checks if handler supports key_type and algorithm */
     if (key_info->flags == HA_SPATIAL)
     {
@@ -698,8 +711,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
         DBUG_RETURN(-1);
       }
     }
-    else if (key_info->algorithm == HA_KEY_ALG_RTREE)
+    else
+#endif
+    if (key_info->algorithm == HA_KEY_ALG_RTREE)
     {
+#ifdef HAVE_RTREE_KEYS
       if ((key_info->key_parts & 1) == 1)
       {
 	my_printf_error(ER_WRONG_ARGUMENTS,
@@ -710,6 +726,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
 		      MYF(0), "RTREE INDEX");
       DBUG_RETURN(-1);
+#else
+      my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+		      "Spatial extentions", "HAVE_SPATIAL");
+      DBUG_RETURN(-1);
+#endif
     }
 
     List_iterator cols(key->columns);
@@ -779,6 +800,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
             DBUG_RETURN(-1);
           }
         }
+#ifdef HAVE_SPATIAL
         if (key->type  == Key::SPATIAL)
         {
           if (!column->length )
@@ -790,6 +812,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
             column->length=4*sizeof(double);
           }
         }
+#endif
         if (!(sql_field->flags & NOT_NULL_FLAG))
         {
           if (key->type == Key::PRIMARY)
@@ -806,11 +829,13 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
                             MYF(0),column->field_name);
             DBUG_RETURN(-1);
           }
+#ifdef HAVE_SPATIAL
           if (key->type == Key::SPATIAL)
           {
             my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
             DBUG_RETURN(-1);
           }
+#endif
         }
         if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
         {
@@ -834,9 +859,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
 	    DBUG_RETURN(-1);
 	  }
 	}
+#ifdef HAVE_SPATIAL  //TODO HF What's this for???
 	else if (f_is_geom(sql_field->pack_flag))
 	{
 	}
+#endif
 	else if (column->length > length ||
 		 ((f_is_packed(sql_field->pack_flag) ||
 		   ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 310d8a41be2..6ab44cb9f08 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -611,7 +611,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 	udf_type if_exists opt_local opt_table_options table_options
         table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
         opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
-        opt_ignore_leaves fulltext_options
+        opt_ignore_leaves fulltext_options spatial_type
 
 %type 
 	ULONG_NUM raid_types merge_insert_types
@@ -628,7 +628,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 	table_wild no_in_expr expr_expr simple_expr no_and_expr
 	using_list expr_or_default set_expr_or_default interval_expr
 	param_marker singlerow_subselect singlerow_subselect_init
-	exists_subselect exists_subselect_init
+	exists_subselect exists_subselect_init geometry_function
 	signed_literal NUM_literal
 
 %type 
@@ -1244,8 +1244,8 @@ field_spec:
 				(enum enum_field_types) $3,
 				lex->length,lex->dec,lex->type,
 				lex->default_value, lex->comment,
-				lex->change,lex->interval,lex->charset,
-				lex->uint_geom_type))
+				lex->change,lex->interval,lex->charset
+				,lex->uint_geom_type))
 	    YYABORT;
 	};
 
@@ -1297,30 +1297,19 @@ type:
 					  $$=FIELD_TYPE_TINY_BLOB; }
 	| BLOB_SYM opt_len		{ Lex->charset=&my_charset_bin;
 					  $$=FIELD_TYPE_BLOB; }
-	| GEOMETRY_SYM			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_GEOMETRY;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| GEOMETRYCOLLECTION		{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_GEOMETRYCOLLECTION;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| POINT_SYM			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_POINT;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| MULTIPOINT			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_MULTIPOINT;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| LINESTRING			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_LINESTRING;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| MULTILINESTRING		{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_MULTILINESTRING;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| POLYGON			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_POLYGON;
-					  $$=FIELD_TYPE_GEOMETRY; }
-	| MULTIPOLYGON			{ Lex->charset=&my_charset_bin;
-					  Lex->uint_geom_type= (uint) Field::GEOM_MULTIPOLYGON;
-					  $$=FIELD_TYPE_GEOMETRY; }
+	| spatial_type			{ 
+#ifdef HAVE_SPATIAL
+					  Lex->charset=&my_charset_bin;
+					  Lex->uint_geom_type= (uint)$1;
+					  $$=FIELD_TYPE_GEOMETRY;
+#else
+	                                  net_printf(Lex->thd, ER_FEATURE_DISABLED,
+			                             ER(ER_FEATURE_DISABLED),
+			                             MYF(0), "Spatial extentions",
+	                                             "HAVE_SPATIAL");
+					  YYABORT;
+#endif
+					}
 	| MEDIUMBLOB			{ Lex->charset=&my_charset_bin;
 					  $$=FIELD_TYPE_MEDIUM_BLOB; }
 	| LONGBLOB			{ Lex->charset=&my_charset_bin;
@@ -1359,6 +1348,17 @@ type:
 	  }
 	;
 
+spatial_type:
+	GEOMETRY_SYM	      { $$= Field::GEOM_GEOMETRY; }
+	| GEOMETRYCOLLECTION  { $$= Field::GEOM_GEOMETRYCOLLECTION; }
+	| POINT_SYM           { $$= Field::GEOM_POINT; }
+	| MULTIPOINT          { $$= Field::GEOM_MULTIPOINT; }
+	| LINESTRING          { $$= Field::GEOM_LINESTRING; }
+	| MULTILINESTRING     { $$= Field::GEOM_MULTILINESTRING; }
+	| POLYGON             { $$= Field::GEOM_POLYGON; }
+	| MULTIPOLYGON        { $$= Field::GEOM_MULTIPOLYGON; }
+	;
+
 char:
 	CHAR_SYM {}
 	;
@@ -1591,8 +1591,30 @@ key_type:
 	key_or_index			    { $$= Key::MULTIPLE; }
 	| FULLTEXT_SYM			    { $$= Key::FULLTEXT; }
 	| FULLTEXT_SYM key_or_index	    { $$= Key::FULLTEXT; }
-	| SPATIAL_SYM			    { $$= Key::SPATIAL; }
-	| SPATIAL_SYM key_or_index	    { $$= Key::SPATIAL; };
+	| SPATIAL_SYM
+	  {
+#ifdef HAVE_SPATIAL
+	    $$= Key::SPATIAL;
+#else
+	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
+	               ER(ER_FEATURE_DISABLED),
+		       MYF(0), "Spatial extentions",
+	               "HAVE_SPATIAL");
+	    YYABORT;
+#endif
+	  }
+	| SPATIAL_SYM key_or_index
+	  {
+#ifdef HAVE_SPATIAL
+	    $$= Key::SPATIAL;
+#else
+	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
+	               ER(ER_FEATURE_DISABLED),
+	               MYF(0), "Spatial extentions",
+	               "HAVE_SPATIAL");
+	    YYABORT;
+#endif
+	  };
 
 constraint_key_type:
 	PRIMARY_SYM KEY_SYM  { $$= Key::PRIMARY; }
@@ -1617,7 +1639,18 @@ opt_unique_or_fulltext:
 	/* empty */	{ $$= Key::MULTIPLE; }
 	| UNIQUE_SYM	{ $$= Key::UNIQUE; }
 	| FULLTEXT_SYM	{ $$= Key::FULLTEXT;}
-	| SPATIAL_SYM	{ $$= Key::SPATIAL; }
+	| SPATIAL_SYM
+	  {
+#ifdef HAVE_SPATIAL
+	    $$= Key::SPATIAL;
+#else
+	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
+	               ER(ER_FEATURE_DISABLED),
+	               MYF(0), "Spatial extentions",
+	               "HAVE_SPATIAL");
+	    YYABORT;
+#endif
+	  }
         ;
 
 key_alg:
@@ -1627,7 +1660,18 @@ key_alg:
 
 opt_btree_or_rtree:
 	BTREE_SYM	{ $$= HA_KEY_ALG_BTREE; }
-	| RTREE_SYM	{ $$= HA_KEY_ALG_RTREE; }
+	| RTREE_SYM
+	  {
+#ifdef HAVE_RTREE_KEYS
+	    $$= HA_KEY_ALG_RTREE;
+#else
+	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
+	               ER(ER_FEATURE_DISABLED),
+	               MYF(0), "RTree keys",
+	               "HAVE_RTREE_KEYS");
+	    YYABORT;
+#endif
+	  }
 	| HASH_SYM	{ $$= HA_KEY_ALG_HASH; };
 
 key_list:
@@ -1725,8 +1769,8 @@ alter_list_item:
                                   (enum enum_field_types) $5,
                                   lex->length,lex->dec,lex->type,
                                   lex->default_value, lex->comment,
-				  $3.str, lex->interval, lex->charset,
-				  lex->uint_geom_type))
+				  $3.str, lex->interval, lex->charset
+				  ,lex->uint_geom_type))
 	       YYABORT;
           }
           opt_place
@@ -2556,13 +2600,53 @@ simple_expr:
 	| VALUES '(' simple_ident ')'
 	  { $$= new Item_insert_value($3); }
 	| FUNC_ARG0 '(' ')'
-	  { $$= ((Item*(*)(void))($1.symbol->create_func))();}
+	  {
+	    if (!$1.symbol->create_func)
+	    {
+	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
+			 ER(ER_FEATURE_DISABLED),
+			 MYF(0), $1.symbol->group->name,
+	                 $1.symbol->group->needed_define);
+	      YYABORT;
+	    }
+	    $$= ((Item*(*)(void))($1.symbol->create_func))();
+	  }
 	| FUNC_ARG1 '(' expr ')'
-	  { $$= ((Item*(*)(Item*))($1.symbol->create_func))($3);}
+	  {
+	    if (!$1.symbol->create_func)
+	    {
+	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
+			 ER(ER_FEATURE_DISABLED),
+			 MYF(0), $1.symbol->group->name,
+	                 $1.symbol->group->needed_define);
+	      YYABORT;
+	    }
+	    $$= ((Item*(*)(Item*))($1.symbol->create_func))($3);
+	  }
 	| FUNC_ARG2 '(' expr ',' expr ')'
-	  { $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);}
+	  {
+	    if (!$1.symbol->create_func)
+	    {
+	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
+			 ER(ER_FEATURE_DISABLED),
+			 MYF(0), $1.symbol->group->name,
+	                 $1.symbol->group->needed_define);
+	      YYABORT;
+	    }
+	    $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);
+	  }
 	| FUNC_ARG3 '(' expr ',' expr ',' expr ')'
-	  { $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);}
+	  {
+	    if (!$1.symbol->create_func)
+	    {
+	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
+			 ER(ER_FEATURE_DISABLED),
+			 MYF(0), $1.symbol->group->name,
+	                 $1.symbol->group->needed_define);
+	      YYABORT;
+	    }
+	    $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);
+	  }
 	| ADDDATE_SYM '(' expr ',' expr ')'
 	  { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);}
 	| ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
@@ -2645,18 +2729,18 @@ simple_expr:
 	  }
 	| FIELD_FUNC '(' expr ',' expr_list ')'
 	  { $5->push_front($3); $$= new Item_func_field(*$5); }
-	| GEOMFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| GEOMFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| GEOMFROMWKB '(' expr ')'
-	  { $$= new Item_func_geometry_from_wkb($3); }
-	| GEOMFROMWKB '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_wkb($3, $5); }
-	| GEOMETRYCOLLECTION '(' expr_list ')'
-	  { $$= new Item_func_spatial_collection(* $3,
-                       Geometry::wkbGeometryCollection,
-                       Geometry::wkbPoint); }
+	| geometry_function
+	  {
+#ifdef HAVE_SPATIAL
+	    $$= $1;
+#else
+	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
+	               ER(ER_FEATURE_DISABLED),
+	               MYF(0), "Spatial extentions",
+	               "HAVE_SPATIAL");
+	    YYABORT;
+#endif
+	  }
 	| GET_FORMAT '(' date_time_type  ',' expr ')'
 	  { $$= new Item_func_get_format($3, $5); }
 	| HOUR_SYM '(' expr ')'
@@ -2690,17 +2774,10 @@ simple_expr:
 	  }
 	| LEFT '(' expr ',' expr ')'
 	  { $$= new Item_func_left($3,$5); }
-	| LINESTRING '(' expr_list ')'
-	  { $$= new Item_func_spatial_collection(* $3,
-               Geometry::wkbLineString, Geometry::wkbPoint); }
 	| LOCATE '(' expr ',' expr ')'
 	  { $$= new Item_func_locate($5,$3); }
 	| LOCATE '(' expr ',' expr ',' expr ')'
 	  { $$= new Item_func_locate($5,$3,$7); }
- 	| GEOMCOLLFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| GEOMCOLLFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
 	| GREATEST_SYM '(' expr ',' expr_list ')'
 	  { $5->push_front($3); $$= new Item_func_max(*$5); }
 	| LEAST_SYM '(' expr ',' expr_list ')'
@@ -2709,10 +2786,6 @@ simple_expr:
 	  { $$= new Item_func_log($3); }
 	| LOG_SYM '(' expr ',' expr ')'
 	  { $$= new Item_func_log($3, $5); }
- 	| LINEFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| LINEFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
 	| MASTER_POS_WAIT '(' expr ',' expr ')'
 	  {
 	    $$= new Item_master_pos_wait($3, $5);
@@ -2731,27 +2804,6 @@ simple_expr:
 	  { $$ = new Item_func_mod( $3, $5); }
 	| MONTH_SYM '(' expr ')'
 	  { $$= new Item_func_month($3); }
- 	| MULTILINESTRING '(' expr_list ')'
- 	  { $$= new Item_func_spatial_collection(* $3,
-                    Geometry::wkbMultiLineString, Geometry::wkbLineString); }
- 	| MLINEFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| MLINEFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| MPOINTFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| MPOINTFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| MPOLYFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| MPOLYFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| MULTIPOINT '(' expr_list ')'
-	  { $$= new Item_func_spatial_collection(* $3,
-                    Geometry::wkbMultiPoint, Geometry::wkbPoint); }
- 	| MULTIPOLYGON '(' expr_list ')'
-	  { $$= new Item_func_spatial_collection(* $3,
-                       Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); }
 	| NOW_SYM optional_braces
 	  { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;}
 	| NOW_SYM '(' expr ')'
@@ -2764,19 +2816,6 @@ simple_expr:
 	  }
 	| OLD_PASSWORD '(' expr ')'
 	  { $$=  new Item_func_old_password($3); }
-	| POINT_SYM '(' expr ',' expr ')'
-	  { $$= new Item_func_point($3,$5); }
- 	| POINTFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| POINTFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| POLYFROMTEXT '(' expr ')'
-	  { $$= new Item_func_geometry_from_text($3); }
-	| POLYFROMTEXT '(' expr ',' expr ')'
-	  { $$= new Item_func_geometry_from_text($3, $5); }
-	| POLYGON '(' expr_list ')'
-	  { $$= new Item_func_spatial_collection(* $3,
-			Geometry::wkbPolygon, Geometry::wkbLineString); }
 	| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
 	  { $$ = new Item_func_locate($5,$3); }
 	| RAND '(' expr ')'
@@ -2914,6 +2953,66 @@ simple_expr:
 	| EXTRACT_SYM '(' interval FROM expr ')'
 	{ $$=new Item_extract( $3, $5); };
 
+geometry_function:
+	GEOMFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| GEOMFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| GEOMFROMWKB '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_wkb($3)); }
+	| GEOMFROMWKB '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); }
+	| GEOMETRYCOLLECTION '(' expr_list ')'
+	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
+                           Geometry::wkbGeometryCollection,
+                           Geometry::wkbPoint)); }
+	| LINESTRING '(' expr_list ')'
+	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
+                  Geometry::wkbLineString, Geometry::wkbPoint)); }
+ 	| MULTILINESTRING '(' expr_list ')'
+	  { $$= GEOM_NEW( Item_func_spatial_collection(* $3,
+                   Geometry::wkbMultiLineString, Geometry::wkbLineString)); }
+ 	| MLINEFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| MLINEFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| MPOINTFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| MPOINTFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| MPOLYFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| MPOLYFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| MULTIPOINT '(' expr_list ')'
+	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
+                  Geometry::wkbMultiPoint, Geometry::wkbPoint)); }
+ 	| MULTIPOLYGON '(' expr_list ')'
+	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
+                  Geometry::wkbMultiPolygon, Geometry::wkbPolygon)); }
+	| POINT_SYM '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_point($3,$5)); }
+ 	| POINTFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| POINTFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| POLYFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| POLYFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	| POLYGON '(' expr_list ')'
+	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
+	          Geometry::wkbPolygon, Geometry::wkbLineString)); }
+ 	| GEOMCOLLFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| GEOMCOLLFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+ 	| LINEFROMTEXT '(' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
+	| LINEFROMTEXT '(' expr ',' expr ')'
+	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
+	;
+
 fulltext_options:
         /* nothing */                   { $$= FT_NL;  }
         | WITH QUERY_SYM EXPANSION_SYM  { $$= FT_NL | FT_EXPAND; }
diff --git a/sql/table.cc b/sql/table.cc
index 912c133e571..724921c956b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -405,8 +405,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
       // charset and geometry_type share the same byte in frm
       if (field_type == FIELD_TYPE_GEOMETRY)
       {
+#ifdef HAVE_SPATIAL
 	geom_type= (Field::geometry_type) strpos[14];
 	charset= &my_charset_bin;
+#else
+	error= 4;  // unsupported field type
+	goto err_not_open;
+#endif
       }
       else
       {
diff --git a/sql/unireg.cc b/sql/unireg.cc
index fc948ddd5a6..6ebba313442 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -471,7 +471,12 @@ static bool pack_fields(File file,List &create_fields)
     buff[12]= (uchar) field->interval_id;
     buff[13]= (uchar) field->sql_type; 
     if (field->sql_type == FIELD_TYPE_GEOMETRY)
+    {
       buff[14]= (uchar) field->geom_type;
+#ifndef HAVE_SPATIAL
+      DBUG_ASSERT(0);                           // Should newer happen
+#endif
+    }
     else if (field->charset) 
       buff[14]= (uchar) field->charset->number;
     else

From 94e6b9be19ecfbb4c541b2f2d49f08ffc351a1ab Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 16 Jan 2004 16:22:59 +0100
Subject: [PATCH 074/157]  - Fixed BUG#2297: cmd-line-utils/libedit/makelist
 used a hard-coded    call to /usr/bin/awk - replaced this with the proper
 autoconf variable    instead (makelist is now generated out of makelist.sh
 during the compile    phase)

cmd-line-utils/libedit/Makefile.am:
   - replace @AWK@ with the correct path to the awk binary determined by
     configure instead of using a hard-coded path (BUG#2297)
cmd-line-utils/libedit/makelist.sh:
   - replace @AWK@ with the correct path to the awk binary determined by
     configure instead of using a hard-coded path (BUG#2297)
---
 cmd-line-utils/libedit/Makefile.am               | 13 ++++++++++++-
 cmd-line-utils/libedit/{makelist => makelist.sh} |  2 +-
 2 files changed, 13 insertions(+), 2 deletions(-)
 rename cmd-line-utils/libedit/{makelist => makelist.sh} (99%)

diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am
index 19171f62ffb..eb6b930c0b2 100644
--- a/cmd-line-utils/libedit/Makefile.am
+++ b/cmd-line-utils/libedit/Makefile.am
@@ -24,10 +24,21 @@ noinst_HEADERS =	chared.h el.h histedit.h key.h \
 			hist.h map.h prompt.h search.h \
 			strlcpy.h libedit_term.h tty.h
 
-EXTRA_DIST = makelist
+EXTRA_DIST = makelist.sh
+
+CLEANFILES = makelist
 
 DEFS =			-DUNDEF_THREADS_HACK -DHAVE_CONFIG_H -DNO_KILL_INTR
 
+SUFFIXES = .sh
+
+.sh:
+	@RM@ -f $@ $@-t
+	@SED@ \
+	  -e 's!@''AWK''@!@AWK@!' \
+	$< > $@-t
+	@MV@ $@-t $@
+
 vi.h: vi.c makelist
 	sh ./makelist -h ./vi.c > $@.tmp && \
 	mv $@.tmp $@
diff --git a/cmd-line-utils/libedit/makelist b/cmd-line-utils/libedit/makelist.sh
similarity index 99%
rename from cmd-line-utils/libedit/makelist
rename to cmd-line-utils/libedit/makelist.sh
index 3c3338e9875..13d37512591 100644
--- a/cmd-line-utils/libedit/makelist
+++ b/cmd-line-utils/libedit/makelist.sh
@@ -39,7 +39,7 @@
 
 # makelist.sh: Automatically generate header files...
 
-AWK=/usr/bin/awk
+AWK=@AWK@
 USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m "
 
 if [ "x$1" = "x" ]

From c217c4867bcf3933f7d889a9eeb41902b9e19261 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 16 Jan 2004 20:05:08 +0200
Subject: [PATCH 075/157] Two bug fixes

mysql-test/t/mysqldump.test:
  Fixing a test to encompass latest Jani's patch to mysqldump.c
sql/sql_union.cc:
  Fix for the unlock problem with a typo correction.
---
 mysql-test/t/mysqldump.test | 12 ++++++------
 sql/sql_union.cc            |  3 ++-
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 1299d73eb99..21004c8c305 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -6,7 +6,7 @@ DROP TABLE IF EXISTS t1, `"t"1`;
 
 CREATE TABLE t1(a int);
 INSERT INTO t1 VALUES (1), (2);
---exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -16,7 +16,7 @@ DROP TABLE t1;
 CREATE TABLE t1 (a decimal(240, 20));
 INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
 ("0987654321098765432109876543210987654321");
---exec $MYSQL_DUMP --skip-comments test t1
+--exec $MYSQL_DUMP --disable-quote --skip-comments test t1
 DROP TABLE t1;
 
 #
@@ -28,12 +28,12 @@ INSERT INTO t1 VALUES (-9e999999);
 # The following replaces is here because some systems replaces the above
 # double with '-inf' and others with MAX_DOUBLE
 --replace_result (-1.79769313486232e+308) (RES) (NULL) (RES)
---exec $MYSQL_DUMP --skip-comments test t1
+--exec $MYSQL_DUMP --disable-quote --skip-comments test t1
 DROP TABLE t1;
 
 CREATE TABLE t1(a int, b text, c varchar(3));
 INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
---exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -42,7 +42,7 @@ DROP TABLE t1;
 
 CREATE TABLE t1 (`a"b"` char(2));
 INSERT INTO t1 VALUES ("1\""), ("\"2");
---exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -51,5 +51,5 @@ DROP TABLE t1;
 
 CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
---exec $MYSQL_DUMP --skip-comments test t1
+--exec $MYSQL_DUMP --disable-quote --skip-comments test t1
 DROP TABLE t1;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 25620229844..cdf8173e1b3 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -145,8 +145,9 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result)
 
   for (;sl; sl= sl->next_select())
   {
+    sl->options|=  SELECT_NO_UNLOCK;
     JOIN *join= new JOIN(thd_arg, sl->item_list, 
-			 sl->options | thd_arg->options | SELECT_NO_UNLOCK,
+			 sl->options | thd_arg->options,
 			 tmp_result);
     thd_arg->lex->current_select= sl;
     offset_limit_cnt= sl->offset_limit;

From 12e7d6a39d7c71b48f04d62e4bd6bc995441d39b Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 17 Jan 2004 12:03:14 +0200
Subject: [PATCH 076/157] mysqldump results fixed

---
 mysql-test/r/mysqldump.result | 42 +++++++++++++++++------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 04effdfef7c..f51caee39d6 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -21,17 +21,17 @@ DROP TABLE t1;
 CREATE TABLE t1 (a decimal(240, 20));
 INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
 ("0987654321098765432109876543210987654321");
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (
-  a decimal(240,20) default NULL
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `a` decimal(240,20) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 
 
-/*!40000 ALTER TABLE t1 DISABLE KEYS */;
-LOCK TABLES t1 WRITE;
-INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890.00000000000000000000"),("0987654321098765432109876543210987654321.00000000000000000000");
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES ("1234567890123456789012345678901234567890.00000000000000000000"),("0987654321098765432109876543210987654321.00000000000000000000");
 UNLOCK TABLES;
-/*!40000 ALTER TABLE t1 ENABLE KEYS */;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
 
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
@@ -41,17 +41,17 @@ UNLOCK TABLES;
 DROP TABLE t1;
 CREATE TABLE t1 (a double);
 INSERT INTO t1 VALUES (-9e999999);
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (
-  a double default NULL
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `a` double default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 
 
-/*!40000 ALTER TABLE t1 DISABLE KEYS */;
-LOCK TABLES t1 WRITE;
-INSERT INTO t1 VALUES (RES);
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (RES);
 UNLOCK TABLES;
-/*!40000 ALTER TABLE t1 ENABLE KEYS */;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
 
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
@@ -105,17 +105,17 @@ INSERT INTO t1 VALUES ("1\""), ("\"2");
 DROP TABLE t1;
 CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1 (
-  a varchar(255) default NULL
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `a` varchar(255) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=koi8r;
 
 
-/*!40000 ALTER TABLE t1 DISABLE KEYS */;
-LOCK TABLES t1 WRITE;
-INSERT INTO t1 VALUES ('Π°Π±Ρ†Π΄Π΅');
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES ('Π°Π±Ρ†Π΄Π΅');
 UNLOCK TABLES;
-/*!40000 ALTER TABLE t1 ENABLE KEYS */;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
 
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

From 2de832dbf99a8796b081419a29cacbeb07cd3871 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 17 Jan 2004 13:00:46 +0200
Subject: [PATCH 077/157] switched to new syntax (TYPE->ENGINE) check of memory
 allocation operation was added

mysql-test/r/subselect_innodb.result:
  switched to new syntax
mysql-test/t/subselect_innodb.test:
  switched to new syntax
sql/sql_select.cc:
  check of memory allocation operation
---
 mysql-test/r/subselect_innodb.result | 4 ++--
 mysql-test/t/subselect_innodb.test   | 4 ++--
 sql/sql_select.cc                    | 3 ++-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index 3a2a36475c5..e3528e06546 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -69,7 +69,7 @@ b int(11) default NULL,
 c char(3) default NULL,
 PRIMARY KEY  (id),
 KEY t2i1 (b)
-) TYPE=innodb DEFAULT CHARSET=latin1;
+) ENGINE=innodb DEFAULT CHARSET=latin1;
 INSERT INTO t1 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL');
 CREATE TABLE t2 (
 id int(11) NOT NULL default '0',
@@ -77,7 +77,7 @@ b int(11) default NULL,
 c char(3) default NULL,
 PRIMARY KEY  (id),
 KEY t2i (b)
-) TYPE=innodb DEFAULT CHARSET=latin1;
+) ENGINE=innodb DEFAULT CHARSET=latin1;
 INSERT INTO t2 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL');
 select (select max(id) from t2 where b=1 group by b) as x,b from t1 where b=1;
 x	b
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index c17f3f30e39..affa6301db4 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -78,7 +78,7 @@ CREATE TABLE t1 (
   c char(3) default NULL,
   PRIMARY KEY  (id),
   KEY t2i1 (b)
-) TYPE=innodb DEFAULT CHARSET=latin1;
+) ENGINE=innodb DEFAULT CHARSET=latin1;
 INSERT INTO t1 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL');
 CREATE TABLE t2 (
   id int(11) NOT NULL default '0',
@@ -86,7 +86,7 @@ CREATE TABLE t2 (
   c char(3) default NULL,
   PRIMARY KEY  (id),
   KEY t2i (b)
-) TYPE=innodb DEFAULT CHARSET=latin1;
+) ENGINE=innodb DEFAULT CHARSET=latin1;
 INSERT INTO t2 VALUES (0,0,'GPL'),(1,0,'GPL'),(2,1,'GPL'),(3,2,'GPL');
 select (select max(id) from t2 where b=1 group by b) as x,b from t1 where b=1;
 drop table t1,t2;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1b03a70c43d..3f9492f1d72 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1586,7 +1586,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
   }
   else
   {
-    join= new JOIN(thd, fields, select_options, result);
+    if (!(join= new JOIN(thd, fields, select_options, result)))
+	DBUG_RETURN(-1);
     thd->proc_info="init";
     thd->used_tables=0;                         // Updated by setup_fields
     if (join->prepare(rref_pointer_array, tables, wild_num,

From 19fe657f4edf5e7f08a91e2c8e20a194ca4f204b Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 17 Jan 2004 13:09:41 +0200
Subject: [PATCH 078/157] commit of forgoten test

---
 mysql-test/t/subselect_innodb.test | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index 9eb35ffc0fd..e1f26776134 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -67,4 +67,15 @@ INSERT INTO t1 VALUES (1),(2),(3);
 INSERT INTO t3 VALUES (1,1),(2,2),(3,3);
 INSERT INTO t2 VALUES (1,1),(2,2),(3,3);
 SELECT distinct p1.processor_id, (SELECT y.yod_id FROM t1 p2, t2 y WHERE p2.processor_id = p1.processor_id and p2.processor_id = y.processor_id) FROM t1 p1;
-drop table t1,t2,t3;
\ No newline at end of file
+drop table t1,t2,t3;
+
+#
+# reiniting innodb tables
+#
+create table t1 (id int not null, value char(255), primary key(id)) engine=innodb;
+create table t2 (id int not null, value char(255)) engine=innodb;
+insert into t1 values (1,'a'),(2,'b');
+insert into t2 values (1,'z'),(2,'x');
+select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
+select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
+drop table t1,t2;

From d63d204c07563050d99f16a9ff35e2c1e93a9d05 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 17 Jan 2004 15:28:20 +0200
Subject: [PATCH 079/157] new test added test fixed

---
 mysql-test/r/derived.result | 12 ++++++------
 mysql-test/t/derived.test   |  5 +++--
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 9b5aa9123a4..8cf0b45102f 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -85,6 +85,10 @@ a	b
 2	b
 3	c
 3	c
+select * from (select * from t1 union all select * from t1 limit 2) a;
+a	b
+1	a
+2	b
 explain select * from (select * from t1 union select * from t1) a;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	3	
@@ -258,17 +262,13 @@ ID int(11) default NULL,
 PARID int(11) default NULL,
 UNIQUE KEY t2_ID_IDX (ID),
 KEY t2_PARID_IDX (PARID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
-Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+) engine=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO t2 VALUES (1000,0),(1001,0),(1002,0),(1003,0),(1008,1),(1009,1),(1010,1),(1011,1),(1016,2);
 CREATE TABLE t3 (
 ID int(11) default NULL,
 DATA decimal(10,2) default NULL,
 UNIQUE KEY t3_ID_IDX (ID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
-Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+) engine=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
 select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
 497	ID	NULL
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index bb61dab6d74..8de95b4b600 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -35,6 +35,7 @@ select a from (select 1 as a) as b;
 select 1 from (select 1) as a;
 select * from (select * from t1 union select * from t1) a;
 select * from (select * from t1 union all select * from t1) a;
+select * from (select * from t1 union all select * from t1 limit 2) a;
 explain select * from (select * from t1 union select * from t1) a;
 explain select * from (select * from t1 union all select * from t1) a;
 CREATE TABLE t2 (a int not null);
@@ -154,13 +155,13 @@ CREATE TABLE t2 (
   PARID int(11) default NULL,
   UNIQUE KEY t2_ID_IDX (ID),
   KEY t2_PARID_IDX (PARID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
+) engine=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO t2 VALUES (1000,0),(1001,0),(1002,0),(1003,0),(1008,1),(1009,1),(1010,1),(1011,1),(1016,2);
 CREATE TABLE t3 (
   ID int(11) default NULL,
   DATA decimal(10,2) default NULL,
   UNIQUE KEY t3_ID_IDX (ID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
+) engine=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
 select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
 drop table t1, t2, t3;

From 62e9ab4515bedc12dfefeb7107b8c46e27494126 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 18 Jan 2004 17:29:27 +0100
Subject: [PATCH 080/157] trivial FT2 bug in mi_write fixed (same as
 ChangeSet@1.1538.36.1, 2003-06-12 12:41:29+02:00, serg@serg.mylan, "FT2 bug
 in mi_delete fixed") BUG#2417

---
 myisam/mi_write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index d13ba6c2c4e..060d4431de6 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -378,7 +378,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
         my_off_t root=info->dupp_key_pos;
         keyinfo=&info->s->ft2_keyinfo;
         key+=off;
-        keypos-=keyinfo->keylength; /* we'll modify key entry 'in vivo' */
+        keypos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */
         error=_mi_ck_real_write_btree(info, keyinfo, key, 0,
                                       &root, comp_flag);
         _mi_dpointer(info, keypos+HA_FT_WLEN, root);

From cf2b6edaadd9fcd1389803545b3716f1cd258753 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 18 Jan 2004 22:30:35 +0000
Subject: [PATCH 081/157] Fix deprecation warning - database_engine =>
 storage_engine

BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
---
 BitKeeper/etc/logging_ok     | 1 +
 mysql-test/r/derived.result  | 2 +-
 mysql-test/r/symlink.result  | 2 +-
 mysql-test/r/warnings.result | 4 ++--
 sql/sql_yacc.yy              | 2 +-
 5 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 785ea13b492..a7eb7c81105 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -5,6 +5,7 @@ Administrator@fred.
 Miguel@light.local
 Sinisa@sinisa.nasamreza.org
 WAX@sergbook.mysql.com
+acurtis@pcgem.rdg.cyberkinetica.com
 administrador@light.hegel.local
 ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
 akishkin@work.mysql.com
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 8cf0b45102f..c0d2ce287db 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -256,7 +256,7 @@ KEY t1_SortIndex (SORTORDER),
 KEY t1_IdIndex (OBJECTID)
 ) TYPE=MyISAM DEFAULT CHARSET=latin1;
 Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
 CREATE TABLE t2 (
 ID int(11) default NULL,
 PARID int(11) default NULL,
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 4ba0ca0eac4..6dc48a0a77e 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -66,7 +66,7 @@ t9	CREATE TABLE `t9` (
 drop database mysqltest;
 create table t1 (a int not null) type=myisam;
 Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index 5c7c75bac00..c3d9f165fed 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -128,10 +128,10 @@ Warning	1265	Using storage engine MyISAM for table 't1'
 drop table t1;
 create table t1 (id int) type=heap;
 Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
 alter table t1 type=myisam;
 Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
 drop table t1;
 set table_type=MYISAM;
 Warnings:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 310d8a41be2..ab95ba312d8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1077,7 +1077,7 @@ create_table_options:
 
 create_table_option:
 	ENGINE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; }
-	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=database_engine","ENGINE=database_engine"); }
+	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine"); }
 	| MAX_ROWS opt_equal ulonglong_num	{ Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
 	| MIN_ROWS opt_equal ulonglong_num	{ Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
 	| AVG_ROW_LENGTH opt_equal ULONG_NUM	{ Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}

From a66924353a9fb4a1c1bfa05ad45aa3cabc34c3b6 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 14:10:05 +0400
Subject: [PATCH 082/157] Test case for the bug #2198: SELECT INTO OUTFILE
 (with Sub-Select) Problem.

---
 mysql-test/r/subselect.result |  9 +++++++++
 mysql-test/t/subselect.test   | 12 ++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 672a39299dd..ded98265a1c 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1569,3 +1569,12 @@ INSERT INTO t2 VALUES (100, 200, 'C');
 SELECT DISTINCT COLC FROM t1 WHERE COLA = (SELECT COLA FROM t2 WHERE COLB = 200 AND COLC ='C' LIMIT 1);
 COLC
 DROP TABLE t1, t2;
+create table t1 (a int, b decimal(13, 3));
+insert into t1 values (1, 0.123);
+select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1;
+delete from t1;
+load data infile "subselect.out.file.1" into table t1;
+select * from t1;
+a	b
+1	0.123
+drop table t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 95e4f022f2d..37dbc8f24d9 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1009,3 +1009,15 @@ INSERT INTO t1 VALUES (1,1,'1A3240'), (1,2,'4W2365');
 INSERT INTO t2 VALUES (100, 200, 'C');
 SELECT DISTINCT COLC FROM t1 WHERE COLA = (SELECT COLA FROM t2 WHERE COLB = 200 AND COLC ='C' LIMIT 1);
 DROP TABLE t1, t2;
+
+#
+# Bug 2198
+#
+
+create table t1 (a int, b decimal(13, 3)); 
+insert into t1 values (1, 0.123);
+select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1;
+delete from t1;
+load data infile "subselect.out.file.1" into table t1;
+select * from t1;
+drop table t1;

From 06de76aec5f3758bb07bdd66950aa4a8f2d5e4f4 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 14:22:38 +0100
Subject: [PATCH 083/157] field length convertion (bytes->chars) should be done
 with rounding UP.

---
 mysql-test/r/ctype_utf8.result | 11 +++++++++++
 mysql-test/t/ctype_utf8.test   | 12 ++++++++++++
 sql/field.cc                   |  6 +++---
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 16c65619878..7c05b1ea446 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
 set names utf8;
 select left(_utf8 0xD0B0D0B1D0B2,1);
 left(_utf8 0xD0B0D0B1D0B2,1)
@@ -68,3 +69,13 @@ this	is a	test
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
 insert("aa",100,1,"b")	insert("aa",1,3,"b")
 aa	b
+create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(4) character set utf8 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t1;
+date_format("2004-01-19 10:10:10", "%Y-%m-%d")
+2004-01-19
+drop table t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 5c924e82729..5e9324dd68f 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -2,6 +2,9 @@
 # Tests with the utf8 character set
 #
 
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
 set names utf8;
 
 select left(_utf8 0xD0B0D0B1D0B2,1);
@@ -41,3 +44,12 @@ select _utf8 0xD0B0D0B1D0B2 like concat(_utf8'%',_utf8 0xD0B1,_utf8 '%');
 #
 select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
 select insert("aa",100,1,"b"),insert("aa",1,3,"b");
+
+#
+# CREATE ... SELECT
+#
+create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
+show create table t1;
+select * from t1;
+drop table t1;
+
diff --git a/sql/field.cc b/sql/field.cc
index 5602231dd9b..1a0716326fe 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5611,16 +5611,16 @@ create_field::create_field(Field *old_field,Field *orig_field)
         case  3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
         default: sql_type= FIELD_TYPE_LONG_BLOB; break;
       }
-      length /= charset->mbmaxlen;		// QQ: Probably not needed
+      length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed
       break;
     case FIELD_TYPE_STRING:
     case FIELD_TYPE_VAR_STRING:
-      length /= charset->mbmaxlen;
+      length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
       break;
     default:
       break;
   }
-  
+
   decimals= old_field->decimals();
   if (sql_type == FIELD_TYPE_STRING)
   {

From 162f1dc5e6f8cd24ec996aa701a50bf20b8f6a36 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 19:16:30 +0400
Subject: [PATCH 084/157] UCS-2 aligning 0xAA -> 0x00AA

---
 include/m_ctype.h             |  3 ++-
 mysql-test/r/ctype_ucs.result | 48 +++++++++++++++++++++++++++++++++++
 mysql-test/t/ctype_ucs.test   | 21 +++++++++++++++
 mysys/charset.c               |  4 ++-
 sql/item.h                    |  4 +--
 sql/sql_string.cc             | 46 +++++++++++++++++++++++++++++++++
 sql/sql_string.h              |  1 +
 strings/ctype-big5.c          |  2 ++
 strings/ctype-bin.c           |  1 +
 strings/ctype-czech.c         |  1 +
 strings/ctype-euc_kr.c        |  2 ++
 strings/ctype-extra.c         |  1 +
 strings/ctype-gb2312.c        |  2 ++
 strings/ctype-gbk.c           |  2 ++
 strings/ctype-latin1.c        |  3 +++
 strings/ctype-sjis.c          |  2 ++
 strings/ctype-tis620.c        |  2 ++
 strings/ctype-ucs2.c          |  2 ++
 strings/ctype-ujis.c          |  2 ++
 strings/ctype-utf8.c          |  2 ++
 strings/ctype-win1250ch.c     |  1 +
 21 files changed, 148 insertions(+), 4 deletions(-)

diff --git a/include/m_ctype.h b/include/m_ctype.h
index 0228b359111..4a9415f43f9 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -206,8 +206,9 @@ typedef struct charset_info_st
   uchar state_map[256];
   uchar ident_map[256];
   uint      strxfrm_multiply;
+  uint      mbminlen;
   uint      mbmaxlen;
-  char    max_sort_char; /* For LIKE optimization */
+  char      max_sort_char; /* For LIKE optimization */
   
   MY_CHARSET_HANDLER *cset;
   MY_COLLATION_HANDLER *coll;
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 58761526150..d6e9cc690a2 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -276,3 +276,51 @@ aardvara
 aardvark
 aardvarz
 DROP TABLE t1;
+SELECT HEX(_ucs2 0x0);
+HEX(_ucs2 0x0)
+0000
+SELECT HEX(_ucs2 0x01);
+HEX(_ucs2 0x01)
+0001
+SELECT HEX(_ucs2 0x012);
+HEX(_ucs2 0x012)
+0012
+SELECT HEX(_ucs2 0x0123);
+HEX(_ucs2 0x0123)
+0123
+SELECT HEX(_ucs2 0x01234);
+HEX(_ucs2 0x01234)
+00001234
+SELECT HEX(_ucs2 0x012345);
+HEX(_ucs2 0x012345)
+00012345
+SELECT HEX(_ucs2 0x0123456);
+HEX(_ucs2 0x0123456)
+00123456
+SELECT HEX(_ucs2 0x01234567);
+HEX(_ucs2 0x01234567)
+01234567
+SELECT HEX(_ucs2 0x012345678);
+HEX(_ucs2 0x012345678)
+000012345678
+SELECT HEX(_ucs2 0x0123456789);
+HEX(_ucs2 0x0123456789)
+000123456789
+SELECT HEX(_ucs2 0x0123456789A);
+HEX(_ucs2 0x0123456789A)
+00123456789A
+SELECT HEX(_ucs2 0x0123456789AB);
+HEX(_ucs2 0x0123456789AB)
+0123456789AB
+SELECT HEX(_ucs2 0x0123456789ABC);
+HEX(_ucs2 0x0123456789ABC)
+0000123456789ABC
+SELECT HEX(_ucs2 0x0123456789ABCD);
+HEX(_ucs2 0x0123456789ABCD)
+000123456789ABCD
+SELECT HEX(_ucs2 0x0123456789ABCDE);
+HEX(_ucs2 0x0123456789ABCDE)
+00123456789ABCDE
+SELECT HEX(_ucs2 0x0123456789ABCDEF);
+HEX(_ucs2 0x0123456789ABCDEF)
+0123456789ABCDEF
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 7eec58563b3..fd2a1b1cd7d 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -197,3 +197,24 @@ DROP TABLE t1;
 # END OF Bug 1264 test
 #
 ########################################################
+
+
+# Bug #2390
+# Check alignment
+#
+SELECT HEX(_ucs2 0x0);
+SELECT HEX(_ucs2 0x01);
+SELECT HEX(_ucs2 0x012);
+SELECT HEX(_ucs2 0x0123);
+SELECT HEX(_ucs2 0x01234);
+SELECT HEX(_ucs2 0x012345);
+SELECT HEX(_ucs2 0x0123456);
+SELECT HEX(_ucs2 0x01234567);
+SELECT HEX(_ucs2 0x012345678);
+SELECT HEX(_ucs2 0x0123456789);
+SELECT HEX(_ucs2 0x0123456789A);
+SELECT HEX(_ucs2 0x0123456789AB);
+SELECT HEX(_ucs2 0x0123456789ABC);
+SELECT HEX(_ucs2 0x0123456789ABCD);
+SELECT HEX(_ucs2 0x0123456789ABCDE);
+SELECT HEX(_ucs2 0x0123456789ABCDEF);
diff --git a/mysys/charset.c b/mysys/charset.c
index 5e9e3c3fcaa..40a026f161f 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -131,7 +131,8 @@ static void simple_cs_init_functions(CHARSET_INFO *cs)
     cs->coll= &my_collation_8bit_simple_ci_handler;
   
   cs->cset= &my_charset_8bit_handler;
-  cs->mbmaxlen    = 1;
+  cs->mbminlen= 1;
+  cs->mbmaxlen= 1;
 }
 
 
@@ -273,6 +274,7 @@ static int simple_cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from)
     if (create_fromuni(to))
       goto err;
   }
+  to->mbminlen= 1;
   to->mbmaxlen= 1;
 
   return 0;
diff --git a/sql/item.h b/sql/item.h
index 5def1e2b710..e6ed8109534 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -477,7 +477,7 @@ public:
   	      CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
   {
     collation.set(cs, dv);
-    str_value.set(str,length,cs);
+    str_value.set_or_copy_aligned(str,length,cs);
     /*
       We have to have a different max_length than 'length' here to
       ensure that we get the right length if we do use the item
@@ -493,7 +493,7 @@ public:
 	      CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
   {
     collation.set(cs, dv);
-    str_value.set(str,length,cs);
+    str_value.set_or_copy_aligned(str,length,cs);
     max_length= str_value.numchars()*cs->mbmaxlen;
     set_name(name_par,0,cs);
     decimals=NOT_FIXED_DEC;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 89f48607969..9534c5605fe 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -228,6 +228,52 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
   return FALSE;
 }
 
+/*
+** For real multi-byte, ascii incompatible charactser sets,
+** like UCS-2, add leading zeros if we have an incomplete character.
+** Thus, 
+**   SELECT _ucs2 0xAA 
+** will automatically be converted into
+**   SELECT _ucs2 0x00AA
+*/
+
+bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
+				 CHARSET_INFO *cs)
+{
+  /* How many bytes are in incomplete character */
+  uint32 offs= (arg_length % cs->mbminlen); 
+
+  if (!offs) /* All characters are complete, just copy */
+  {
+    set(str, arg_length, cs);
+    return FALSE;
+  }
+  
+  offs= cs->mbmaxlen - offs; /* How many zeros we should prepend */
+  uint32 aligned_length= arg_length + offs;
+  if (alloc(aligned_length))
+    return TRUE;
+  
+  /*
+    Probably this condition is not really necessary
+    because if aligned_length is 0 then offs is 0 too
+    and we'll return after calling set().
+  */
+  if ((str_length= aligned_length))
+  {
+    /*
+      Note, this is only safe for little-endian UCS-2.
+      If we add big-endian UCS-2 sometimes, this code
+      will be more complicated. But it's OK for now.
+    */
+    bzero((char*)Ptr, offs);
+    memcpy(Ptr + offs, str, arg_length);
+  }
+  Ptr[aligned_length]=0;
+  str_charset=cs;
+  return FALSE;
+}
+
 	/* Copy with charset convertion */
 
 bool String::copy(const char *str, uint32 arg_length,
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 325611737ca..8817aa8eab8 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -183,6 +183,7 @@ public:
   bool copy();					// Alloc string if not alloced
   bool copy(const String &s);			// Allocate new string
   bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs);	// Allocate new string
+  bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
   bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
 	    CHARSET_INFO *csto);
   bool append(const String &s);
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index c5ddc167d0d..8d4081fb2aa 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6281,6 +6281,7 @@ CHARSET_INFO my_charset_big5_chinese_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_big5_handler,
@@ -6304,6 +6305,7 @@ CHARSET_INFO my_charset_big5_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_big5_handler,
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 6f28c43b2c6..67435b7df6c 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -381,6 +381,7 @@ CHARSET_INFO my_charset_bin =
     NULL,			/* tab_from_uni  */
     "","",
     1,				/* strxfrm_multiply */
+    1,				/* mbminlen      */
     1,				/* mbmaxlen      */
     (char) 255,			/* max_sort_char */
     &my_charset_handler,
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index b2e4f1886ed..1a07a5eba7e 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -631,6 +631,7 @@ CHARSET_INFO my_charset_latin2_czech_ci =
     idx_uni_8859_2,	/* tab_from_uni */
     "","",
     4,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     1,			/* mbmaxlen  */
     0,
     &my_charset_8bit_handler,
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index addd7803680..366a5d500ed 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8689,6 +8689,7 @@ CHARSET_INFO my_charset_euckr_korean_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_handler,
@@ -8712,6 +8713,7 @@ CHARSET_INFO my_charset_euckr_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 55bfa09ea5f..0085d264416 100644
--- a/strings/ctype-extra.c
+++ b/strings/ctype-extra.c
@@ -34,6 +34,7 @@ CHARSET_INFO compiled_charsets[] = {
     0,
     0,
     0,
+    0,
     NULL,
     NULL
   }
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index b84ddc9081b..44a58b2b906 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5740,6 +5740,7 @@ CHARSET_INFO my_charset_gb2312_chinese_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_handler,
@@ -5762,6 +5763,7 @@ CHARSET_INFO my_charset_gb2312_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen   */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 585dc66be4c..5475c3bd363 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9936,6 +9936,7 @@ CHARSET_INFO my_charset_gbk_chinese_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen */
     0,
     &my_charset_handler,
@@ -9958,6 +9959,7 @@ CHARSET_INFO my_charset_gbk_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 15798abb85b..c00ded21575 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -215,6 +215,7 @@ CHARSET_INFO my_charset_latin1=
     NULL,		/* tab_from_uni */
     "","",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     1,			/* mbmaxlen  */
     0,
     &my_charset_handler,
@@ -410,6 +411,7 @@ CHARSET_INFO my_charset_latin1_german2_ci=
   NULL,					/* tab_from_uni */
   "","",
   2,					/* strxfrm_multiply */
+  1,					/* mbminlen   */
   1,					/* mbmaxlen  */
   0,
   &my_charset_handler,
@@ -433,6 +435,7 @@ CHARSET_INFO my_charset_latin1_bin=
   "",
   "",
   1,					/* strxfrm_multiply */
+  1,					/* mbminlen   */
   1,					/* mbmaxlen  */
   0,
   &my_charset_handler,
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index a84fbd16e5d..42f32fe739b 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4525,6 +4525,7 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen */
     0,
     &my_charset_handler,
@@ -4547,6 +4548,7 @@ CHARSET_INFO my_charset_sjis_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     2,			/* mbmaxlen */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 92b2eeb25e0..09552a0dc23 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -956,6 +956,7 @@ CHARSET_INFO my_charset_tis620_thai_ci=
     "",
     "",
     4,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     1,			/* mbmaxlen  */
     0,
     &my_charset_handler,
@@ -978,6 +979,7 @@ CHARSET_INFO my_charset_tis620_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen   */
     1,			/* mbmaxlen  */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index beb803a69f2..a7a59fc50f7 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1322,6 +1322,7 @@ CHARSET_INFO my_charset_ucs2_general_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    2,			/* mbminlen     */
     2,			/* mbmaxlen     */
     0,
     &my_charset_ucs2_handler,
@@ -1345,6 +1346,7 @@ CHARSET_INFO my_charset_ucs2_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    2,			/* mbminlen     */
     2,			/* mbmaxlen     */
     0,
     &my_charset_ucs2_handler,
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 2815b70351b..f6928e9426e 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8480,6 +8480,7 @@ CHARSET_INFO my_charset_ujis_japanese_ci=
     NULL,		/* tab_from_uni */
     "","",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen     */
     3,			/* mbmaxlen     */
     0,
     &my_charset_handler,
@@ -8502,6 +8503,7 @@ CHARSET_INFO my_charset_ujis_bin=
     NULL,		/* tab_from_uni */
     "","",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen     */
     3,			/* mbmaxlen     */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index b5716c53ea2..8004fba75b7 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2006,6 +2006,7 @@ CHARSET_INFO my_charset_utf8_general_ci=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen     */
     3,			/* mbmaxlen     */
     0,
     &my_charset_handler,
@@ -2029,6 +2030,7 @@ CHARSET_INFO my_charset_utf8_bin=
     "",
     "",
     1,			/* strxfrm_multiply */
+    1,			/* mbminlen     */
     3,			/* mbmaxlen     */
     0,
     &my_charset_handler,
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index 60a5737009f..d3b5c9d1796 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -671,6 +671,7 @@ CHARSET_INFO my_charset_cp1250_czech_ci =
     idx_uni_cp1250,		/* tab_from_uni */
     "","",
     2,				/* strxfrm_multiply */
+    1,				/* mbminlen  */
     1,				/* mbmaxlen  */
     0,
     &my_charset_8bit_handler,

From c8eff1773e1a0896ccba36da559bb5db3b8197c8 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 19:53:25 +0400
Subject: [PATCH 085/157] Code cleanup (working on PS & cleanup() code) Item &
 changed with Item* in Item_xxx constructors tables_list.first ->
 get_table_list()

sql/item.cc:
  Item& -> Item*
sql/item.h:
  Item& -> Item*
sql/item_cmpfunc.cc:
  Item& -> Item*
sql/item_cmpfunc.h:
  Item& -> Item*
sql/item_func.cc:
  Item& -> Item*
sql/item_func.h:
  Item& -> Item*
sql/item_sum.cc:
  Item& -> Item*
sql/item_sum.h:
  Item& -> Item*
sql/item_uniq.h:
  Item& -> Item*
sql/sql_prepare.cc:
  Code cleanup
sql/sql_select.cc:
  Item& -> Item*
---
 sql/item.cc         |  49 +++++++++--------
 sql/item.h          |  14 ++---
 sql/item_cmpfunc.cc |   6 +--
 sql/item_cmpfunc.h  |  12 ++---
 sql/item_func.cc    |  14 ++---
 sql/item_func.h     |   4 +-
 sql/item_sum.cc     |  38 +++++++-------
 sql/item_sum.h      | 124 ++++++++++++++++++++++----------------------
 sql/item_uniq.h     |   4 +-
 sql/sql_prepare.cc  |   4 +-
 sql/sql_select.cc   |   2 +-
 11 files changed, 135 insertions(+), 136 deletions(-)

diff --git a/sql/item.cc b/sql/item.cc
index e364f095a70..cbac16cba8d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -71,18 +71,18 @@ Item::Item():
   Used for duplicating lists in processing queries with temporary
   tables
 */
-Item::Item(THD *thd, Item &item):
-  str_value(item.str_value),
-  name(item.name),
-  max_length(item.max_length),
-  marker(item.marker),
-  decimals(item.decimals),
-  maybe_null(item.maybe_null),
-  null_value(item.null_value),
-  unsigned_flag(item.unsigned_flag),
-  with_sum_func(item.with_sum_func),
-  fixed(item.fixed),
-  collation(item.collation)
+Item::Item(THD *thd, Item *item):
+  str_value(item->str_value),
+  name(item->name),
+  max_length(item->max_length),
+  marker(item->marker),
+  decimals(item->decimals),
+  maybe_null(item->maybe_null),
+  null_value(item->null_value),
+  unsigned_flag(item->unsigned_flag),
+  with_sum_func(item->with_sum_func),
+  fixed(item->fixed),
+  collation(item->collation)
 {
   next= thd->free_list;				// Put in free list
   thd->free_list= this;
@@ -110,12 +110,12 @@ Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
 }
 
 // Constructor used by Item_field & Item_ref (see Item comment)
-Item_ident::Item_ident(THD *thd, Item_ident &item):
+Item_ident::Item_ident(THD *thd, Item_ident *item):
   Item(thd, item),
-  db_name(item.db_name),
-  table_name(item.table_name),
-  field_name(item.field_name),
-  depended_from(item.depended_from)
+  db_name(item->db_name),
+  table_name(item->table_name),
+  field_name(item->field_name),
+  depended_from(item->depended_from)
 {}
 
 bool Item_ident::remove_dependence_processor(byte * arg)
@@ -296,10 +296,10 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
 }
 
 // Constructor need to process subselect with temporary tables (see Item)
-Item_field::Item_field(THD *thd, Item_field &item)
+Item_field::Item_field(THD *thd, Item_field *item)
   :Item_ident(thd, item),
-   field(item.field),
-   result_field(item.result_field)
+   field(item->field),
+   result_field(item->result_field)
 {
   collation.set(DERIVATION_IMPLICIT);
 }
@@ -455,7 +455,7 @@ table_map Item_field::used_tables() const
 
 Item *Item_field::get_tmp_table_item(THD *thd)
 {
-  Item_field *new_item= new Item_field(thd, *this);
+  Item_field *new_item= new Item_field(thd, this);
   if (new_item)
     new_item->field= new_item->result_field;
   return new_item;
@@ -937,7 +937,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 	if (last->having_fix_field)
 	{
 	  Item_ref *rf;
-	  *ref= rf= new Item_ref(ref, this,
+	  *ref= rf= new Item_ref(ref, *ref,
 				 (where->db[0]?where->db:0), 
 				 (char *)where->alias,
 				 (char *)field_name);
@@ -967,8 +967,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 void Item_field::cleanup()
 {
   Item_ident::cleanup();
-  field= 0;
-  result_field= 0;
+  field= result_field= 0;
 }
 
 void Item::init_make_field(Send_field *tmp_field,
@@ -2028,7 +2027,7 @@ void Item_cache_row::bring_value()
 
 
 Item_type_holder::Item_type_holder(THD *thd, Item *item)
-  :Item(thd, *item), item_type(item->result_type())
+  :Item(thd, item), item_type(item->result_type())
 {
   DBUG_ASSERT(item->fixed);
 
diff --git a/sql/item.h b/sql/item.h
index e1318224498..dc3a9114601 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -124,7 +124,7 @@ public:
      top AND/OR ctructure of WHERE clause to protect it of
      optimisation changes in prepared statements
   */
-  Item(THD *thd, Item &item);
+  Item(THD *thd, Item *item);
   virtual ~Item() { name=0; cleanup(); }		/*lint -e1509 */
   void set_name(const char *str,uint length, CHARSET_INFO *cs);
   void init_make_field(Send_field *tmp_field,enum enum_field_types type);
@@ -240,7 +240,7 @@ public:
   st_select_lex *depended_from;
   Item_ident(const char *db_name_par,const char *table_name_par,
 	     const char *field_name_par);
-  Item_ident::Item_ident(THD *thd, Item_ident &item);
+  Item_ident::Item_ident(THD *thd, Item_ident *item);
   const char *full_name() const;
 
   bool remove_dependence_processor(byte * arg);
@@ -259,7 +259,7 @@ public:
     :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
   { collation.set(DERIVATION_IMPLICIT); }
   // Constructor need to process subselect with temporary tables (see Item)
-  Item_field(THD *thd, Item_field &item);
+  Item_field(THD *thd, Item_field *item);
   Item_field(Field *field);
   enum Type type() const { return FIELD_ITEM; }
   bool eq(const Item *item, bool binary_cmp) const;
@@ -581,8 +581,8 @@ public:
   Field *result_field;				/* Save result here */
   Item_result_field() :result_field(0) {}
   // Constructor used for Item_sum/Item_cond_and/or (see Item comment)
-  Item_result_field(THD *thd, Item_result_field &item):
-    Item(thd, item), result_field(item.result_field)
+  Item_result_field(THD *thd, Item_result_field *item):
+    Item(thd, item), result_field(item->result_field)
   {}
   ~Item_result_field() {}			/* Required with gcc 2.95 */
   Field *get_tmp_table_field() { return result_field; }
@@ -614,8 +614,8 @@ public:
     :Item_ident(NullS,table_name_par,field_name_par),
     ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {}
   // Constructor need to process subselect with temporary tables (see Item)
-  Item_ref(THD *thd, Item_ref &item, Item **hook)
-    :Item_ident(thd, item), ref(item.ref), 
+  Item_ref(THD *thd, Item_ref *item, Item **hook)
+    :Item_ident(thd, item), ref(item->ref), 
     hook_ptr(hook), orig_item(hook ? *hook : 0) {}
   enum Type type() const		{ return REF_ITEM; }
   bool eq(const Item *item, bool binary_cmp) const
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 4b270c6aad0..0b9c7f8d92a 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1651,10 +1651,10 @@ longlong Item_func_bit_and::val_int()
   return (longlong) (arg1 & arg2);
 }
 
-Item_cond::Item_cond(THD *thd, Item_cond &item)
+Item_cond::Item_cond(THD *thd, Item_cond *item)
   :Item_bool_func(thd, item),
-   abort_on_null(item.abort_on_null),
-   and_tables_cache(item.and_tables_cache)
+   abort_on_null(item->abort_on_null),
+   and_tables_cache(item->and_tables_cache)
 {
   /*
     here should be following text:
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 50c5449c1ec..3ad3b928c01 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -82,7 +82,7 @@ public:
   Item_bool_func() :Item_int_func() {}
   Item_bool_func(Item *a) :Item_int_func(a) {}
   Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
-  Item_bool_func(THD *thd, Item_bool_func &item) :Item_int_func(thd, item) {}
+  Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
   void fix_length_and_dec() { decimals=0; max_length=1; }
 };
 
@@ -889,7 +889,7 @@ public:
     list.push_back(i1);
     list.push_back(i2);
   }
-  Item_cond(THD *thd, Item_cond &item);
+  Item_cond(THD *thd, Item_cond *item);
   Item_cond(List &nlist)
     :Item_bool_func(), list(nlist), abort_on_null(0) {}
   bool add(Item *item) { return list.push_back(item); }
@@ -914,7 +914,7 @@ class Item_cond_and :public Item_cond
 public:
   Item_cond_and() :Item_cond() {}
   Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
-  Item_cond_and(THD *thd, Item_cond_and &item) :Item_cond(thd, item) {}
+  Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
   Item_cond_and(List &list): Item_cond(list) {}
   enum Functype functype() const { return COND_AND_FUNC; }
   longlong val_int();
@@ -922,7 +922,7 @@ public:
   Item* copy_andor_structure(THD *thd)
   {
     Item_cond_and *item;
-    if((item= new Item_cond_and(thd, *this)))
+    if((item= new Item_cond_and(thd, this)))
        item->copy_andor_arguments(thd, this);
     return item;
   }
@@ -934,7 +934,7 @@ class Item_cond_or :public Item_cond
 public:
   Item_cond_or() :Item_cond() {}
   Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
-  Item_cond_or(THD *thd, Item_cond_or &item) :Item_cond(thd, item) {}
+  Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {}
   Item_cond_or(List &list): Item_cond(list) {}
   enum Functype functype() const { return COND_OR_FUNC; }
   longlong val_int();
@@ -943,7 +943,7 @@ public:
   Item* copy_andor_structure(THD *thd)
   {
     Item_cond_or *item;
-    if((item= new Item_cond_or(thd, *this)))
+    if((item= new Item_cond_or(thd, this)))
       item->copy_andor_arguments(thd, this);
     return item;
   }
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 6dbfcc3ef8c..592195dd4b8 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -130,13 +130,13 @@ Item_func::Item_func(List &list)
   set_arguments(list);
 }
 
-Item_func::Item_func(THD *thd, Item_func &item)
+Item_func::Item_func(THD *thd, Item_func *item)
   :Item_result_field(thd, item),
-   allowed_arg_cols(item.allowed_arg_cols),
-   arg_count(item.arg_count),
-   used_tables_cache(item.used_tables_cache),
-   not_null_tables_cache(item.not_null_tables_cache),
-   const_item_cache(item.const_item_cache)
+   allowed_arg_cols(item->allowed_arg_cols),
+   arg_count(item->arg_count),
+   used_tables_cache(item->used_tables_cache),
+   not_null_tables_cache(item->not_null_tables_cache),
+   const_item_cache(item->const_item_cache)
 {
   if (arg_count)
   {
@@ -147,7 +147,7 @@ Item_func::Item_func(THD *thd, Item_func &item)
       if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
 	return;
     }
-    memcpy((char*) args, (char*) item.args, sizeof(Item*)*arg_count);
+    memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
   }
 }
 
diff --git a/sql/item_func.h b/sql/item_func.h
index 634880db7ad..75839bb80c3 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -106,7 +106,7 @@ public:
   }
   Item_func(List &list);
   // Constructor used for Item_cond_and/or (see Item comment)
-  Item_func(THD *thd, Item_func &item);
+  Item_func(THD *thd, Item_func *item);
   bool fix_fields(THD *,struct st_table_list *, Item **ref);
   table_map used_tables() const;
   table_map not_null_tables() const;
@@ -199,7 +199,7 @@ public:
   Item_int_func(Item *a,Item *b) :Item_func(a,b) { max_length=21; }
   Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
   Item_int_func(List &list) :Item_func(list) { max_length=21; }
-  Item_int_func(THD *thd, Item_int_func &item) :Item_func(thd, item) {}
+  Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {}
   double val() { return (double) val_int(); }
   String *val_str(String*str);
   enum Item_result result_type () const { return INT_RESULT; }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 84d00ce8732..7c2d5501c06 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -42,17 +42,17 @@ Item_sum::Item_sum(List &list)
 }
 
 // Constructor used in processing select with temporary tebles
-Item_sum::Item_sum(THD *thd, Item_sum &item):
-  Item_result_field(thd, item), quick_group(item.quick_group)
+Item_sum::Item_sum(THD *thd, Item_sum *item):
+  Item_result_field(thd, item), quick_group(item->quick_group)
 {
-  arg_count= item.arg_count;
+  arg_count= item->arg_count;
   if (arg_count <= 2)
     args=tmp_args;
   else
     if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
       return;
   for (uint i= 0; i < arg_count; i++)
-    args[i]= item.args[i];
+    args[i]= item->args[i];
 }
 
 void Item_sum::mark_as_sum_func()
@@ -240,7 +240,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 
 Item *Item_sum_sum::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_sum(thd, *this);
+  return new (&thd->mem_root) Item_sum_sum(thd, this);
 }
 
 
@@ -267,7 +267,7 @@ double Item_sum_sum::val()
 
 Item *Item_sum_count::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_count(thd, *this);
+  return new (&thd->mem_root) Item_sum_count(thd, this);
 }
 
 
@@ -301,7 +301,7 @@ longlong Item_sum_count::val_int()
 
 Item *Item_sum_avg::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_avg(thd, *this);
+  return new (&thd->mem_root) Item_sum_avg(thd, this);
 }
 
 
@@ -346,7 +346,7 @@ double Item_sum_std::val()
 
 Item *Item_sum_std::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_std(thd, *this);
+  return new (&thd->mem_root) Item_sum_std(thd, this);
 }
 
 
@@ -356,7 +356,7 @@ Item *Item_sum_std::copy_or_same(THD* thd)
 
 Item *Item_sum_variance::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_variance(thd, *this);
+  return new (&thd->mem_root) Item_sum_variance(thd, this);
 }
 
 
@@ -497,7 +497,7 @@ Item_sum_hybrid::val_str(String *str)
 
 Item *Item_sum_min::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_min(thd, *this);
+  return new (&thd->mem_root) Item_sum_min(thd, this);
 }
 
 
@@ -550,7 +550,7 @@ bool Item_sum_min::add()
 
 Item *Item_sum_max::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_max(thd, *this);
+  return new (&thd->mem_root) Item_sum_max(thd, this);
 }
 
 
@@ -616,7 +616,7 @@ void Item_sum_bit::clear()
 
 Item *Item_sum_or::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_or(thd, *this);
+  return new (&thd->mem_root) Item_sum_or(thd, this);
 }
 
 
@@ -630,7 +630,7 @@ bool Item_sum_or::add()
 
 Item *Item_sum_xor::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_xor(thd, *this);
+  return new (&thd->mem_root) Item_sum_xor(thd, this);
 }
 
 
@@ -644,7 +644,7 @@ bool Item_sum_xor::add()
 
 Item *Item_sum_and::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_and(thd, *this);
+  return new (&thd->mem_root) Item_sum_and(thd, this);
 }
 
 
@@ -1281,7 +1281,7 @@ int Item_sum_count_distinct::tree_to_myisam()
 
 Item *Item_sum_count_distinct::copy_or_same(THD* thd) 
 {
-  return new (&thd->mem_root) Item_sum_count_distinct(thd, *this);
+  return new (&thd->mem_root) Item_sum_count_distinct(thd, this);
 }
 
 
@@ -1381,7 +1381,7 @@ bool Item_udf_sum::add()
 
 Item *Item_sum_udf_float::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_udf_float(thd, *this);
+  return new (&thd->mem_root) Item_sum_udf_float(thd, this);
 }
 
 double Item_sum_udf_float::val()
@@ -1404,7 +1404,7 @@ String *Item_sum_udf_float::val_str(String *str)
 
 Item *Item_sum_udf_int::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_udf_int(thd, *this);
+  return new (&thd->mem_root) Item_sum_udf_int(thd, this);
 }
 
 
@@ -1440,7 +1440,7 @@ void Item_sum_udf_str::fix_length_and_dec()
 
 Item *Item_sum_udf_str::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_sum_udf_str(thd, *this);
+  return new (&thd->mem_root) Item_sum_udf_str(thd, this);
 }
 
 
@@ -1701,7 +1701,7 @@ Item_func_group_concat::~Item_func_group_concat()
 
 Item *Item_func_group_concat::copy_or_same(THD* thd)
 {
-  return new (&thd->mem_root) Item_func_group_concat(thd, *this);
+  return new (&thd->mem_root) Item_func_group_concat(thd, this);
 }
 
 
diff --git a/sql/item_sum.h b/sql/item_sum.h
index dd180d42011..9f1c8a09a4e 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -57,7 +57,7 @@ public:
   }
   Item_sum(List &list);
   //Copy constructor, need to perform subselects with temporary tables
-  Item_sum(THD *thd, Item_sum &item);
+  Item_sum(THD *thd, Item_sum *item);
   void cleanup()
   {
     Item_result_field::cleanup();
@@ -110,7 +110,7 @@ public:
   Item_sum_num(Item *item_par) :Item_sum(item_par) {}
   Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
   Item_sum_num(List &list) :Item_sum(list) {}
-  Item_sum_num(THD *thd, Item_sum_num &item) :Item_sum(thd, item) {}
+  Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
   bool fix_fields(THD *, TABLE_LIST *, Item **);
   longlong val_int() { return (longlong) val(); } /* Real as default */
   String *val_str(String*str);
@@ -123,7 +123,7 @@ class Item_sum_int :public Item_sum_num
 public:
   Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
   Item_sum_int(List &list) :Item_sum_num(list) {}
-  Item_sum_int(THD *thd, Item_sum_int &item) :Item_sum_num(thd, item) {}
+  Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
   double val() { return (double) val_int(); }
   String *val_str(String*str);
   enum Item_result result_type () const { return INT_RESULT; }
@@ -139,8 +139,8 @@ class Item_sum_sum :public Item_sum_num
 
   public:
   Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {}
-  Item_sum_sum(THD *thd, Item_sum_sum &item) 
-    :Item_sum_num(thd, item), sum(item.sum) {}
+  Item_sum_sum(THD *thd, Item_sum_sum *item) 
+    :Item_sum_num(thd, item), sum(item->sum) {}
   enum Sumfunctype sum_func () const {return SUM_FUNC;}
   void clear();
   bool add();
@@ -162,9 +162,9 @@ class Item_sum_count :public Item_sum_int
   Item_sum_count(Item *item_par)
     :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0)
   {}
-  Item_sum_count(THD *thd, Item_sum_count &item)
-    :Item_sum_int(thd, item), count(item.count),
-     used_table_cache(item.used_table_cache)
+  Item_sum_count(THD *thd, Item_sum_count *item)
+    :Item_sum_int(thd, item), count(item->count),
+     used_table_cache(item->used_table_cache)
   {}
   table_map used_tables() const { return used_table_cache; }
   bool const_item() const { return !used_table_cache; }
@@ -230,14 +230,14 @@ class Item_sum_count_distinct :public Item_sum_int
      tmp_table_param(0), tree(&tree_base), original(0), use_tree(0),
      always_null(0)
   { quick_group= 0; }
-  Item_sum_count_distinct(THD *thd, Item_sum_count_distinct &item)
-    :Item_sum_int(thd, item), table(item.table),
-     used_table_cache(item.used_table_cache),
-     field_lengths(item.field_lengths), tmp_table_param(item.tmp_table_param),
-     tree(item.tree), original(&item), key_length(item.key_length),
-     max_elements_in_tree(item.max_elements_in_tree),
-     rec_offset(item.rec_offset), use_tree(item.use_tree),
-     always_null(item.always_null)
+  Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
+    :Item_sum_int(thd, item), table(item->table),
+     used_table_cache(item->used_table_cache),
+     field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param),
+     tree(item->tree), original(item), key_length(item->key_length),
+     max_elements_in_tree(item->max_elements_in_tree),
+     rec_offset(item->rec_offset), use_tree(item->use_tree),
+     always_null(item->always_null)
   {}
   void cleanup();
 
@@ -285,8 +285,8 @@ class Item_sum_avg :public Item_sum_num
 
   public:
   Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {}
-  Item_sum_avg(THD *thd, Item_sum_avg &item)
-    :Item_sum_num(thd, item), sum(item.sum), count(item.count) {}
+  Item_sum_avg(THD *thd, Item_sum_avg *item)
+    :Item_sum_num(thd, item), sum(item->sum), count(item->count) {}
   enum Sumfunctype sum_func () const {return AVG_FUNC;}
   void clear();
   bool add();
@@ -337,9 +337,9 @@ class Item_sum_variance : public Item_sum_num
 
   public:
   Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
-  Item_sum_variance(THD *thd, Item_sum_variance &item):
-    Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr),
-    count(item.count) {}
+  Item_sum_variance(THD *thd, Item_sum_variance *item):
+    Item_sum_num(thd, item), sum(item->sum), sum_sqr(item->sum_sqr),
+    count(item->count) {}
   enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
   void clear();
   bool add();
@@ -370,7 +370,7 @@ class Item_sum_std :public Item_sum_variance
 {
   public:
   Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {}
-  Item_sum_std(THD *thd, Item_sum_std &item)
+  Item_sum_std(THD *thd, Item_sum_std *item)
     :Item_sum_variance(thd, item)
     {}
   enum Sumfunctype sum_func () const { return STD_FUNC; }
@@ -401,11 +401,11 @@ class Item_sum_hybrid :public Item_sum
     used_table_cache(~(table_map) 0),
     cmp_charset(&my_charset_bin)
   {}
-  Item_sum_hybrid(THD *thd, Item_sum_hybrid &item):
-    Item_sum(thd, item), value(item.value), tmp_value(item.tmp_value),
-    sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type),
-    hybrid_field_type(item.hybrid_field_type),cmp_sign(item.cmp_sign), 
-    used_table_cache(item.used_table_cache), cmp_charset(item.cmp_charset) {}
+  Item_sum_hybrid(THD *thd, Item_sum_hybrid *item):
+    Item_sum(thd, item), value(item->value), tmp_value(item->tmp_value),
+    sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type),
+    hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), 
+    used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {}
   bool fix_fields(THD *, TABLE_LIST *, Item **);
   table_map used_tables() const { return used_table_cache; }
   bool const_item() const { return !used_table_cache; }
@@ -436,7 +436,7 @@ class Item_sum_min :public Item_sum_hybrid
 {
 public:
   Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {}
-  Item_sum_min(THD *thd, Item_sum_min &item) :Item_sum_hybrid(thd, item) {}
+  Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {}
   enum Sumfunctype sum_func () const {return MIN_FUNC;}
 
   bool add();
@@ -449,7 +449,7 @@ class Item_sum_max :public Item_sum_hybrid
 {
 public:
   Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {}
-  Item_sum_max(THD *thd, Item_sum_max &item) :Item_sum_hybrid(thd, item) {}
+  Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {}
   enum Sumfunctype sum_func () const {return MAX_FUNC;}
 
   bool add();
@@ -466,8 +466,8 @@ protected:
 public:
   Item_sum_bit(Item *item_par,ulonglong reset_arg)
     :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {}
-  Item_sum_bit(THD *thd, Item_sum_bit &item):
-    Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {}
+  Item_sum_bit(THD *thd, Item_sum_bit *item):
+    Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits) {}
   enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
   void clear();
   longlong val_int();
@@ -482,7 +482,7 @@ class Item_sum_or :public Item_sum_bit
 {
 public:
   Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
-  Item_sum_or(THD *thd, Item_sum_or &item) :Item_sum_bit(thd, item) {}
+  Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {}
   bool add();
   const char *func_name() const { return "bit_or"; }
   Item *copy_or_same(THD* thd);
@@ -493,7 +493,7 @@ class Item_sum_and :public Item_sum_bit
 {
   public:
   Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {}
-  Item_sum_and(THD *thd, Item_sum_and &item) :Item_sum_bit(thd, item) {}
+  Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {}
   bool add();
   const char *func_name() const { return "bit_and"; }
   Item *copy_or_same(THD* thd);
@@ -503,7 +503,7 @@ class Item_sum_xor :public Item_sum_bit
 {
   public:
   Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
-  Item_sum_xor(THD *thd, Item_sum_xor &item) :Item_sum_bit(thd, item) {}
+  Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {}
   bool add();
   const char *func_name() const { return "bit_xor"; }
   Item *copy_or_same(THD* thd);
@@ -525,8 +525,8 @@ public:
   Item_udf_sum( udf_func *udf_arg, List &list )
     :Item_sum( list ), udf(udf_arg)
   { quick_group=0;}
-  Item_udf_sum(THD *thd, Item_udf_sum &item)
-    :Item_sum(thd, item), udf(item.udf) {}
+  Item_udf_sum(THD *thd, Item_udf_sum *item)
+    :Item_sum(thd, item), udf(item->udf) {}
   const char *func_name() const { return udf.name(); }
   bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
   {
@@ -549,7 +549,7 @@ class Item_sum_udf_float :public Item_udf_sum
   Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
   Item_sum_udf_float(udf_func *udf_arg, List &list)
     :Item_udf_sum(udf_arg,list) {}
-  Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
+  Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
     :Item_udf_sum(thd, item) {}
   longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
   double val();
@@ -565,7 +565,7 @@ public:
   Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
   Item_sum_udf_int(udf_func *udf_arg, List &list)
     :Item_udf_sum(udf_arg,list) {}
-  Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
+  Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
     :Item_udf_sum(thd, item) {}
   longlong val_int();
   double val() { return (double) Item_sum_udf_int::val_int(); }
@@ -582,7 +582,7 @@ public:
   Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
   Item_sum_udf_str(udf_func *udf_arg, List &list)
     :Item_udf_sum(udf_arg,list) {}
-  Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
+  Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
     :Item_udf_sum(thd, item) {}
   String *val_str(String *);
   double val()
@@ -704,31 +704,31 @@ class Item_func_group_concat : public Item_sum
   Item_func_group_concat(bool is_distinct,List *is_select,
                          SQL_LIST *is_order,String *is_separator);
 			 
-  Item_func_group_concat(THD *thd, Item_func_group_concat &item)
+  Item_func_group_concat(THD *thd, Item_func_group_concat *item)
     :Item_sum(thd, item),item_thd(thd),
-     tmp_table_param(item.tmp_table_param),
-     max_elements_in_tree(item.max_elements_in_tree),
-     warning(item.warning),
-     warning_available(item.warning_available),
-     key_length(item.key_length), 
-     rec_offset(item.rec_offset), 
-     tree_mode(item.tree_mode),
-     distinct(item.distinct),
-     warning_for_row(item.warning_for_row),
-     separator(item.separator),
-     tree(item.tree),
-     table(item.table),
-     order(item.order),
-     tables_list(item.tables_list),
-     group_concat_max_len(item.group_concat_max_len),
-     show_elements(item.show_elements),
-     arg_count_order(item.arg_count_order),
-     arg_count_field(item.arg_count_field),
-     arg_show_fields(item.arg_show_fields),
-     count_cut_values(item.count_cut_values),
-     original(&item)
+     tmp_table_param(item->tmp_table_param),
+     max_elements_in_tree(item->max_elements_in_tree),
+     warning(item->warning),
+     warning_available(item->warning_available),
+     key_length(item->key_length), 
+     rec_offset(item->rec_offset), 
+     tree_mode(item->tree_mode),
+     distinct(item->distinct),
+     warning_for_row(item->warning_for_row),
+     separator(item->separator),
+     tree(item->tree),
+     table(item->table),
+     order(item->order),
+     tables_list(item->tables_list),
+     group_concat_max_len(item->group_concat_max_len),
+     show_elements(item->show_elements),
+     arg_count_order(item->arg_count_order),
+     arg_count_field(item->arg_count_field),
+     arg_show_fields(item->arg_show_fields),
+     count_cut_values(item->count_cut_values),
+     original(item)
     {
-     quick_group= item.quick_group;
+     quick_group= item->quick_group;
     };
   ~Item_func_group_concat();
   void cleanup();
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 5c6f6eefb6b..47f967b52c6 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -38,7 +38,7 @@ class Item_sum_unique_users :public Item_sum_num
 public:
   Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg)
     :Item_sum_num(item_arg) {}
-  Item_sum_unique_users(THD *thd, Item_sum_unique_users &item)
+  Item_sum_unique_users(THD *thd, Item_sum_unique_users *item)
     :Item_sum_num(thd, item) {}
   double val() { return 0.0; }  
   enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
@@ -53,7 +53,7 @@ public:
   }
   Item *copy_or_same(THD* thd)
   {
-    return new Item_sum_unique_users(thd, *this);
+    return new Item_sum_unique_users(thd, this);
   }
   void print(String *str) { str->append("0.0", 3); }
 };
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index dd5825f27ac..52ad9b5e5fc 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -756,9 +756,8 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
     JOIN *join= new JOIN(thd, fields, select_options, result);
     thd->used_tables= 0;	// Updated by setup_fields  
 
-//    if (join->prepare(&select_lex->ref_pointer_array, tables, 
     if (join->prepare(&select_lex->ref_pointer_array,
-		      (TABLE_LIST*)select_lex->table_list.first,
+		      (TABLE_LIST*)select_lex->get_table_list(),
                       wild_num, conds, og_num, order, group, having, proc, 
                       select_lex, unit))
       DBUG_RETURN(1);
@@ -1106,6 +1105,7 @@ void mysql_stmt_free(THD *thd, char *packet)
   if (!(stmt= find_prepared_statement(thd, stmt_id, "close")))
     DBUG_VOID_RETURN;
 
+  free_items(stmt->free_list);
   /* Statement map deletes statement on erase */
   thd->stmt_map.erase(stmt);
   DBUG_VOID_RETURN;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a1f6abfd53a..58b876704b0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8282,7 +8282,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
     if (pos->type() == Item::FIELD_ITEM)
     {
       Item_field *item;
-      if (!(item= new Item_field(thd, *((Item_field*) pos))))
+      if (!(item= new Item_field(thd, ((Item_field*) pos))))
 	goto err;
       pos= item;
       if (item->field->flags & BLOB_FLAG)

From 584e137887326584e1f24d2061e75486d745584e Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 21:05:26 +0400
Subject: [PATCH 086/157] Code cleanup Superfluous line removed

sql/sql_prepare.cc:
  Line is not needed
---
 sql/sql_prepare.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 52ad9b5e5fc..b5dd4083dcf 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1105,7 +1105,6 @@ void mysql_stmt_free(THD *thd, char *packet)
   if (!(stmt= find_prepared_statement(thd, stmt_id, "close")))
     DBUG_VOID_RETURN;
 
-  free_items(stmt->free_list);
   /* Statement map deletes statement on erase */
   thd->stmt_map.erase(stmt);
   DBUG_VOID_RETURN;

From 7db61ce021642bb3bbee1c341d94f3539037df80 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 20 Jan 2004 00:32:25 +0400
Subject: [PATCH 087/157] Fixed bug #2310 "INET_ATON handles short-forms
 addresses incorrectly"

mysql-test/r/func_misc.result:
  added new test for inet_aton (short-forms addresses)
mysql-test/t/func_misc.test:
  added new test for inet_aton (short-forms addresses)
sql/item_func.cc:
  Change Item_func_inet_aton::val_int to parse short-forms addresses correctly
---
 mysql-test/r/func_misc.result | 11 ++++++++++-
 mysql-test/t/func_misc.test   |  4 ++++
 sql/item_func.cc              |  9 +++++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index d51bea020ed..ec5f76409e7 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -6,10 +6,19 @@ inet_ntoa(inet_aton("255.255.255.255.255.255.255.255"))
 NULL
 select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
 inet_aton("255.255.255.255.255")	inet_aton("255.255.1.255")	inet_aton("0.1.255")
-1099511627775	4294902271	511
+1099511627775	4294902271	65791
 select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
 inet_ntoa(1099511627775)	inet_ntoa(4294902271)	inet_ntoa(511)
 NULL	255.255.1.255	0.0.1.255
+select hex(inet_aton('127'));
+hex(inet_aton('127'))
+7F
+select hex(inet_aton('127.1'));
+hex(inet_aton('127.1'))
+7F000001
+select hex(inet_aton('127.1.1'));
+hex(inet_aton('127.1.1'))
+7F010001
 select length(format('nan', 2)) > 0;
 length(format('nan', 2)) > 0
 1
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index d15c26279ec..9759127b222 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -8,6 +8,10 @@ select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255"));
 select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
 select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
 
+select hex(inet_aton('127'));
+select hex(inet_aton('127.1'));
+select hex(inet_aton('127.1.1'));
+
 #
 # Test for core dump with nan
 #
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 5af64ca0be4..802b6dbb8d6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2618,6 +2618,7 @@ longlong Item_func_inet_aton::val_int()
   const char *p,* end;
   char c = '.'; // we mark c to indicate invalid IP in case length is 0
   char buff[36];
+  int dot_count= 0;
 
   String *s,tmp(buff,sizeof(buff),&my_charset_bin);
   if (!(s = args[0]->val_str(&tmp)))		// If null value
@@ -2636,6 +2637,7 @@ longlong Item_func_inet_aton::val_int()
     }
     else if (c == '.')
     {
+      dot_count++;
       result= (result << 8) + (ulonglong) byte_result;
       byte_result = 0;
     }
@@ -2643,7 +2645,14 @@ longlong Item_func_inet_aton::val_int()
       goto err;					// Invalid character
   }
   if (c != '.')					// IP number can't end on '.'
+  {
+    switch (dot_count)
+    {
+    case 1: result<<= 8;
+    case 2: result<<= 8;
+    }
     return (result << 8) + (ulonglong) byte_result;
+  }
 
 err:
   null_value=1;

From eead0c1b822070aebdaede48930249aea610fc98 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 23:34:39 +0300
Subject: [PATCH 088/157] More comments to THD::lock and THD::locked_tables
 commented

---
 sql/sql_class.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5390e8a4ac4..4bdf5c38a2c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -624,6 +624,19 @@ public:
      and are still in use by this thread
   */
   TABLE   *open_tables,*temporary_tables, *handler_tables, *derived_tables;
+  /*
+    During a MySQL session, one can lock tables in two modes: automatic
+    or manual. In automatic mode all necessary tables are locked just before
+    statement execution, and all acquired locks are stored in a 'lock'
+    member. Unlocking takes place automatically as well, when the
+    statement ends.
+    Manual mode comes into play when a user issues a 'LOCK TABLES'
+    statement. In this mode the user can only use the locked tables.
+    Trying to use any other tables will give an error. The locked tables are
+    stored in a 'locked_tables' member.  Manual locking is described in
+    the 'LOCK_TABLES' chapter of the MySQL manual.
+    See also lock_tables() for details.
+  */
   MYSQL_LOCK	*lock;				/* Current locks */
   MYSQL_LOCK	*locked_tables;			/* Tables locked with LOCK */
   /*

From b89abbf8a154376678a3ed8a9fe6ea25b5209aba Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 23:34:40 +0300
Subject: [PATCH 089/157] more clear (grammar mistake)

---
 sql/sql_class.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql/sql_class.h b/sql/sql_class.h
index 4bdf5c38a2c..7971137d848 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -627,13 +627,13 @@ public:
   /*
     During a MySQL session, one can lock tables in two modes: automatic
     or manual. In automatic mode all necessary tables are locked just before
-    statement execution, and all acquired locks are stored in a 'lock'
+    statement execution, and all acquired locks are stored in 'lock'
     member. Unlocking takes place automatically as well, when the
     statement ends.
     Manual mode comes into play when a user issues a 'LOCK TABLES'
     statement. In this mode the user can only use the locked tables.
     Trying to use any other tables will give an error. The locked tables are
-    stored in a 'locked_tables' member.  Manual locking is described in
+    stored in 'locked_tables' member.  Manual locking is described in
     the 'LOCK_TABLES' chapter of the MySQL manual.
     See also lock_tables() for details.
   */

From 43abc597b8854c44465a8a936febe780f223628c Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 19 Jan 2004 23:51:17 +0100
Subject: [PATCH 090/157] Code cleanup Fixed bug in optimizer where it didn't
 choose right table order in some cases

myisam/mi_delete.c:
  Remove not needed include errno.h
myisam/mi_delete_table.c:
  Remove not needed include errno.h
myisam/mi_extra.c:
  Remove not needed include errno.h
myisam/mi_locking.c:
  Remove not needed include errno.h
myisam/mi_log.c:
  Remove not needed include errno.h
myisam/mi_page.c:
  Remove not needed include errno.h
myisam/mi_rename.c:
  Remove not needed include errno.h
myisam/mi_update.c:
  Remove not needed include errno.h
myisam/mi_write.c:
  Remove not needed include errno.h
mysql-test/r/subselect.result:
  Update of test after optimzier fix
mysys/charset.c:
  Code cleanup
sql/item_cmpfunc.cc:
  Removed not needed comment
  Indentation cleanup
sql/item_cmpfunc.h:
  Indentation cleanup
sql/mysqld.cc:
  Updated comment for expire_logs_days
sql/set_var.cc:
  Remved duplicate code
sql/sql_select.cc:
  Fixed bug in optimizer where it didn't choose right table order in some cases (Bug found and fixed by Igor)
---
 myisam/mi_delete.c            |  4 ----
 myisam/mi_delete_table.c      |  3 ---
 myisam/mi_extra.c             |  3 ---
 myisam/mi_locking.c           |  3 ---
 myisam/mi_log.c               |  1 -
 myisam/mi_page.c              |  3 ---
 myisam/mi_rename.c            |  3 ---
 myisam/mi_update.c            |  5 -----
 myisam/mi_write.c             |  4 ----
 mysql-test/r/subselect.result |  4 ++--
 mysys/charset.c               | 13 +++++++------
 sql/item_cmpfunc.cc           | 15 ++++-----------
 sql/item_cmpfunc.h            |  6 +++---
 sql/mysqld.cc                 |  2 +-
 sql/set_var.cc                | 10 ----------
 sql/sql_select.cc             | 21 +++++++++++++++++----
 16 files changed, 34 insertions(+), 66 deletions(-)

diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index a55d5b2a5ca..19cfc050ea1 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -20,10 +20,6 @@
 #include "rt_index.h"
 #include 
 
-#ifdef	__WIN__
-#include 
-#endif
-
 static int d_search(MI_INFO *info,MI_KEYDEF *keyinfo,uint comp_flag,
                     uchar *key,uint key_length,my_off_t page,uchar *anc_buff);
 static int del(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
diff --git a/myisam/mi_delete_table.c b/myisam/mi_delete_table.c
index 6d842d7e6a4..6843881568d 100644
--- a/myisam/mi_delete_table.c
+++ b/myisam/mi_delete_table.c
@@ -19,9 +19,6 @@
 */
 
 #include "fulltext.h"
-#ifdef	__WIN__
-#include 
-#endif
 
 int mi_delete_table(const char *name)
 {
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 10f52f1e39a..ce072d7d57e 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -18,9 +18,6 @@
 #ifdef HAVE_MMAP
 #include 
 #endif
-#ifdef	__WIN__
-#include 
-#endif
 
 /*
   Set options and buffers to optimize table handling
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 67ccca52d08..816748d459a 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -22,9 +22,6 @@
   */
 
 #include "myisamdef.h"
-#ifdef	__WIN__
-#include 
-#endif
 
 	/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
 
diff --git a/myisam/mi_log.c b/myisam/mi_log.c
index 1dcfd5250d2..13842c56828 100644
--- a/myisam/mi_log.c
+++ b/myisam/mi_log.c
@@ -21,7 +21,6 @@
 
 #include "myisamdef.h"
 #if defined(MSDOS) || defined(__WIN__)
-#include 
 #include 
 #ifndef __WIN__
 #include 
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index c70209c2da6..16713c87e10 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -17,9 +17,6 @@
 /* Read and write key blocks */
 
 #include "myisamdef.h"
-#ifdef	__WIN__
-#include 
-#endif
 
 	/* Fetch a key-page in memory */
 
diff --git a/myisam/mi_rename.c b/myisam/mi_rename.c
index db44b8fe28f..8380ee1bfad 100644
--- a/myisam/mi_rename.c
+++ b/myisam/mi_rename.c
@@ -19,9 +19,6 @@
 */
 
 #include "fulltext.h"
-#ifdef	__WIN__
-#include 
-#endif
 
 int mi_rename(const char *old_name, const char *new_name)
 {
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index d1d41ac351a..f62be133ed9 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -19,11 +19,6 @@
 #include "fulltext.h"
 #include "rt_index.h"
 
-#ifdef	__WIN__
-#include 
-#endif
-
-
 int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
 {
   int flag,key_changed,save_errno;
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index d13ba6c2c4e..4b7a22dac84 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -20,10 +20,6 @@
 #include "rt_index.h"
 #include 
 
-#ifdef	__WIN__
-#include 
-#endif
-
 #define MAX_POINTER_LENGTH 8
 
 	/* Functions declared in this file */
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 672a39299dd..edc8e56f442 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1340,8 +1340,8 @@ a
 explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
-2	DEPENDENT SUBQUERY	t3	index	a	a	5	NULL	3	Using index
-2	DEPENDENT SUBQUERY	t1	ref	a	a	10	func,test.t3.a	1000	Using where; Using index
+2	DEPENDENT SUBQUERY	t1	ref	a	a	5	func	1001	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	index	a	a	5	NULL	3	Using where; Using index
 Warnings:
 Note	1003	select high_priority test.t2.a AS `a` from test.t2 where (test.t2.a,(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and ((test.t2.a) = test.t1.a)) limit 1))
 insert into t1 values (3,31);
diff --git a/mysys/charset.c b/mysys/charset.c
index f8c8237c88b..fec0778213f 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -533,14 +533,15 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
   */
   pthread_mutex_lock(&THR_LOCK_charset);
 
-  cs= all_charsets[cs_number];
-
-  if (cs && !(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
+  if ((cs= all_charsets[cs_number]))
   {
-     strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
-     my_read_charset_file(buf,flags);
+    if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
+    {
+      strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS);
+      my_read_charset_file(buf,flags);
+    }
+    cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
   }
-  cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
   pthread_mutex_unlock(&THR_LOCK_charset);
   return cs;
 }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a79ef21e97a..5b27091321c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1658,26 +1658,19 @@ Item_cond::Item_cond(THD *thd, Item_cond &item)
    and_tables_cache(item.and_tables_cache)
 {
   /*
-    here should be following text:
-
-  List_iterator_fast li(item.list);
-  while(Item *it= li++)
-    list.push_back(it);
-
-    but it do not need,
-    because this constructor used only for AND/OR and
-    argument list will be copied by copy_andor_arguments call
+    item->list will be copied by copy_andor_arguments() call
   */
-
 }
 
+
 void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
 {
   List_iterator_fast li(item->list);
-  while(Item *it= li++)
+  while (Item *it= li++)
     list.push_back(it->copy_andor_structure(thd));
 }
 
+
 bool
 Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 {
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 541bc47557d..f5cd608ebad 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -919,8 +919,8 @@ public:
   Item* copy_andor_structure(THD *thd)
   {
     Item_cond_and *item;
-    if((item= new Item_cond_and(thd, *this)))
-       item->copy_andor_arguments(thd, this);
+    if ((item= new Item_cond_and(thd, *this)))
+      item->copy_andor_arguments(thd, this);
     return item;
   }
   Item *neg_transformer();
@@ -940,7 +940,7 @@ public:
   Item* copy_andor_structure(THD *thd)
   {
     Item_cond_or *item;
-    if((item= new Item_cond_or(thd, *this)))
+    if ((item= new Item_cond_or(thd, *this)))
       item->copy_andor_arguments(thd, this);
     return item;
   }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e81113f6111..6387e99ca05 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4619,7 +4619,7 @@ The minimum value for this variable is 4096.",
    (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
    REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
   {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS,
-   "Logs will be rotated after expire-log-days days ",
+   "Binary logs will be rotated after expire-log-days days ",
    (gptr*) &expire_logs_days,
    (gptr*) &expire_logs_days, 0, GET_ULONG,
    REQUIRED_ARG, 0, 0, 99, 0, 1, 0},
diff --git a/sql/set_var.cc b/sql/set_var.cc
index c8b11eb0f58..ecb85440068 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2629,11 +2629,6 @@ ulong fix_sql_mode(ulong sql_mode)
 		MODE_IGNORE_SPACE |
 		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
 		MODE_NO_FIELD_OPTIONS);
-  if (sql_mode & MODE_MSSQL)
-    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
-		MODE_IGNORE_SPACE |
-		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
-		MODE_NO_FIELD_OPTIONS);
   if (sql_mode & MODE_POSTGRESQL)
     sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
 		MODE_IGNORE_SPACE |
@@ -2644,11 +2639,6 @@ ulong fix_sql_mode(ulong sql_mode)
 		MODE_IGNORE_SPACE |
 		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
 		MODE_NO_FIELD_OPTIONS);
-  if (sql_mode & MODE_DB2)
-    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
-		MODE_IGNORE_SPACE |
-		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
-		MODE_NO_FIELD_OPTIONS);
   if (sql_mode & MODE_MAXDB)
     sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
 		MODE_IGNORE_SPACE |
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a1f6abfd53a..92cdd12ad37 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2688,22 +2688,35 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
 	  do
 	  {
             uint keypart=keyuse->keypart;
-	    uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL;
+            table_map best_part_found_ref= 0;
+            double best_prev_record_reads= DBL_MAX;
 	    do
 	    {
 	      if (!(rest_tables & keyuse->used_tables) &&
 		  !(found_ref_or_null & keyuse->optimize))
 	      {
 		found_part|=keyuse->keypart_map;
-		found_ref|= keyuse->used_tables;
+                double tmp= prev_record_reads(join,
+					      (found_ref |
+					       keyuse->used_tables));
+                if (tmp < best_prev_record_reads)
+                {
+                  best_part_found_ref= keyuse->used_tables;
+                  best_prev_record_reads= tmp;
+                }
 		if (rec > keyuse->ref_table_rows)
 		  rec= keyuse->ref_table_rows;
-		found_part_ref_or_null&= keyuse->optimize;
+		/*
+		  If there is one 'key_column IS NULL' expression, we can
+		  use this ref_or_null optimsation of this field
+		*/
+		found_ref_or_null|= (keyuse->optimize &
+				     KEY_OPTIMIZE_REF_OR_NULL);
               }
 	      keyuse++;
-	      found_ref_or_null|= found_part_ref_or_null;
 	    } while (keyuse->table == table && keyuse->key == key &&
 		     keyuse->keypart == keypart);
+	    found_ref|= best_part_found_ref;
 	  } while (keyuse->table == table && keyuse->key == key);
 
 	  /*

From 4e6744a45fd95a5ca86b183277fe0684b0c9d795 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 20 Jan 2004 17:35:51 +0200
Subject: [PATCH 091/157] row0sel.c:   Remove extra mtr_start()

innobase/row/row0sel.c:
  Remove extra mtr_start()
---
 innobase/row/row0sel.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 5a5da3ba59a..57de309c090 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2903,8 +2903,6 @@ row_search_for_mysql(
 
 	mtr_start(&mtr);
 
-	mtr_start(&mtr);
-
 	/*-------------------------------------------------------------*/
 	/* PHASE 2: Try fast adaptive hash index search if possible */
 

From 9768dc84c83eee93954a57f310ef3896861432b2 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 20 Jan 2004 20:55:47 +0400
Subject: [PATCH 092/157] Pack of changes about 'cleanup()'-s Some errorneous
 code trimmed

sql/item.cc:
  initialization of the Item_type_holder::orig_item added
sql/item.h:
  No use to call cleanup() in ~Item
  this only calls Item::cleanup()

  We should use item->delete_self() instead of 'delete item' now

  Code added to restore Item_type_holder::item_type value
sql/item_row.h:
  this cleanup is wrong
sql/item_sum.cc:
  initialization added
sql/item_sum.h:
  Item_xxx& -> Item_xxx*
sql/sql_parse.cc:
  delete item -> item->delete_self()
---
 sql/item.cc      |  3 ++-
 sql/item.h       | 13 ++++++++++++-
 sql/item_row.h   | 10 ----------
 sql/item_sum.cc  |  1 +
 sql/item_sum.h   |  6 +++---
 sql/sql_parse.cc |  2 +-
 6 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/sql/item.cc b/sql/item.cc
index 72c5ac3fd55..09328dfbf07 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2024,7 +2024,8 @@ void Item_cache_row::bring_value()
 
 
 Item_type_holder::Item_type_holder(THD *thd, Item *item)
-  :Item(thd, item), item_type(item->result_type())
+  :Item(thd, item), item_type(item->result_type()),
+   orig_type(item_type)
 {
   DBUG_ASSERT(item->fixed);
 
diff --git a/sql/item.h b/sql/item.h
index e9d34568350..d06977f555e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -125,7 +125,7 @@ public:
      optimisation changes in prepared statements
   */
   Item(THD *thd, Item *item);
-  virtual ~Item() { name=0; cleanup(); }		/*lint -e1509 */
+  virtual ~Item() { name=0; }		/*lint -e1509 */
   void set_name(const char *str,uint length, CHARSET_INFO *cs);
   void init_make_field(Send_field *tmp_field,enum enum_field_types type);
   virtual void cleanup() { fixed=0; }
@@ -227,6 +227,11 @@ public:
   
   /* Used in sql_select.cc:eliminate_not_funcs() */
   virtual Item *neg_transformer() { return NULL; }
+  void delete_self()
+  {
+    cleanup();
+    delete this;
+  }
 };
 
 
@@ -1003,6 +1008,7 @@ class Item_type_holder: public Item
 {
 protected:
   Item_result item_type;
+  Item_result orig_type;
   Field *field_example;
 public:
   Item_type_holder(THD*, Item*);
@@ -1014,6 +1020,11 @@ public:
   String *val_str(String*);
   bool join_types(THD *thd, Item *);
   Field *example() { return field_example; }
+  void cleanup()
+  {
+    Item::cleanup();
+    item_type= orig_type;
+  }
 };
 
 
diff --git a/sql/item_row.h b/sql/item_row.h
index 1b792f981fd..f87b4f66e80 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -34,16 +34,6 @@ public:
     with_null(0)
   {}
 
-  void cleanup()
-  {
-    if (array_holder && items)
-    {
-      sql_element_free(items);
-      items= 0;
-      array_holder= 0;
-    }
-  }
-
   enum Type type() const { return ROW_ITEM; };
   void illegal_method_call(const char *);
   bool is_null() { return null_value; }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 7c2d5501c06..e01f9db3463 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1097,6 +1097,7 @@ void Item_sum_count_distinct::cleanup()
     if (use_tree)
       delete_tree(tree);
     table= 0;
+    use_tree= 0;
   }
 }
 
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 9f1c8a09a4e..dc84e4d4ab7 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -610,7 +610,7 @@ class Item_sum_udf_float :public Item_sum_num
  public:
   Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
   Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_sum_num() {}
-  Item_sum_udf_float(THD *thd, Item_sum_udf_float &item)
+  Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
     :Item_sum_num(thd, item) {}
   enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
   double val() { return 0.0; }
@@ -625,7 +625,7 @@ class Item_sum_udf_int :public Item_sum_num
 public:
   Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
   Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_sum_num() {}
-  Item_sum_udf_int(THD *thd, Item_sum_udf_int &item)
+  Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
     :Item_sum_num(thd, item) {}
   enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
   longlong val_int() { return 0; }
@@ -641,7 +641,7 @@ class Item_sum_udf_str :public Item_sum_num
 public:
   Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
   Item_sum_udf_str(udf_func *udf_arg, List &list)  :Item_sum_num() {}
-  Item_sum_udf_str(THD *thd, Item_sum_udf_str &item)
+  Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
     :Item_sum_num(thd, item) {}
   String *val_str(String *) { null_value=1; return 0; }
   double val() { null_value=1; return 0.0; }
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index de75ed301e5..7929247676f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1109,7 +1109,7 @@ end:
 void free_items(Item *item)
 {
   for (; item ; item=item->next)
-    delete item;
+    item->delete_self();
 }
 
     /* This works because items are allocated with sql_alloc() */

From 7a1a5cd2d828d67120d10eb623c6c5bd83733260 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 20 Jan 2004 19:16:18 +0200
Subject: [PATCH 093/157] for multy-delete command used same algorithm of table
 reference (alias)

mysql-test/t/multi_update.test:
  new results of changed multi-delete
mysql-test/t/update.test:
  new results of changed multi-delete
mysql-test/r/multi_update.result:
  new results of changed multi-delete
mysql-test/r/update.result:
  new results of changed multi-delete
---
 mysql-test/r/multi_update.result | 2 +-
 mysql-test/r/update.result       | 2 +-
 mysql-test/t/multi_update.test   | 2 +-
 mysql-test/t/update.test         | 2 +-
 sql/sql_parse.cc                 | 5 ++---
 5 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index d335c9c1d10..a61ce31b8ae 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -244,7 +244,7 @@ select * from t2;
 n	d
 1	30
 1	30
-DELETE t1, t2  FROM t1 a,t2 b where a.n=b.n;
+DELETE a, b  FROM t1 a,t2 b where a.n=b.n;
 select * from t1;
 n	d
 3	2
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index 6a5546200ce..0037fb9ea95 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -158,7 +158,7 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6),
 ('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2),
 ('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4),
 ('2','2','0',1,7);
-delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
+delete from m1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
 select * from t1;
 F1	F2	F3	cnt	groupid
 0	0	0	1	6
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 6f012801972..e52b373a4a6 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -218,7 +218,7 @@ select * from t2;
 UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n;
 select * from t1;
 select * from t2;
-DELETE t1, t2  FROM t1 a,t2 b where a.n=b.n;
+DELETE a, b  FROM t1 a,t2 b where a.n=b.n;
 select * from t1;
 select * from t2;
 drop table t1,t2;
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 8e50fee56fd..3406dfd6158 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -126,6 +126,6 @@ insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6),
 ('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4),
 ('2','2','0',1,7);
 
-delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
+delete from m1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
 select * from t1;
 drop table t1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4310f69d2a7..64af7d21927 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2665,9 +2665,8 @@ mysql_execute_command(THD *thd)
       TABLE_LIST *walk;
       for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
       {
-	if ((!strcmp(auxi->real_name,walk->real_name) ||
-	     !strcmp(auxi->real_name,walk->alias)) &&
-	    !strcmp(walk->db,auxi->db))
+	if (!strcmp(auxi->real_name, walk->alias) &&
+	    !strcmp(walk->db, auxi->db))
 	  break;
       }
       if (!walk)

From 53d6a088bcbab1777e32777e80a548b46f1140af Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 21 Jan 2004 00:08:18 +0400
Subject: [PATCH 094/157] Fix for #2278 (mysql_prepare and mysql_execute not
 exported in libmysqld.dll)

Actually no PS-related methods were exported.
Now they're in the libmysqld.def


VC++Files/libmysqld/libmysqld.def:
  PS related methods added
---
 VC++Files/libmysqld/libmysqld.def | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def
index c3f757b5f1a..37a6114a6d0 100644
--- a/VC++Files/libmysqld/libmysqld.def
+++ b/VC++Files/libmysqld/libmysqld.def
@@ -92,6 +92,28 @@ EXPORTS
 	mysql_thread_safe
 	mysql_use_result
 	mysql_warning_count
+	mysql_prepare
+	mysql_execute
+	mysql_param_count
+	mysql_bind_param
+	mysql_bind_result
+	mysql_fetch
+	mysql_fetch_column
+	mysql_send_long_data
+	mysql_get_metadata
+	mysql_param_result
+	mysql_stmt_close
+	mysql_stmt_reset
+	mysql_stmt_free_result
+	mysql_stmt_errno
+	mysql_stmt_error
+	mysql_stmt_sqlstate
+	mysql_stmt_affected_rows
+	mysql_stmt_store_result
+	mysql_stmt_row_seek
+	mysql_stmt_row_tell
+	mysql_stmt_data_seek
+	mysql_stmt_num_rows
 	net_buffer_length
 	set_dynamic
 	strcend

From cf240e4ee83b39fbbccf92a35f394cb2793437a5 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 21 Jan 2004 14:15:19 +0400
Subject: [PATCH 095/157] Further fixes for 2390: ucs2 alignment

---
 mysql-test/r/ctype_ucs.result | 56 +++++++++++++++++++++++++++++++++++
 mysql-test/t/ctype_ucs.test   | 38 +++++++++++++++++++++++-
 sql/field.cc                  | 16 ++++------
 sql/sql_string.cc             | 54 ++++++++++++++++++++++++++++++---
 sql/sql_string.h              |  3 ++
 5 files changed, 152 insertions(+), 15 deletions(-)

diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index d6e9cc690a2..8d9c7579771 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -324,3 +324,59 @@ HEX(_ucs2 0x0123456789ABCDE)
 SELECT HEX(_ucs2 0x0123456789ABCDEF);
 HEX(_ucs2 0x0123456789ABCDEF)
 0123456789ABCDEF
+SELECT hex(cast(0xAA as char character set ucs2));
+hex(cast(0xAA as char character set ucs2))
+00AA
+SELECT hex(convert(0xAA using ucs2));
+hex(convert(0xAA using ucs2))
+00AA
+CREATE TABLE t1 (a char(10) character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+HEX(a)
+000A
+00AA
+0AAA
+AAAA
+000AAAAA
+DROP TABLE t1;
+CREATE TABLE t1 (a varchar(10) character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+HEX(a)
+000A
+00AA
+0AAA
+AAAA
+000AAAAA
+DROP TABLE t1;
+CREATE TABLE t1 (a text character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+HEX(a)
+000A
+00AA
+0AAA
+AAAA
+000AAAAA
+DROP TABLE t1;
+CREATE TABLE t1 (a mediumtext character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+HEX(a)
+000A
+00AA
+0AAA
+AAAA
+000AAAAA
+DROP TABLE t1;
+CREATE TABLE t1 (a longtext character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+HEX(a)
+000A
+00AA
+0AAA
+AAAA
+000AAAAA
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index fd2a1b1cd7d..021147e258a 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -200,7 +200,7 @@ DROP TABLE t1;
 
 
 # Bug #2390
-# Check alignment
+# Check alignment for constants
 #
 SELECT HEX(_ucs2 0x0);
 SELECT HEX(_ucs2 0x01);
@@ -218,3 +218,39 @@ SELECT HEX(_ucs2 0x0123456789ABC);
 SELECT HEX(_ucs2 0x0123456789ABCD);
 SELECT HEX(_ucs2 0x0123456789ABCDE);
 SELECT HEX(_ucs2 0x0123456789ABCDEF);
+
+#
+# Check alignment for from-binary-conversion with CAST and CONVERT
+#
+SELECT hex(cast(0xAA as char character set ucs2));
+SELECT hex(convert(0xAA using ucs2));
+
+#
+# Check alignment for string types
+#
+CREATE TABLE t1 (a char(10) character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a varchar(10) character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a text character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a mediumtext character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a longtext character set ucs2);
+INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
+SELECT HEX(a) FROM t1;
+DROP TABLE t1;
+
+-- the same should be also done with enum and set
diff --git a/sql/field.cc b/sql/field.cc
index 1a0716326fe..8dc133adae8 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4055,18 +4055,13 @@ void Field_datetime::sql_type(String &res) const
 
 	/* Copy a string and fill with space */
 
-static bool use_conversion(CHARSET_INFO *cs1, CHARSET_INFO *cs2)
-{
-  return (cs1 != &my_charset_bin) && (cs2 != &my_charset_bin) && (cs1!=cs2);
-}
-
 int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   int error= 0;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
   /* Convert character set if nesessary */
-  if (use_conversion(cs, field_charset))
+  if (String::needs_conversion(from, length, cs, field_charset))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -4254,7 +4249,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
   /* Convert character set if nesessary */
-  if (use_conversion(cs, field_charset))
+  if (String::needs_conversion(from, length, cs, field_charset))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -4572,7 +4567,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
     String tmpstr(buff,sizeof(buff), &my_charset_bin);
 
     /* Convert character set if nesessary */
-    if ((was_conversion= use_conversion(cs, field_charset)))
+    if ((was_conversion= String::needs_conversion(from, length,
+						  cs, field_charset)))
     { 
       tmpstr.copy(from, length, cs, field_charset);
       from= tmpstr.ptr();
@@ -5082,7 +5078,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
   /* Convert character set if nesessary */
-  if (use_conversion(cs, field_charset))
+  if (String::needs_conversion(from, length, cs, field_charset))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -5263,7 +5259,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
 
   /* Convert character set if nesessary */
-  if (use_conversion(cs, field_charset))
+  if (String::needs_conversion(from, length, cs, field_charset))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 9534c5605fe..225076bc555 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -228,6 +228,32 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
   return FALSE;
 }
 
+
+/*
+  Checks that the source string can be just copied
+  to the destination string without conversion.
+  If either character set conversion or adding leading
+  zeros (e.g. for UCS-2) must be done then return 
+  value is TRUE else FALSE.
+*/
+bool String::needs_conversion(const char *str, uint32 arg_length,
+				     CHARSET_INFO *from_cs,
+				     CHARSET_INFO *to_cs)
+{
+  if (to_cs == &my_charset_bin)
+    return FALSE;
+  if (to_cs == from_cs)
+    return FALSE;
+  if (my_charset_same(from_cs, to_cs))
+    return FALSE;
+  if ((from_cs == &my_charset_bin))
+  {
+    if (!(arg_length % to_cs->mbminlen))
+      return FALSE;
+  }
+  return TRUE;
+}
+
 /*
 ** For real multi-byte, ascii incompatible charactser sets,
 ** like UCS-2, add leading zeros if we have an incomplete character.
@@ -237,15 +263,15 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
 **   SELECT _ucs2 0x00AA
 */
 
-bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
-				 CHARSET_INFO *cs)
+bool String::copy_aligned(const char *str,uint32 arg_length,
+			  CHARSET_INFO *cs)
 {
   /* How many bytes are in incomplete character */
   uint32 offs= (arg_length % cs->mbminlen); 
 
   if (!offs) /* All characters are complete, just copy */
   {
-    set(str, arg_length, cs);
+    copy(str, arg_length, cs);
     return FALSE;
   }
   
@@ -274,15 +300,35 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
   return FALSE;
 }
 
+
+bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
+				 CHARSET_INFO *cs)
+{
+  /* How many bytes are in incomplete character */
+  uint32 offs= (arg_length % cs->mbminlen); 
+  
+  if (!offs) /* All characters are complete, just copy */
+  {
+    set(str, arg_length, cs);
+    return FALSE;
+  }
+  return copy_aligned(str, arg_length, cs);
+}
+
 	/* Copy with charset convertion */
 
 bool String::copy(const char *str, uint32 arg_length,
 		  CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 {
-  if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin))
+  if (!needs_conversion(str, arg_length, from_cs, to_cs))
   {
     return copy(str, arg_length, to_cs);
   }
+  if ((from_cs == &my_charset_bin) && (arg_length % to_cs->mbminlen))
+  {
+    return copy_aligned(str, arg_length, to_cs);
+  }
+  
   uint32 new_length= to_cs->mbmaxlen*arg_length;
   if (alloc(new_length))
     return TRUE;
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 8817aa8eab8..9c0900137e3 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -183,6 +183,9 @@ public:
   bool copy();					// Alloc string if not alloced
   bool copy(const String &s);			// Allocate new string
   bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs);	// Allocate new string
+  static bool needs_conversion(const char *s, uint32 arg_length,
+  			       CHARSET_INFO *cs_from, CHARSET_INFO *cs_to);
+  bool copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
   bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
   bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
 	    CHARSET_INFO *csto);

From 335ad8f25514a3c78887a7c8a34f47efc2cf71de Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 21 Jan 2004 14:32:02 +0400
Subject: [PATCH 096/157] sql_string.cc:   Rewrote to comply the coding style

sql/sql_string.cc:
  Rewrote to comply the coding style
---
 sql/sql_string.cc | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 225076bc555..42e700b27aa 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -240,17 +240,12 @@ bool String::needs_conversion(const char *str, uint32 arg_length,
 				     CHARSET_INFO *from_cs,
 				     CHARSET_INFO *to_cs)
 {
-  if (to_cs == &my_charset_bin)
+  if ((to_cs == &my_charset_bin) || 
+      (to_cs == from_cs) ||
+      my_charset_same(from_cs, to_cs) ||
+      ((from_cs == &my_charset_bin) && (!(arg_length % to_cs->mbminlen))))
     return FALSE;
-  if (to_cs == from_cs)
-    return FALSE;
-  if (my_charset_same(from_cs, to_cs))
-    return FALSE;
-  if ((from_cs == &my_charset_bin))
-  {
-    if (!(arg_length % to_cs->mbminlen))
-      return FALSE;
-  }
+  
   return TRUE;
 }
 

From b5567d15031a8a84d184038f73fedc5f24fc1a08 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 21 Jan 2004 15:47:47 +0400
Subject: [PATCH 097/157] yet another cleanup()-related fix

sql/sql_lex.cc:
  We need these to be clean.
  Otherwise restoring of the order_list and group_list could fail
  in mysql_stmt_execute()
---
 sql/sql_lex.cc | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index efb0ce92ad0..fea16dccd4a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -127,6 +127,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
   lex->select_lex.expr_list.empty();
   lex->select_lex.ftfunc_list_alloc.empty();
   lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
+  lex->select_lex.group_list.empty();
+  lex->select_lex.order_list.empty();
   lex->current_select= &lex->select_lex;
   lex->yacc_yyss=lex->yacc_yyvs=0;
   lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);

From 9138a61cf8365b4542669b61bd63ca39258b90ac Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 21 Jan 2004 20:25:49 +0100
Subject: [PATCH 098/157] no unnecessary includes (Intel ecc 7.0 compatibility
 fix)

---
 mysys/my_new.cc | 4 ++--
 mysys/raid.cc   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/mysys/my_new.cc b/mysys/my_new.cc
index 5f2da90bbd1..ec27502d8aa 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -19,9 +19,9 @@
   with gcc 3.0.x to avoid including libstdc++
 */
 
-#include "mysys_priv.h"
+#ifdef USE_MYSYS_NEW
 
-#ifdef USE_MYSYS_NEW  
+#include "mysys_priv.h"
 
 void *operator new (size_t sz)
 {
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 0b688464fb3..7eb19ffb16a 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -70,6 +70,8 @@
    tonu@mysql.com & monty@mysql.com
 */
 
+#if defined(USE_RAID) && !defined(MYSQL_CLIENT)
+
 #ifdef __GNUC__
 #pragma implementation				// gcc: Class implementation
 #endif
@@ -79,8 +81,6 @@
 #include 
 #include 
 
-#if defined(USE_RAID) && !defined(MYSQL_CLIENT)
-
 #define RAID_SEEK_DONE ~(off_t) 0
 #define RAID_SIZE_UNKNOWN ~(my_off_t) 0
 

From 4d2a1ed59eb1acc446c7ea1a448783cb3b9c4535 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 22 Jan 2004 12:55:37 +0100
Subject: [PATCH 099/157] enforcing coding style to cause an intentional merge
 conflict with 4.0

---
 sql/item_strfunc.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4507b2598a3..6f580317447 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1647,11 +1647,11 @@ void Item_func_elt::fix_length_and_dec()
 {
   max_length=0;
   decimals=0;
-  
+
   if (agg_arg_collations(collation, args+1, arg_count-1))
     return;
 
-  for (uint i=1 ; i < arg_count ; i++)
+  for (uint i= 1 ; i < arg_count ; i++)
   {
     set_if_bigger(max_length,args[i]->max_length);
     set_if_bigger(decimals,args[i]->decimals);

From 989cb2f29bc54d4b7e8181d11f8c37d7a358ec51 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 22 Jan 2004 22:13:24 +0200
Subject: [PATCH 100/157] Fix for a bug #2422, where CONVERT(expr, cast) was
 masked by CONVERT(expr, expr, expr);

mysql-test/t/mysqldump.test:
  fix for my previous result fix of Jani's changes.
---
 mysql-test/r/cast.result    |  3 +++
 mysql-test/t/cast.test      |  1 +
 mysql-test/t/mysqldump.test | 12 ++++++------
 sql/sql_yacc.yy             | 12 ++----------
 4 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 24d33e79411..893452290b2 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -33,6 +33,9 @@ cast("2001-1-1" as DATE)	cast("2001-1-1" as DATETIME)
 select cast("1:2:3" as TIME);
 cast("1:2:3" as TIME)
 01:02:03
+select CONVERT("2004-01-22 21:45:33",DATE);
+CONVERT("2004-01-22 21:45:33",DATE)
+2004-01-22
 set names binary;
 select cast(_latin1'test' as char character set latin2);
 cast(_latin1'test' as char character set latin2)
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index cb5f10515bd..e1cfe5760ee 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -13,6 +13,7 @@ select cast(5 as unsigned) -6.0;
 select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A";
 select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
 select cast("1:2:3" as TIME);
+select CONVERT("2004-01-22 21:45:33",DATE);
 
 #
 # Character set convertion
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 21004c8c305..93b0dd4a75d 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -6,7 +6,7 @@ DROP TABLE IF EXISTS t1, `"t"1`;
 
 CREATE TABLE t1(a int);
 INSERT INTO t1 VALUES (1), (2);
---exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -16,7 +16,7 @@ DROP TABLE t1;
 CREATE TABLE t1 (a decimal(240, 20));
 INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
 ("0987654321098765432109876543210987654321");
---exec $MYSQL_DUMP --disable-quote --skip-comments test t1
+--exec $MYSQL_DUMP --skip-comments test t1
 DROP TABLE t1;
 
 #
@@ -28,12 +28,12 @@ INSERT INTO t1 VALUES (-9e999999);
 # The following replaces is here because some systems replaces the above
 # double with '-inf' and others with MAX_DOUBLE
 --replace_result (-1.79769313486232e+308) (RES) (NULL) (RES)
---exec $MYSQL_DUMP --disable-quote --skip-comments test t1
+--exec $MYSQL_DUMP  --skip-comments test t1
 DROP TABLE t1;
 
 CREATE TABLE t1(a int, b text, c varchar(3));
 INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
---exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP  --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -42,7 +42,7 @@ DROP TABLE t1;
 
 CREATE TABLE t1 (`a"b"` char(2));
 INSERT INTO t1 VALUES ("1\""), ("\"2");
---exec $MYSQL_DUMP --disable-quote --skip-all --skip-comments -X test t1
+--exec $MYSQL_DUMP  --skip-all --skip-comments -X test t1
 DROP TABLE t1;
 
 #
@@ -51,5 +51,5 @@ DROP TABLE t1;
 
 CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
---exec $MYSQL_DUMP --disable-quote --skip-comments test t1
+--exec $MYSQL_DUMP  --skip-comments test t1
 DROP TABLE t1;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5ab53a1b934..fe8f0b2b2ee 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -664,7 +664,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 
 %type  handler_rkey_mode
 
-%type  cast_type cast_type_finalize
+%type  cast_type
 
 %type  udf_func_type
 
@@ -3003,11 +3003,7 @@ in_sum_expr:
 	  $$= $3;
 	};
 
-cast_type_init:
-	{ Lex->charset= NULL; Lex->length= (char*)0; }
-	;
-
-cast_type_finalize:
+cast_type:
 	BINARY			{ $$=ITEM_CAST_BINARY; }
 	| CHAR_SYM opt_len opt_binary	{ $$=ITEM_CAST_CHAR; }
 	| NCHAR_SYM opt_len	{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; }
@@ -3020,10 +3016,6 @@ cast_type_finalize:
 	| DATETIME		{ $$=ITEM_CAST_DATETIME; }
 	;
 
-cast_type:
-	cast_type_init cast_type_finalize { $$= $2; }
-	;
-
 expr_list:
 	{ Select->expr_list.push_front(new List); }
 	expr_list2

From acf9821b160d07753051d3acf58dab29fb60a4ba Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 11:56:37 +0100
Subject: [PATCH 101/157] patch reverted - USE_RAID is defined in my_config.h

mysql-test/r/derived.result:
  result updated
---
 mysql-test/r/derived.result | 2 +-
 mysys/raid.cc               | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index d38601c331f..170c393524b 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -254,7 +254,7 @@ CREATE TABLE `t1` (
 `M` tinyint(1) default '0',
 ) TYPE=MyISAM DEFAULT CHARSET=latin1;
 Warnings:
-Warning	1286	'TYPE=database_engine' is deprecated. Use 'ENGINE=database_engine' instead.
+Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
 INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
 select * from t1;
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 7eb19ffb16a..0b688464fb3 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -70,8 +70,6 @@
    tonu@mysql.com & monty@mysql.com
 */
 
-#if defined(USE_RAID) && !defined(MYSQL_CLIENT)
-
 #ifdef __GNUC__
 #pragma implementation				// gcc: Class implementation
 #endif
@@ -81,6 +79,8 @@
 #include 
 #include 
 
+#if defined(USE_RAID) && !defined(MYSQL_CLIENT)
+
 #define RAID_SEEK_DONE ~(off_t) 0
 #define RAID_SIZE_UNKNOWN ~(my_off_t) 0
 

From 214c178f1763c14934a337c2ebce89f10aa18741 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 16:02:57 +0400
Subject: [PATCH 102/157] SCRUM wl #1163 (Make spatial code optional) Patch I
 cleaned with Serg & Monty's suggestions

sql/gen_lex_hash.cc:
  mysql_priv.h was included for SYM_GROUP declaration
sql/lex.h:
  sym_group_xxx made global so we can use texts from them
  throughout the code
sql/lex_symbol.h:
  SYM_GROUP declaration moved to mysql_priv.h
sql/mysql_priv.h:
  declarations about SYM_GROUP
sql/sql_table.cc:
  sym_group_xxx objects used instead of text constants
  a couple of HAVE_SPATIAL removed
sql/sql_yacc.yy:
  sym_group_xxx used instead of text constants
  some duplicated code restructured
  MYF(0) parameters removed from net_printf calls
---
 sql/gen_lex_hash.cc |  3 ++-
 sql/lex.h           |  9 +++----
 sql/lex_symbol.h    |  7 ++---
 sql/mysql_priv.h    |  9 +++++++
 sql/sql_table.cc    | 13 +++-------
 sql/sql_yacc.yy     | 62 +++++++++++++++------------------------------
 6 files changed, 42 insertions(+), 61 deletions(-)

diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7126b7ee577..6df7d867a4d 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -81,9 +81,10 @@ TODO:
 #endif
 #include 
 #include "mysql_version.h"
+#include "mysql_priv.h"
 #include "lex.h"
 
-static struct my_option my_long_options[] =
+struct my_option my_long_options[] =
 {
   {"help", '?', "Display help and exit",
    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/sql/lex.h b/sql/lex.h
index 78a22fad153..93c3ec2f01e 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -20,8 +20,9 @@
 #include "lex_symbol.h"
 
 /* We don't want to include sql_yacc.h into gen_lex_hash */
-static SYM_GROUP sym_group_common= {"", ""};
-static SYM_GROUP sym_group_geom= {"Spatial extentions", "HAVE_SPATIAL"};
+SYM_GROUP sym_group_common= {"", ""};
+SYM_GROUP sym_group_geom= {"Spatial extentions", "HAVE_SPATIAL"};
+SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
 
 #ifdef NO_YACC_SYMBOLS
 #define SYM_OR_NULL(A) 0
@@ -457,7 +458,6 @@ static SYMBOL symbols[] = {
 
 static SYMBOL sql_functions[] = {
   { "ABS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)},
-#ifdef DUMMY
   { "ACOS",		F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)},
   { "ADDDATE",		SYM(ADDDATE_SYM)},
   { "ADDTIME",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)},
@@ -534,7 +534,7 @@ static SYMBOL sql_functions[] = {
   { "FROM_UNIXTIME",	SYM(FROM_UNIXTIME)},
   { "GET_LOCK",		F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)},
   { "GEOMETRYN",	F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_geometryn)},
-  { "GEOMETRYTYPE",	SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_geometry_type)},
+  { "GEOMETRYTYPE",	F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_geometry_type)},
   { "GEOMCOLLFROMTEXT",	SYM(GEOMCOLLFROMTEXT)},
   { "GEOMCOLLFROMWKB",	SYM(GEOMFROMWKB)},
   { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT)},
@@ -657,7 +657,6 @@ static SYMBOL sql_functions[] = {
   { "SUBSTR",	  	SYM(SUBSTRING)},
   { "SUBSTRING",	SYM(SUBSTRING)},
   { "SUBSTRING_INDEX",	SYM(SUBSTRING_INDEX)},
-#endif /*dummy*/
   { "SUBTIME",          F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
   { "SUM",		SYM(SUM_SYM)},
   { "SYSDATE",		SYM(NOW_SYM)},
diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h
index 63d4f9d69c2..d1d30a73669 100644
--- a/sql/lex_symbol.h
+++ b/sql/lex_symbol.h
@@ -20,17 +20,14 @@
 #ifndef _lex_symbol_h
 #define _lex_symbol_h
 
-typedef struct st_sym_group {
-  const char *name;
-  const char *needed_define;
-} SYM_GROUP;
+struct st_sym_group;
 
 typedef struct st_symbol {
   const char *name;
   uint	tok;
   uint length;
   void *create_func;
-  SYM_GROUP *group;
+  struct st_sym_group *group;
 } SYMBOL;
 
 typedef struct st_lex_symbol
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 15a99385285..43478d8d0a4 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1099,3 +1099,12 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
   table->map= (table_map) 1 << tablenr;
   table->force_index= table_list->force_index;
 }
+
+typedef struct st_sym_group {
+  const char *name;
+  const char *needed_define;
+} SYM_GROUP;
+
+extern SYM_GROUP sym_group_common;
+extern SYM_GROUP sym_group_geom;
+extern SYM_GROUP sym_group_rtree;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 127dc4c3474..3a7055c8078 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -528,7 +528,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       break;
 #else
       my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
-		      "Spatial extentions", "HAVE_SPATIAL");
+		      sym_group_geom.name, sym_group_geom.needed_define);
       DBUG_RETURN(-1);
 #endif /*HAVE_SPATIAL*/
     case FIELD_TYPE_VAR_STRING:
@@ -669,7 +669,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
         break;
 #else
 	my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
-			"Spatial extentions", "HAVE_SPATIAL");
+			sym_group_geom.name, sym_group_geom.needed_define);
 	DBUG_RETURN(-1);
 #endif
     case Key::FOREIGN_KEY:
@@ -700,7 +700,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
        checking for proper key parts number:
     */
 
-#ifdef HAVE_SPATIAL
     /* TODO: Add proper checks if handler supports key_type and algorithm */
     if (key_info->flags == HA_SPATIAL)
     {
@@ -712,7 +711,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       }
     }
     else
-#endif
     if (key_info->algorithm == HA_KEY_ALG_RTREE)
     {
 #ifdef HAVE_RTREE_KEYS
@@ -728,7 +726,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
       DBUG_RETURN(-1);
 #else
       my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
-		      "Spatial extentions", "HAVE_SPATIAL");
+		      sym_group_rtree.name, sym_group_rtree.needed_define);
       DBUG_RETURN(-1);
 #endif
     }
@@ -829,13 +827,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
                             MYF(0),column->field_name);
             DBUG_RETURN(-1);
           }
-#ifdef HAVE_SPATIAL
           if (key->type == Key::SPATIAL)
           {
             my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
             DBUG_RETURN(-1);
           }
-#endif
         }
         if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
         {
@@ -859,11 +855,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
 	    DBUG_RETURN(-1);
 	  }
 	}
-#ifdef HAVE_SPATIAL  //TODO HF What's this for???
+        /* TODO HF What's this for??? */
 	else if (f_is_geom(sql_field->pack_flag))
 	{
 	}
-#endif
 	else if (column->length > length ||
 		 ((f_is_packed(sql_field->pack_flag) ||
 		   ((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6ab44cb9f08..f4c68b79053 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1244,8 +1244,8 @@ field_spec:
 				(enum enum_field_types) $3,
 				lex->length,lex->dec,lex->type,
 				lex->default_value, lex->comment,
-				lex->change,lex->interval,lex->charset
-				,lex->uint_geom_type))
+				lex->change,lex->interval,lex->charset,
+				lex->uint_geom_type))
 	    YYABORT;
 	};
 
@@ -1305,8 +1305,8 @@ type:
 #else
 	                                  net_printf(Lex->thd, ER_FEATURE_DISABLED,
 			                             ER(ER_FEATURE_DISABLED),
-			                             MYF(0), "Spatial extentions",
-	                                             "HAVE_SPATIAL");
+			                             sym_group_geom.name,
+	                                             sym_group_geom.needed_define);
 					  YYABORT;
 #endif
 					}
@@ -1589,42 +1589,32 @@ delete_option:
 
 key_type:
 	key_or_index			    { $$= Key::MULTIPLE; }
-	| FULLTEXT_SYM			    { $$= Key::FULLTEXT; }
-	| FULLTEXT_SYM key_or_index	    { $$= Key::FULLTEXT; }
-	| SPATIAL_SYM
+	| FULLTEXT_SYM opt_key_or_index	    { $$= Key::FULLTEXT; }
+	| SPATIAL_SYM opt_key_or_index
 	  {
 #ifdef HAVE_SPATIAL
 	    $$= Key::SPATIAL;
 #else
 	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
 	               ER(ER_FEATURE_DISABLED),
-		       MYF(0), "Spatial extentions",
-	               "HAVE_SPATIAL");
-	    YYABORT;
-#endif
-	  }
-	| SPATIAL_SYM key_or_index
-	  {
-#ifdef HAVE_SPATIAL
-	    $$= Key::SPATIAL;
-#else
-	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
-	               ER(ER_FEATURE_DISABLED),
-	               MYF(0), "Spatial extentions",
-	               "HAVE_SPATIAL");
+		       sym_group_geom.name, sym_group_geom.needed_define);
 	    YYABORT;
 #endif
 	  };
 
 constraint_key_type:
 	PRIMARY_SYM KEY_SYM  { $$= Key::PRIMARY; }
-	| UNIQUE_SYM	    { $$= Key::UNIQUE; }
-	| UNIQUE_SYM key_or_index { $$= Key::UNIQUE; };
+	| UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; };
 
 key_or_index:
 	KEY_SYM {}
 	| INDEX {};
 
+opt_key_or_index:
+	/* empty */ {}
+	| key_or_index
+	;
+
 opt_keys_or_index:
 	/* empty */ {}
 	| keys_or_index
@@ -1646,8 +1636,7 @@ opt_unique_or_fulltext:
 #else
 	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
 	               ER(ER_FEATURE_DISABLED),
-	               MYF(0), "Spatial extentions",
-	               "HAVE_SPATIAL");
+	               sym_group_geom.name, sym_group_geom.needed_define);
 	    YYABORT;
 #endif
 	  }
@@ -1662,15 +1651,7 @@ opt_btree_or_rtree:
 	BTREE_SYM	{ $$= HA_KEY_ALG_BTREE; }
 	| RTREE_SYM
 	  {
-#ifdef HAVE_RTREE_KEYS
 	    $$= HA_KEY_ALG_RTREE;
-#else
-	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
-	               ER(ER_FEATURE_DISABLED),
-	               MYF(0), "RTree keys",
-	               "HAVE_RTREE_KEYS");
-	    YYABORT;
-#endif
 	  }
 	| HASH_SYM	{ $$= HA_KEY_ALG_HASH; };
 
@@ -1769,8 +1750,8 @@ alter_list_item:
                                   (enum enum_field_types) $5,
                                   lex->length,lex->dec,lex->type,
                                   lex->default_value, lex->comment,
-				  $3.str, lex->interval, lex->charset
-				  ,lex->uint_geom_type))
+				  $3.str, lex->interval, lex->charset,
+				  lex->uint_geom_type))
 	       YYABORT;
           }
           opt_place
@@ -2605,7 +2586,7 @@ simple_expr:
 	    {
 	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
 			 ER(ER_FEATURE_DISABLED),
-			 MYF(0), $1.symbol->group->name,
+			 $1.symbol->group->name,
 	                 $1.symbol->group->needed_define);
 	      YYABORT;
 	    }
@@ -2617,7 +2598,7 @@ simple_expr:
 	    {
 	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
 			 ER(ER_FEATURE_DISABLED),
-			 MYF(0), $1.symbol->group->name,
+			 $1.symbol->group->name,
 	                 $1.symbol->group->needed_define);
 	      YYABORT;
 	    }
@@ -2629,7 +2610,7 @@ simple_expr:
 	    {
 	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
 			 ER(ER_FEATURE_DISABLED),
-			 MYF(0), $1.symbol->group->name,
+			 $1.symbol->group->name,
 	                 $1.symbol->group->needed_define);
 	      YYABORT;
 	    }
@@ -2641,7 +2622,7 @@ simple_expr:
 	    {
 	      net_printf(Lex->thd, ER_FEATURE_DISABLED,
 			 ER(ER_FEATURE_DISABLED),
-			 MYF(0), $1.symbol->group->name,
+			 $1.symbol->group->name,
 	                 $1.symbol->group->needed_define);
 	      YYABORT;
 	    }
@@ -2736,8 +2717,7 @@ simple_expr:
 #else
 	    net_printf(Lex->thd, ER_FEATURE_DISABLED,
 	               ER(ER_FEATURE_DISABLED),
-	               MYF(0), "Spatial extentions",
-	               "HAVE_SPATIAL");
+	               sym_group_geom.name, sym_group_geom.needed_define);
 	    YYABORT;
 #endif
 	  }

From 2320323a344759567d702b257fb965646e6d8e7a Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 15:31:16 +0200
Subject: [PATCH 103/157] Reverted an addition to be able to use ';' as a
 comment starting character elsewhere than in the beginning of a line, because
 it affected some innodb options that had ';' in them.

---
 mysys/default.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mysys/default.c b/mysys/default.c
index 81e1fd06374..d27efce27ed 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -462,7 +462,7 @@ static char *remove_end_comment(char *ptr)
 	quote= 0;
     }
     /* We are not inside a comment */
-    if (!quote && (*ptr == '#' || *ptr == ';'))
+    if (!quote && *ptr == '#')
     {
       *ptr= 0;
       return ptr;

From 87b3ca5fe0f66b0d7546b6175d8b1d50d6d3a838 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 19:54:22 +0400
Subject: [PATCH 104/157] SCRUM WL#1163 (Make spatial code separable) fixes
 before the push

include/my_global.h:
  Temporary place for these defines
include/mysqld_error.h:
  ER_FEATURE_DISABLED definition
sql/item_geofunc.cc:
  #ifdef HAVE_SPATIAL moved to the better place
sql/share/english/errmsg.txt:
  Message for ER_FEATURE_DISABLED
---
 include/my_global.h          | 2 ++
 include/mysqld_error.h       | 3 ++-
 sql/item_geofunc.cc          | 4 ++--
 sql/share/english/errmsg.txt | 1 +
 4 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/my_global.h b/include/my_global.h
index 32516cd5810..c9660d4d649 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -1168,4 +1168,6 @@ typedef union {
 #define MYSQL_UNIVERSAL_CLIENT_CHARSET MYSQL_DEFAULT_CHARSET_NAME
 #endif
 
+#define HAVE_SPATIAL
+#define HAVE_RTREE_KEYS
 #endif /* my_global_h */
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 6a484d0419c..ac3437595fe 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -303,4 +303,5 @@
 #define ER_WARN_HOSTNAME_WONT_WORK 1284
 #define ER_UNKNOWN_STORAGE_ENGINE 1285
 #define ER_WARN_DEPRECATED_SYNTAX 1286
-#define ER_ERROR_MESSAGES 287
+#define ER_FEATURE_DISABLED 1287
+#define ER_ERROR_MESSAGES 288
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 671c4ed6de4..6934ad9d3b0 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -17,13 +17,13 @@
 
 /* This file defines all spatial functions */
 
-#ifdef HAVE_SPATIAL
-
 #ifdef __GNUC__
 #pragma implementation				// gcc: Class implementation
 #endif
 
 #include "mysql_priv.h"
+
+#ifdef HAVE_SPATIAL
 #include "sql_acl.h"
 #include 
 
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index afce57a9a74..1c93d0aa5e5 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -290,3 +290,4 @@ character-set=latin1
 "MySQL is started in --skip-name-resolve mode. You need to restart it without this switch for this grant to work",
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"

From 2e5dfc5ec4bbf4af6bc35733983e15e2b516a4c6 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 20:03:42 +0400
Subject: [PATCH 105/157] Error message added

---
 sql/share/czech/errmsg.txt        | 1 +
 sql/share/danish/errmsg.txt       | 1 +
 sql/share/dutch/errmsg.txt        | 1 +
 sql/share/estonian/errmsg.txt     | 1 +
 sql/share/french/errmsg.txt       | 1 +
 sql/share/german/errmsg.txt       | 1 +
 sql/share/greek/errmsg.txt        | 1 +
 sql/share/hungarian/errmsg.txt    | 1 +
 sql/share/italian/errmsg.txt      | 1 +
 sql/share/japanese/errmsg.txt     | 1 +
 sql/share/korean/errmsg.txt       | 1 +
 sql/share/norwegian-ny/errmsg.txt | 1 +
 sql/share/norwegian/errmsg.txt    | 1 +
 sql/share/polish/errmsg.txt       | 1 +
 sql/share/portuguese/errmsg.txt   | 1 +
 sql/share/romanian/errmsg.txt     | 1 +
 sql/share/russian/errmsg.txt      | 1 +
 sql/share/serbian/errmsg.txt      | 1 +
 sql/share/slovak/errmsg.txt       | 1 +
 sql/share/spanish/errmsg.txt      | 1 +
 sql/share/swedish/errmsg.txt      | 1 +
 sql/share/ukrainian/errmsg.txt    | 1 +
 22 files changed, 22 insertions(+)

diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index cf5f573774b..16c04fc7656 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -300,3 +300,4 @@ character-set=latin2
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 2a42570ded3..99470e1a32c 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 53463c31d02..0b4a8139e57 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -302,3 +302,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index fecf0cde7be..a54bc435fc1 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -296,3 +296,4 @@ character-set=latin7
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index afc1879a526..accf5913ce2 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 56e263bc64e..79b8ad5fe64 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -303,3 +303,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 1596b1adbab..09928aed242 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -291,3 +291,4 @@ character-set=greek
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index bcd17fca7cc..b7491154815 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin2
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 22a09ac1a1b..829428f2fd4 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index b76fa5d8f6d..2acd11a399e 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -293,3 +293,4 @@ character-set=ujis
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 482bc91852c..0533f52fc12 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -291,3 +291,4 @@ character-set=euckr
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index a442a5879b8..bb6b5b8cb11 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 47660e29676..b8a678d9b64 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 7f81facf6f5..04cf28915b5 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -295,3 +295,4 @@ character-set=latin2
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 8ddd281b346..16620380603 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "Motor de tabela desconhecido '%s'",
 "'%s' ι desatualizado. Use '%s' em seu lugar.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 2235871738c..6ccccd95417 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -295,3 +295,4 @@ character-set=latin2
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 76fc04f42e4..c5d06722cd8 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -293,3 +293,4 @@ character-set=koi8r
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "τΑΒΜΙΓΑ %-.100s Χ %s ΞΕ ΝΟΦΕΤ ΙΪΝΕΞΡΤΣΡ.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index a61c6a25ccc..c47c7b66e5a 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -286,3 +286,4 @@ character-set=cp1250
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 36437930095..8820b36b746 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -299,3 +299,4 @@ character-set=latin2
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 8e61ce6a62f..a17d58c2d35 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 9c13347cc3c..f9f05c7e122 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -291,3 +291,4 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index b5d5f74ef77..255083529c3 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -296,3 +296,4 @@ character-set=koi8u
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "τΑΒΜΙΓΡ %-.100s Υ %s ΞΕ ΝΟΦΕ ΟΞΟΧΜΐΧΑΤΙΣΨ.",
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"

From 7580623ec7a365d4b1ca8c8e333a7fbe64bbf900 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 20:52:35 +0400
Subject: [PATCH 106/157] define name fixed

sql/lex.h:
  Wrong define name
---
 sql/lex.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql/lex.h b/sql/lex.h
index 93c3ec2f01e..029a8ac4218 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -35,7 +35,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
 
 #define CREATE_FUNC(A) (void *)(SYM_OR_NULL(A)), &sym_group_common
 
-#ifdef HAVE_GEOM
+#ifdef HAVE_SPATIAL
 #define CREATE_FUNC_GEOM(A) (void *)(SYM_OR_NULL(A)), &sym_group_geom
 #else
 #define CREATE_FUNC_GEOM(A) 0, &sym_group_geom

From 8cfd6d0c1da8fc6589b11c06a09a2ffcb89f63c3 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 23 Jan 2004 21:26:13 -0800
Subject: [PATCH 107/157] mysqld.cc:   Fixed a typo bug.

sql/mysqld.cc:
  Fixed a typo bug.
---
 sql/mysqld.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 595792c22cf..6848955629d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4336,7 +4336,7 @@ replicating a LOAD DATA INFILE command.",
    (gptr*) 0,
    0, (enum get_opt_var_type) (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
    1, 100, 0, 1, 0},
-  {"key_cache_division_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
+  {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
    "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
    (gptr*) &dflt_key_cache_var.param_age_threshold,
    (gptr*) 0,

From 0314c772b5c7a6566c61167577a529bc098c27fd Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 26 Jan 2004 15:12:52 +0200
Subject: [PATCH 108/157] Fixed a bug in slave-compressed-protocol. Using this
 option from command line did not work.

---
 sql/mysqld.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6848955629d..36c7c9c364c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4556,7 +4556,7 @@ The minimum value for this variable is 4096.",
    "Use compression on master/slave protocol.",
    (gptr*) &opt_slave_compressed_protocol,
    (gptr*) &opt_slave_compressed_protocol,
-   0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
+   0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
   {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT,
    "Number of seconds to wait for more data from a master/slave connection before aborting the read.",
    (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,

From 0a3ca2f6408429f1943a13b692461b7dd53288ff Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 26 Jan 2004 20:31:38 +0400
Subject: [PATCH 109/157] Fix for bug#2505: MySQL reports "out of memory" when
 DROP USER if --skip-grant-tables

---
 include/mysqld_error.h            |  3 ++-
 sql/share/czech/errmsg.txt        |  1 +
 sql/share/danish/errmsg.txt       |  1 +
 sql/share/dutch/errmsg.txt        |  1 +
 sql/share/english/errmsg.txt      |  3 ++-
 sql/share/estonian/errmsg.txt     |  1 +
 sql/share/french/errmsg.txt       |  1 +
 sql/share/german/errmsg.txt       |  1 +
 sql/share/greek/errmsg.txt        |  1 +
 sql/share/hungarian/errmsg.txt    |  1 +
 sql/share/italian/errmsg.txt      |  1 +
 sql/share/japanese/errmsg.txt     |  1 +
 sql/share/korean/errmsg.txt       |  1 +
 sql/share/norwegian-ny/errmsg.txt |  1 +
 sql/share/norwegian/errmsg.txt    |  1 +
 sql/share/polish/errmsg.txt       |  1 +
 sql/share/portuguese/errmsg.txt   |  1 +
 sql/share/romanian/errmsg.txt     |  1 +
 sql/share/russian/errmsg.txt      |  1 +
 sql/share/serbian/errmsg.txt      |  1 +
 sql/share/slovak/errmsg.txt       |  1 +
 sql/share/spanish/errmsg.txt      |  1 +
 sql/share/swedish/errmsg.txt      |  1 +
 sql/share/ukrainian/errmsg.txt    |  1 +
 sql/sql_acl.cc                    | 28 +++++++++++++++++-----------
 25 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 80cfed9e338..fbf89bdb3e1 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -305,4 +305,5 @@
 #define ER_WARN_DEPRECATED_SYNTAX 1286
 #define ER_NON_UPDATABLE_TABLE 1287
 #define ER_FEATURE_DISABLED 1288
-#define ER_ERROR_MESSAGES 289
+#define ER_SKIP_GRANT_TABLES 1289
+#define ER_ERROR_MESSAGES 290
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 16c04fc7656..917b2259e24 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -301,3 +301,4 @@ character-set=latin2
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 99470e1a32c..591e007f5a6 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -295,3 +295,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 0b4a8139e57..3a0d77187bf 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -303,3 +303,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 0f9d9fc1144..38ca4966dfe 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -291,4 +291,5 @@ character-set=latin1
 "Unknown table engine '%s'",
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
-"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"The '%s' feature was disabled. You need MySQL built with '%s' define to have it working",
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index a54bc435fc1..f0882d5602b 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -297,3 +297,4 @@ character-set=latin7
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index accf5913ce2..d3c7c3ebde1 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 79b8ad5fe64..48eff8831d5 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -304,3 +304,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 09928aed242..1e3c436e3d0 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -292,3 +292,4 @@ character-set=greek
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index b7491154815..402933d7ef7 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin2
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 829428f2fd4..d9be6ebb32d 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 2acd11a399e..cc36dd60e85 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -294,3 +294,4 @@ character-set=ujis
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 0533f52fc12..0bbea735a09 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -292,3 +292,4 @@ character-set=euckr
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index bb6b5b8cb11..2372e7a9690 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index b8a678d9b64..f946e988fb0 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 04cf28915b5..c6bb914d38c 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -296,3 +296,4 @@ character-set=latin2
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 16620380603..537162fc1d0 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -293,3 +293,4 @@ character-set=latin1
 "'%s' ι desatualizado. Use '%s' em seu lugar.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 6ccccd95417..8da92d48883 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -296,3 +296,4 @@ character-set=latin2
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index c5d06722cd8..d5d91deb280 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -294,3 +294,4 @@ character-set=koi8r
 "'%s' is deprecated. Use '%s' instead.",
 "τΑΒΜΙΓΑ %-.100s Χ %s ΞΕ ΝΟΦΕΤ ΙΪΝΕΞΡΤΣΡ.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index c47c7b66e5a..8fa7933b871 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -287,3 +287,4 @@ character-set=cp1250
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 8820b36b746..90fbe450bb1 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -300,3 +300,4 @@ character-set=latin2
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index a17d58c2d35..644a5c7a515 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -294,3 +294,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index f9f05c7e122..22a6cecd773 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -292,3 +292,4 @@ character-set=latin1
 "'%s' is deprecated. Use '%s' instead.",
 "The target table %-.100s of the %s is not updatable.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 255083529c3..2d4ce67e2e5 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -297,3 +297,4 @@ character-set=koi8u
 "'%s' is deprecated. Use '%s' instead.",
 "τΑΒΜΙΓΡ %-.100s Υ %s ΞΕ ΝΟΦΕ ΟΞΟΧΜΐΧΑΤΙΣΨ.",
 "The '%s' feature was disabled. You need MySQL built with '%s' define to have it working"
+"MySQL is started in --skip-grant-tables mode. You can't use this command"
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 282a9afa038..77131a37869 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1114,8 +1114,8 @@ bool check_change_password(THD *thd, const char *host, const char *user)
 {
   if (!initialized)
   {
-    send_error(thd, ER_PASSWORD_NOT_ALLOWED); /* purecov: inspected */
-    return(1); /* purecov: inspected */
+    send_error(thd, ER_SKIP_GRANT_TABLES); /* purecov: inspected */
+    return(1);                             /* purecov: inspected */
   }
   if (!thd->slave_thread &&
       (strcmp(thd->user,user) ||
@@ -1590,8 +1590,14 @@ static int replace_db_table(TABLE *table, const char *db,
   char what= (revoke_grant) ? 'N' : 'Y';
   DBUG_ENTER("replace_db_table");
 
+  if (!initialized)
+  {
+    my_error(ER_SKIP_GRANT_TABLES, MYF(0));
+    DBUG_RETURN(-1);
+  }
+
   /* Check if there is such a user in user table in memory? */
-  if (!initialized || !find_acl_user(combo.host.str,combo.user.str))
+  if (!find_acl_user(combo.host.str,combo.user.str))
   {
     my_error(ER_PASSWORD_NO_MATCH,MYF(0));
     DBUG_RETURN(-1);
@@ -2167,7 +2173,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
 
   if (!initialized)
   {
-    send_error(thd, ER_UNKNOWN_COM_ERROR);	/* purecov: inspected */
+    send_error(thd, ER_SKIP_GRANT_TABLES);	/* purecov: inspected */
     DBUG_RETURN(1);				/* purecov: inspected */
   }
   if (rights & ~TABLE_ACLS)
@@ -2377,8 +2383,8 @@ int mysql_grant(THD *thd, const char *db, List  &list,
   DBUG_ENTER("mysql_grant");
   if (!initialized)
   {
-    my_error(ER_UNKNOWN_COM_ERROR, MYF(0));	/* purecov: tested */
-    return -1;					/* purecov: tested */
+    my_error(ER_SKIP_GRANT_TABLES, MYF(0));	/* purecov: tested */
+    DBUG_RETURN(-1);				/* purecov: tested */
   }
 
   if (lower_case_table_names && db)
@@ -2982,8 +2988,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
   LINT_INIT(acl_user);
   if (!initialized)
   {
-    send_error(thd, ER_UNKNOWN_COM_ERROR);
-    DBUG_RETURN(-1);
+    send_error(thd, ER_SKIP_GRANT_TABLES);
+    DBUG_RETURN(1);
   }
   if (lex_user->host.length > HOSTNAME_LENGTH ||
       lex_user->user.length > USERNAME_LENGTH)
@@ -3335,7 +3341,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
 
   if (!initialized)
   {
-    send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+    send_error(thd, ER_SKIP_GRANT_TABLES);
     DBUG_RETURN(-1);
   }
 
@@ -3416,7 +3422,7 @@ int mysql_drop_user(THD *thd, List  &list)
   DBUG_ENTER("mysql_drop_user");
 
   if ((result= open_grant_tables(thd, tables)))
-    DBUG_RETURN(result == 1 ? 0 : -1);
+    DBUG_RETURN(result == 1 ? 0 : 1);
 
   rw_wrlock(&LOCK_grant);
   VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -3529,7 +3535,7 @@ int mysql_revoke_all(THD *thd,  List  &list)
   DBUG_ENTER("mysql_revoke_all");
 
   if ((result= open_grant_tables(thd, tables)))
-    DBUG_RETURN(result == 1 ? 0 : -1);
+    DBUG_RETURN(result == 1 ? 0 : 1);
 
   rw_wrlock(&LOCK_grant);
   VOID(pthread_mutex_lock(&acl_cache->lock));

From 9a1d21f0d1f36f8b748ec2c2e0b72640b54be5d5 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 26 Jan 2004 19:39:00 +0100
Subject: [PATCH 110/157] fix for BUG#2516: "SLAVE START may crash mysqld"

sql/sql_yacc.yy:
  Enable UNTIL in SLAVE START; bzero() fixes the bug.
---
 sql/sql_yacc.yy | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d4cbd01dc17..4dbd7519fbd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1823,7 +1823,6 @@ opt_to:
 
 /*
   SLAVE START and SLAVE STOP are deprecated. We keep them for compatibility.
-  To use UNTIL, one must use START SLAVE, not SLAVE START.
 */
 
 slave:
@@ -1848,7 +1847,11 @@ slave:
 	   LEX *lex=Lex;
            lex->sql_command = SQLCOM_SLAVE_START;
 	   lex->type = 0;
-         }
+	    /* We'll use mi structure for UNTIL options */
+	    bzero((char*) &lex->mi, sizeof(lex->mi));
+          }
+          slave_until
+          {}
 	| SLAVE STOP_SYM slave_thread_opts
          {
 	   LEX *lex=Lex;

From a5af8f1f808a46a958ff665e250b51acb3204693 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 26 Jan 2004 20:16:37 +0100
Subject: [PATCH 111/157] warning comment

---
 sql/sql_yacc.yy | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 4dbd7519fbd..fac0a7388c3 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1833,6 +1833,7 @@ slave:
 	    lex->type = 0;
 	    /* We'll use mi structure for UNTIL options */
 	    bzero((char*) &lex->mi, sizeof(lex->mi));
+            /* If you change this code don't forget to update SLAVE START too */
           }
           slave_until
           {}
@@ -1841,6 +1842,7 @@ slave:
 	    LEX *lex=Lex;
             lex->sql_command = SQLCOM_SLAVE_STOP;
 	    lex->type = 0;
+            /* If you change this code don't forget to update SLAVE STOP too */
           }
 	| SLAVE START_SYM slave_thread_opts
          {

From 36ab3e0dfef031b0c69fa6f7050bec2111b3c987 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 27 Jan 2004 11:25:07 +0400
Subject: [PATCH 112/157] code cleanup (unnecessary line in
 libmysqld/Makefile.am)

libmysqld/Makefile.am:
  superfluous line deleted
---
 libmysqld/Makefile.am | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index e51fb5e315e..f9e73d1e219 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -74,7 +74,6 @@ INC_LIB=	$(top_builddir)/regex/libregex.a \
 		$(top_builddir)/mysys/libmysys.a \
 		$(top_builddir)/strings/libmystrings.a \
 		$(top_builddir)/dbug/libdbug.a \
-		$(top_builddir)/regex/libregex.a \
 		$(top_builddir)/vio/libvio.a
 
 #

From 58e442caf3740ef27e9349e9a50954ecbfd679ce Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 27 Jan 2004 13:46:47 +0400
Subject: [PATCH 113/157] bugfix to #1224 code slightly modified with Monty's
 suggestions

libmysqld/lib_sql.cc:
  copying of pointers replaced with my_strdup()-s
sql/sql_class.cc:
  this code should work anyway now
---
 libmysqld/lib_sql.cc | 8 ++++----
 sql/sql_class.cc     | 2 --
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 2d451d6cecd..741916064b0 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -484,7 +484,7 @@ int check_embedded_connection(MYSQL *mysql)
   THD *thd= (THD*)mysql->thd;
   thd->host= (char*)my_localhost;
   thd->host_or_ip= thd->host;
-  thd->user= mysql->user;
+  thd->user= my_strdup(mysql->user, MYF(0));
   return 0;
 }
 
@@ -498,8 +498,8 @@ int check_embedded_connection(MYSQL *mysql)
 
   if (mysql->options.client_ip)
   {
-    thd->host= mysql->options.client_ip;
-    thd->ip= thd->host;
+    thd->host= my_strdup(mysql->options.client_ip, MYF(0));
+    thd->ip= my_strdup(thd->host, MYF(0));
   }
   else
     thd->host= (char*)my_localhost;
@@ -511,7 +511,7 @@ int check_embedded_connection(MYSQL *mysql)
     goto err;
   }
 
-  thd->user= mysql->user;
+  thd->user= my_strdup(mysql->user, MYF(0));
   if (mysql->passwd && mysql->passwd[0])
   {
     memset(thd->scramble, 55, SCRAMBLE_LENGTH); // dummy scramble
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ce30c6f3d09..7b3d1fd3cd2 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -323,13 +323,11 @@ THD::~THD()
 #endif
 
   DBUG_PRINT("info", ("freeing host"));
-#ifndef EMBEDDED_LIBRARY
   if (host != my_localhost)			// If not pointer to constant
     safeFree(host);
   if (user != delayed_user)
     safeFree(user);
   safeFree(ip);
-#endif
   safeFree(db);
   free_root(&warn_root,MYF(0));
   free_root(&transaction.mem_root,MYF(0));

From 2746e7de02698856d6b19bb526cd104c2cd74163 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 27 Jan 2004 16:51:11 +0400
Subject: [PATCH 114/157] Fix for #2209 mysql->server_status wasn't set after
 the query

libmysqld/lib_sql.cc:
  Server status assignement added
---
 libmysqld/lib_sql.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 741916064b0..e36e878d4b1 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -96,6 +96,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
     net->last_error[0]= 0;
     strmov(net->sqlstate, not_error_sqlstate);
   }
+  mysql->server_status= thd->server_status;
   mysql->warning_count= ((THD*)mysql->thd)->total_warn_count;
   return result;
 }

From d01e81012876416b3691a513a13af26d13d2f307 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 28 Jan 2004 12:38:17 +0400
Subject: [PATCH 115/157] Fix for #2210 (SHOW TABLE STATUS fails when .frm is
 corrupted) We signed error instead of returning the result

sql/sql_show.cc:
  we need this assignement in libmysqld to not to issue error
---
 sql/sql_show.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 4ae59093a0e..0100390afa0 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -520,6 +520,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
       // Send error to Comment field
       protocol->store(thd->net.last_error, system_charset_info);
       thd->net.last_error[0]=0;
+      thd->net.last_errno= 0;
     }
     else
     {

From 96abffd4a4d6562a2cf3e0b55eb2c478739e3083 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 28 Jan 2004 19:02:58 +0200
Subject: [PATCH 116/157] Fixed a bug in GREATES() and LEAST() function, that
 caused a core dump when result was NULL.

mysql-test/r/func_test.result:
  Added a test for GREATEST() and LEAST() core dump bug.
mysql-test/t/func_test.test:
  Added a test for GREATEST() and LEAST() core dump bug.
---
 mysql-test/r/func_test.result | 6 ++++++
 mysql-test/t/func_test.test   | 8 ++++++++
 sql/item_func.cc              | 2 ++
 3 files changed, 16 insertions(+)

diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index 4bb2e067f9c..7d0a76424fe 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -165,3 +165,9 @@ SELECT f_acc.rank, a1.rank, a2.rank  FROM t1 LEFT JOIN t1 f1 ON  (f1.access_id=1
 rank	rank	rank
 2	2	NULL
 DROP TABLE t1,t2;
+CREATE TABLE t1 (d varchar(6), k int);
+INSERT INTO t1 VALUES (NULL, 2);
+SELECT GREATEST(d,d) FROM t1 WHERE k=2;
+GREATEST(d,d)
+NULL
+DROP TABLE t1;
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index 1559fef7e6e..0d055549866 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -85,3 +85,11 @@ CREATE TABLE t2 (  access_id smallint(6) NOT NULL default '0',   name varchar(20
 INSERT INTO t2 VALUES (1,'Everyone',2),(2,'Help',3),(3,'Customer Support',1);
 SELECT f_acc.rank, a1.rank, a2.rank  FROM t1 LEFT JOIN t1 f1 ON  (f1.access_id=1 AND f1.faq_group_id = t1.faq_group_id) LEFT JOIN t2 a1 ON (a1.access_id =  f1.access_id) LEFT JOIN t1 f2 ON (f2.access_id=3 AND  f2.faq_group_id = t1.faq_group_id) LEFT  JOIN t2 a2 ON (a2.access_id = f2.access_id), t2 f_acc WHERE LEAST(a1.rank,a2.rank) =  f_acc.rank;
 DROP TABLE t1,t2;
+
+#
+# Test for GREATEST() and LEAST() bug, which segfaulted 4.1.1 server
+#
+CREATE TABLE t1 (d varchar(6), k int);
+INSERT INTO t1 VALUES (NULL, 2);
+SELECT GREATEST(d,d) FROM t1 WHERE k=2;
+DROP TABLE t1;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4c3db4b3373..f90fcd5149e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1068,6 +1068,8 @@ String *Item_func_min_max::val_str(String *str)
 	}
       }
     }
+    if (!res)  // If NULL
+      return 0;
     res->set_charset(collation.collation);
     return res;
   }

From 832ea1206d74bba03cee2b7a9e88a622d8b7ac23 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 28 Jan 2004 18:35:52 +0100
Subject: [PATCH 117/157] better fix BUG#2361: ALTER TABLE ... DROP PRIMARY KEY
 drops a non-primary key

---
 mysql-test/r/alter_table.result |  9 ++++++---
 mysql-test/t/alter_table.test   |  4 +++-
 sql/mysql_priv.h                |  1 -
 sql/sql_base.cc                 |  4 ++--
 sql/sql_lex.h                   |  2 +-
 sql/sql_parse.cc                |  4 ++--
 sql/sql_table.cc                | 13 ++-----------
 sql/sql_yacc.yy                 |  7 ++++---
 8 files changed, 20 insertions(+), 24 deletions(-)

diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 33af0b30d1c..ce324dc1fa8 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -412,12 +412,15 @@ t1	0	PRIMARY	1	Host	A	NULL	NULL	NULL		BTREE
 t1	0	PRIMARY	2	User	A	0	NULL	NULL		BTREE	
 t1	1	Host	1	Host	A	NULL	NULL	NULL		BTREE	disabled
 DROP TABLE t1;
-CREATE TABLE t1 (a int UNIQUE);
+CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE);
 ALTER TABLE t1 DROP PRIMARY KEY;
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `a` int(11) default NULL,
-  UNIQUE KEY `a` (`a`)
+  `a` int(11) NOT NULL default '0',
+  `b` int(11) default NULL,
+  UNIQUE KEY `b` (`b`)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 DROP PRIMARY KEY;
+ERROR 42000: Can't DROP 'PRIMARY'. Check that column/key exists
 DROP TABLE t1;
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 71991973105..c013b2251a9 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -249,7 +249,9 @@ DROP TABLE t1;
 # Bug 2361
 #
 
-CREATE TABLE t1 (a int UNIQUE);
+CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE);
 ALTER TABLE t1 DROP PRIMARY KEY;
 SHOW CREATE TABLE t1;
+--error 1091
+ALTER TABLE t1 DROP PRIMARY KEY;
 DROP TABLE t1;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e7faaf1767d..8963fea29f6 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -509,7 +509,6 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
 		      List &keys,List &drop_list,
 		      List &alter_list,
                       uint order_num, ORDER *order,
-		      bool drop_primary,
 		      enum enum_duplicates handle_duplicates,
 		      enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
 		      enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3125c392751..2a4f73a986c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2395,7 +2395,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys)
   create_info.default_table_charset= thd->variables.collation_database;
   DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
 				&create_info, table_list,
-				fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
+				fields, keys, drop, alter, 0, (ORDER*)0,
 				DUP_ERROR));
 }
 
@@ -2412,7 +2412,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List &drop)
   create_info.default_table_charset= thd->variables.collation_database;
   DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
 				&create_info, table_list,
-				fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
+				fields, keys, drop, alter, 0, (ORDER*)0,
 				DUP_ERROR));
 }
 
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index bcbd60e9716..68385bc7bba 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -575,7 +575,7 @@ typedef struct st_lex
   uint param_count;
   uint slave_thd_opt;
   uint8 describe;
-  bool drop_primary, drop_if_exists, drop_temporary, local_file;
+  bool drop_if_exists, drop_temporary, local_file;
   bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
   bool derived_tables;
   bool safe_to_cache_query;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index cbf091069d6..2e728e4ae6d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2319,7 +2319,7 @@ mysql_execute_command(THD *thd)
 			       lex->key_list, lex->drop_list, lex->alter_list,
 			       select_lex->order_list.elements,
                                (ORDER *) select_lex->order_list.first,
-			       lex->drop_primary, lex->duplicates,
+			       lex->duplicates,
 			       lex->alter_keys_onoff,
                                lex->tablespace_op,
 			       lex->simple_alter);
@@ -2466,7 +2466,7 @@ mysql_execute_command(THD *thd)
 			     tables, lex->create_list,
 			     lex->key_list, lex->drop_list, lex->alter_list,
                              0, (ORDER *) 0,
-			     0, DUP_ERROR);
+			     DUP_ERROR);
     }
     else
       res = mysql_optimize_table(thd, tables, &lex->check_opt);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 60da32fceca..4e66154e2a2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1962,7 +1962,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
 		      List &keys,List &drop_list,
 		      List &alter_list,
                       uint order_num, ORDER *order,
-		      bool drop_primary,
 		      enum enum_duplicates handle_duplicates,
 	              enum enum_enable_or_disable keys_onoff,
 		      enum tablespace_op_type tablespace_op,
@@ -2171,7 +2170,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
     def_it.rewind();
     while ((def=def_it++))
     {
-      if (def->change && 
+      if (def->change &&
           !my_strcasecmp(system_charset_info,field->field_name, def->change))
 	break;
     }
@@ -2265,14 +2264,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
   for (uint i=0 ; i < table->keys ; i++,key_info++)
   {
     char *key_name= key_info->name;
-
-    if (drop_primary && (key_info-> flags & HA_NOSAME) &&
-	!my_strcasecmp(system_charset_info, key_name, primary_key_name))
-    {
-      drop_primary= 0;
-      continue;
-    }
-
     Alter_drop *drop;
     drop_it.rewind();
     while ((drop=drop_it++))
@@ -2315,7 +2306,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
       {						// Check if sub key
 	if (cfield->field->type() != FIELD_TYPE_BLOB &&
 	    (cfield->field->pack_length() == key_part_length ||
-	     cfield->length <= key_part_length / 
+	     cfield->length <= key_part_length /
 			       key_part->field->charset()->mbmaxlen))
 	  key_part_length=0;			// Use whole field
       }
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index fac0a7388c3..76a0f384b15 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1689,7 +1689,6 @@ alter:
 	  if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
 						 TL_OPTION_UPDATING))
 	    YYABORT;
-	  lex->drop_primary=0;
 	  lex->create_list.empty();
 	  lex->key_list.empty();
 	  lex->col_list.empty();
@@ -1761,12 +1760,14 @@ alter_list_item:
 	    lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
 					    $3.str)); lex->simple_alter=0;
 	  }
+	| DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
 	| DROP PRIMARY_SYM KEY_SYM
 	  {
 	    LEX *lex=Lex;
-	    lex->drop_primary=1; lex->simple_alter=0;
+	    lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
+						    primary_key_name));
+	    lex->simple_alter=0;
 	  }
-	| DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
 	| DROP key_or_index field_ident
 	  {
 	    LEX *lex=Lex;

From 735eab8a07ab7097ce46bc1be692c5a92a278d24 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 29 Jan 2004 01:16:24 +0200
Subject: [PATCH 118/157] Fixed Bug#2479, "dependant subquery with limit
 crash". The problem was that memory was free'd, but it was referenced later.
 This free was unneccessary anyway, because join_free() / JOIN::cleanup takes
 care of this later on.

Added test case into t/subselect.test for it.

Regards,
Jani


mysql-test/r/subselect.result:
  Added a test case for Bug#2479.
mysql-test/t/subselect.test:
  Added a test case for Bug#2479.
sql/sql_select.cc:
  Fixed Bug#2479, "dependant subquery with limit crash".
  The problem was that memory was free'd, but it was referenced
  later. This free was unneccessary anyway, because join_free() /
  JOIN::cleanup takes care of this later on.
---
 mysql-test/r/subselect.result | 47 ++++++++++++++++++++++++++++++
 mysql-test/t/subselect.test   | 54 +++++++++++++++++++++++++++++++++++
 sql/sql_select.cc             |  1 -
 3 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ded98265a1c..a398b13498b 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1578,3 +1578,50 @@ select * from t1;
 a	b
 1	0.123
 drop table t1;
+CREATE TABLE tab_01 (
+id int(11) NOT NULL auto_increment,
+ts timestamp NOT NULL,
+id_cns tinyint(3) unsigned NOT NULL default '0',
+id_desc_nota int(11) NOT NULL default '1',
+id_publ_uff int(11) NOT NULL default '0',
+tipo enum('','UNO','DUE') NOT NULL default '',
+f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL
+default '',
+anno_dep smallint(4) unsigned zerofill NOT NULL default '0000',
+data_dep smallint(4) unsigned zerofill NOT NULL default '0000',
+particolare mediumint(8) unsigned NOT NULL default '0',
+generale mediumint(8) unsigned NOT NULL default '0',
+bis tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY(id),
+UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
+UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
+INSERT INTO tab_01 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
+anno_dep, data_dep, particolare, generale, bis) VALUES
+(NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
+(NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
+(NULL, NULL,  16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0),
+(NULL, NULL,  16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0),
+(NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
+(NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
+CREATE TABLE tab_02 (
+id tinyint(3) unsigned NOT NULL auto_increment,
+descr varchar(40) NOT NULL default '',
+f_servizi set('UNO','DUE') NOT NULL default '',
+data_uno_min int(8) unsigned NOT NULL default '0',
+data_due_min int(8) unsigned NOT NULL default '0',
+max_anno_dep smallint(6) unsigned NOT NULL default '0',
+data_agg int(8) unsigned NOT NULL default '0',
+PRIMARY KEY  (id)
+);
+INSERT INTO tab_02 (id, descr, f_servizi, data_uno_min, data_due_min,
+max_anno_dep, data_agg) VALUES 
+(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
+(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
+SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM tab_01 AS s WHERE
+s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
+tab_02 AS cns;
+PIPPO
+1
+NULL
+DROP TABLE tab_01, tab_02;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 37dbc8f24d9..55ca8afe7fd 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1021,3 +1021,57 @@ delete from t1;
 load data infile "subselect.out.file.1" into table t1;
 select * from t1;
 drop table t1;
+
+#
+# Bug 2479
+#
+
+CREATE TABLE tab_01 (
+id int(11) NOT NULL auto_increment,
+ts timestamp NOT NULL,
+id_cns tinyint(3) unsigned NOT NULL default '0',
+id_desc_nota int(11) NOT NULL default '1',
+id_publ_uff int(11) NOT NULL default '0',
+tipo enum('','UNO','DUE') NOT NULL default '',
+f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL
+default '',
+anno_dep smallint(4) unsigned zerofill NOT NULL default '0000',
+data_dep smallint(4) unsigned zerofill NOT NULL default '0000',
+particolare mediumint(8) unsigned NOT NULL default '0',
+generale mediumint(8) unsigned NOT NULL default '0',
+bis tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY(id),
+UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
+UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
+
+INSERT INTO tab_01 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
+anno_dep, data_dep, particolare, generale, bis) VALUES
+(NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
+(NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
+(NULL, NULL,  16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0),
+(NULL, NULL,  16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0),
+(NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
+(NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
+  
+CREATE TABLE tab_02 (
+id tinyint(3) unsigned NOT NULL auto_increment,
+descr varchar(40) NOT NULL default '',
+f_servizi set('UNO','DUE') NOT NULL default '',
+data_uno_min int(8) unsigned NOT NULL default '0',
+data_due_min int(8) unsigned NOT NULL default '0',
+max_anno_dep smallint(6) unsigned NOT NULL default '0',
+data_agg int(8) unsigned NOT NULL default '0',
+PRIMARY KEY  (id)
+);
+
+INSERT INTO tab_02 (id, descr, f_servizi, data_uno_min, data_due_min,
+max_anno_dep, data_agg) VALUES 
+(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
+(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
+
+SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM tab_01 AS s WHERE
+s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
+tab_02 AS cns;
+
+DROP TABLE tab_01, tab_02;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e4f7214ad00..f6e7a474eca 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7200,7 +7200,6 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
   table->sort.found_records=filesort(thd, table,sortorder, length,
                                      select, filesort_limit, &examined_rows);
   tab->records=table->sort.found_records;		// For SQL_CALC_ROWS
-  delete select;				// filesort did select
   tab->select=0;
   tab->select_cond=0;
   tab->type=JT_ALL;				// Read with normal read_record

From 86351fe428dae9686aa784f615b5c14ab786f572 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 29 Jan 2004 15:08:22 +0200
Subject: [PATCH 119/157] ibuf0ibuf.c:   Correct the comment about the ibuf
 record format in >= 4.1.1

innobase/ibuf/ibuf0ibuf.c:
  Correct the comment about the ibuf record format in >= 4.1.1
---
 innobase/ibuf/ibuf0ibuf.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index b4a28d5fcd8..805f08af361 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -48,9 +48,12 @@ insert buffer tree, and that is in the system tablespace of InnoDB.
 1. The first field is the space id.
 2. The second field is a one-byte marker which differentiates records from
    the < 4.1.x storage format.
-3. The third field contains the type info, where we have also added 2 bytes to
-   store the charset.
-4. The rest of the fields contain the fields of the actual index record.
+3. The third field is the page number.
+4. The fourth field contains the type info, where we have also added 2 bytes to
+   store the charset. In the compressed table format of 5.0.x we must add more
+   information here so that we can build a dummy 'index' struct which 5.0.x
+   can use in the binary search on the index page in the ibuf merge phase.
+5. The rest of the fields contain the fields of the actual index record.
 
 */
 

From e7a336d869830cd75581f5dc61bf79000d7050ae Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 29 Jan 2004 18:27:52 +0300
Subject: [PATCH 120/157] Unused variable removed (cleanup spotted in bug
 #2214)

---
 sql/sql_lex.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index fea16dccd4a..65c958093bd 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1177,7 +1177,6 @@ void st_select_lex_unit::exclude_level()
 */
 void st_select_lex_unit::exclude_tree()
 {
-  SELECT_LEX_UNIT *units= 0;
   for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
   {
     // unlink current level from global SELECTs list

From a2d67665d5901ee889839a87843bbd6d0b1cef23 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 30 Jan 2004 07:32:35 +0100
Subject: [PATCH 121/157] SHOW CREATE DATABASE moved to sql_show.cc where it
 belongs db name is printed with append_identifier for a proper quoting

---
 sql/mysql_priv.h |  2 ++
 sql/sql_db.cc    | 91 +-----------------------------------------------
 sql/sql_show.cc  | 88 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 90 deletions(-)

diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 8963fea29f6..35740ff8bf1 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -763,6 +763,8 @@ uint check_word(TYPELIB *lib, const char *val, const char *end,
 void free_items(Item *item);
 void cleanup_items(Item *item);
 
+#define MY_DB_OPT_FILE "db.opt"
+bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
 
 /*
   External variables
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 697859eb264..b9da6ffd3f4 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -25,8 +25,6 @@
 #include 
 #endif
 
-#define MY_DB_OPT_FILE "db.opt"
-
 const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
 static TYPELIB deletable_extentions=
 {array_elements(del_exts)-1,"del_exts", del_exts};
@@ -92,7 +90,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
 
 */
 
-static bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
+bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
 {
   File file;
   char buf[256];
@@ -668,90 +666,3 @@ bool mysql_change_db(THD *thd, const char *name)
   DBUG_RETURN(0);
 }
 
-
-int mysqld_show_create_db(THD *thd, char *dbname,
-			  HA_CREATE_INFO *create_info)
-{
-  int length;
-  char	path[FN_REFLEN], *to;
-  uint db_access;
-  bool found_libchar;
-  HA_CREATE_INFO create;
-  uint create_options = create_info ? create_info->options : 0;
-  Protocol *protocol=thd->protocol;
-  DBUG_ENTER("mysql_show_create_db");
-
-  if (check_db_name(dbname))
-  {
-    net_printf(thd,ER_WRONG_DB_NAME, dbname);
-    DBUG_RETURN(1);
-  }
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-  if (test_all_bits(thd->master_access,DB_ACLS))
-    db_access=DB_ACLS;
-  else
-    db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
-		thd->master_access);
-  if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
-  {
-    net_printf(thd,ER_DBACCESS_DENIED_ERROR,
-	       thd->priv_user,
-	       thd->host_or_ip,
-	       dbname);
-    mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
-		    thd->priv_user,
-		    thd->host_or_ip,
-		    dbname);
-    DBUG_RETURN(1);
-  }
-#endif
-
-  (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
-  length=unpack_dirname(path,path);		// Convert if not unix
-  found_libchar= 0;
-  if (length && path[length-1] == FN_LIBCHAR)
-  {
-    found_libchar= 1;
-    path[length-1]=0;				// remove ending '\'
-  }
-  if (access(path,F_OK))
-  {
-    net_printf(thd,ER_BAD_DB_ERROR,dbname);
-    DBUG_RETURN(1);
-  }
-  if (found_libchar)
-    path[length-1]= FN_LIBCHAR;
-  strmov(path+length, MY_DB_OPT_FILE);
-  load_db_opt(thd, path, &create);
-  
-  List field_list;
-  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
-  field_list.push_back(new Item_empty_string("Create Database",1024));
-  
-  if (protocol->send_fields(&field_list,1))
-    DBUG_RETURN(1);
-  
-  protocol->prepare_for_resend();
-  protocol->store(dbname, strlen(dbname), system_charset_info);
-  to= strxmov(path, "CREATE DATABASE ", NullS);
-  if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
-    to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS);
-  to=strxmov(to,"`",dbname,"`", NullS);
-  
-  if (create.default_table_charset)
-  {
-    int cl= (create.default_table_charset->state & MY_CS_PRIMARY) ? 0 : 1;
-    to= strxmov(to," /*!40100"
-		" DEFAULT CHARACTER SET ",create.default_table_charset->csname,
-		cl ? " COLLATE " : "",
-		cl ? create.default_table_charset->name : "",
-		" */",NullS);
-  }
-  protocol->store(path, (uint) (to-path), system_charset_info);
-  
-  if (protocol->write())
-    DBUG_RETURN(1);
-  send_eof(thd);
-  DBUG_RETURN(0);
-}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 0100390afa0..3b937f97089 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -813,6 +813,94 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
   DBUG_RETURN(0);
 }
 
+int mysqld_show_create_db(THD *thd, char *dbname,
+			  HA_CREATE_INFO *create_info)
+{
+  int length;
+  char	path[FN_REFLEN];
+  char buff[2048];
+  String buffer(buff, sizeof(buff), system_charset_info);
+  uint db_access;
+  bool found_libchar;
+  HA_CREATE_INFO create;
+  uint create_options = create_info ? create_info->options : 0;
+  Protocol *protocol=thd->protocol;
+  DBUG_ENTER("mysql_show_create_db");
+
+  if (check_db_name(dbname))
+  {
+    net_printf(thd,ER_WRONG_DB_NAME, dbname);
+    DBUG_RETURN(1);
+  }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  if (test_all_bits(thd->master_access,DB_ACLS))
+    db_access=DB_ACLS;
+  else
+    db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
+		thd->master_access);
+  if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
+  {
+    net_printf(thd,ER_DBACCESS_DENIED_ERROR,
+	       thd->priv_user, thd->host_or_ip, dbname);
+    mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
+		    thd->priv_user, thd->host_or_ip, dbname);
+    DBUG_RETURN(1);
+  }
+#endif
+
+  (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
+  length=unpack_dirname(path,path);		// Convert if not unix
+  found_libchar= 0;
+  if (length && path[length-1] == FN_LIBCHAR)
+  {
+    found_libchar= 1;
+    path[length-1]=0;				// remove ending '\'
+  }
+  if (access(path,F_OK))
+  {
+    net_printf(thd,ER_BAD_DB_ERROR,dbname);
+    DBUG_RETURN(1);
+  }
+  if (found_libchar)
+    path[length-1]= FN_LIBCHAR;
+  strmov(path+length, MY_DB_OPT_FILE);
+  load_db_opt(thd, path, &create);
+
+  List field_list;
+  field_list.push_back(new Item_empty_string("Database",NAME_LEN));
+  field_list.push_back(new Item_empty_string("Create Database",1024));
+
+  if (protocol->send_fields(&field_list,1))
+    DBUG_RETURN(1);
+
+  protocol->prepare_for_resend();
+  protocol->store(dbname, strlen(dbname), system_charset_info);
+  buffer.length(0);
+  buffer.append("CREATE DATABASE ", 16);
+  if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
+    buffer.append("/*!32312 IF NOT EXISTS*/ ", 25);
+  append_identifier(thd, &buffer, dbname, strlen(dbname));
+
+  if (create.default_table_charset)
+  {
+    buffer.append(" /*!40100", 9);
+    buffer.append(" DEFAULT CHARACTER SET ", 23);
+    buffer.append(create.default_table_charset->csname);
+    if (!(create.default_table_charset->state & MY_CS_PRIMARY))
+    {
+      buffer.append(" COLLATE ", 9);
+      buffer.append(create.default_table_charset->name);
+    }
+    buffer.append(" */", 3);
+  }
+  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
+
+  if (protocol->write())
+    DBUG_RETURN(1);
+  send_eof(thd);
+  DBUG_RETURN(0);
+}
 
 int
 mysqld_show_logs(THD *thd)

From 14ede384fe113fbccd38d9389cdcb5391ca65403 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 30 Jan 2004 08:09:42 +0100
Subject: [PATCH 122/157] catch accesses to deleted objects double delete bug
 fixed

sql/sql_list.h:
  catch accesses to deleted objects
sql/sql_union.cc:
  double delete fixed
---
 sql/sql_list.h   | 10 ++++++++--
 sql/sql_union.cc |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/sql/sql_list.h b/sql/sql_list.h
index 0972d0341f6..c7faef88358 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -21,6 +21,12 @@
 
 /* mysql standard class memoryallocator */
 
+#ifdef PEDANTIC_SAFEMALLOC
+#define TRASH(XX,YY) bfill((XX), (YY), 0x8F)
+#else
+#define TRASH(XX,YY) /* no-op */
+#endif
+
 class Sql_alloc
 {
 public:
@@ -34,8 +40,8 @@ public:
   }
   static void *operator new(size_t size, MEM_ROOT *mem_root)
   { return (void*) alloc_root(mem_root, (uint) size); }
-  static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
-  static void operator delete[](void *ptr, size_t size) {}
+  static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
+  static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); }
 #ifdef HAVE_purify
   bool dummy;
   inline Sql_alloc() :dummy(0) {}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1cb01c6b3ef..226086d0d24 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -445,6 +445,7 @@ int st_select_lex_unit::cleanup()
   if (union_result)
   {
     delete union_result;
+    union_result=0; // Safety
     if (table)
       free_tmp_table(thd, table);
     table= 0; // Safety

From 7bdc4c4faf0be072d0c31328bb21bc894f29c042 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 30 Jan 2004 08:40:01 +0100
Subject: [PATCH 123/157] incorrect fix undone, as it causes memory leaks (e.g.
 in key.test)

---
 sql/sql_select.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f6e7a474eca..874a3b16312 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7200,6 +7200,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
   table->sort.found_records=filesort(thd, table,sortorder, length,
                                      select, filesort_limit, &examined_rows);
   tab->records=table->sort.found_records;		// For SQL_CALC_ROWS
+  delete select;
   tab->select=0;
   tab->select_cond=0;
   tab->type=JT_ALL;				// Read with normal read_record

From 150c99dffe2737ef4de7534bf297ff6943612cd0 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 30 Jan 2004 08:56:32 +0100
Subject: [PATCH 124/157] cleanup

---
 mysql-test/r/subselect.result | 14 +++++++-------
 mysql-test/t/subselect.test   | 14 +++++++-------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index a398b13498b..c5050cf5f27 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1578,7 +1578,7 @@ select * from t1;
 a	b
 1	0.123
 drop table t1;
-CREATE TABLE tab_01 (
+CREATE TABLE t1 (
 id int(11) NOT NULL auto_increment,
 ts timestamp NOT NULL,
 id_cns tinyint(3) unsigned NOT NULL default '0',
@@ -1596,7 +1596,7 @@ PRIMARY KEY(id),
 UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
 UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
-INSERT INTO tab_01 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
+INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
 anno_dep, data_dep, particolare, generale, bis) VALUES
 (NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
 (NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
@@ -1604,7 +1604,7 @@ anno_dep, data_dep, particolare, generale, bis) VALUES
 (NULL, NULL,  16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0),
 (NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
 (NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
-CREATE TABLE tab_02 (
+CREATE TABLE t2 (
 id tinyint(3) unsigned NOT NULL auto_increment,
 descr varchar(40) NOT NULL default '',
 f_servizi set('UNO','DUE') NOT NULL default '',
@@ -1614,14 +1614,14 @@ max_anno_dep smallint(6) unsigned NOT NULL default '0',
 data_agg int(8) unsigned NOT NULL default '0',
 PRIMARY KEY  (id)
 );
-INSERT INTO tab_02 (id, descr, f_servizi, data_uno_min, data_due_min,
+INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min,
 max_anno_dep, data_agg) VALUES 
 (16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
 (50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
-SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM tab_01 AS s WHERE
+SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE
 s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
-tab_02 AS cns;
+t2 AS cns;
 PIPPO
 1
 NULL
-DROP TABLE tab_01, tab_02;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 55ca8afe7fd..c4392186055 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1026,7 +1026,7 @@ drop table t1;
 # Bug 2479
 #
 
-CREATE TABLE tab_01 (
+CREATE TABLE t1 (
 id int(11) NOT NULL auto_increment,
 ts timestamp NOT NULL,
 id_cns tinyint(3) unsigned NOT NULL default '0',
@@ -1045,7 +1045,7 @@ UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
 UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
 
-INSERT INTO tab_01 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
+INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
 anno_dep, data_dep, particolare, generale, bis) VALUES
 (NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
 (NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
@@ -1054,7 +1054,7 @@ anno_dep, data_dep, particolare, generale, bis) VALUES
 (NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
 (NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
   
-CREATE TABLE tab_02 (
+CREATE TABLE t2 (
 id tinyint(3) unsigned NOT NULL auto_increment,
 descr varchar(40) NOT NULL default '',
 f_servizi set('UNO','DUE') NOT NULL default '',
@@ -1065,13 +1065,13 @@ data_agg int(8) unsigned NOT NULL default '0',
 PRIMARY KEY  (id)
 );
 
-INSERT INTO tab_02 (id, descr, f_servizi, data_uno_min, data_due_min,
+INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min,
 max_anno_dep, data_agg) VALUES 
 (16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
 (50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
 
-SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM tab_01 AS s WHERE
+SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE
 s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
-tab_02 AS cns;
+t2 AS cns;
 
-DROP TABLE tab_01, tab_02;
+DROP TABLE t1, t2;

From abc17f8f3c132971a04cc76543d3c0ef23386b79 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sat, 31 Jan 2004 10:04:16 +0400
Subject: [PATCH 125/157] fix for the bug #2419: order by ignores rows.
 null_ref_key moved to TABLE_REF. new null range created if necessary.

mysql-test/r/order_by.result:
  fix for the bug #2419: order by ignores rows
mysql-test/t/order_by.test:
  fix for the bug #2419: order by ignores rows
sql/item_subselect.cc:
  fix for the bug #2419: order by ignores rows
sql/opt_range.cc:
  fix for the bug #2419: order by ignores rows
sql/sql_select.cc:
  fix for the bug #2419: order by ignores rows
sql/sql_select.h:
  fix for the bug #2419: order by ignores rows
---
 mysql-test/r/order_by.result | 21 +++++++++++++++++++++
 mysql-test/t/order_by.test   | 12 ++++++++++++
 sql/item_subselect.cc        |  4 ++--
 sql/opt_range.cc             | 21 +++++++++++++++++++--
 sql/sql_select.cc            | 16 +++++++++-------
 sql/sql_select.h             |  3 ++-
 6 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 4d166a961f3..c1053087603 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -590,3 +590,24 @@ SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ;
 id
 11392
 drop table t1;
+create table t1(a int, b int, index(b));
+insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
+explain select * from t1 where b=1 or b is null order by a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref_or_null	b	b	5	const	3	Using where; Using filesort
+select * from t1 where b=1 or b is null order by a;
+a	b
+1	1
+2	1
+3	NULL
+4	NULL
+explain select * from t1 where b=2 or b is null order by a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref_or_null	b	b	5	const	4	Using where; Using filesort
+select * from t1 where b=2 or b is null order by a;
+a	b
+3	NULL
+4	NULL
+5	2
+6	2
+drop table t1;
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 1db783c212b..bbb0046b47f 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -381,3 +381,15 @@ CREATE TABLE t1 (  id smallint(6) unsigned NOT NULL default '0',  menu tinyint(4
 INSERT INTO t1 VALUES (11384, 2),(11392, 2);
 SELECT id FROM t1 WHERE id <11984 AND menu =2 ORDER BY id DESC LIMIT 1 ;
 drop table t1;
+
+#
+# REF_OR_NULL optimization + filesort (bug #2419)
+#
+
+create table t1(a int, b int, index(b));
+insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
+explain select * from t1 where b=1 or b is null order by a;
+select * from t1 where b=1 or b is null order by a;
+explain select * from t1 where b=2 or b is null order by a;
+select * from t1 where b=2 or b is null order by a;
+drop table t1;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 518b712ad18..5b3cc326679 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1110,7 +1110,7 @@ int subselect_indexsubquery_engine::exec()
   if (check_null)
   {
     /* We need to check for NULL if there wasn't a matching value */
-    *tab->null_ref_key= 0;			// Search first for not null
+    *tab->ref.null_ref_key= 0;			// Search first for not null
     ((Item_in_subselect *) item)->was_null= 0;
   }
 
@@ -1155,7 +1155,7 @@ int subselect_indexsubquery_engine::exec()
 	{
 	  if (!check_null || null_finding)
 	    break;			/* We don't need to check nulls */
-	  *tab->null_ref_key= 1;
+	  *tab->ref.null_ref_key= 1;
 	  null_finding= 1;
 	  /* Check if there exists a row with a null value in the index */
 	  if ((error= (safe_index_read(tab) == 1)))
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index acc23924f75..9f56064cfb1 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2513,8 +2513,25 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
       key_part->part_length+=HA_KEY_BLOB_LENGTH;
     key_part->null_bit=     key_info->key_part[part].null_bit;
   }
-  if (!quick->ranges.push_back(range))
-    return quick;
+  if (quick->ranges.push_back(range))
+    goto err;
+
+  if (ref->null_ref_key)
+  {
+    QUICK_RANGE *null_range;
+
+    *ref->null_ref_key= 1;		// Set null byte then create a range
+    if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length,
+				      ref->key_buff, ref->key_length,
+				      EQ_RANGE)))
+      goto err;
+    *ref->null_ref_key= 0;		// Clear null byte
+    /* Do we need to do something with key_parts here? Looks like we don't */
+    if (quick->ranges.push_back(null_range))
+      goto err;
+  }
+
+  return quick;
 
 err:
   delete quick;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 874a3b16312..5e2445be845 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -860,8 +860,10 @@ JOIN::optimize()
     as in other cases the join is done before the sort.
   */
   if (const_tables != tables &&
-      (order || group_list) && join_tab[const_tables].type != JT_ALL &&
+      (order || group_list) && 
+      join_tab[const_tables].type != JT_ALL &&
       join_tab[const_tables].type != JT_FT &&
+      join_tab[const_tables].type != JT_REF_OR_NULL &&
       (order && simple_order || group_list && simple_group))
   {
     if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
@@ -3257,7 +3259,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
   {
     /* Must read with repeat */
     j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
-    j->null_ref_key= null_ref_key;
+    j->ref.null_ref_key= null_ref_key;
   }
   else if (ref_key == j->ref.key_copy)
   {
@@ -6208,12 +6210,12 @@ join_read_always_key_or_null(JOIN_TAB *tab)
   int res;
 
   /* First read according to key which is NOT NULL */
-  *tab->null_ref_key=0;
+  *tab->ref.null_ref_key= 0;			// Clear null byte
   if ((res= join_read_always_key(tab)) >= 0)
     return res;
 
   /* Then read key with null value */
-  *tab->null_ref_key= 1;
+  *tab->ref.null_ref_key= 1;			// Set null byte
   return safe_index_read(tab);
 }
 
@@ -6227,10 +6229,10 @@ join_read_next_same_or_null(READ_RECORD *info)
   JOIN_TAB *tab= info->table->reginfo.join_tab;
 
   /* Test if we have already done a read after null key */
-  if (*tab->null_ref_key)
+  if (*tab->ref.null_ref_key)
     return -1;					// All keys read
-  *tab->null_ref_key= 1;			// Read null key
-  return safe_index_read(tab);
+  *tab->ref.null_ref_key= 1;			// Set null byte
+  return safe_index_read(tab);			// then read null keys
 }
 
 
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 7cc71117914..ed650c450c0 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -46,6 +46,8 @@ typedef struct st_table_ref
   store_key     **key_copy;               //
   Item          **items;                  // val()'s for each keypart
   table_map	depend_map;		  // Table depends on these tables.
+  byte          *null_ref_key;		  // null byte position in the key_buf.
+  					  // used for REF_OR_NULL optimization.
 } TABLE_REF;
 
 /*
@@ -88,7 +90,6 @@ typedef struct st_join_table {
   QUICK_SELECT	*quick;
   Item		*on_expr;
   const char	*info;
-  byte		*null_ref_key;
   int		(*read_first_record)(struct st_join_table *tab);
   int		(*next_select)(JOIN *,struct st_join_table *,bool);
   READ_RECORD	read_record;

From 68c0a299876b01dbf72cd948708afef4a2c27b47 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 1 Feb 2004 15:30:32 +0200
Subject: [PATCH 126/157] now all tables of query are locked in one place
 (including derived tables) fixed BUG#2120 and other problem with EXPLAINing
 derived tables

mysql-test/r/derived.result:
  correct tables names & Co in derived tables
  test case for BUG#2120
mysql-test/t/derived.test:
  test case for BUG#2120
sql/mysql_priv.h:
  derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/repl_failsafe.cc:
  correct initialization of TABLE_LIST
sql/sql_acl.cc:
  used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX
sql/sql_base.cc:
  derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/sql_delete.cc:
  all tables processing is done during opening
sql/sql_derived.cc:
  derived tables processing moved after open/locking all tables (in open_and_lock_tables) to sutisfy "all query tables locking" at the moment
sql/sql_insert.cc:
  all tables processing is done during opening
  correct initialization of TABLE_LIST
sql/sql_lex.cc:
  now table list will be created for whole query
  layout fix
  correct check of updated table in subqueries
sql/sql_lex.h:
  now table list will be created for whole query
  correct check of updated table in subqueries
sql/sql_olap.cc:
  THIS FUNCTION IS USED NOWHERE
  it will be good to remove it at all (handle_olaps)
sql/sql_parse.cc:
  derived tables processing moved after open/locking all tables (in open_and_lock_tables)
sql/sql_prepare.cc:
  new creating list parameters
  all tables processing is done during opening
sql/sql_select.cc:
  all tables processing is done during opening
sql/sql_select.h:
  now it used only within file where is defined
sql/sql_udf.cc:
  used simple table opening without derived table processing to avoid unneeded initialization of SELECT_LEX
sql/sql_update.cc:
  all tables processing is done during opening
---
 mysql-test/r/derived.result |  23 +++-
 mysql-test/t/derived.test   |   9 ++
 sql/mysql_priv.h            |   4 +-
 sql/repl_failsafe.cc        |   2 +-
 sql/sql_acl.cc              |  10 +-
 sql/sql_base.cc             |  69 ++++++++--
 sql/sql_delete.cc           |   1 -
 sql/sql_derived.cc          | 247 +++++++++++++++++-------------------
 sql/sql_insert.cc           |   4 +-
 sql/sql_lex.cc              |  86 +++++++++++--
 sql/sql_lex.h               |   9 +-
 sql/sql_olap.cc             |  12 --
 sql/sql_parse.cc            |  74 ++++-------
 sql/sql_prepare.cc          |   3 +-
 sql/sql_select.cc           |   1 -
 sql/sql_select.h            |   1 -
 sql/sql_udf.cc              |   2 +-
 sql/sql_update.cc           |   2 -
 18 files changed, 311 insertions(+), 248 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 170c393524b..a89494645fa 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -59,7 +59,7 @@ explain select * from t1 as x1, (select * from t1) as x2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	x1	ALL	NULL	NULL	NULL	NULL	4	
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	4	
-2	DERIVED	x1	ALL	NULL	NULL	NULL	NULL	4	
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	4	
 drop table if exists  t2,t3;
 select * from (select 1) as a;
 1
@@ -141,7 +141,7 @@ a	t
 explain select count(*) from t1 as tt1, (select * from t1) as tt2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
-2	DERIVED	tt1	ALL	NULL	NULL	NULL	NULL	10000	
+2	DERIVED	t1	index	NULL	a	4	NULL	10000	Using index
 drop table t1;
 SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
 (SELECT * FROM (SELECT 1 as a) as a )
@@ -189,13 +189,13 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	m2	ALL	NULL	NULL	NULL	NULL	9	
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	6	Using where
 2	DERIVED	mp	ALL	NULL	NULL	NULL	NULL	9	Using temporary; Using filesort
-2	DERIVED	m2	index	NULL	PRIMARY	3	NULL	9	Using index
+2	DERIVED	m1	index	NULL	PRIMARY	3	NULL	9	Using index
 explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2  INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	m2	ALL	NULL	NULL	NULL	NULL	9	
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	6	Using where
 2	DERIVED	mp	ALL	NULL	NULL	NULL	NULL	9	Using temporary; Using filesort
-2	DERIVED	m2	index	NULL	PRIMARY	3	NULL	9	Using index
+2	DERIVED	m1	index	NULL	PRIMARY	3	NULL	9	Using index
 drop table t1,t2;
 SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
 x
@@ -229,8 +229,8 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	2	
 1	PRIMARY	t1	eq_ref	PRIMARY	PRIMARY	4	THEMAX.E2	1	Using where
-2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
-3	DEPENDENT SUBQUERY	B	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DERIVED	A	index	NULL	PRIMARY	4	NULL	2	Using where; Using index
+3	DEPENDENT SUBQUERY	B	index	NULL	PRIMARY	4	NULL	2	Using where; Using index
 drop table t1;
 create table t1 (a int);
 insert into t1 values (1),(2);
@@ -298,3 +298,14 @@ INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00
 select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
 497	ID	NULL
 drop table t1, t2, t3;
+CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL);
+INSERT INTO t1 VALUES ('a',1),  ('a',2),  ('a',2),  ('a',2),  ('a',3),  ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5);
+SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
+name	median
+a	7.0000
+b	3.5000
+explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY		ALL	NULL	NULL	NULL	NULL	3	Using temporary; Using filesort
+2	DERIVED	x	ALL	NULL	NULL	NULL	NULL	17	Using temporary; Using filesort
+2	DERIVED	y	ALL	NULL	NULL	NULL	NULL	17	Using where
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 154fc4b3834..b412555f1e8 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -183,3 +183,12 @@ CREATE TABLE t3 (
 INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
 select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA      from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
 drop table t1, t2, t3;
+
+
+#
+# explain derived
+#
+CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL);
+INSERT INTO t1 VALUES ('a',1),  ('a',2),  ('a',2),  ('a',2),  ('a',3),  ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5);
+SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
+explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e7faaf1767d..c1365baaf0a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -481,14 +481,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
 		 SELECT_LEX *select_lex);
 void free_underlaid_joins(THD *thd, SELECT_LEX *select);
 void fix_tables_pointers(SELECT_LEX *select_lex);
-void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
 int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
 			select_result *result);
 int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
 			 select_result *result);
 int mysql_union(THD *thd, LEX *lex, select_result *result,
 		SELECT_LEX_UNIT *unit);
-int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
+int mysql_handle_derived(LEX *lex);
 Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
 			Item ***copy_func, Field **from_field,
 			bool group,bool modify_item);
@@ -676,6 +675,7 @@ int setup_ftfuncs(SELECT_LEX* select);
 int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
 void wait_for_refresh(THD *thd);
 int open_tables(THD *thd,TABLE_LIST *tables);
+int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
 int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
 int lock_tables(THD *thd,TABLE_LIST *tables);
 TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 81ea9d9e2ac..d125c95e839 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
     int error;
     if (table_rules_on)
     {
-      table.next= 0;
+      bzero((char*) &table, sizeof(table)); //just for safe
       table.db= (char*) db;
       table.real_name= (char*) table_name;
       table.updating= 1;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 77131a37869..8ef6a32a430 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2247,7 +2247,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
   }
 #endif
 
-  if (open_and_lock_tables(thd,tables))
+  if (simple_open_n_lock_tables(thd,tables))
   {						// Should never happen
     close_thread_tables(thd);			/* purecov: deadcode */
     DBUG_RETURN(-1);				/* purecov: deadcode */
@@ -2395,7 +2395,7 @@ int mysql_grant(THD *thd, const char *db, List  &list,
   }
 
   /* open the mysql.user and mysql.db tables */
-
+  bzero((char*) &tables,sizeof(tables));
   tables[0].alias=tables[0].real_name=(char*) "user";
   tables[1].alias=tables[1].real_name=(char*) "db";
   tables[0].next=tables+1;
@@ -2421,7 +2421,7 @@ int mysql_grant(THD *thd, const char *db, List  &list,
   }
 #endif
 
-  if (open_and_lock_tables(thd,tables))
+  if (simple_open_n_lock_tables(thd,tables))
   {						// This should never happen
     close_thread_tables(thd);			/* purecov: deadcode */
     DBUG_RETURN(-1);				/* purecov: deadcode */
@@ -2517,7 +2517,7 @@ my_bool grant_init(THD *org_thd)
   thd->store_globals();
   thd->db= my_strdup("mysql",MYF(0));
   thd->db_length=5;				// Safety
-  bzero((char*) &tables,sizeof(tables));
+  bzero((char*) &tables, sizeof(tables));
   tables[0].alias=tables[0].real_name= (char*) "tables_priv";
   tables[1].alias=tables[1].real_name= (char*) "columns_priv";
   tables[0].next=tables+1;
@@ -3376,7 +3376,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
   }
 #endif
 
-  if (open_and_lock_tables(thd, tables))
+  if (simple_open_n_lock_tables(thd, tables))
   {						// This should never happen
     close_thread_tables(thd);
     DBUG_RETURN(-1);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3125c392751..5707b58299f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1305,6 +1305,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
       goto err;					// Can't repair the table
 
     TABLE_LIST table_list;
+    bzero((char*) &table_list, sizeof(table_list)); // just for safe
     table_list.db=(char*) db;
     table_list.real_name=(char*) name;
     table_list.next=0;
@@ -1372,11 +1373,13 @@ int open_tables(THD *thd,TABLE_LIST *start)
   thd->proc_info="Opening tables";
   for (tables=start ; tables ; tables=tables->next)
   {
+    if (tables->derived)
+      continue;
     if (!tables->table &&
-	!(tables->table=open_table(thd,
-				   tables->db,
-				   tables->real_name,
-				   tables->alias, &refresh)))
+	!(tables->table= open_table(thd,
+				    tables->db,
+				    tables->real_name,
+				    tables->alias, &refresh)))
     {
       if (refresh)				// Refresh in progress
       {
@@ -1522,15 +1525,47 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
 
 
 /*
-  Open all tables in list and locks them for read.
-  The lock will automaticly be freed by close_thread_tables()
+  Open all tables in list and locks them for read without derived
+  tables processing.
+
+  SYNOPSIS
+    simple_open_n_lock_tables()
+    thd		- thread handler
+    tables	- list of tables for open&locking
+
+  NOTE
+    The lock will automaticly be freed by close_thread_tables()
 */
 
-int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
+int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
 {
-  if (open_tables(thd,tables) || lock_tables(thd,tables))
-    return -1;					/* purecov: inspected */
-  return 0;
+  DBUG_ENTER("open_n_lock_tables");
+  if (open_tables(thd, tables) || lock_tables(thd, tables))
+    DBUG_RETURN(-1);				/* purecov: inspected */
+  DBUG_RETURN(0);
+}
+
+
+/*
+  Open all tables in list, locks them and process derived tables
+  tables processing.
+
+  SYNOPSIS
+    simple_open_n_lock_tables()
+    thd		- thread handler
+    tables	- list of tables for open&locking
+
+  NOTE
+    The lock will automaticly be freed by close_thread_tables()
+*/
+
+int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
+{
+  DBUG_ENTER("open_and_lock_tables");
+  if (open_tables(thd, tables) || lock_tables(thd, tables))
+    DBUG_RETURN(-1);				/* purecov: inspected */
+  fix_tables_pointers(thd->lex->all_selects_list);
+  DBUG_RETURN(mysql_handle_derived(thd->lex));
 }
 
 
@@ -1563,12 +1598,18 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
     DBUG_ASSERT(thd->lock == 0);	// You must lock everything at once
     uint count=0;
     for (table = tables ; table ; table=table->next)
-      count++;
+    {
+      if (!table->derived)
+	count++;
+    }
     TABLE **start,**ptr;
     if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
       return -1;
     for (table = tables ; table ; table=table->next)
-      *(ptr++)= table->table;
+    {
+      if (!table->derived)
+	*(ptr++)= table->table;
+    }
     if (!(thd->lock=mysql_lock_tables(thd,start,count)))
       return -1;				/* purecov: inspected */
   }
@@ -1576,7 +1617,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
   {
     for (table = tables ; table ; table=table->next)
     {
-      if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
+      if (!table->derived && 
+	  check_lock_and_start_stmt(thd, table->table, table->lock_type))
       {
 	ha_rollback_stmt(thd);
 	return -1;
@@ -2165,6 +2207,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
       /* Ensure that we have access right to all columns */
       if (!(table->grant.privilege & SELECT_ACL) &&
+	  !tables->derived &&
 	  check_grant_all_columns(thd,SELECT_ACL,table))
 	DBUG_RETURN(-1);
 #endif
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 9ac7b7596fe..2204466b9d1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -43,7 +43,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
 
   if ((open_and_lock_tables(thd, table_list)))
     DBUG_RETURN(-1);
-  fix_tables_pointers(thd->lex->all_selects_list);
   table= table_list->table;
   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
   thd->proc_info="init";
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 374e56ecdd4..8fa5694714c 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -25,6 +25,49 @@
 #include "sql_select.h"
 #include "sql_acl.h"
 
+int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
+
+/*
+  Resolve derived tables in all queries
+
+  SYNOPSIS
+    mysql_handle_derived()
+    lex                 LEX for this thread
+
+  RETURN
+    0	ok
+    -1	Error
+    1	Error and error message given
+*/
+int
+mysql_handle_derived(LEX *lex)
+{
+  int res= 0;
+  if (lex->derived_tables)
+  {
+    for (SELECT_LEX *sl= lex->all_selects_list;
+	 sl;
+	 sl= sl->next_select_in_list())
+    {
+      for (TABLE_LIST *cursor= sl->get_table_list();
+	   cursor;
+	   cursor= cursor->next)
+      {
+	if (cursor->derived && (res=mysql_derived(lex->thd, lex,
+						  cursor->derived,
+						  cursor)))
+	{
+	  if (res < 0 || lex->thd->net.report_error)
+	    send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0);
+	  return 1;
+	}
+      }
+    }
+  }
+  return 0;
+}
+
+
 /*
   Resolve derived tables in all queries
 
@@ -49,9 +92,6 @@
     Derived tables is stored in thd->derived_tables and freed in
     close_thread_tables()
 
-  TODO
-    Move creation of derived tables in open_and_lock_tables()
-
   RETURN
     0	ok
     1	Error
@@ -72,143 +112,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
   bool is_subsel= first_select->first_inner_unit() ? 1: 0;
   SELECT_LEX *save_current_select= lex->current_select;
   DBUG_ENTER("mysql_derived");
-  
-  /*
-    In create_total_list, derived tables have to be treated in case of
-    EXPLAIN, This is because unit/node is not deleted in that
-    case. Current code in this function has to be improved to
-    recognize better when this function is called from derived tables
-    and when from other functions.
-  */
-  if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
-    DBUG_RETURN(-1);
 
-  /*
-    We have to do access checks here as this code is executed before any
-    sql command is started to execute.
-  */
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-  if (tables)
-    res= check_table_access(thd,SELECT_ACL, tables,0);
-  else
-    res= check_access(thd, SELECT_ACL, any_db,0,0,0);
-  if (res)
-    DBUG_RETURN(1);
-#endif
+  if (!(derived_result= new select_union(0)))
+    DBUG_RETURN(1); // out of memory
 
-  if (!(res=open_and_lock_tables(thd,tables)))
-  {
-    if (is_union || is_subsel)
-    {
-      /* 
-	 The following code is a re-do of fix_tables_pointers() found
-	 in sql_select.cc for UNION's within derived tables. The only
-	 difference is in navigation, as in derived tables we care for
-	 this level only.
+  // st_select_lex_unit::prepare correctly work for single select
+  if ((res= unit->prepare(thd, derived_result, 0)))
+    goto exit;
 
-      */
-      fix_tables_pointers(unit);
-    }
-
-    if (!(derived_result= new select_union(0)))
-      DBUG_RETURN(1); // out of memory
-
-    // st_select_lex_unit::prepare correctly work for single select
-    if ((res= unit->prepare(thd, derived_result, 0)))
-      goto exit;
-
-    /* 
-       This is done in order to redo all field optimisations when any of the 
-       involved tables is used in the outer query 
-    */
-    if (tables)
-    {
-      for (TABLE_LIST *cursor= tables;  cursor;  cursor= cursor->next)
-	cursor->table->clear_query_id= 1;
-    }
 	
-    derived_result->tmp_table_param.init();
-    derived_result->tmp_table_param.field_count= unit->types.elements;
-    /*
-      Temp table is created so that it hounours if UNION without ALL is to be 
-      processed
-    */
-    if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
-				  unit->types, (ORDER*) 0, 
-				  is_union && !unit->union_option, 1,
-				  (first_select->options | thd->options |
-				   TMP_TABLE_ALL_COLUMNS),
-				  HA_POS_ERROR,
-				  org_table_list->alias)))
-    {
-      res= -1;
-      goto exit;
-    }
-    derived_result->set_table(table);
+  derived_result->tmp_table_param.init();
+  derived_result->tmp_table_param.field_count= unit->types.elements;
+  /*
+    Temp table is created so that it hounours if UNION without ALL is to be 
+    processed
+  */
+  if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
+				unit->types, (ORDER*) 0, 
+				is_union && !unit->union_option, 1,
+				(first_select->options | thd->options |
+				 TMP_TABLE_ALL_COLUMNS),
+				HA_POS_ERROR,
+				org_table_list->alias)))
+  {
+    res= -1;
+    goto exit;
+  }
+  derived_result->set_table(table);
 
-    if (is_union)
-      res= mysql_union(thd, lex, derived_result, unit);
+
+  if (is_union)
+    res= mysql_union(thd, lex, derived_result, unit);
+  else
+  {
+    unit->offset_limit_cnt= first_select->offset_limit;
+    unit->select_limit_cnt= first_select->select_limit+
+      first_select->offset_limit;
+    if (unit->select_limit_cnt < first_select->select_limit)
+      unit->select_limit_cnt= HA_POS_ERROR;
+    if (unit->select_limit_cnt == HA_POS_ERROR)
+      first_select->options&= ~OPTION_FOUND_ROWS;
+
+    lex->current_select= first_select;
+    res= mysql_select(thd, &first_select->ref_pointer_array, 
+		      (TABLE_LIST*) first_select->table_list.first,
+		      first_select->with_wild,
+		      first_select->item_list, first_select->where,
+		      (first_select->order_list.elements+
+		       first_select->group_list.elements),
+		      (ORDER *) first_select->order_list.first,
+		      (ORDER *) first_select->group_list.first,
+		      first_select->having, (ORDER*) NULL,
+		      (first_select->options | thd->options |
+		       SELECT_NO_UNLOCK),
+		      derived_result, unit, first_select);
+  }
+
+  if (!res)
+  {
+    /*
+      Here we entirely fix both TABLE_LIST and list of SELECT's as
+      there were no derived tables
+    */
+    if (derived_result->flush())
+      res= 1;
     else
     {
-      unit->offset_limit_cnt= first_select->offset_limit;
-      unit->select_limit_cnt= first_select->select_limit+
-	first_select->offset_limit;
-      if (unit->select_limit_cnt < first_select->select_limit)
-	unit->select_limit_cnt= HA_POS_ERROR;
-      if (unit->select_limit_cnt == HA_POS_ERROR)
-	first_select->options&= ~OPTION_FOUND_ROWS;
-
-      lex->current_select= first_select;
-      res= mysql_select(thd, &first_select->ref_pointer_array, 
-			(TABLE_LIST*) first_select->table_list.first,
-			first_select->with_wild,
-			first_select->item_list, first_select->where,
-			(first_select->order_list.elements+
-			 first_select->group_list.elements),
-			(ORDER *) first_select->order_list.first,
-			(ORDER *) first_select->group_list.first,
-			first_select->having, (ORDER*) NULL,
-			(first_select->options | thd->options |
-			 SELECT_NO_UNLOCK),
-			derived_result, unit, first_select);
-    }
-
-    if (!res)
-    {
-      /*
-	Here we entirely fix both TABLE_LIST and list of SELECT's as
-	there were no derived tables
-      */
-      if (derived_result->flush())
-	res= 1;
-      else
+      org_table_list->real_name= table->real_name;
+      org_table_list->table= table;
+      if (org_table_list->table_list)
       {
-	org_table_list->real_name=table->real_name;
-	org_table_list->table=table;
-	table->derived_select_number= first_select->select_number;
-	table->tmp_table= TMP_TABLE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-	org_table_list->grant.privilege= SELECT_ACL;
-#endif
-	if (lex->describe)
-	{
-	  // to fix a problem in EXPLAIN
-	  if (tables)
-	  {
-	    for (TABLE_LIST *cursor= tables;  cursor;  cursor= cursor->next)
-	      if (cursor->table_list)
-		cursor->table_list->table=cursor->table;
-	  }
-	}
-	else
-	{
-	  unit->exclude_tree();
-	  unit->cleanup();
-	}
-	org_table_list->db= (char *)"";
-	  // Force read of table stats in the optimizer
-	table->file->info(HA_STATUS_VARIABLE);
+	org_table_list->table_list->real_name= table->real_name;
+	org_table_list->table_list->table= table;
       }
+      table->derived_select_number= first_select->select_number;
+      table->tmp_table= TMP_TABLE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+      org_table_list->grant.privilege= SELECT_ACL;
+#endif
+      org_table_list->db= (char *)"";
+      // Force read of table stats in the optimizer
+      table->file->info(HA_STATUS_VARIABLE);
     }
 
     if (res)
@@ -223,7 +207,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
 exit:
     delete derived_result;
     lex->current_select= save_current_select;
-    close_thread_tables(thd, 0, 1);
   }
   DBUG_RETURN(res);
 }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c2f3e737daf..342089987dc 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -188,7 +188,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
     res= open_and_lock_tables(thd, table_list);
   if (res)
     DBUG_RETURN(-1);
-  fix_tables_pointers(thd->lex->all_selects_list);
 
   table= table_list->table;
   thd->proc_info="init";
@@ -646,7 +645,8 @@ public:
     thd.command=COM_DELAYED_INSERT;
     thd.lex->current_select= 0; /* for my_message_sql */
 
-    bzero((char*) &thd.net,sizeof(thd.net));	// Safety
+    bzero((char*) &thd.net, sizeof(thd.net));		// Safety
+    bzero((char*) &table_list, sizeof(table_list));	// Safety
     thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT;
     thd.host_or_ip= "";
     bzero((char*) &info,sizeof(info));
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 65c958093bd..62f255ea178 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1286,12 +1286,10 @@ bool st_select_lex::test_limit()
     !0 - error
 */
 bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
-					   TABLE_LIST **result_arg,
-					   bool check_derived)
+					   TABLE_LIST **result_arg)
 {
   *result_arg= 0;
-  res= create_total_list_n_last_return(thd_arg, lex, &result_arg,
-				       check_derived);
+  res= create_total_list_n_last_return(thd_arg, lex, &result_arg);
   return res;
 }
 
@@ -1303,8 +1301,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
     thd            THD pointer
     lex            pointer on LEX stricture
     result         pointer on pointer on result list of tables pointer
-    check_derived  force derived table chacking (used for creating 
-                   table list for derived query)
+
   DESCRIPTION
     This is used for UNION & subselect to create a new table list of all used 
     tables.
@@ -1318,8 +1315,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
 bool st_select_lex_unit::
 create_total_list_n_last_return(THD *thd_arg,
 				st_lex *lex,
-				TABLE_LIST ***result_arg,
-				bool check_derived)
+				TABLE_LIST ***result_arg)
 {
   TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
   TABLE_LIST **new_table_list= *result_arg, *aux;
@@ -1345,15 +1341,12 @@ create_total_list_n_last_return(THD *thd_arg,
       return 1;
     }
 
-    if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
-      goto end;
-
     for (SELECT_LEX_UNIT *inner=  sl->first_inner_unit();
 	 inner;
 	 inner= inner->next_unit())
     {
       if (inner->create_total_list_n_last_return(thd, lex,
-						 &slave_list_last, 0))
+						 &slave_list_last))
 	return 1;
     }
 
@@ -1400,63 +1393,75 @@ end:
   return 0;
 }
 
+
 st_select_lex_unit* st_select_lex_unit::master_unit()
 {
     return this;
 }
 
+
 st_select_lex* st_select_lex_unit::outer_select()
 {
   return (st_select_lex*) master;
 }
 
+
 bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
 {
   return add_to_list(thd, order_list, item, asc);
 }
 
+
 bool st_select_lex::add_item_to_list(THD *thd, Item *item)
 {
   return item_list.push_back(item);
 }
 
+
 bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
 {
   return add_to_list(thd, group_list, item, asc);
 }
 
+
 bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
 {
   return !func || ftfunc_list->push_back(func); // end of memory?
 }
 
+
 st_select_lex_unit* st_select_lex::master_unit()
 {
   return (st_select_lex_unit*) master;
 }
 
+
 st_select_lex* st_select_lex::outer_select()
 {
   return (st_select_lex*) master->get_master();
 }
 
+
 bool st_select_lex::set_braces(bool value)
 {
   braces= value;
   return 0; 
 }
 
+
 bool st_select_lex::inc_in_sum_expr()
 {
   in_sum_expr++;
   return 0;
 }
 
+
 uint st_select_lex::get_in_sum_expr()
 {
   return in_sum_expr;
 }
 
+
 TABLE_LIST* st_select_lex::get_table_list()
 {
   return (TABLE_LIST*) table_list.first;
@@ -1467,21 +1472,25 @@ List* st_select_lex::get_item_list()
   return &item_list;
 }
 
+
 List* st_select_lex::get_use_index()
 {
   return use_index_ptr;
 }
 
+
 List* st_select_lex::get_ignore_index()
 {
   return ignore_index_ptr;
 }
 
+
 ulong st_select_lex::get_table_join_options()
 {
   return table_join_options;
 }
 
+
 bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
 {
   if (ref_pointer_array)
@@ -1493,6 +1502,58 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
 			       order_group_num)* 5)) == 0;
 }
 
+
+/*
+  Find db.table which will be updated in this unit
+
+  SYNOPSIS
+    st_select_lex_unit::check_updateable()
+    db		- data base name
+    table	- real table name
+
+  RETURN
+    1 - found
+    0 - OK (table did not found)
+*/
+bool st_select_lex_unit::check_updateable(char *db, char *table)
+{
+  for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+    if (sl->check_updateable(db, table))
+      return 1;
+  return 0;
+}
+
+
+/*
+  Find db.table which will be updated in this select and 
+  underlayed ones (except derived tables)
+
+  SYNOPSIS
+    st_select_lex::check_updateable()
+    db		- data base name
+    table	- real table name
+
+  RETURN
+    1 - found
+    0 - OK (table did not found)
+*/
+bool st_select_lex::check_updateable(char *db, char *table)
+{
+  if (find_real_table_in_list(get_table_list(), db, table))
+    return 1;
+
+  for (SELECT_LEX_UNIT *un= first_inner_unit();
+       un;
+       un= un->next_unit())
+  {
+    if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
+	un->check_updateable(db, table))
+      return 1;
+  }
+  return 0;
+}
+
+
 void st_select_lex_unit::print(String *str)
 {
   for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
@@ -1535,6 +1596,7 @@ void st_select_lex::print_order(String *str, ORDER *order)
   }
 }
  
+
 void st_select_lex::print_limit(THD *thd, String *str)
 {
   if (!thd)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index bcbd60e9716..b1f0b63b5cd 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -336,8 +336,7 @@ public:
   uint union_option;
 
   void init_query();
-  bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
-			 bool check_current_derived);
+  bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
   st_select_lex_unit* master_unit();
   st_select_lex* outer_select();
   st_select_lex* first_select() { return (st_select_lex*) slave; }
@@ -355,14 +354,15 @@ public:
   int exec();
   int cleanup();
 
+  bool check_updateable(char *db, char *table);
   void print(String *str);
+  
 
   friend void mysql_init_query(THD *thd);
   friend int subselect_union_engine::exec();
 private:
   bool create_total_list_n_last_return(THD *thd, st_lex *lex,
-				       TABLE_LIST ***result,
-				       bool check_current_derived);
+				       TABLE_LIST ***result);
 };
 typedef class st_select_lex_unit SELECT_LEX_UNIT;
 
@@ -497,6 +497,7 @@ public:
     init_select();
   }
   bool setup_ref_array(THD *thd, uint order_group_num);
+  bool check_updateable(char *db, char *table);
   void print(THD *thd, String *str);
   static void print_order(String *str, ORDER *order);
   void print_limit(THD *thd, String *str);
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 1d16771c1a4..efc4cf0921d 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -143,18 +143,6 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
   int count=select_lex->group_list.elements;
   int sl_return=0;
 
-// a fix for UNION's
-  for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first;
-       cursor;
-       cursor=cursor->next)
-  {
-    if (cursor->do_redirect)
-    {
-      //Sinisa TODO: there are function for this purpose: fix_tables_pointers
-      cursor->table= cursor->table_list->table;
-      cursor->do_redirect= 0;
-    }
-  }
 
   lex->last_selects=select_lex;
 
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index cbf091069d6..dbce5cf75a4 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1789,34 +1789,9 @@ mysql_execute_command(THD *thd)
 #endif
   }
 #endif /* !HAVE_REPLICATION */
-  /*
-    TODO: make derived tables processing 'inside' SELECT processing.
-    TODO: solve problem with depended derived tables in subselects
-  */
-  if (lex->derived_tables)
-  {
-    for (SELECT_LEX *sl= lex->all_selects_list;
-	 sl;
-	 sl= sl->next_select_in_list())
-    {
-      for (TABLE_LIST *cursor= sl->get_table_list();
-	   cursor;
-	   cursor= cursor->next)
-      {
-	if (cursor->derived && (res=mysql_derived(thd, lex,
-						  cursor->derived,
-						  cursor)))
-	{
-	  if (res < 0 || thd->net.report_error)
-	    send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
-	  DBUG_VOID_RETURN;
-	}
-      }
-    }
-  }
   if (&lex->select_lex != lex->all_selects_list &&
       lex->sql_command != SQLCOM_CREATE_TABLE &&
-      lex->unit.create_total_list(thd, lex, &tables, 0))
+      lex->unit.create_total_list(thd, lex, &tables))
     DBUG_VOID_RETURN;
   
   /*
@@ -1875,7 +1850,6 @@ mysql_execute_command(THD *thd)
 	}
 	else
 	  thd->send_explain_fields(result);
-	fix_tables_pointers(lex->all_selects_list);
 	res= mysql_explain_union(thd, &thd->lex->unit, result);
 	MYSQL_LOCK *save_lock= thd->lock;
 	thd->lock= (MYSQL_LOCK *)0;
@@ -1918,7 +1892,6 @@ mysql_execute_command(THD *thd)
 		   (res= open_and_lock_tables(thd,tables))))
 	break;
 
-    fix_tables_pointers(lex->all_selects_list);
     res= mysql_do(thd, *lex->insert_list);
     if (thd->net.report_error)
       res= -1;
@@ -2127,7 +2100,7 @@ mysql_execute_command(THD *thd)
     lex->select_lex.table_list.first= (byte*) (tables);
     create_table->next= 0;
     if (&lex->select_lex != lex->all_selects_list &&
-	lex->unit.create_total_list(thd, lex, &tables, 0))
+	lex->unit.create_total_list(thd, lex, &tables))
       DBUG_VOID_RETURN;
 
     ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
@@ -2342,6 +2315,8 @@ mysql_execute_command(THD *thd)
       if (grant_option)
       {
 	TABLE_LIST old_list,new_list;
+	bzero((char*) &old_list, sizeof(old_list));
+	bzero((char*) &new_list, sizeof(new_list)); // Safety
 	old_list=table[0];
 	new_list=table->next[0];
 	old_list.next=new_list.next=0;
@@ -2673,23 +2648,15 @@ mysql_execute_command(THD *thd)
       }
       if (!walk)
       {
-	if (lex->derived_tables)
-	{
-	  // are we trying to delete derived table?
-	  for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
-	  {
-	    if (!strcmp(auxi->real_name,walk->alias) &&
-		walk->derived)
-	    {
-	      net_printf(thd, ER_NON_UPDATABLE_TABLE,
-			 auxi->real_name, "DELETE");
-	      goto error;
-	    }
-	  }
-	}
 	net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
 	goto error;
       }
+      if (walk->derived)
+      {
+	net_printf(thd, ER_NON_UPDATABLE_TABLE,
+		   auxi->real_name, "DELETE");
+	goto error;
+      }
       walk->lock_type= auxi->lock_type;
       auxi->table_list=  walk;		// Remember corresponding table
     }
@@ -2703,21 +2670,27 @@ mysql_execute_command(THD *thd)
       break;
     /* Fix tables-to-be-deleted-from list to point at opened tables */
     for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
-      auxi->table= auxi->table_list->table;
-    if (&lex->select_lex != lex->all_selects_list)
     {
-      for (TABLE_LIST *t= select_lex->get_table_list();
-	   t; t= t->next)
+      auxi->table= auxi->table_list->table;
+      /* 
+	 Multi-delete can't be constucted over-union => we always have
+	 single SELECT on top and have to check underlayed SELECTs of it
+      */
+      for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
+	   un;
+	   un= un->next_unit())
       {
-	if (find_real_table_in_list(t->table_list->next, t->db, t->real_name))
+	if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
+	    un->check_updateable(auxi->table_list->db,
+				 auxi->table_list->real_name))
 	{
-	  my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name);
+	  my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name);
 	  res= -1;
 	  break;
 	}
       }
     }
-    fix_tables_pointers(lex->all_selects_list);
+
     if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
 							  table_count)))
     {
@@ -2962,7 +2935,6 @@ mysql_execute_command(THD *thd)
     if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
 		   (res= open_and_lock_tables(thd,tables))))
       break;
-    fix_tables_pointers(lex->all_selects_list);
     if (!(res= sql_set_variables(thd, &lex->var_list)))
       send_ok(thd);
     if (thd->net.report_error)
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index de0d0c8aca8..1d5233d5803 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -733,7 +733,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
     DBUG_RETURN(1);
 #endif
   if ((&lex->select_lex != lex->all_selects_list &&
-       lex->unit.create_total_list(thd, lex, &tables, 0)))
+       lex->unit.create_total_list(thd, lex, &tables)))
    DBUG_RETURN(1);
     
   if (open_and_lock_tables(thd, tables))
@@ -746,7 +746,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
   }
   else 
   {
-    fix_tables_pointers(lex->all_selects_list);
     if (!result && !(result= new select_send()))
     {
       send_error(thd, ER_OUT_OF_RESOURCES);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f6e7a474eca..9ad7ba606be 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -175,7 +175,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
   register SELECT_LEX *select_lex = &lex->select_lex;
   DBUG_ENTER("handle_select");
 
-  fix_tables_pointers(lex->all_selects_list);
   if (select_lex->next_select())
     res=mysql_union(thd, lex, result, &lex->unit);
   else
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 7cc71117914..aa1d7673176 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -427,7 +427,6 @@ public:
 
 bool cp_buffer_from_ref(TABLE_REF *ref);
 bool error_if_full_join(JOIN *join);
-void relink_tables(SELECT_LEX *select_lex);
 int report_error(TABLE *table, int error);
 int safe_index_read(JOIN_TAB *tab);
 COND *eliminate_not_funcs(COND *cond);
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 337f2540a39..6e8aae54b23 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -149,7 +149,7 @@ void udf_init()
   tables.lock_type = TL_READ;
   tables.db=new_thd->db;
 
-  if (open_and_lock_tables(new_thd, &tables))
+  if (simple_open_n_lock_tables(new_thd, &tables))
   {
     DBUG_PRINT("error",("Can't open udf table"));
     sql_print_error("Can't open mysql/func table");
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 8ee00f2bca6..45f7a73f6b5 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -79,7 +79,6 @@ int mysql_update(THD *thd,
   if ((open_and_lock_tables(thd, table_list)))
     DBUG_RETURN(-1);
   thd->proc_info="init";
-  fix_tables_pointers(thd->lex->all_selects_list);
   table= table_list->table;
   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
 
@@ -431,7 +430,6 @@ int mysql_multi_update(THD *thd,
 #endif
   if ((res=open_and_lock_tables(thd,table_list)))
     DBUG_RETURN(res);
-  fix_tables_pointers(thd->lex->all_selects_list);
 
   select_lex->select_limit= HA_POS_ERROR;
 

From 1f739ca45eb009de8dadd4503374bc4a5c6bf5c0 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Sun, 1 Feb 2004 20:07:44 +0200
Subject: [PATCH 127/157] make JOIN::prepare, JOIN::optimize only once for
 EXPLAIN of derived table (BUG#2120 sfter merge)

mysql-test/r/derived.result:
  correct results of derived tble EXPLAIN
  test of "Using Index" with derived tables
mysql-test/t/derived.test:
  test of "Using Index" with derived tables
sql/mysql_priv.h:
  way to force derived table save JOIN after execution
sql/sql_derived.cc:
  way to force derived table save JOIN after execution
sql/sql_lex.h:
  way to force derived table save JOIN after execution
sql/sql_select.cc:
  make JOIN::prepare, JOIN::optimize only once for EXPLAIN of derived table
---
 mysql-test/r/derived.result | 21 ++++++++++++++++-----
 mysql-test/t/derived.test   | 10 ++++++++++
 sql/mysql_priv.h            |  4 +++-
 sql/sql_derived.cc          |  9 +++++++++
 sql/sql_lex.h               |  1 +
 sql/sql_select.cc           | 18 ++++++++----------
 6 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index a89494645fa..dea4dd9b4c2 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -141,7 +141,7 @@ a	t
 explain select count(*) from t1 as tt1, (select * from t1) as tt2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
-2	DERIVED	t1	index	NULL	a	4	NULL	10000	Using index
+2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	10000	
 drop table t1;
 SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
 (SELECT * FROM (SELECT 1 as a) as a )
@@ -189,13 +189,13 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	m2	ALL	NULL	NULL	NULL	NULL	9	
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	6	Using where
 2	DERIVED	mp	ALL	NULL	NULL	NULL	NULL	9	Using temporary; Using filesort
-2	DERIVED	m1	index	NULL	PRIMARY	3	NULL	9	Using index
+2	DERIVED	m1	eq_ref	PRIMARY	PRIMARY	3	test.mp.mat_id	1	
 explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2  INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	m2	ALL	NULL	NULL	NULL	NULL	9	
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	6	Using where
 2	DERIVED	mp	ALL	NULL	NULL	NULL	NULL	9	Using temporary; Using filesort
-2	DERIVED	m1	index	NULL	PRIMARY	3	NULL	9	Using index
+2	DERIVED	m1	eq_ref	PRIMARY	PRIMARY	3	test.mp.mat_id	1	
 drop table t1,t2;
 SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
 x
@@ -229,8 +229,8 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	2	
 1	PRIMARY	t1	eq_ref	PRIMARY	PRIMARY	4	THEMAX.E2	1	Using where
-2	DERIVED	A	index	NULL	PRIMARY	4	NULL	2	Using where; Using index
-3	DEPENDENT SUBQUERY	B	index	NULL	PRIMARY	4	NULL	2	Using where; Using index
+2	DERIVED	A	ALL	NULL	NULL	NULL	NULL	2	Using where
+3	DEPENDENT SUBQUERY	B	ALL	NULL	NULL	NULL	NULL	2	Using where
 drop table t1;
 create table t1 (a int);
 insert into t1 values (1),(2);
@@ -309,3 +309,14 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY		ALL	NULL	NULL	NULL	NULL	3	Using temporary; Using filesort
 2	DERIVED	x	ALL	NULL	NULL	NULL	NULL	17	Using temporary; Using filesort
 2	DERIVED	y	ALL	NULL	NULL	NULL	NULL	17	Using where
+drop table t1;
+create table t2 (a int, b int, primary key (a));
+insert into t2 values (1,7),(2,7);
+explain select a from t2 where a>1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	range	PRIMARY	PRIMARY	4	NULL	2	Using where; Using index
+explain select a from (select a from t2 where a>1) tt;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY		system	NULL	NULL	NULL	NULL	1	
+2	DERIVED	t2	range	PRIMARY	PRIMARY	4	NULL	2	Using where; Using index
+drop table t2;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index b412555f1e8..988ef30d1dc 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -192,3 +192,13 @@ CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL);
 INSERT INTO t1 VALUES ('a',1),  ('a',2),  ('a',2),  ('a',2),  ('a',3),  ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5);
 SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
 explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
+drop table t1;
+
+#
+# "Using index" in explain
+#
+create table t2 (a int, b int, primary key (a));
+insert into t2 values (1,7),(2,7);
+explain select a from t2 where a>1;
+explain select a from (select a from t2 where a>1) tt;
+drop table t2;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 7e1923b1825..4d03feae07c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -247,7 +247,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
 // uncachable cause
 #define UNCACHEABLE_DEPENDENT   1
 #define UNCACHEABLE_RAND        2
-#define UNCACHEABLE_SIDEEFFECT 4
+#define UNCACHEABLE_SIDEEFFECT	4
+// forcing to save JOIN for explain
+#define UNCACHEABLE_EXPLAIN     8
 
 #ifdef EXTRA_DEBUG
 /*
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 8fa5694714c..a307b59b525 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -62,6 +62,15 @@ mysql_handle_derived(LEX *lex)
 	  return 1;
 	}
       }
+      if (lex->describe)
+      {
+	/*
+	  Force join->join_tmp creation, because we will use this JOIN
+	  twice for EXPLAIN and we have to have unchanged join for EXPLAINing
+	*/
+	sl->uncacheable|= UNCACHEABLE_EXPLAIN;
+	sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
+      }
     }
   }
   return 0;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4ada72167be..3b1b3873706 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -232,6 +232,7 @@ public:
       UNCACHEABLE_DEPENDENT
       UNCACHEABLE_RAND
       UNCACHEABLE_SIDEEFFECT
+      UNCACHEABLE_EXPLAIN
   */
   uint8 uncacheable;
   enum sub_select_type linkage;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ede6e837984..e47ed8fcbbc 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1579,8 +1579,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
 	  goto err;
 	}
       }
-      free_join= 0;
     }
+    free_join= 0;
     join->select_options= select_options;
   }
   else
@@ -3769,11 +3769,6 @@ JOIN::join_free(bool full)
       {
 	if (tab->table)
 	{
-	  if (tab->table->key_read)
-	  {
-	    tab->table->key_read= 0;
-	    tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
-	  }
 	  /* Don't free index if we are using read_record */
 	  if (!tab->read_record.table)
 	    tab->table->file->index_end();
@@ -9128,6 +9123,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
        sl;
        sl= sl->next_select())
   {
+    // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
+    uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
+
     res= mysql_explain_select(thd, sl,
 			      (((&thd->lex->select_lex)==sl)?
 			       ((thd->lex->all_selects_list != sl) ? 
@@ -9135,13 +9133,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
 			       ((sl == first)?
 				((sl->linkage == DERIVED_TABLE_TYPE) ?
 				 "DERIVED":
-				((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
+				((uncacheable & UNCACHEABLE_DEPENDENT) ?
 				 "DEPENDENT SUBQUERY":
-				 (sl->uncacheable?"UNCACHEABLE SUBQUERY":
+				 (uncacheable?"UNCACHEABLE SUBQUERY":
 				   "SUBQUERY"))):
-				((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
+				((uncacheable & UNCACHEABLE_DEPENDENT) ?
 				 "DEPENDENT UNION":
-				 sl->uncacheable?"UNCACHEABLE UNION":
+				 uncacheable?"UNCACHEABLE UNION":
 				  "UNION"))),
 			      result);
     if (res)

From c91c1470c8294a4ebdec2f31f115c8a05693f4f5 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 2 Feb 2004 00:19:51 -0800
Subject: [PATCH 128/157] preload.result, key_cache.result, preload.test,
 key_cache.test, sql_yacc.yy:   Fixed bug #2602 in CACHE INDEX, LOAD INDEX

sql/sql_yacc.yy:
  Fixed bug #2602 in CACHE INDEX, LOAD INDEX
mysql-test/t/key_cache.test:
  Fixed bug #2602 in CACHE INDEX, LOAD INDEX
mysql-test/t/preload.test:
  Fixed bug #2602 in CACHE INDEX, LOAD INDEX
mysql-test/r/key_cache.result:
  Fixed bug #2602 in CACHE INDEX, LOAD INDEX
mysql-test/r/preload.result:
  Fixed bug #2602 in CACHE INDEX, LOAD INDEX
---
 mysql-test/r/key_cache.result | 4 ++--
 mysql-test/r/preload.result   | 6 +++---
 mysql-test/t/key_cache.test   | 4 ++--
 mysql-test/t/preload.test     | 6 +++---
 sql/sql_yacc.yy               | 7 +------
 5 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index af3cf956222..b83a226776d 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -100,7 +100,7 @@ p	i	a
 4	3	zzzz
 update t1 set p=2 where p=1;
 update t2 set i=2 where i=1;
-cache index t1 keys (`primary`) in keycache1;
+cache index t1 key (`primary`) in keycache1;
 Table	Op	Msg_type	Msg_text
 test.t1	assign_to_keycache	status	OK
 explain select p from t1;
@@ -177,7 +177,7 @@ yyyy
 zzzz
 cache index t1 in unknown_key_cache;
 ERROR HY000: Unknown key cache 'unknown_key_cache'
-cache index t1 keys (unknown_key) in keycache1;
+cache index t1 key (unknown_key) in keycache1;
 Table	Op	Msg_type	Msg_text
 test.t1	assign_to_keycache	error	Key column 'unknown_key' doesn't exist in table
 test.t1	assign_to_keycache	status	Operation failed
diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result
index bd7b828d5b9..f0b99a8d6f1 100644
--- a/mysql-test/r/preload.result
+++ b/mysql-test/r/preload.result
@@ -117,7 +117,7 @@ set session preload_buffer_size=1*1024;
 select @@preload_buffer_size;
 @@preload_buffer_size
 1024
-load index into cache t1, t2 keys (primary,b) ignore leaves;
+load index into cache t1, t2 key (primary,b) ignore leaves;
 Table	Op	Msg_type	Msg_text
 test.t1	preload_keys	status	OK
 test.t2	preload_keys	status	OK
@@ -141,7 +141,7 @@ show status like "key_read%";
 Variable_name	Value
 Key_read_requests	0
 Key_reads	0
-load index into cache t3, t2 keys (primary,b) ;
+load index into cache t3, t2 key (primary,b) ;
 Table	Op	Msg_type	Msg_text
 test.t3	preload_keys	error	Table 'test.t3' doesn't exist
 test.t2	preload_keys	status	OK
@@ -155,7 +155,7 @@ show status like "key_read%";
 Variable_name	Value
 Key_read_requests	0
 Key_reads	0
-load index into cache t3 keys (b), t2 keys (c) ;
+load index into cache t3 key (b), t2 key (c) ;
 Table	Op	Msg_type	Msg_text
 test.t3	preload_keys	error	Table 'test.t3' doesn't exist
 test.t2	preload_keys	error	Key column 'c' doesn't exist in table
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index b2bc57f3804..d9a2200a636 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -75,7 +75,7 @@ select * from t2;
 update t1 set p=2 where p=1;
 update t2 set i=2 where i=1;
 
-cache index t1 keys (`primary`) in keycache1;
+cache index t1 key (`primary`) in keycache1;
 
 explain select p from t1;
 select p from t1;
@@ -101,7 +101,7 @@ select a from t2;
 # Test some error conditions
 --error 1283
 cache index t1 in unknown_key_cache;
-cache index t1 keys (unknown_key) in keycache1;
+cache index t1 key (unknown_key) in keycache1;
 
 select @@keycache2.key_buffer_size;
 select @@keycache2.key_cache_block_size;
diff --git a/mysql-test/t/preload.test b/mysql-test/t/preload.test
index 7eff5cee08f..7a049d06a86 100644
--- a/mysql-test/t/preload.test
+++ b/mysql-test/t/preload.test
@@ -81,7 +81,7 @@ flush tables; flush status;
 show status like "key_read%";
 set session preload_buffer_size=1*1024;
 select @@preload_buffer_size;
-load index into cache t1, t2 keys (primary,b) ignore leaves;
+load index into cache t1, t2 key (primary,b) ignore leaves;
 show status like "key_read%";
 select count(*) from t1 where b = 'test1';
 select count(*) from t2 where b = 'test1';
@@ -89,12 +89,12 @@ show status like "key_read%";
 
 flush tables; flush status;
 show status like "key_read%";
-load index into cache t3, t2 keys (primary,b) ;
+load index into cache t3, t2 key (primary,b) ;
 show status like "key_read%";
 
 flush tables; flush status;
 show status like "key_read%";
-load index into cache t3 keys (b), t2 keys (c) ;
+load index into cache t3 key (b), t2 key (c) ;
 show status like "key_read%";
 
 drop table t1, t2;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 76a0f384b15..f04cc9ec1dc 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1615,11 +1615,6 @@ opt_key_or_index:
 	| key_or_index
 	;
 
-opt_keys_or_index:
-	/* empty */ {}
-	| keys_or_index
-	;
-
 keys_or_index:
 	KEYS {}
 	| INDEX {}
@@ -2120,7 +2115,7 @@ cache_keys_spec:
 
 cache_key_list_or_empty:
 	/* empty */	{ Lex->select_lex.use_index_ptr= 0; }
-	| opt_keys_or_index '(' key_usage_list2 ')'
+	| opt_key_or_index '(' key_usage_list2 ')'
 	  {
             SELECT_LEX *sel= &Lex->select_lex;
 	    sel->use_index_ptr= &sel->use_index;

From 65534b77a18aebb602ac23ed84351349818f0a2f Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 2 Feb 2004 17:50:14 +0400
Subject: [PATCH 129/157] Indexes can be used for optimization if the operation
 collation is the same with the index collation.

---
 mysql-test/r/ctype_collate.result | 47 ++++++++++++++++++++
 mysql-test/t/ctype_collate.test   | 38 ++++++++++++++++
 sql/item.h                        |  1 +
 sql/item_cmpfunc.h                |  7 +++
 sql/opt_range.cc                  | 73 +++++++++++++++++++------------
 sql/sql_select.cc                 | 21 ++++++---
 6 files changed, 153 insertions(+), 34 deletions(-)

diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index a3e29d24264..add730fe68f 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -541,3 +541,50 @@ s2 CHAR(5) COLLATE latin1_swedish_ci);
 SELECT * FROM t1 WHERE s1 = s2;
 ERROR HY000: Illegal mix of collations (latin1_german1_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation '='
 DROP TABLE t1;
+SET NAMES latin1;
+CREATE TABLE t1 
+(s1 char(10) COLLATE latin1_german1_ci,
+s2 char(10) COLLATE latin1_swedish_ci,
+KEY(s1),
+KEY(s2));
+INSERT INTO t1 VALUES ('a','a');
+INSERT INTO t1 VALUES ('b','b');
+INSERT INTO t1 VALUES ('c','c');
+INSERT INTO t1 VALUES ('d','d');
+INSERT INTO t1 VALUES ('e','e');
+INSERT INTO t1 VALUES ('f','f');
+INSERT INTO t1 VALUES ('g','g');
+INSERT INTO t1 VALUES ('h','h');
+INSERT INTO t1 VALUES ('i','i');
+INSERT INTO t1 VALUES ('j','j');
+EXPLAIN SELECT * FROM t1 WHERE s1='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	s1	s1	11	const	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE s2='a';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	s2	s2	11	const	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	s1	s1	11	const	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	s2	NULL	NULL	NULL	10	Using where
+EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	s1	s1	11	NULL	2	Using where
+EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	s2	NULL	NULL	NULL	10	Using where
+EXPLAIN SELECT * FROM t1 WHERE s1 IN  ('a','b' COLLATE latin1_german1_ci);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	s1	s1	11	NULL	2	Using where
+EXPLAIN SELECT * FROM t1 WHERE s2 IN  ('a','b' COLLATE latin1_german1_ci);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	s2	NULL	NULL	NULL	10	Using where
+EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	s1	s1	11	NULL	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	s2	NULL	NULL	NULL	10	Using where
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_collate.test b/mysql-test/t/ctype_collate.test
index 2d9a4be5b36..5916e3da241 100644
--- a/mysql-test/t/ctype_collate.test
+++ b/mysql-test/t/ctype_collate.test
@@ -156,3 +156,41 @@ CREATE TABLE t1
 --error 1266
 SELECT * FROM t1 WHERE s1 = s2;
 DROP TABLE t1;
+
+
+#
+# Test that optimizer doesn't use indexes with wrong collation
+#
+SET NAMES latin1;
+CREATE TABLE t1 
+(s1 char(10) COLLATE latin1_german1_ci,
+ s2 char(10) COLLATE latin1_swedish_ci,
+ KEY(s1),
+ KEY(s2));
+
+INSERT INTO t1 VALUES ('a','a');
+INSERT INTO t1 VALUES ('b','b');
+INSERT INTO t1 VALUES ('c','c');
+INSERT INTO t1 VALUES ('d','d');
+INSERT INTO t1 VALUES ('e','e');
+INSERT INTO t1 VALUES ('f','f');
+INSERT INTO t1 VALUES ('g','g');
+INSERT INTO t1 VALUES ('h','h');
+INSERT INTO t1 VALUES ('i','i');
+INSERT INTO t1 VALUES ('j','j');
+
+EXPLAIN SELECT * FROM t1 WHERE s1='a';
+EXPLAIN SELECT * FROM t1 WHERE s2='a';
+EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
+EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
+
+EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
+EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
+
+EXPLAIN SELECT * FROM t1 WHERE s1 IN  ('a','b' COLLATE latin1_german1_ci);
+EXPLAIN SELECT * FROM t1 WHERE s2 IN  ('a','b' COLLATE latin1_german1_ci);
+
+EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
+EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
+
+DROP TABLE t1;
diff --git a/sql/item.h b/sql/item.h
index 7b5c506079d..a5648c5889b 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -204,6 +204,7 @@ public:
   virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
 
   CHARSET_INFO *default_charset() const;
+  virtual CHARSET_INFO *compare_collation() { return NULL; }
 
   virtual bool walk(Item_processor processor, byte *arg)
   {
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 3ad3b928c01..7079fcf193d 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -191,6 +191,7 @@ public:
   bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
   void print(String *str) { Item_func::print_op(str); }
   bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
+  CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
 
   friend class  Arg_comparator;
 };
@@ -340,6 +341,7 @@ public:
   const char *func_name() const { return "between"; }
   void fix_length_and_dec();
   void print(String *str);
+  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
 };
 
 
@@ -479,6 +481,7 @@ public:
   const char *func_name() const { return "case"; }
   void print(String *str);
   Item *find_item(String *str);
+  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
 };
 
 
@@ -726,6 +729,7 @@ class Item_func_in :public Item_int_func
   enum Functype functype() const { return IN_FUNC; }
   const char *func_name() const { return " IN "; }
   bool nulls_in_row();
+  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
 };
 
 /* Functions used by where clause */
@@ -766,6 +770,7 @@ public:
   table_map not_null_tables() const { return 0; }
   optimize_type select_optimize() const { return OPTIMIZE_NULL; }
   Item *neg_transformer();
+  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
 };
 
 /* Functions used by HAVING for rewriting IN subquery */
@@ -800,6 +805,7 @@ public:
   table_map not_null_tables() const { return 0; }
   Item *neg_transformer();
   void print(String *str);
+  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
 };
 
 
@@ -854,6 +860,7 @@ public:
   bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
   const char *func_name() const { return "regexp"; }
   void print(String *str) { print_op(str); }
+  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
 };
 
 #else
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index acc23924f75..ffa51826206 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -291,10 +291,11 @@ typedef struct st_qsel_param {
   bool quick;				// Don't calulate possible keys
 } PARAM;
 
-static SEL_TREE * get_mm_parts(PARAM *param,Field *field,
+static SEL_TREE * get_mm_parts(PARAM *param,COND *cond_func,Field *field,
 			       Item_func::Functype type,Item *value,
 			       Item_result cmp_type);
-static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part,
+static SEL_ARG *get_mm_leaf(PARAM *param,COND *cond_func,Field *field,
+			    KEY_PART *key_part,
 			    Item_func::Functype type,Item *value);
 static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
 static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
@@ -834,10 +835,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
       Field *field=((Item_field*) (cond_func->arguments()[0]))->field;
       Item_result cmp_type=field->cmp_type();
       DBUG_RETURN(tree_and(param,
-			   get_mm_parts(param, field,
+			   get_mm_parts(param, cond_func, field,
 					Item_func::GE_FUNC,
 					cond_func->arguments()[1], cmp_type),
-			   get_mm_parts(param, field,
+			   get_mm_parts(param, cond_func, field,
 					Item_func::LE_FUNC,
 					cond_func->arguments()[2], cmp_type)));
     }
@@ -850,13 +851,14 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
     {
       Field *field=((Item_field*) (func->key_item()))->field;
       Item_result cmp_type=field->cmp_type();
-      tree= get_mm_parts(param,field,Item_func::EQ_FUNC,
+      tree= get_mm_parts(param,cond_func,field,Item_func::EQ_FUNC,
 			 func->arguments()[1],cmp_type);
       if (!tree)
 	DBUG_RETURN(tree);			// Not key field
       for (uint i=2 ; i < func->argument_count(); i++)
       {
-	SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC,
+	SEL_TREE *new_tree=get_mm_parts(param,cond_func,field,
+					Item_func::EQ_FUNC,
 					func->arguments()[i],cmp_type);
 	tree=tree_or(param,tree,new_tree);
       }
@@ -875,7 +877,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
   /* btw, ft_func's arguments()[0] isn't FIELD_ITEM.  SerG*/
   if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
   {
-    tree= get_mm_parts(param,
+    tree= get_mm_parts(param, cond_func,
 		       ((Item_field*) (cond_func->arguments()[0]))->field,
 		       cond_func->functype(),
 		       cond_func->arg_count > 1 ? cond_func->arguments()[1] :
@@ -888,7 +890,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
       cond_func->have_rev_func() &&
       cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
   {
-    DBUG_RETURN(get_mm_parts(param,
+    DBUG_RETURN(get_mm_parts(param, cond_func,
 			     ((Item_field*)
 			      (cond_func->arguments()[1]))->field,
 			     ((Item_bool_func2*) cond_func)->rev_functype(),
@@ -902,7 +904,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
 
 
 static SEL_TREE *
-get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, 
+get_mm_parts(PARAM *param, COND *cond_func, Field *field,
+	     Item_func::Functype type, 
 	     Item *value, Item_result cmp_type)
 {
   bool ne_func= FALSE;
@@ -931,7 +934,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
 	DBUG_RETURN(0);				// OOM
       if (!value || !(value->used_tables() & ~param->read_tables))
       {
-	sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value);
+	sel_arg=get_mm_leaf(param,cond_func,
+			    key_part->field,key_part,type,value);
 	if (!sel_arg)
 	  continue;
 	if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
@@ -953,7 +957,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
 
   if (ne_func)
   {
-    SEL_TREE *tree2= get_mm_parts(param, field, Item_func::GT_FUNC,
+    SEL_TREE *tree2= get_mm_parts(param, cond_func,
+				  field, Item_func::GT_FUNC,
                                   value, cmp_type);
     if (tree2)
       tree= tree_or(param,tree,tree2);
@@ -963,7 +968,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
 
 
 static SEL_ARG *
-get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
+get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
 	    Item_func::Functype type,Item *value)
 {
   uint maybe_null=(uint) field->real_maybe_null(), copies;
@@ -972,6 +977,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
   char *str, *str2;
   DBUG_ENTER("get_mm_leaf");
 
+  if (!value)					// IS NULL or IS NOT NULL
+  {
+    if (field->table->outer_join)		// Can't use a key on this
+      DBUG_RETURN(0);
+    if (!maybe_null)				// Not null field
+      DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
+    if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
+      DBUG_RETURN(0);		// out of memory
+    if (type == Item_func::ISNOTNULL_FUNC)
+    {
+      tree->min_flag=NEAR_MIN;		    /* IS NOT NULL ->  X > NULL */
+      tree->max_flag=NO_MAX_RANGE;
+    }
+    DBUG_RETURN(tree);
+  }
+
+  /*
+    We can't use an index when comparing stings of 
+    different collations 
+  */
+  if (field->result_type() == STRING_RESULT &&
+      value->result_type() == STRING_RESULT &&
+      key_part->image_type == Field::itRAW &&
+      ((Field_str*)field)->charset() != conf_func->compare_collation())
+    DBUG_RETURN(0);
+
   if (type == Item_func::LIKE_FUNC)
   {
     bool like_error;
@@ -1035,22 +1066,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
     DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
   }
 
-  if (!value)					// IS NULL or IS NOT NULL
-  {
-    if (field->table->outer_join)		// Can't use a key on this
-      DBUG_RETURN(0);
-    if (!maybe_null)				// Not null field
-      DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
-    if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
-      DBUG_RETURN(0);		// out of memory
-    if (type == Item_func::ISNOTNULL_FUNC)
-    {
-      tree->min_flag=NEAR_MIN;		    /* IS NOT NULL ->  X > NULL */
-      tree->max_flag=NO_MAX_RANGE;
-    }
-    DBUG_RETURN(tree);
-  }
-
   if (!field->optimize_range(param->real_keynr[key_part->key]) &&
       type != Item_func::EQ_FUNC &&
       type != Item_func::EQUAL_FUNC)
@@ -1064,7 +1079,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
       value->result_type() != STRING_RESULT &&
       field->cmp_type() != value->result_type())
     DBUG_RETURN(0);
-
+ 
   if (value->save_in_field(field, 1) > 0)
   {
     /* This happens when we try to insert a NULL field in a not null column */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 874a3b16312..40816be1340 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2131,7 +2131,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
 */
 
 static void
-add_key_field(KEY_FIELD **key_fields,uint and_level,
+add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond,
 	      Field *field,bool eq_func,Item **value, uint num_values,
 	      table_map usable_tables)
 {
@@ -2198,6 +2198,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
 	  (*value)->result_type() != STRING_RESULT &&
 	  field->cmp_type() != (*value)->result_type())
 	return;
+      
+      /*
+        We can't use indexes if the effective collation
+        of the operation differ from the field collation.
+      */
+      if (field->result_type() == STRING_RESULT &&
+	  (*value)->result_type() == STRING_RESULT &&
+	  field->cmp_type() == STRING_RESULT &&
+	  ((Field_str*)field)->charset() != cond->compare_collation())
+	return;
+
     }
   }
   DBUG_ASSERT(num_values == 1);
@@ -2261,7 +2272,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
     // BETWEEN or IN
     if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
 	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
-      add_key_field(key_fields,*and_level,
+      add_key_field(key_fields,*and_level,cond_func,
 		    ((Item_field*) (cond_func->key_item()->real_item()))->
 		    field, 0,
                     cond_func->arguments()+1, cond_func->argument_count()-1,
@@ -2275,7 +2286,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
     if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
 	!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
     {
-      add_key_field(key_fields,*and_level,
+      add_key_field(key_fields,*and_level,cond_func,
 		    ((Item_field*) (cond_func->arguments()[0])->real_item())
 		    ->field,
 		    equal_func,
@@ -2285,7 +2296,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
 	cond_func->functype() != Item_func::LIKE_FUNC &&
 	!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
     {
-      add_key_field(key_fields,*and_level,
+      add_key_field(key_fields,*and_level,cond_func,
 		    ((Item_field*) (cond_func->arguments()[1])->real_item())
 		    ->field,
 		    equal_func,
@@ -2301,7 +2312,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
       Item *tmp=new Item_null;
       if (!tmp)					// Should never be true
 	return;
-      add_key_field(key_fields,*and_level,
+      add_key_field(key_fields,*and_level,cond_func,
 		    ((Item_field*) (cond_func->arguments()[0])->real_item())
 		    ->field,
 		    cond_func->functype() == Item_func::ISNULL_FUNC,

From 8131ccaf8007d23d452dde6d0dc210cc57c7f661 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 2 Feb 2004 19:32:49 +0400
Subject: [PATCH 130/157] Added a comment for NULL range creation.

---
 sql/opt_range.cc | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9f56064cfb1..2ebc60ca711 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2516,6 +2516,12 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
   if (quick->ranges.push_back(range))
     goto err;
 
+  /* 
+     Add a NULL range if REF_OR_NULL optimization is used.
+     For example:
+       if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above
+       and have ref->null_ref_key set. Will create a new NULL range here.
+  */
   if (ref->null_ref_key)
   {
     QUICK_RANGE *null_range;
@@ -2526,7 +2532,6 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
 				      EQ_RANGE)))
       goto err;
     *ref->null_ref_key= 0;		// Clear null byte
-    /* Do we need to do something with key_parts here? Looks like we don't */
     if (quick->ranges.push_back(null_range))
       goto err;
   }

From f1bfba29d4e61daaafdf60df402dca3f70e2c79d Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 2 Feb 2004 20:25:39 +0400
Subject: [PATCH 131/157] just tried to find all 'skipp' and replace it with
 'skip'.

client/sql_string.cc:
  skipp -> skip
dbug/dbug.c:
  skipp -> skip
myisam/mi_create.c:
  skipp -> skip
myisam/mi_dynrec.c:
  skipp -> skip
myisam/mi_packrec.c:
  skipp -> skip
myisam/mi_rrnd.c:
  skipp -> skip
myisam/mi_test1.c:
  skipp -> skip
myisam/myisampack.c:
  skipp -> skip
myisam/rt_test.c:
  skipp -> skip
myisam/sp_test.c:
  skipp -> skip
mysys/default.c:
  skipp -> skip
mysys/mf_iocache.c:
  skipp -> skip
mysys/mf_pack.c:
  skipp -> skip
mysys/mf_wcomp.c:
  skipp -> skip
mysys/typelib.c:
  skipp -> skip
sql/filesort.cc:
  skipp -> skip
sql/item_strfunc.cc:
  skipp -> skip
sql/mysqld.cc:
  skipp -> skip
sql/opt_range.h:
  skipp -> skip
sql/sql_delete.cc:
  skipp -> skip
sql/sql_select.cc:
  skipp -> skip
sql/sql_string.cc:
  skipp -> skip
sql/sql_update.cc:
  skipp -> skip
strings/ctype-bin.c:
  skipp -> skip
strings/ctype-simple.c:
  skipp -> skip
strings/r_strinstr.c:
  skipp -> skip
strings/strinstr.c:
  skipp -> skip
strings/strstr.c:
  skipp -> skip
---
 client/sql_string.cc   | 12 ++++++------
 dbug/dbug.c            |  2 +-
 myisam/mi_create.c     | 18 +++++++++---------
 myisam/mi_dynrec.c     | 10 +++++-----
 myisam/mi_packrec.c    | 18 +++++++++---------
 myisam/mi_rrnd.c       |  8 ++++----
 myisam/mi_statrec.c    |  6 +++---
 myisam/mi_test1.c      |  2 +-
 myisam/myisampack.c    |  8 ++++----
 myisam/rt_test.c       |  2 +-
 myisam/sp_test.c       |  2 +-
 mysys/default.c        |  2 +-
 mysys/mf_iocache.c     |  2 +-
 mysys/mf_pack.c        |  2 +-
 mysys/mf_wcomp.c       |  2 +-
 mysys/typelib.c        |  2 +-
 sql/filesort.cc        |  2 +-
 sql/item_strfunc.cc    |  8 ++++----
 sql/mysqld.cc          |  4 ++--
 sql/opt_range.h        |  2 +-
 sql/sql_delete.cc      |  2 +-
 sql/sql_select.cc      | 14 +++++++-------
 sql/sql_string.cc      | 12 ++++++------
 sql/sql_update.cc      |  4 ++--
 strings/ctype-bin.c    |  4 ++--
 strings/ctype-simple.c |  4 ++--
 strings/r_strinstr.c   |  4 ++--
 strings/strinstr.c     |  4 ++--
 strings/strstr.c       |  4 ++--
 29 files changed, 83 insertions(+), 83 deletions(-)

diff --git a/client/sql_string.cc b/client/sql_string.cc
index 65a9ff68c53..7de0df02f53 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc
@@ -415,7 +415,7 @@ int String::strstr(const String &s,uint32 offset)
     register const char *search=s.ptr();
     const char *end=Ptr+str_length-s.length()+1;
     const char *search_end=s.ptr()+s.length();
-skipp:
+skip:
     while (str != end)
     {
       if (*str++ == *search)
@@ -423,7 +423,7 @@ skipp:
 	register char *i,*j;
 	i=(char*) str; j=(char*) search+1;
 	while (j != search_end)
-	  if (*i++ != *j++) goto skipp;
+	  if (*i++ != *j++) goto skip;
 	return (int) (str-Ptr) -1;
       }
     }
@@ -447,7 +447,7 @@ int String::strstr_case(const String &s,uint32 offset)
     register const char *search=s.ptr();
     const char *end=Ptr+str_length-s.length()+1;
     const char *search_end=s.ptr()+s.length();
-skipp:
+skip:
     while (str != end)
     {
       if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
@@ -457,7 +457,7 @@ skipp:
 	while (j != search_end)
 	  if (str_charset->sort_order[*i++] != 
               str_charset->sort_order[*j++]) 
-            goto skipp;
+            goto skip;
 	return (int) (str-Ptr) -1;
       }
     }
@@ -480,7 +480,7 @@ int String::strrstr(const String &s,uint32 offset)
 
     const char *end=Ptr+s.length()-2;
     const char *search_end=s.ptr()-1;
-skipp:
+skip:
     while (str != end)
     {
       if (*str-- == *search)
@@ -488,7 +488,7 @@ skipp:
 	register char *i,*j;
 	i=(char*) str; j=(char*) search-1;
 	while (j != search_end)
-	  if (*i-- != *j--) goto skipp;
+	  if (*i-- != *j--) goto skip;
 	return (int) (i-Ptr) +1;
       }
     }
diff --git a/dbug/dbug.c b/dbug/dbug.c
index d96ef0cae09..4e4dd87d0a3 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -1640,7 +1640,7 @@ static char *static_strtok (char *s1, pchar separator)
 	  cpy--;		/* Point at separator */
 	  break;
 	}
-	end++;			/* Two separators in a row, skipp one */
+	end++;			/* Two separators in a row, skip one */
       }
     } while (*end != EOS);
     *cpy=EOS;			/* Replace last separator */
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 9036ced751c..72633966b54 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -42,7 +42,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
   int errpos,save_errno;
   myf create_flag;
   uint fields,length,max_key_length,packed,pointer,
-       key_length,info_length,key_segs,options,min_key_length_skipp,
+       key_length,info_length,key_segs,options,min_key_length_skip,
        base_pos,varchar_count,long_varchar_count,varchar_length,
        max_key_block_length,unique_key_parts,fulltext_keys,offset;
   ulong reclength, real_reclength,min_pack_length;
@@ -238,7 +238,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
   {
 
     share.state.key_root[i]= HA_OFFSET_ERROR;
-    min_key_length_skipp=length=0;
+    min_key_length_skip=length=0;
     key_length=pointer;
     if (keydef->flag & HA_SPATIAL)
     {
@@ -269,7 +269,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
       keydef->keysegs+=sp_segs;
       key_length+=SPLEN*sp_segs;
       length++;                              /* At least one length byte */
-      min_key_length_skipp+=SPLEN*2*SPDIMS;
+      min_key_length_skip+=SPLEN*2*SPDIMS;
     }
     else
     if (keydef->flag & HA_FULLTEXT)
@@ -291,7 +291,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
       fulltext_keys++;
       key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
       length++;                              /* At least one length byte */
-      min_key_length_skipp+=HA_FT_MAXBYTELEN;
+      min_key_length_skip+=HA_FT_MAXBYTELEN;
     }
     else
     {
@@ -348,10 +348,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
 	  keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
 	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
 	  length++;				/* At least one length byte */
-	  min_key_length_skipp+=keyseg->length;
+	  min_key_length_skip+=keyseg->length;
 	  if (keyseg->length >= 255)
 	  {					/* prefix may be 3 bytes */
-	    min_key_length_skipp+=2;
+	    min_key_length_skip+=2;
 	    length+=2;
 	  }
 	}
@@ -360,10 +360,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
 	  keydef->flag|=HA_VAR_LENGTH_KEY;
 	  length++;				/* At least one length byte */
 	  options|=HA_OPTION_PACK_KEYS;		/* Using packed keys */
-	  min_key_length_skipp+=keyseg->length;
+	  min_key_length_skip+=keyseg->length;
 	  if (keyseg->length >= 255)
 	  {					/* prefix may be 3 bytes */
-	    min_key_length_skipp+=2;
+	    min_key_length_skip+=2;
 	    length+=2;
 	  }
 	}
@@ -395,7 +395,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
     }
     set_if_bigger(max_key_block_length,keydef->block_length);
     keydef->keylength= (uint16) key_length;
-    keydef->minlength= (uint16) (length-min_key_length_skipp);
+    keydef->minlength= (uint16) (length-min_key_length_skip);
     keydef->maxlength= (uint16) length;
 
     if (length > max_key_length)
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index e1bfe4c3ac5..079779bd0ef 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -1248,7 +1248,7 @@ err:
 
 int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
 				register my_off_t filepos,
-				my_bool skipp_deleted_blocks)
+				my_bool skip_deleted_blocks)
 {
   int flag,info_read,save_errno;
   uint left_len,b_type;
@@ -1299,7 +1299,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
     {
       if (_mi_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
 			 sizeof(block_info.header),
-			 (!flag && skipp_deleted_blocks ? READING_NEXT : 0) |
+			 (!flag && skip_deleted_blocks ? READING_NEXT : 0) |
 			 READING_HEADER))
 	goto panic;
       b_type=_mi_get_block_info(&block_info,-1,filepos);
@@ -1318,7 +1318,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
 		  BLOCK_FATAL_ERROR))
     {
       if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
-	  && skipp_deleted_blocks)
+	  && skip_deleted_blocks)
       {
 	filepos=block_info.filepos+block_info.block_len;
 	block_info.second_read=0;
@@ -1374,7 +1374,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
       {
 	if (_mi_read_cache(&info->rec_cache,(byte*) to,filepos,
 			   block_info.data_len,
-			   (!flag && skipp_deleted_blocks) ? READING_NEXT :0))
+			   (!flag && skip_deleted_blocks) ? READING_NEXT :0))
 	  goto panic;
       }
       else
@@ -1391,7 +1391,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf,
     if (flag++ == 0)
     {
       info->nextpos=block_info.filepos+block_info.block_len;
-      skipp_deleted_blocks=0;
+      skip_deleted_blocks=0;
     }
     left_len-=block_info.data_len;
     to+=block_info.data_len;
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index b21bf0b2163..94eb2de17e2 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -32,7 +32,7 @@
 		     (BU)->current_byte & ((mi_bit_type) 1 << --(BU)->bits) :\
 		     (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,\
 		      (BU)->current_byte & ((mi_bit_type) 1 << (BITS_SAVED-1))))
-#define skipp_to_next_byte(BU) ((BU)->bits&=~7)
+#define skip_to_next_byte(BU) ((BU)->bits&=~7)
 #define get_bits(BU,count) (((BU)->bits >= count) ? (((BU)->current_byte >> ((BU)->bits-=count)) & mask[count]) : fill_and_get_bits(BU,count))
 
 #define decode_bytes_test_bit(bit) \
@@ -58,9 +58,9 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))(MI_COLUMNDEF *field,
 						    MI_BIT_BUFF *buff,
 						    uchar *to,
 						    uchar *end);
-static void uf_zerofill_skipp_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
+static void uf_zerofill_skip_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
 				   uchar *to,uchar *end);
-static void uf_skipp_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
+static void uf_skip_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
 			  uchar *to,uchar *end);
 static void uf_space_normal(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
 			    uchar *to,uchar *end);
@@ -210,7 +210,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
 								huff_tree_bits);
     share->rec[i].unpack=get_unpack_function(share->rec+i);
   }
-  skipp_to_next_byte(&bit_buff);
+  skip_to_next_byte(&bit_buff);
   decode_table=share->decode_tables;
   for (i=0 ; i < trees ; i++)
     read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
@@ -291,7 +291,7 @@ static void read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
     else
       *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
   }
-  skipp_to_next_byte(bit_buff);
+  skip_to_next_byte(bit_buff);
 
   decode_tree->table= *decode_table;
   decode_tree->intervalls= *intervall_buff;
@@ -468,8 +468,8 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
   switch (rec->base_type) {
   case FIELD_SKIP_ZERO:
     if (rec->pack_type & PACK_TYPE_ZERO_FILL)
-      return &uf_zerofill_skipp_zero;
-    return &uf_skipp_zero;
+      return &uf_zerofill_skip_zero;
+    return &uf_skip_zero;
   case FIELD_NORMAL:
     if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
       return &uf_space_normal;
@@ -515,7 +515,7 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
 
 	/* De different functions to unpack a field */
 
-static void uf_zerofill_skipp_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
+static void uf_zerofill_skip_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
 				   uchar *to, uchar *end)
 {
   if (get_bit(bit_buff))
@@ -528,7 +528,7 @@ static void uf_zerofill_skipp_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
   }
 }
 
-static void uf_skipp_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
+static void uf_skip_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, uchar *to,
 			  uchar *end)
 {
   if (get_bit(bit_buff))
diff --git a/myisam/mi_rrnd.c b/myisam/mi_rrnd.c
index 29f686b0456..f6a2f021662 100644
--- a/myisam/mi_rrnd.c
+++ b/myisam/mi_rrnd.c
@@ -32,14 +32,14 @@
 
 int mi_rrnd(MI_INFO *info, byte *buf, register my_off_t filepos)
 {
-  my_bool skipp_deleted_blocks;
+  my_bool skip_deleted_blocks;
   DBUG_ENTER("mi_rrnd");
 
-  skipp_deleted_blocks=0;
+  skip_deleted_blocks=0;
 
   if (filepos == HA_OFFSET_ERROR)
   {
-    skipp_deleted_blocks=1;
+    skip_deleted_blocks=1;
     if (info->lastpos == HA_OFFSET_ERROR)	/* First read ? */
       filepos= info->s->pack.header_length;	/* Read first record */
     else
@@ -56,5 +56,5 @@ int mi_rrnd(MI_INFO *info, byte *buf, register my_off_t filepos)
   if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
     DBUG_RETURN(my_errno);
 
-  DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skipp_deleted_blocks));
+  DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skip_deleted_blocks));
 }
diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c
index 9afebce2ae6..8f5cde45e24 100644
--- a/myisam/mi_statrec.c
+++ b/myisam/mi_statrec.c
@@ -202,7 +202,7 @@ int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
 
 int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
 			       register my_off_t filepos,
-			       my_bool skipp_deleted_blocks)
+			       my_bool skip_deleted_blocks)
 {
   int locked,error,cache_read;
   uint cache_length;
@@ -212,13 +212,13 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
   cache_read=0;
   cache_length=0;
   if (info->opt_flag & WRITE_CACHE_USED &&
-      (info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) &&
+      (info->rec_cache.pos_in_file <= filepos || skip_deleted_blocks) &&
       flush_io_cache(&info->rec_cache))
     DBUG_RETURN(my_errno);
   if (info->opt_flag & READ_CACHE_USED)
   {						/* Cache in use */
     if (filepos == my_b_tell(&info->rec_cache) &&
-	(skipp_deleted_blocks || !filepos))
+	(skip_deleted_blocks || !filepos))
     {
       cache_read=1;				/* Read record using cache */
       cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 64ffbe2db1d..77c4d3dfbad 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -318,7 +318,7 @@ static int run_test(const char *filename)
   return (0);
 err:
   printf("got error: %3d when using myisam-database\n",my_errno);
-  return 1;			/* skipp warning */
+  return 1;			/* skip warning */
 }
 
 
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 93edde33bdb..b6d862e38b5 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -1071,7 +1071,7 @@ test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
 {
   int min_pos;
   uint length_bits,i;
-  my_off_t space_count,min_space_count,min_pack,new_length,skipp;
+  my_off_t space_count,min_space_count,min_pack,new_length,skip;
 
   length_bits=max_bit(max_space_length);
 
@@ -1091,15 +1091,15 @@ test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
     min_space_count=space_count;
   }
 	/* Test with length-flag */
-  for (skipp=0L, i=0 ; i < 8 ; i++)
+  for (skip=0L, i=0 ; i < 8 ; i++)
   {
     if (space_counts[i])
     {
       if (i)
 	huff_counts->counts[(uint) ' ']+=space_counts[i];
-      skipp+=huff_counts->pre_space[i];
+      skip+=huff_counts->pre_space[i];
       new_length=calc_packed_length(huff_counts,0)+
-	(records+(records-skipp)*(1+length_bits))/8;
+	(records+(records-skip)*(1+length_bits))/8;
       if (new_length < min_pack)
       {
 	min_pos=(int) i;
diff --git a/myisam/rt_test.c b/myisam/rt_test.c
index 61890bfded1..bbeb8fce2d1 100644
--- a/myisam/rt_test.c
+++ b/myisam/rt_test.c
@@ -307,7 +307,7 @@ int run_test(const char *filename)
   
 err:
   printf("got error: %3d when using myisam-database\n",my_errno);
-  return 1;           /* skipp warning */
+  return 1;           /* skip warning */
 }
 
 
diff --git a/myisam/sp_test.c b/myisam/sp_test.c
index 16a97771887..5cbf5e87579 100644
--- a/myisam/sp_test.c
+++ b/myisam/sp_test.c
@@ -283,7 +283,7 @@ int run_test(const char *filename)
   
 err:
   printf("got error: %3d when using myisam-database\n",my_errno);
-  return 1;           /* skipp warning */
+  return 1;           /* skip warning */
 }
 
 
diff --git a/mysys/default.c b/mysys/default.c
index d27efce27ed..a01ed4dd39f 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -224,7 +224,7 @@ int load_defaults(const char *conf_file, const char **groups,
   if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
   {
     found_print_defaults=1;
-    --*argc; ++*argv;				/* skipp argument */
+    --*argc; ++*argv;				/* skip argument */
   }
 
   if (*argc)
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 1dd3108e151..f64dc5abf2d 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -829,7 +829,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
     next_pos_in_file=(info->pos_in_file+ (uint)
 		      (info->read_end - info->request_pos));
 
-	/* If reading large blocks, or first read or read with skipp */
+	/* If reading large blocks, or first read or read with skip */
   if (Count)
   {
     if (next_pos_in_file == info->end_of_file)
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index e2e811fe89a..638bbaf7baf 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -146,7 +146,7 @@ uint cleanup_dirname(register my_string to, const char *from)
     if (*pos == FN_LIBCHAR)
     {
       if ((uint) (pos-start) > length && bcmp(pos-length,parent,length) == 0)
-      {						/* If .../../; skipp prev */
+      {						/* If .../../; skip prev */
 	pos-=length;
 	if (pos != start)
 	{					 /* not /../ */
diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c
index c2a103688f2..1a01388a3db 100644
--- a/mysys/mf_wcomp.c
+++ b/mysys/mf_wcomp.c
@@ -49,7 +49,7 @@ int wild_compare(register const char *str, register const char *wildstr,
     if (*wildstr++ == wild_one)
     {
       if (! *str || (str_is_pattern && *str == wild_many))
-        DBUG_RETURN(1);                     /* One char; skipp */
+        DBUG_RETURN(1);                     /* One char; skip */
       if (*str++ == wild_prefix && str_is_pattern && *str)
         str++;
     }
diff --git a/mysys/typelib.c b/mysys/typelib.c
index e4eda5bd675..9aaf97d143f 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -66,7 +66,7 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name)
     if (! *j)
     {
       while (*i == ' ')
-	i++;					/* skipp_end_space */
+	i++;					/* skip_end_space */
       if (! *i)
 	DBUG_RETURN(pos+1);
     }
diff --git a/sql/filesort.cc b/sql/filesort.cc
index b69aaf44e46..43a99a36287 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -399,7 +399,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
     }
     if (error == 0)
       param->examined_rows++;
-    if (error == 0 && (!select || select->skipp_record() == 0))
+    if (error == 0 && (!select || select->skip_record() == 0))
     {
       if (idx == param->keys)
       {
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5420a8f69e4..f5922d03868 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -780,7 +780,7 @@ redo:
           register char *i,*j;
           i=(char*) ptr+1; j=(char*) search+1;
           while (j != search_end)
-            if (*i++ != *j++) goto skipp;
+            if (*i++ != *j++) goto skip;
           offset= (int) (ptr-res->ptr());
           if (res->length()-from_length + to_length >
 	      current_thd->variables.max_allowed_packet)
@@ -794,7 +794,7 @@ redo:
 	  offset+=(int) to_length;
           goto redo;
         }
-skipp:
+skip:
         if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
         else ++ptr;
     }
@@ -1089,13 +1089,13 @@ String *Item_func_substr_index::val_str(String *str)
 	  register char *i,*j;
 	  i=(char*) ptr+1; j=(char*) search+1;
 	  while (j != search_end)
-	    if (*i++ != *j++) goto skipp;
+	    if (*i++ != *j++) goto skip;
 	  if (pass==0) ++n;
 	  else if (!--c) break;
 	  ptr+=delimeter_length;
 	  continue;
 	}
-    skipp:
+    skip:
         if ((l=my_ismbchar(res->charset(), ptr,strend))) ptr+=l;
         else ++ptr;
       } /* either not found or got total number when count<0 */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 36c7c9c364c..53cf792a86c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5919,7 +5919,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
       {
 	if (my_toupper(mysqld_charset,*i++) !=
             my_toupper(mysqld_charset,*j++))
-	  goto skipp;
+	  goto skip;
       }
       found_int=bit;
       if (! *i)
@@ -5931,7 +5931,7 @@ static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
       {
 	found_count++;				// Could be one of two values
       }
-skipp: ;
+skip: ;
     }
     if (found_count != 1)
       DBUG_RETURN(~(ulong) 0);				// No unique value
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 1c209dc7027..c413b1f4021 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -129,7 +129,7 @@ class SQL_SELECT :public Sql_alloc {
   ~SQL_SELECT();
   bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
   { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; }
-  inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
+  inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; }
   int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
 			ha_rows limit, bool force_quick_range=0);
 };
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 9ac7b7596fe..ed9136a6d5b 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -159,7 +159,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
 	 !thd->net.report_error)
   {
     // thd->net.report_error is tested to disallow delete row on error
-    if (!(select && select->skipp_record())&& !thd->net.report_error )
+    if (!(select && select->skip_record())&& !thd->net.report_error )
     {
       if (!(error=table->file->delete_row(table->record[0])))
       {
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 015d329cc7f..ad5799f4c42 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -82,7 +82,7 @@ static int do_select(JOIN *join,List *fields,TABLE *tmp_table,
 		     Procedure *proc);
 static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
 static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
-static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last);
+static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
 static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
 static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
 static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
@@ -5759,14 +5759,14 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
 
 
 static int
-flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
+flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
 {
   int error;
   READ_RECORD *info;
 
   if (!join_tab->cache.records)
     return 0;				/* Nothing to do */
-  if (skipp_last)
+  if (skip_last)
     (void) store_record_in_cache(&join_tab->cache); // Must save this for later
   if (join_tab->use_quick == 2)
   {
@@ -5800,21 +5800,21 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
     }
     SQL_SELECT *select=join_tab->select;
     if (!error && (!join_tab->cache.select ||
-		   !join_tab->cache.select->skipp_record()))
+		   !join_tab->cache.select->skip_record()))
     {
       uint i;
       reset_cache(&join_tab->cache);
-      for (i=(join_tab->cache.records- (skipp_last ? 1 : 0)) ; i-- > 0 ;)
+      for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
       {
 	read_cached_record(join_tab);
-	if (!select || !select->skipp_record())
+	if (!select || !select->skip_record())
 	  if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
 	    return error; /* purecov: inspected */
       }
     }
   } while (!(error=info->read_record(info)));
 
-  if (skipp_last)
+  if (skip_last)
     read_cached_record(join_tab);		// Restore current record
   reset_cache(&join_tab->cache);
   join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 42e700b27aa..7f26a0febda 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -521,7 +521,7 @@ int String::strstr(const String &s,uint32 offset)
     register const char *search=s.ptr();
     const char *end=Ptr+str_length-s.length()+1;
     const char *search_end=s.ptr()+s.length();
-skipp:
+skip:
     while (str != end)
     {
       if (*str++ == *search)
@@ -529,7 +529,7 @@ skipp:
 	register char *i,*j;
 	i=(char*) str; j=(char*) search+1;
 	while (j != search_end)
-	  if (*i++ != *j++) goto skipp;
+	  if (*i++ != *j++) goto skip;
 	return (int) (str-Ptr) -1;
       }
     }
@@ -553,7 +553,7 @@ int String::strstr_case(const String &s,uint32 offset)
     register const char *search=s.ptr();
     const char *end=Ptr+str_length-s.length()+1;
     const char *search_end=s.ptr()+s.length();
-skipp:
+skip:
     while (str != end)
     {
       if (str_charset->sort_order[*str++] == str_charset->sort_order[*search])
@@ -563,7 +563,7 @@ skipp:
 	while (j != search_end)
 	  if (str_charset->sort_order[*i++] != 
               str_charset->sort_order[*j++]) 
-            goto skipp;
+            goto skip;
 	return (int) (str-Ptr) -1;
       }
     }
@@ -586,7 +586,7 @@ int String::strrstr(const String &s,uint32 offset)
 
     const char *end=Ptr+s.length()-2;
     const char *search_end=s.ptr()-1;
-skipp:
+skip:
     while (str != end)
     {
       if (*str-- == *search)
@@ -594,7 +594,7 @@ skipp:
 	register char *i,*j;
 	i=(char*) str; j=(char*) search-1;
 	while (j != search_end)
-	  if (*i-- != *j--) goto skipp;
+	  if (*i-- != *j--) goto skip;
 	return (int) (i-Ptr) +1;
       }
     }
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 8ee00f2bca6..c6e470fd09f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -245,7 +245,7 @@ int mysql_update(THD *thd,
 
       while (!(error=info.read_record(&info)) && !thd->killed)
       {
-	if (!(select && select->skipp_record()))
+	if (!(select && select->skip_record()))
 	{
 	  table->file->position(table->record[0]);
 	  if (my_b_write(&tempfile,table->file->ref,
@@ -302,7 +302,7 @@ int mysql_update(THD *thd,
 
   while (!(error=info.read_record(&info)) && !thd->killed)
   {
-    if (!(select && select->skipp_record()))
+    if (!(select && select->skip_record()))
     {
       store_record(table,record[1]);
       if (fill_record(fields,values, 0) || thd->net.report_error)
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 67435b7df6c..43575bbc277 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -294,7 +294,7 @@ uint my_instr_bin(CHARSET_INFO *cs __attribute__((unused)),
     end= (const uchar*) b+b_length-s_length+1;
     search_end= (const uchar*) s + s_length;
 
-skipp:
+skip:
     while (str != end)
     {
       if ( (*str++) == (*search))
@@ -306,7 +306,7 @@ skipp:
 
 	while (j != search_end)
 	  if ((*i++) != (*j++))
-            goto skipp;
+            goto skip;
 
         if (nmatch > 0)
 	{
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index 6f77d6f3e16..62eb1418970 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1055,7 +1055,7 @@ uint my_instr_simple(CHARSET_INFO *cs,
     end= (const uchar*) b+b_length-s_length+1;
     search_end= (const uchar*) s + s_length;
     
-skipp:
+skip:
     while (str != end)
     {
       if (cs->sort_order[*str++] == cs->sort_order[*search])
@@ -1067,7 +1067,7 @@ skipp:
 	
 	while (j != search_end)
 	  if (cs->sort_order[*i++] != cs->sort_order[*j++]) 
-            goto skipp;
+            goto skip;
         
 	if (nmatch > 0)
 	{
diff --git a/strings/r_strinstr.c b/strings/r_strinstr.c
index 76d310a3fda..fdd6e010a22 100644
--- a/strings/r_strinstr.c
+++ b/strings/r_strinstr.c
@@ -35,7 +35,7 @@ uint r_strinstr(reg1 my_string str,int from, reg4 my_string search)
   /* pointer to the last char of search */
   my_string	search_end = search + len - 1;
 
- skipp:
+ skip:
   while (start >= str)		/* Cant be != because the first char */
   {
     if (*start-- == *search_end)
@@ -43,7 +43,7 @@ uint r_strinstr(reg1 my_string str,int from, reg4 my_string search)
       i = start; j = search_end - 1;
       while (j >= search && start > str)
 	if (*i-- != *j--)
-	  goto skipp;
+	  goto skip;
       return (uint) ((start - len) - str + 3);
     }
   }
diff --git a/strings/strinstr.c b/strings/strinstr.c
index 1c814d19d47..457581af950 100644
--- a/strings/strinstr.c
+++ b/strings/strinstr.c
@@ -34,14 +34,14 @@ uint strinstr(reg1 const char *str,reg4 const char *search)
   reg2 my_string i,j;
   my_string start = (my_string) str;
 
- skipp:
+ skip:
   while (*str != '\0')
   {
     if (*str++ == *search)
     {
       i=(my_string) str; j= (my_string) search+1;
       while (*j)
-	if (*i++ != *j++) goto skipp;
+	if (*i++ != *j++) goto skip;
       return ((uint) (str - start));
     }
   }
diff --git a/strings/strstr.c b/strings/strstr.c
index ca845568ddb..bd65ef654b1 100644
--- a/strings/strstr.c
+++ b/strings/strstr.c
@@ -37,12 +37,12 @@ char *strstr(register const char *str,const char *search)
  register char *i,*j;
  register char first= *search;
 
-skipp:
+skip:
   while (*str != '\0') {
     if (*str++ == first) {
       i=(char*) str; j=(char*) search+1;
       while (*j)
-	if (*i++ != *j++) goto skipp;
+	if (*i++ != *j++) goto skip;
       return ((char*) str-1);
     }
   }

From bbdba29229f561e9ca5ba9ff828efb5f933ffe67 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 3 Feb 2004 01:07:43 +0400
Subject: [PATCH 132/157] changed allocation of st_table::insert_values from
 table->mem_root to thd->mem_root (fixed bug #2438 "Runaway memory
 consumption")

---
 sql/sql_insert.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c2f3e737daf..74de1772555 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -198,7 +198,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
   if (duplic == DUP_UPDATE && !table->insert_values)
   {
     /* it should be allocated before Item::fix_fields() */
-    table->insert_values=(byte *)alloc_root(&table->mem_root, table->rec_buff_length);
+    table->insert_values= 
+      (byte *)alloc_root(&thd->mem_root, table->rec_buff_length);
     if (!table->insert_values)
       goto abort;
   }

From 453a32e92720f4b3bb504d88c70433333190f174 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 3 Feb 2004 14:35:24 +0400
Subject: [PATCH 133/157] Code cleanup: we don't need opt_range.h and
 opt_range.cc files at all.

BitKeeper/deleted/.del-opt_ft.cc~2048ffa561f9c59:
  Delete: sql/opt_ft.cc
BitKeeper/deleted/.del-opt_ft.h~24aac1d29304599a:
  Delete: sql/opt_ft.h
---
 libmysqld/Makefile.am |  2 +-
 sql/Makefile.am       |  4 ++--
 sql/opt_ft.cc         | 36 ------------------------------------
 sql/opt_ft.h          | 41 -----------------------------------------
 sql/opt_range.h       | 11 +++++++++++
 sql/sql_select.cc     |  7 +++----
 6 files changed, 17 insertions(+), 84 deletions(-)
 delete mode 100644 sql/opt_ft.cc
 delete mode 100644 sql/opt_ft.h

diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index f9e73d1e219..da58a711d22 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -46,7 +46,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
 	item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
 	item_geofunc.cc item_uniq.cc item_subselect.cc item_row.cc\
 	key.cc lock.cc log.cc log_event.cc sql_state.c \
-	protocol.cc net_serv.cc opt_ft.cc opt_range.cc \
+	protocol.cc net_serv.cc opt_range.cc \
 	opt_sum.cc procedure.cc records.cc sql_acl.cc \
 	sql_load.cc sql_olap.cc \
 	sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
diff --git a/sql/Makefile.am b/sql/Makefile.am
index e2ab55da6a2..4aa6aaaa1ee 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -52,7 +52,7 @@ noinst_HEADERS =	item.h item_func.h item_sum.h item_cmpfunc.h \
 			field.h handler.h \
 			ha_isammrg.h ha_isam.h ha_myisammrg.h\
 			ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
-			opt_range.h opt_ft.h protocol.h \
+			opt_range.h protocol.h \
 			sql_select.h structs.h table.h sql_udf.h hash_filo.h\
 			lex.h lex_symbol.h sql_acl.h sql_crypt.h  \
 			log_event.h sql_repl.h slave.h \
@@ -75,7 +75,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.cc \
 			procedure.cc item_uniq.cc sql_test.cc \
 			log.cc log_event.cc init.cc derror.cc sql_acl.cc \
 			unireg.cc des_key_file.cc \
-			time.cc opt_range.cc opt_sum.cc opt_ft.cc \
+			time.cc opt_range.cc opt_sum.cc \
 		   	records.cc filesort.cc handler.cc \
 		        ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
 	                ha_berkeley.cc ha_innodb.cc \
diff --git a/sql/opt_ft.cc b/sql/opt_ft.cc
deleted file mode 100644
index 74349819937..00000000000
--- a/sql/opt_ft.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-#ifdef __GNUC__
-#pragma implementation				// gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#include "sql_select.h"
-#include "opt_ft.h"
-
-/****************************************************************************
-** Create a FT or QUICK RANGE based on a key
-****************************************************************************/
-
-QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
-					     JOIN_TAB *tab)
-{
-  if (tab->type == JT_FT)
-    return new FT_SELECT(thd, table, &tab->ref);
-  return get_quick_select_for_ref(thd, table, &tab->ref);
-}
-
diff --git a/sql/opt_ft.h b/sql/opt_ft.h
deleted file mode 100644
index 69b6b72f3fc..00000000000
--- a/sql/opt_ft.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-
-/* classes to use when handling where clause */
-
-#ifndef _opt_ft_h
-#define _opt_ft_h
-
-#ifdef __GNUC__
-#pragma interface			/* gcc class implementation */
-#endif
-
-class FT_SELECT: public QUICK_SELECT {
-public:
-  TABLE_REF *ref;
-
-  FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) :
-      QUICK_SELECT (thd, table, tref->key, 1), ref(tref) { init(); }
-
-  int init() { return error=file->ft_init(); }
-  int get_next() { return error=file->ft_read(record); }
-};
-
-QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
-					     JOIN_TAB *tab);
-
-#endif
diff --git a/sql/opt_range.h b/sql/opt_range.h
index c413b1f4021..bb1cd0f7513 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -134,6 +134,17 @@ class SQL_SELECT :public Sql_alloc {
 			ha_rows limit, bool force_quick_range=0);
 };
 
+
+class FT_SELECT: public QUICK_SELECT {
+public:
+  FT_SELECT(THD *thd, TABLE *table, uint key):
+    QUICK_SELECT (thd, table, key, 1) { init(); }
+
+  int init() { return error= file->ft_init(); }
+  int get_next() { return error= file->ft_read(record); }
+};
+
+
 QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
 				       struct st_table_ref *ref);
 
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ad5799f4c42..1c734a2b625 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -24,8 +24,6 @@
 #include "mysql_priv.h"
 #include "sql_select.h"
 
-#include "opt_ft.h"
-
 #include 
 #include 
 #include 
@@ -7203,8 +7201,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
 	For impossible ranges (like when doing a lookup on NULL on a NOT NULL
 	field, quick will contain an empty record set.
       */
-      if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd,
-							 table, tab)))
+      if (!(select->quick= tab->type == JT_FT ?
+			   new FT_SELECT(thd, table, tab->ref.key) :
+			   get_quick_select_for_ref(thd, table, &tab->ref)))
 	goto err;
     }
   }

From 786a5b6bc3a5de8dcd44b1d10b64c8799ceebbca Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 3 Feb 2004 18:14:23 +0400
Subject: [PATCH 134/157] Bug #2619  	ucs2 LIKE comparison fails in some
 cases

---
 mysql-test/r/func_like.result | 30 ++++++++++++++++++++++++++++++
 mysql-test/t/func_like.test   | 19 +++++++++++++++++++
 sql/item_cmpfunc.cc           | 12 ++++++------
 3 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index cf07ba88477..085e2f2f37e 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -104,3 +104,33 @@ a
 ΖΩΧΑΠΟΜΔφ
 ζωχαπςομδφ
 DROP TABLE t1;
+SET NAMES cp1250;
+CREATE TABLE t1 (a varchar(250) NOT NULL) DEFAULT CHARACTER SET=cp1250;
+INSERT INTO t1 VALUES
+('Techni Tapes Sp. z o.o.'),
+('Pojazdy Szynowe PESA Bydgoszcz SA Holding'),
+('AKAPESTER 1 P.P.H.U.'),
+('Pojazdy Szynowe PESA Bydgoszcz S A Holding'),
+('PPUH PESKA-I Maria Struniarska');
+select * from t1 where a like '%PESA%';
+a
+Pojazdy Szynowe PESA Bydgoszcz SA Holding
+Pojazdy Szynowe PESA Bydgoszcz S A Holding
+select * from t1 where a like '%PESA %';
+a
+Pojazdy Szynowe PESA Bydgoszcz SA Holding
+Pojazdy Szynowe PESA Bydgoszcz S A Holding
+select * from t1 where a like '%PES%';
+a
+Techni Tapes Sp. z o.o.
+Pojazdy Szynowe PESA Bydgoszcz SA Holding
+AKAPESTER 1 P.P.H.U.
+Pojazdy Szynowe PESA Bydgoszcz S A Holding
+PPUH PESKA-I Maria Struniarska
+select * from t1 where a like '%PESKA%';
+a
+PPUH PESKA-I Maria Struniarska
+select * from t1 where a like '%ESKA%';
+a
+PPUH PESKA-I Maria Struniarska
+DROP TABLE t1;
diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test
index 0cd85385df4..a05a2a3bdaa 100644
--- a/mysql-test/t/func_like.test
+++ b/mysql-test/t/func_like.test
@@ -44,3 +44,22 @@ SELECT * FROM t1 WHERE a LIKE '%
 SELECT * FROM t1 WHERE a LIKE 'ΖωΧΑ%';
 
 DROP TABLE t1;
+
+# Bug #2547 Strange "like" behaviour in tables with default charset=cp1250
+# Test like with non-default character set using TurboBM
+#
+SET NAMES cp1250;
+CREATE TABLE t1 (a varchar(250) NOT NULL) DEFAULT CHARACTER SET=cp1250;
+INSERT INTO t1 VALUES
+('Techni Tapes Sp. z o.o.'),
+('Pojazdy Szynowe PESA Bydgoszcz SA Holding'),
+('AKAPESTER 1 P.P.H.U.'),
+('Pojazdy Szynowe PESA Bydgoszcz S A Holding'),
+('PPUH PESKA-I Maria Struniarska');
+
+select * from t1 where a like '%PESA%';
+select * from t1 where a like '%PESA %';
+select * from t1 where a like '%PES%';
+select * from t1 where a like '%PESKA%';
+select * from t1 where a like '%ESKA%';
+DROP TABLE t1;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 0b9c7f8d92a..59fd180c79f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2197,11 +2197,11 @@ void Item_func_like::turboBM_compute_suffixes(int *suff)
   int            f = 0;
   int            g = plm1;
   int *const splm1 = suff + plm1;
-  CHARSET_INFO	*cs=system_charset_info;	// QQ Needs to be fixed
+  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
 
   *splm1 = pattern_len;
 
-  if (cmp.cmp_collation.collation == &my_charset_bin)
+  if (cs == &my_charset_bin)
   {
     int i;
     for (i = pattern_len - 2; i >= 0; i--)
@@ -2299,12 +2299,12 @@ void Item_func_like::turboBM_compute_bad_character_shifts()
   int *end = bmBc + alphabet_size;
   int j;
   const int plm1 = pattern_len - 1;
-  CHARSET_INFO	*cs=system_charset_info;	// QQ Needs to be fixed
+  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
 
   for (i = bmBc; i < end; i++)
     *i = pattern_len;
 
-  if (cmp.cmp_collation.collation == &my_charset_bin)
+  if (cs == &my_charset_bin)
   {
     for (j = 0; j < plm1; j++)
       bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
@@ -2329,13 +2329,13 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
   int shift = pattern_len;
   int j     = 0;
   int u     = 0;
-  CHARSET_INFO	*cs= cmp.cmp_collation.collation;	// QQ Needs to be fixed
+  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
 
   const int plm1=  pattern_len - 1;
   const int tlmpl= text_len - pattern_len;
 
   /* Searching */
-  if (cmp.cmp_collation.collation == &my_charset_bin)
+  if (cs == &my_charset_bin)
   {
     while (j <= tlmpl)
     {

From f0a715f3adf1f1b975545e69c3758dd39afbbd39 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 3 Feb 2004 23:34:31 +0300
Subject: [PATCH 135/157] cleanup: #ifdef DELETE_ITEMS removed

sql/item.cc:
  #ifdef DELETE_ITEMS removed
sql/item_cmpfunc.cc:
  #ifdef DELETE_ITEMS removed
sql/sql_parse.cc:
  #ifdef DELETE_ITEMS removed
sql/sql_select.cc:
  #ifdef DELETE_ITEMS removed
---
 sql/item.cc         | 14 --------------
 sql/item_cmpfunc.cc |  3 ---
 sql/sql_parse.cc    |  4 ----
 sql/sql_select.cc   |  8 --------
 4 files changed, 29 deletions(-)

diff --git a/sql/item.cc b/sql/item.cc
index 09328dfbf07..4d06d0d7765 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1779,17 +1779,9 @@ Item *resolve_const_item(Item *item,Item *comp_item)
     String tmp(buff,sizeof(buff),&my_charset_bin),*result;
     result=item->val_str(&tmp);
     if (item->null_value)
-    {
-#ifdef DELETE_ITEMS
-      delete item;
-#endif
       return new Item_null(name);
-    }
     uint length=result->length();
     char *tmp_str=sql_strmake(result->ptr(),length);
-#ifdef DELETE_ITEMS
-    delete item;
-#endif
     return new Item_string(name,tmp_str,length,result->charset());
   }
   if (res_type == INT_RESULT)
@@ -1797,9 +1789,6 @@ Item *resolve_const_item(Item *item,Item *comp_item)
     longlong result=item->val_int();
     uint length=item->max_length;
     bool null_value=item->null_value;
-#ifdef DELETE_ITEMS
-    delete item;
-#endif
     return (null_value ? (Item*) new Item_null(name) :
 	    (Item*) new Item_int(name,result,length));
   }
@@ -1808,9 +1797,6 @@ Item *resolve_const_item(Item *item,Item *comp_item)
     double result=item->val();
     uint length=item->max_length,decimals=item->decimals;
     bool null_value=item->null_value;
-#ifdef DELETE_ITEMS
-    delete item;
-#endif
     return (null_value ? (Item*) new Item_null(name) :
 	    (Item*) new Item_real(name,result,decimals,length));
   }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 59fd180c79f..55d511bb39d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1703,9 +1703,6 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
     {						// Identical function
       li.replace(((Item_cond*) item)->list);
       ((Item_cond*) item)->list.empty();
-#ifdef DELETE_ITEMS
-      delete (Item_cond*) item;
-#endif
       item= *li.ref();				// new current item
     }
     if (abort_on_null)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2e728e4ae6d..9d742995976 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1899,10 +1899,6 @@ mysql_execute_command(THD *thd)
 	  if (!(result=new select_send()))
 	  {
 	    res= -1;
-#ifdef DELETE_ITEMS
-	    delete select_lex->having;
-	    delete select_lex->where;
-#endif
 	    break;
 	  }
 	}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1c734a2b625..aeaad4559e2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4395,17 +4395,9 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
     {
       Item *new_item=remove_eq_conds(item,&tmp_cond_value);
       if (!new_item)
-      {
-#ifdef DELETE_ITEMS
-	delete item;				// This may be shared
-#endif
 	li.remove();
-      }
       else if (item != new_item)
       {
-#ifdef DELETE_ITEMS
-	delete item;				// This may be shared
-#endif
 	VOID(li.replace(new_item));
 	should_fix_fields=1;
       }

From 7f6f30284e8834985884578dc723582e1e266aea Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 4 Feb 2004 12:49:54 +0400
Subject: [PATCH 136/157] Client character set is now not set from the server
 value.

---
 mysql-test/r/ctype_latin1_de.result |  2 +
 mysql-test/t/ctype_latin1_de.test   |  3 ++
 sql-common/client.c                 | 63 ++++++++++++-----------------
 3 files changed, 30 insertions(+), 38 deletions(-)

diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index 7f150cb0698..c500019042f 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -1,3 +1,5 @@
+set names latin1;
+set @@collation_connection=latin1_german2_ci;
 select @@collation_connection;
 @@collation_connection
 latin1_german2_ci
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index a5d0c29baf6..e29e43496af 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -2,6 +2,9 @@
 # Test latin_de character set
 #
 
+set names latin1;
+set @@collation_connection=latin1_german2_ci;
+
 select @@collation_connection;
 
 --disable_warnings
diff --git a/sql-common/client.c b/sql-common/client.c
index 08b39d2ca58..1c58bd04d0e 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1429,14 +1429,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 		       const char *passwd, const char *db,
 		       uint port, const char *unix_socket,ulong client_flag)
 {
-  char		buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16];
-  char		*end,*host_info,*charset_name;
+  char		buff[NAME_LEN+USERNAME_LENGTH+100];
+  char		*end,*host_info;
   my_socket	sock;
   in_addr_t	ip_addr;
   struct	sockaddr_in sock_addr;
   ulong		pkt_length;
   NET		*net= &mysql->net;
-  uint		charset_number;
 #ifdef MYSQL_SERVER
   thr_alarm_t   alarmed;
   ALARM		alarm_buff;
@@ -1762,10 +1761,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
     goto error;
   }
 
-  charset_number= mysql->server_language;
-
   /* Set character set */
-  if ((charset_name=mysql->options.charset_name))
+  if (mysql->options.charset_name)
   {
     const char *save= charsets_dir;
     if (mysql->options.charset_dir)
@@ -1773,44 +1770,34 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
     mysql->charset=get_charset_by_csname(mysql->options.charset_name,
 					 MY_CS_PRIMARY,
 					 MYF(MY_WME));
-    charset_number= mysql->charset ? mysql->charset->number : 0;
     charsets_dir= save;
-  }
-  else if (mysql->server_language)
-  {
-    charset_name=charset_name_buff;
-    /* Save name in case of errors */
-    int10_to_str(mysql->server_language, charset_name, 10);
-    if (!(mysql->charset =
-	  get_charset((uint8) mysql->server_language, MYF(0))))
-      mysql->charset = default_charset_info; /* shouldn't be fatal */
+
+    if (!mysql->charset)
+    {
+      net->last_errno=CR_CANT_READ_CHARSET;
+      strmov(net->sqlstate, unknown_sqlstate);
+      if (mysql->options.charset_dir)
+        my_snprintf(net->last_error, sizeof(net->last_error)-1,
+		    ER(net->last_errno),
+		    mysql->options.charset_name,
+		    mysql->options.charset_dir);
+      else
+      {
+        char cs_dir_name[FN_REFLEN];
+        get_charsets_dir(cs_dir_name);
+        my_snprintf(net->last_error, sizeof(net->last_error)-1,
+		  ER(net->last_errno),
+		  mysql->options.charset_name,
+		  cs_dir_name);
+      }
+      goto error;
+    }
   }
   else
   {
     mysql->charset= default_charset_info;
-    charset_number= mysql->charset->number;
   }
 
-  if (!mysql->charset)
-  {
-    net->last_errno=CR_CANT_READ_CHARSET;
-    strmov(net->sqlstate, unknown_sqlstate);
-    if (mysql->options.charset_dir)
-      my_snprintf(net->last_error, sizeof(net->last_error)-1,
-		  ER(net->last_errno),
-		  charset_name ? charset_name : "unknown",
-		  mysql->options.charset_dir);
-    else
-    {
-      char cs_dir_name[FN_REFLEN];
-      get_charsets_dir(cs_dir_name);
-      my_snprintf(net->last_error, sizeof(net->last_error)-1,
-		  ER(net->last_errno),
-		  charset_name ? charset_name : "unknown",
-		  cs_dir_name);
-    }
-    goto error;
-  }
 
   /* Save connection information */
   if (!my_multi_malloc(MYF(0),
@@ -1870,7 +1857,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
     /* 4.1 server and 4.1 client has a 32 byte option flag */
     int4store(buff,client_flag);
     int4store(buff+4, net->max_packet_size);
-    buff[8]= (char) charset_number;
+    buff[8]= (char) mysql->charset->number;
     bzero(buff+9, 32-9);
     end= buff+32;
   }

From 03f098d57e194ea363b1985a9e2df955a312baab Mon Sep 17 00:00:00 2001
From: unknown 
Date: Wed, 4 Feb 2004 18:16:28 +0400
Subject: [PATCH 137/157] http://bugs.mysql.com/bug.php?id=2619 Bug #2619  
 ucs2 LIKE comparison fails in some cases Fixes

---
 mysql-test/r/ctype_ucs.result | 75 +++++++++++++++++++++++++++++++++++
 mysql-test/t/ctype_ucs.test   | 29 ++++++++++++++
 strings/ctype-ucs2.c          | 22 +++++-----
 3 files changed, 116 insertions(+), 10 deletions(-)

diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 8d9c7579771..30795aaf106 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -77,6 +77,9 @@ a
 test
 select * from t1 where a like "%a%";
 a
+a
+abc
+abcd
 select * from t1 where a like "%abcd%";
 a
 abcd
@@ -84,6 +87,78 @@ select * from t1 where a like "%abc\d%";
 a
 abcd
 drop table t1;
+select 'AA' like 'AA';
+'AA' like 'AA'
+1
+select 'AA' like 'A%A';
+'AA' like 'A%A'
+1
+select 'AA' like 'A%%A';
+'AA' like 'A%%A'
+1
+select 'AA' like 'AA%';
+'AA' like 'AA%'
+1
+select 'AA' like '%AA%';
+'AA' like '%AA%'
+1
+select 'AA' like '%A';
+'AA' like '%A'
+1
+select 'AA' like '%AA';
+'AA' like '%AA'
+1
+select 'AA' like 'A%A%';
+'AA' like 'A%A%'
+1
+select 'AA' like '_%_%';
+'AA' like '_%_%'
+1
+select 'AA' like '%A%A';
+'AA' like '%A%A'
+1
+select 'AAA'like 'A%A%A';
+'AAA'like 'A%A%A'
+1
+select 'AZ' like 'AZ';
+'AZ' like 'AZ'
+1
+select 'AZ' like 'A%Z';
+'AZ' like 'A%Z'
+1
+select 'AZ' like 'A%%Z';
+'AZ' like 'A%%Z'
+1
+select 'AZ' like 'AZ%';
+'AZ' like 'AZ%'
+1
+select 'AZ' like '%AZ%';
+'AZ' like '%AZ%'
+1
+select 'AZ' like '%Z';
+'AZ' like '%Z'
+1
+select 'AZ' like '%AZ';
+'AZ' like '%AZ'
+1
+select 'AZ' like 'A%Z%';
+'AZ' like 'A%Z%'
+1
+select 'AZ' like '_%_%';
+'AZ' like '_%_%'
+1
+select 'AZ' like '%A%Z';
+'AZ' like '%A%Z'
+1
+select 'AZ' like 'A_';
+'AZ' like 'A_'
+1
+select 'AZ' like '_Z';
+'AZ' like '_Z'
+1
+select 'AMZ'like 'A%M%Z';
+'AMZ'like 'A%M%Z'
+1
 CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2);
 INSERT INTO t1 VALUES ('ΖΩΧΑ'),('ζΩΧΑ'),('ΖωΧΑ'),('ΖΩχΑ'),('ΖΩΧα'),('ζωχα');
 INSERT INTO t1 VALUES ('ΖΩΧΑΠΟΜΔΦ'),('ζΩΧΑΠΟΜΔΦ'),('ΖωΧΑΠΟΜΔΦ'),('ΖΩχΑΠΟΜΔΦ');
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 021147e258a..5b1a5923ad4 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -69,6 +69,35 @@ select * from t1 where a like "%abcd%";
 select * from t1 where a like "%abc\d%";
 drop table t1;
 
+#
+# More LIKE test: bug#2619
+#
+select 'AA' like 'AA'; 
+select 'AA' like 'A%A';
+select 'AA' like 'A%%A';
+select 'AA' like 'AA%';
+select 'AA' like '%AA%';
+select 'AA' like '%A';
+select 'AA' like '%AA';
+select 'AA' like 'A%A%';
+select 'AA' like '_%_%';
+select 'AA' like '%A%A';
+select 'AAA'like 'A%A%A';
+
+select 'AZ' like 'AZ'; 
+select 'AZ' like 'A%Z';
+select 'AZ' like 'A%%Z';
+select 'AZ' like 'AZ%';
+select 'AZ' like '%AZ%';
+select 'AZ' like '%Z';
+select 'AZ' like '%AZ';
+select 'AZ' like 'A%Z%';
+select 'AZ' like '_%_%';
+select 'AZ' like '%A%Z';
+select 'AZ' like 'A_';
+select 'AZ' like '_Z';
+select 'AMZ'like 'A%M%Z';
+
 CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2);
 INSERT INTO t1 VALUES ('ΖΩΧΑ'),('ζΩΧΑ'),('ΖωΧΑ'),('ΖΩχΑ'),('ΖΩΧα'),('ζωχα');
 INSERT INTO t1 VALUES ('ΖΩΧΑΠΟΜΔΦ'),('ζΩΧΑΠΟΜΔΦ'),('ΖωΧΑΠΟΜΔΦ'),('ΖΩχΑΠΟΜΔΦ');
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index a7a59fc50f7..775501027d0 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1044,14 +1044,13 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
       scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend);
       if (scan <= 0)
         return 1;
-      wildstr+= scan;
       
       if (w_wc ==  (my_wc_t)escape)
       {
+        wildstr+= scan;
         scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend);
         if (scan <= 0)
           return 1;
-        wildstr+= scan;
       }
       
       if (w_wc == (my_wc_t)w_many)
@@ -1060,6 +1059,7 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
         break;
       }
       
+      wildstr+= scan;
       scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str, (const uchar*)str_end);
       if (scan <=0)
         return 1;
@@ -1095,13 +1095,16 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
         scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend);
         if (scan <= 0)
           return 1;
-        wildstr+= scan;
         
 	if (w_wc == (my_wc_t)w_many)
+	{
+	  wildstr+= scan;
 	  continue;
+	} 
 	
 	if (w_wc == (my_wc_t)w_one)
 	{
+	  wildstr+= scan;
 	  scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str, (const uchar*)str_end);
           if (scan <=0)
             return 1;
@@ -1120,17 +1123,16 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
       scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend);
       if (scan <= 0)
         return 1;
-      wildstr+= scan;
       
       if (w_wc ==  (my_wc_t)escape)
       {
+        wildstr+= scan;
         scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend);
         if (scan <= 0)
           return 1;
-        wildstr+= scan;
       }
       
-      do
+      while (1)
       {
         /* Skip until the first character from wildstr is found */
         while (str != str_end)
@@ -1138,8 +1140,6 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
           scan= my_ucs2_uni(cs,&s_wc, (const uchar*)str, (const uchar*)str_end);
           if (scan <= 0)
             return 1;
-          str+= scan;
-          
           if (weights)
           {
             plane=(s_wc>>8) & 0xFF;
@@ -1150,17 +1150,19 @@ int my_wildcmp_ucs2(CHARSET_INFO *cs,
           
           if (s_wc == w_wc)
             break;
+          str+= scan;
         }
         if (str == str_end)
           return -1;
         
         result= my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend,escape,
                                 w_one,w_many,weights);
+        
         if (result <= 0)
           return result;
         
-      } while (str != str_end && w_wc != (my_wc_t)w_many);
-      return -1;
+        str+= scan;
+      } 
     }
   }
   return (str != str_end ? 1 : 0);

From 7b0ee22df4c8c8fe815165191ee20d952b9f987c Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 5 Feb 2004 02:30:28 +0000
Subject: [PATCH 138/157] Bug#2634   Emit "TYPE=" for 4.0 and 3.23 compatible
 modes

mysql-test/r/mysqldump.result:
  Bug#2634
    New test case
mysql-test/t/mysqldump.test:
  Bug#2634
    New test case
---
 mysql-test/r/mysqldump.result | 37 +++++++++++++++++++++++++++++++++++
 mysql-test/t/mysqldump.test   | 10 ++++++++++
 sql/sql_show.cc               |  5 ++++-
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index f51caee39d6..bdcdb0532f7 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -123,3 +123,40 @@ UNLOCK TABLES;
 /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 
 DROP TABLE t1;
+CREATE TABLE t1 (a int) ENGINE=MYISAM;
+INSERT INTO t1 VALUES (1), (2);
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `a` int(11) default NULL
+) TYPE=MyISAM;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1),(2);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+  `a` int(11) default NULL
+) TYPE=MyISAM;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+INSERT INTO `t1` VALUES (1),(2);
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 93b0dd4a75d..9bfaaa51b09 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -53,3 +53,13 @@ CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
 --exec $MYSQL_DUMP  --skip-comments test t1
 DROP TABLE t1;
+
+#
+# Bug #2634
+#
+
+CREATE TABLE t1 (a int) ENGINE=MYISAM;
+INSERT INTO t1 VALUES (1), (2);
+--exec $MYSQL_DUMP --skip-comments --compatible=mysql40 test t1
+--exec $MYSQL_DUMP --skip-comments --compatible=mysql323 test t1
+DROP TABLE t1;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 3b937f97089..5f6167f2cd1 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1338,7 +1338,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
   packet->append("\n)", 2);
   if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
   {
-    packet->append(" ENGINE=", 8);
+    if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
+      packet->append(" TYPE=", 6);
+    else
+      packet->append(" ENGINE=", 8);
     packet->append(file->table_type());
     
     if (table->table_charset &&

From 0db0b601abb3be2fdafa612583f4e03360876236 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 5 Feb 2004 10:22:08 +0100
Subject: [PATCH 139/157] Added SQL_SELECT::cleanup() to make it easier to
 reuse SQL_SELECT item's for sub selects. Needed for proper fix for bug #2479.
 Added 'select_to_file' class to be able to merge identical code for
 select_export and select_dump

client/mysql.cc:
  Print mysql_insert_id() in 'status'
mysys/charset.c:
  after merge fixup
sql/item_func.cc:
  Code cleanup + new comments
sql/opt_range.cc:
  Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects.
sql/opt_range.h:
  Added SQL_SELECT::cleanup() to make it easier to reuse SQL_SELECT item's for sub selects.
sql/sql_class.cc:
  Added 'select_to_file' class to be able to merge identical code for select_export and select_dump
sql/sql_class.h:
  Added 'select_to_file' class to be able to merge identical code for select_export and select_dump
sql/sql_select.cc:
  Fixed bug when calling 'delete select' in sub selects. (Bug 2479)
  (Test case is already commited to global source repository)
---
 client/mysql.cc   |   8 +++-
 mysys/charset.c   |   2 -
 sql/item_func.cc  |  13 ++++--
 sql/opt_range.cc  |  21 ++++++---
 sql/opt_range.h   |   1 +
 sql/sql_class.cc  | 110 +++++++++++++++++++++++++---------------------
 sql/sql_class.h   |  58 ++++++++++++------------
 sql/sql_select.cc |  13 +++---
 8 files changed, 131 insertions(+), 95 deletions(-)

diff --git a/client/mysql.cc b/client/mysql.cc
index 2cdcd23165e..665a8dde82d 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -44,7 +44,7 @@
 #include 
 #endif
 
-const char *VER= "14.4";
+const char *VER= "14.5";
 
 /* Don't try to make a nice table if the data is too big */
 #define MAX_COLUMN_LENGTH	     1024
@@ -2703,6 +2703,9 @@ com_status(String *buffer __attribute__((unused)),
 	   char *line __attribute__((unused)))
 {
   const char *status;
+  char buff[22];
+  ulonglong id;
+
   tee_puts("--------------", stdout);
   usage(1);					/* Print version */
   if (connected)
@@ -2748,6 +2751,9 @@ com_status(String *buffer __attribute__((unused)),
   tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql));
   tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
   tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
+  if ((id= mysql_insert_id(&mysql)))
+    tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff));
+
   tee_fprintf(stdout, "Client characterset:\t%s\n",
 	      charset_info->name);
   tee_fprintf(stdout, "Server characterset:\t%s\n", mysql.charset->name);
diff --git a/mysys/charset.c b/mysys/charset.c
index c0d8b183c17..5bf0ea972a5 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -537,7 +537,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
     while we may changing the cs_info_table
   */
   pthread_mutex_lock(&THR_LOCK_charset);
-
   if ((cs= all_charsets[cs_number]))
   {
     if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED))
@@ -548,7 +547,6 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
     cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL;
   }
   pthread_mutex_unlock(&THR_LOCK_charset);
- pthread_mutex_unlock(&THR_LOCK_charset);
   return cs;
 }
 
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 802b6dbb8d6..c995b50109f 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2646,10 +2646,15 @@ longlong Item_func_inet_aton::val_int()
   }
   if (c != '.')					// IP number can't end on '.'
   {
-    switch (dot_count)
-    {
-    case 1: result<<= 8;
-    case 2: result<<= 8;
+    /*
+      Handle short-forms addresses according to standard. Examples:
+      127		-> 0.0.0.127
+      127.1		-> 127.0.0.1
+      127.2.1		-> 127.2.0.1
+    */
+    switch (dot_count) {
+    case 1: result<<= 8; /* Fall through */
+    case 2: result<<= 8; /* Fall through */
     }
     return (result << 8) + (ulonglong) byte_result;
   }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index acc23924f75..17fc948dd6e 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -369,14 +369,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0)
 }
 
 
-SQL_SELECT::~SQL_SELECT()
+void SQL_SELECT::cleanup()
 {
   delete quick;
+  quick= 0;
   if (free_cond)
+  {
+    free_cond=0;
     delete cond;
+    cond= 0;
+  }    
   close_cached_file(&file);
 }
 
+
+SQL_SELECT::~SQL_SELECT()
+{
+  cleanup();
+}
+
 #undef index					// Fix for Unixware 7
 
 QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
@@ -2180,6 +2191,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
     param->table->quick_rows[key]=records;
     param->table->quick_key_parts[key]=param->max_key_part+1;
   }
+  DBUG_PRINT("exit", ("Records: %lu", (ulong) records));
   DBUG_RETURN(records);
 }
 
@@ -2532,12 +2544,7 @@ int QUICK_SELECT::get_next()
     int result;
     if (range)
     {						// Already read through key
-/*       result=((range->flag & EQ_RANGE) ?
-	       file->index_next_same(record, (byte*) range->min_key,
-				     range->min_length) :
-	       file->index_next(record));
-*/
-       result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
+       result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ?
 	       file->index_next_same(record, (byte*) range->min_key,
 				     range->min_length) :
 	       file->index_next(record));
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 1c209dc7027..bb0d27b722c 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -127,6 +127,7 @@ class SQL_SELECT :public Sql_alloc {
 
   SQL_SELECT();
   ~SQL_SELECT();
+  void cleanup();
   bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
   { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; }
   inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ce30c6f3d09..2b743fc83c7 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -679,12 +679,24 @@ bool select_send::send_eof()
 }
 
 
-/***************************************************************************
-** Export of select to textfile
-***************************************************************************/
+/************************************************************************
+  Handling writing to file
+************************************************************************/
+
+void select_to_file::send_error(uint errcode,const char *err)
+{
+  ::send_error(thd,errcode,err);
+  if (file > 0)
+  {
+    (void) end_io_cache(&cache);
+    (void) my_close(file,MYF(0));
+    (void) my_delete(path,MYF(0));		// Delete file on error
+    file= -1;
+  }
+}
 
 
-select_export::~select_export()
+select_to_file::~select_to_file()
 {
   if (file >= 0)
   {					// This only happens in case of error
@@ -692,17 +704,42 @@ select_export::~select_export()
     (void) my_close(file,MYF(0));
     file= -1;
   }
+}
+
+/***************************************************************************
+** Export of select to textfile
+***************************************************************************/
+
+select_export::~select_export()
+{
   thd->sent_row_count=row_count;
 }
 
 
-static int create_file(THD *thd, char *path, sql_exchange *exchange,
-		       File *file, IO_CACHE *cache)
+/*
+  Create file with IO cache
+
+  SYNOPSIS
+    create_file()
+    thd			Thread handle
+    path		File name
+    exchange		Excange class
+    cache		IO cache
+
+  RETURN
+    >= 0 	File handle
+   -1		Error
+*/
+
+
+static File create_file(THD *thd, char *path, sql_exchange *exchange,
+			IO_CACHE *cache)
 {
-  uint option= 4;
+  File file;
+  uint option= MY_UNPACK_FILENAME;
 
 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
-  option|= 1;					// Force use of db directory
+  option|= MY_REPLACE_DIR;			// Force use of db directory
 #endif
   (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "",
 		   option);
@@ -712,35 +749,32 @@ static int create_file(THD *thd, char *path, sql_exchange *exchange,
     return 1;
   }
   /* Create the file world readable */
-  if ((*file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
-    return 1;
+  if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
+    return file;
 #ifdef HAVE_FCHMOD
-  (void) fchmod(*file, 0666);			// Because of umask()
+  (void) fchmod(file, 0666);			// Because of umask()
 #else
   (void) chmod(path, 0666);
 #endif
-  if (init_io_cache(cache, *file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
+  if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
   {
-    my_close(*file, MYF(0));
+    my_close(file, MYF(0));
     my_delete(path, MYF(0));  // Delete file on error, it was just created 
-    *file= -1;
-    end_io_cache(cache);
-    return 1;
+    return -1;
   }
-  return 0;
+  return file;
 }
 
 
 int
 select_export::prepare(List &list, SELECT_LEX_UNIT *u)
 {
-  char path[FN_REFLEN];
   bool blob_flag=0;
   unit= u;
   if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
     strmake(path,exchange->file_name,FN_REFLEN-1);
 
-  if (create_file(thd, path, exchange, &file, &cache))
+  if ((file= create_file(thd, path, exchange, &cache)) < 0)
     return 1;
   /* Check if there is any blobs in data */
   {
@@ -912,14 +946,6 @@ err:
 }
 
 
-void select_export::send_error(uint errcode, const char *err)
-{
-  ::send_error(thd,errcode,err);
-  (void) my_close(file,MYF(0));
-  file= -1;
-}
-
-
 bool select_export::send_eof()
 {
   int error=test(end_io_cache(&cache));
@@ -937,24 +963,12 @@ bool select_export::send_eof()
 ***************************************************************************/
 
 
-select_dump::~select_dump()
-{
-  if (file >= 0)
-  {					// This only happens in case of error
-    (void) end_io_cache(&cache);
-    (void) my_close(file,MYF(0));
-    file= -1;
-  }
-}
-
 int
 select_dump::prepare(List &list __attribute__((unused)),
 		     SELECT_LEX_UNIT *u)
 {
   unit= u;
-  if (create_file(thd, path, exchange, &file, &cache))
-    return 1;
-  return 0;
+  return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
 }
 
 
@@ -997,13 +1011,6 @@ err:
 }
 
 
-void select_dump::send_error(uint errcode,const char *err)
-{
-  ::send_error(thd,errcode,err);
-  (void) my_close(file,MYF(0));
-  file= -1;
-}
-
 bool select_dump::send_eof()
 {
   int error=test(end_io_cache(&cache));
@@ -1015,11 +1022,13 @@ bool select_dump::send_eof()
   return error;
 }
 
+
 select_subselect::select_subselect(Item_subselect *item_arg)
 {
   item= item_arg;
 }
 
+
 bool select_singlerow_subselect::send_data(List &items)
 {
   DBUG_ENTER("select_singlerow_subselect::send_data");
@@ -1042,6 +1051,7 @@ bool select_singlerow_subselect::send_data(List &items)
   DBUG_RETURN(0);
 }
 
+
 bool select_max_min_finder_subselect::send_data(List &items)
 {
   DBUG_ENTER("select_max_min_finder_subselect::send_data");
@@ -1147,8 +1157,9 @@ bool select_exists_subselect::send_data(List &items)
 
 
 /***************************************************************************
-** Dump  of select to variables
+  Dump of select to variables
 ***************************************************************************/
+
 int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u)
 {
   List_iterator_fast li(list);
@@ -1165,7 +1176,8 @@ int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u)
   {
     ls= gl++;
     Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
-    xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,&item);
+    xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,
+		   &item);
     xx->fix_length_and_dec();
     vars.push_back(xx);
   }
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7971137d848..51dc8270d09 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -962,41 +962,45 @@ public:
 };
 
 
-class select_export :public select_result {
-  sql_exchange *exchange;
-  File file;
-  IO_CACHE cache;
-  ha_rows row_count;
-  uint field_term_length;
-  int field_sep_char,escape_char,line_sep_char;
-  bool fixed_row_size;
-public:
-  select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
-  ~select_export();
-  int prepare(List &list, SELECT_LEX_UNIT *u);
-  bool send_fields(List &list,
-		   uint flag) { return 0; }
-  bool send_data(List &items);
-  void send_error(uint errcode,const char *err);
-  bool send_eof();
-};
-
-
-class select_dump :public select_result {
+class select_to_file :public select_result {
+protected:
   sql_exchange *exchange;
   File file;
   IO_CACHE cache;
   ha_rows row_count;
   char path[FN_REFLEN];
+
 public:
-  select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
+  select_to_file(sql_exchange *ex) :exchange(ex), file(-1),row_count(0L)
   { path[0]=0; }
-  ~select_dump();
-  int prepare(List &list, SELECT_LEX_UNIT *u);
-  bool send_fields(List &list,
-		   uint flag) { return 0; }
-  bool send_data(List &items);
+  ~select_to_file();
+  bool send_fields(List &list, uint flag) { return 0; }
   void send_error(uint errcode,const char *err);
+};
+
+
+class select_export :public select_to_file {
+  uint field_term_length;
+  int field_sep_char,escape_char,line_sep_char;
+  bool fixed_row_size;
+public:
+  select_export(sql_exchange *ex) :select_to_file(ex) {}
+  ~select_export();
+  int prepare(List &list, SELECT_LEX_UNIT *u);
+  bool send_data(List &items);
+  bool send_eof();
+};
+
+
+class select_dump :public select_to_file {
+  sql_exchange *exchange;
+  File file;
+  IO_CACHE cache;
+  ha_rows row_count;
+public:
+  select_dump(sql_exchange *ex) :select_to_file(ex) {}
+  int prepare(List &list, SELECT_LEX_UNIT *u);
+  bool send_data(List &items);
   bool send_eof();
 };
 
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 75a94995830..34739c36b9d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1648,8 +1648,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
   {
     select->head=table;
     table->reginfo.impossible_range=0;
-    if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit))
-	== 1)
+    if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
+					 limit)) == 1)
       DBUG_RETURN(select->quick->records);
     if (error == -1)
     {
@@ -7212,9 +7212,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
     table->file->info(HA_STATUS_VARIABLE);	// Get record count
   table->sort.found_records=filesort(thd, table,sortorder, length,
                                      select, filesort_limit, &examined_rows);
-  tab->records=table->sort.found_records;		// For SQL_CALC_ROWS
-  delete select;				// filesort did select
-  tab->select=0;
+  tab->records=table->sort.found_records;	// For SQL_CALC_ROWS
+  if (select)
+  {
+    select->cleanup();				// filesort did select
+    tab->select= 0;
+  }
   tab->select_cond=0;
   tab->type=JT_ALL;				// Read with normal read_record
   tab->read_first_record= join_init_read_record;

From 04675623d691f539b25ac95b76425477f7a448d9 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Thu, 5 Feb 2004 18:58:10 +0400
Subject: [PATCH 140/157] code and comments cleanup

---
 sql/item_func.cc | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sql/item_func.cc b/sql/item_func.cc
index f90fcd5149e..e49980af733 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2648,10 +2648,9 @@ longlong Item_func_inet_aton::val_int()
   }
   if (c != '.')					// IP number can't end on '.'
   {
-    switch (dot_count)
-    {
-    case 1: result<<= 8;
-    case 2: result<<= 8;
+    switch (dot_count) {
+    case 1: result<<= 8; /* fall through */
+    case 2: result<<= 8; /* fall through */
     }
     return (result << 8) + (ulonglong) byte_result;
   }

From faa8a41b1db57e643617eda8c49803f6e1287f87 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Fri, 6 Feb 2004 16:59:25 +0400
Subject: [PATCH 141/157] Problem fix: http://bugs.mysql.com/bug.php?id=2366
 Wrong utf8 behaviour when data is trancated

---
 include/m_ctype.h              |  4 +++
 mysql-test/r/ctype_mb.result   |  2 +-
 mysql-test/r/ctype_utf8.result | 10 ++++++-
 mysql-test/t/ctype_utf8.test   |  7 +++++
 sql/field.cc                   | 48 +++++++++++++++++++---------------
 sql/item_strfunc.h             |  3 ++-
 sql/item_timefunc.cc           |  5 ++--
 strings/ctype-big5.c           |  1 +
 strings/ctype-bin.c            |  1 +
 strings/ctype-euc_kr.c         |  1 +
 strings/ctype-gb2312.c         |  1 +
 strings/ctype-gbk.c            |  1 +
 strings/ctype-latin1.c         |  1 +
 strings/ctype-mb.c             | 16 ++++++++++++
 strings/ctype-simple.c         | 10 +++++++
 strings/ctype-sjis.c           |  1 +
 strings/ctype-tis620.c         |  7 +++--
 strings/ctype-ucs2.c           | 12 +++++++++
 strings/ctype-ujis.c           |  1 +
 strings/ctype-utf8.c           |  1 +
 20 files changed, 105 insertions(+), 28 deletions(-)

diff --git a/include/m_ctype.h b/include/m_ctype.h
index 4a9415f43f9..88c3418fc0d 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -144,6 +144,8 @@ typedef struct my_charset_handler_st
   int     (*mbcharlen)(struct charset_info_st *, uint);
   uint    (*numchars)(struct charset_info_st *, const char *b, const char *e);
   uint    (*charpos)(struct charset_info_st *, const char *b, const char *e, uint pos);
+  uint    (*wellformedlen)(struct charset_info_st *,
+  			   const char *b,const char *e, uint nchars);
   uint    (*lengthsp)(struct charset_info_st *, const char *ptr, uint length);
   
   /* Unicode convertion */
@@ -311,6 +313,7 @@ int my_wildcmp_8bit(CHARSET_INFO *,
 
 uint my_numchars_8bit(CHARSET_INFO *, const char *b, const char *e);
 uint my_charpos_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos);
+uint my_wellformedlen_8bit(CHARSET_INFO *, const char *b, const char *e, uint pos);
 int my_mbcharlen_8bit(CHARSET_INFO *, uint c);
 
 
@@ -327,6 +330,7 @@ int my_wildcmp_mb(CHARSET_INFO *,
 		  int escape, int w_one, int w_many);
 uint my_numchars_mb(CHARSET_INFO *, const char *b, const char *e);
 uint my_charpos_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
+uint my_wellformedlen_mb(CHARSET_INFO *, const char *b, const char *e, uint pos);
 uint my_instr_mb(struct charset_info_st *,
                  const char *b, uint b_length,
                  const char *s, uint s_length,
diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result
index 288033e7530..edccb047c85 100644
--- a/mysql-test/r/ctype_mb.result
+++ b/mysql-test/r/ctype_mb.result
@@ -22,7 +22,7 @@ Warning	1264	Data truncated for column 'c2' at row 1
 Warning	1264	Data truncated for column 'c3' at row 1
 SELECT * FROM t1;
 c1	c2	c3
-aaaabbbbcccc	aaaabbbbcccc	aaaabbbbcccc
+aaaa	aaaa	aaaa
 DROP TABLE t1;
 CREATE TABLE t1 (a CHAR(4) CHARACTER SET utf8, KEY key_a(a(3)));
 SHOW CREATE TABLE t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 7c05b1ea446..31f26c421b6 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -73,9 +73,17 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(4) character set utf8 default NULL
+  `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) character set utf8 default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select * from t1;
 date_format("2004-01-19 10:10:10", "%Y-%m-%d")
 2004-01-19
 drop table t1;
+set names koi8r;
+create table t1 (s1 char(1) character set utf8);
+insert into t1 values (_koi8r'ΑΒ');
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
+s1	hex(s1)	char_length(s1)	octet_length(s1)
+Α	D0B0	1	2
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 5e9324dd68f..c2ea1ed20a4 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -53,3 +53,10 @@ show create table t1;
 select * from t1;
 drop table t1;
 
+#
+# Bug #2366  	Wrong utf8 behaviour when data is trancated
+#
+set names koi8r;
+create table t1 (s1 char(1) character set utf8);
+insert into t1 values (_koi8r'ΑΒ');
+select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
diff --git a/sql/field.cc b/sql/field.cc
index 9f25b770ab0..57b77693275 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4060,6 +4060,8 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
   int error= 0;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
+  uint copy_length;
+
   /* Convert character set if nesessary */
   if (String::needs_conversion(from, length, cs, field_charset))
   { 
@@ -4067,27 +4069,31 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
     from= tmpstr.ptr();
     length=  tmpstr.length();
   }
-  if (length <= field_length)
-  {
-    memcpy(ptr,from,length);
-    if (length < field_length)
-      field_charset->cset->fill(field_charset,ptr+length,field_length-length,
-				' ');
-  }
-  else
-  {
-    memcpy(ptr,from,field_length);
-    if (current_thd->count_cuted_fields)
-    {						// Check if we loosed some info
-      const char *end=from+length;
-      from+= field_length;
-      from+= field_charset->cset->scan(field_charset, from, end,
-				       MY_SEQ_SPACES);
-      if (from != end)
-      {
-        set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
-	error=1;
-      }
+
+  /* 
+    Make sure we don't break a multybite sequence
+    as well as don't copy a malformed data.
+  */
+  copy_length= field_charset->cset->wellformedlen(field_charset,
+						  from,from+length,
+						  field_length/
+						  field_charset->mbmaxlen);
+  memcpy(ptr,from,copy_length);
+  if (copy_length < field_length)	// Append spaces if shorter
+    field_charset->cset->fill(field_charset,ptr+copy_length,
+			      field_length-copy_length,' ');
+  
+  
+  if (current_thd->count_cuted_fields && (copy_length < length))
+  {					// Check if we loosed some info
+    const char *end=from+length;
+    from+= copy_length;
+    from+= field_charset->cset->scan(field_charset, from, end,
+				     MY_SEQ_SPACES);
+    if (from != end)
+    {
+      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+      error=1;
     }
   }
   return error;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index fd0afb19726..465300e721e 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -518,7 +518,8 @@ public:
   void fix_length_and_dec() 
   { 
     collation.set(default_charset());
-    decimals=0; max_length=args[0]->max_length*2;
+    decimals=0;
+    max_length=args[0]->max_length*2*collation.collation->mbmaxlen;
   }
 };
 
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index ed5b9ecc0db..062e7fc7b44 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1286,12 +1286,13 @@ void Item_func_date_format::fix_length_and_dec()
   if (args[1]->type() == STRING_ITEM)
   {						// Optimize the normal case
     fixed_length=1;
-    max_length=format_length(((Item_string*) args[1])->const_string());
+    max_length= format_length(((Item_string*) args[1])->const_string())*
+		collation.collation->mbmaxlen;
   }
   else
   {
     fixed_length=0;
-    max_length=args[1]->max_length*10;
+    max_length=args[1]->max_length*10*collation.collation->mbmaxlen;
     set_if_smaller(max_length,MAX_BLOB_WIDTH);
   }
   maybe_null=1;					// If wrong date
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 8d4081fb2aa..574156a99ed 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6245,6 +6245,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler=
   mbcharlen_big5,
   my_numchars_mb,
   my_charpos_mb,
+  my_wellformedlen_mb,
   my_lengthsp_8bit,
   my_mb_wc_big5,	/* mb_wc       */
   my_wc_mb_big5,	/* wc_mb       */
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 43575bbc277..fc22938d46e 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -347,6 +347,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
     my_mbcharlen_8bit,		/* mbcharlen     */
     my_numchars_8bit,
     my_charpos_8bit,
+    my_wellformedlen_8bit,
     my_lengthsp_8bit,
     my_mb_wc_bin,
     my_wc_mb_bin,
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index 366a5d500ed..278e8529e83 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8653,6 +8653,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
   mbcharlen_euc_kr,
   my_numchars_mb,
   my_charpos_mb,
+  my_wellformedlen_mb,
   my_lengthsp_8bit,
   my_mb_wc_euc_kr,	/* mb_wc   */
   my_wc_mb_euc_kr,	/* wc_mb   */
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index 44a58b2b906..722f00f0f7a 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5704,6 +5704,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
   mbcharlen_gb2312,
   my_numchars_mb,
   my_charpos_mb,
+  my_wellformedlen_mb,
   my_lengthsp_8bit,
   my_mb_wc_gb2312,	/* mb_wc      */
   my_wc_mb_gb2312,	/* wc_mb      */
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 5475c3bd363..9e71a18e531 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9900,6 +9900,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
   mbcharlen_gbk,
   my_numchars_mb,
   my_charpos_mb,
+  my_wellformedlen_mb,
   my_lengthsp_8bit,
   my_mb_wc_gbk,
   my_wc_mb_gbk,
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index c00ded21575..933737b5f61 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -180,6 +180,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
     my_mbcharlen_8bit,
     my_numchars_8bit,
     my_charpos_8bit,
+    my_wellformedlen_8bit,
     my_lengthsp_8bit,
     my_mb_wc_latin1,
     my_wc_mb_latin1,
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index b5e8c4598a0..377bf311d38 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -274,6 +274,22 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
   return pos ? e+2-b0 : b-b0;
 }
 
+uint my_wellformedlen_mb(CHARSET_INFO *cs __attribute__((unused)),
+		     const char *b, const char *e, uint pos)
+{
+  uint mblen;
+  const char *b0=b;
+  
+  while (pos && b
Date: Sat, 7 Feb 2004 02:22:12 +0400
Subject: [PATCH 142/157] fixed bug #2592 mysqldump doesn't quote "tricky"
 names correctly

mysql-test/r/mysqldump.result:
  added test for
  bug #2592 mysqldump doesn't quote "tricky" names correctly
  please note, output's still looking wrong because of bug #2593
  it will be fixed when fix for bug #2593 will be pushed
mysql-test/t/mysqldump.test:
  added test for bug
  #2592 mysqldump doesn't quote "tricky" names correctly
sql/sql_lex.cc:
  fixed processing of multibyte quoted variables
---
 client/mysqldump.c            |  4 ++--
 mysql-test/r/mysqldump.result | 18 ++++++++++++++++++
 mysql-test/t/mysqldump.test   |  8 ++++++++
 sql/sql_lex.cc                | 30 +++++++++++++++++++-----------
 4 files changed, 47 insertions(+), 13 deletions(-)

diff --git a/client/mysqldump.c b/client/mysqldump.c
index 921ffbaab5b..74799ff4845 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -649,7 +649,7 @@ static char *quote_name(const char *name, char *buff, my_bool force)
   while (*name)
   {
     if (*name == QUOTE_CHAR)
-      *to= QUOTE_CHAR;
+      *to++= QUOTE_CHAR;
     *to++= *name++;
   }
   to[0]=QUOTE_CHAR;
@@ -1647,7 +1647,7 @@ static int dump_all_tables_in_db(char *database)
   if (opt_xml)
     fputs("\n", md_result_file);
   if (lock_tables)
-    mysql_query(sock,"UNLOCK_TABLES");
+    mysql_query(sock,"UNLOCK TABLES");
   return 0;
 } /* dump_all_tables_in_db */
 
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index f51caee39d6..651a33ac1db 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -123,3 +123,21 @@ UNLOCK TABLES;
 /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 
 DROP TABLE t1;
+create table ```a` (i int);
+DROP TABLE IF EXISTS ```a`;
+CREATE TABLE ``a` (
+  `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE ```a` DISABLE KEYS */;
+LOCK TABLES ```a` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE ```a` ENABLE KEYS */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+drop table ```a`;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 93b0dd4a75d..e6115b61bbf 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -53,3 +53,11 @@ CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
 --exec $MYSQL_DUMP  --skip-comments test t1
 DROP TABLE t1;
+
+#
+# Bug #2592
+#
+
+create table ```a` (i int);
+--exec $MYSQL_DUMP  --skip-comments test
+drop table ```a`;
\ No newline at end of file
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 65c958093bd..017b5677ced 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -667,13 +667,24 @@ int yylex(void *arg, void *yythd)
 
     case MY_LEX_USER_VARIABLE_DELIMITER:
     {
-      char delim= c;				// Used char
+      uint double_quotes= 0;
+      char quote_char= c;                       // Used char
       lex->tok_start=lex->ptr;			// Skip first `
 #ifdef USE_MB
       if (use_mb(cs))
       {
-	while ((c=yyGet()) && c != delim && c != (uchar) NAMES_SEP_CHAR)
+	while ((c= yyGet()))
 	{
+	  if (c == quote_char)
+	  {
+	    if (yyPeek() != quote_char)
+	      break;
+	    c= yyGet();
+	    double_quotes++;
+	    continue;
+	  }
+	  if (c == (uchar) NAMES_SEP_CHAR)
+	    break;
           if (my_mbcharlen(cs, c) > 1)
           {
             int l;
@@ -684,13 +695,10 @@ int yylex(void *arg, void *yythd)
             lex->ptr += l-1;
           }
         }
-	yylval->lex_str=get_token(lex,yyLength());
       }
       else
 #endif
       {
-	uint double_quotes= 0;
-	char quote_char= c;
 	while ((c=yyGet()))
 	{
 	  if (c == quote_char)
@@ -704,13 +712,13 @@ int yylex(void *arg, void *yythd)
 	  if (c == (uchar) NAMES_SEP_CHAR)
 	    break;
 	}
-	if (double_quotes)
-	  yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes,
-					   quote_char);
-	else
-	  yylval->lex_str=get_token(lex,yyLength());
       }
-      if (c == delim)
+      if (double_quotes)
+	yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes,
+					 quote_char);
+      else
+	yylval->lex_str=get_token(lex,yyLength());
+      if (c == quote_char)
 	yySkip();			// Skip end `
       lex->next_state= MY_LEX_START;
       return(IDENT_QUOTED);

From 35b1f5445056951dda823b6ec4ee6f06ca612714 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 9 Feb 2004 12:31:03 +0100
Subject: [PATCH 143/157] Added --compact to mysqlbinlog Fixed output from
 mysqlbinlog when using --skip-comments Fixed warnings from valgrind Fixed
 ref_length when used with HEAP tables More efficent need_conversion() Fixed
 error handling in UPDATE with not updateable tables Fixed bug in null
 handling in CAST to signed/unsigned

client/client_priv.h:
  cleanup & added OPT_COMPACT
client/mysqldump.c:
  Added option --compact to get a compact readable dump.
  Ensure that SET CHARACTER_SET_CLIENT is not done if we have not remembered the old character set
  Print optimization comments even if --skip-comments are given as these are not true comments. (Before these where only printed at end, which was a bug)
mysql-test/r/cast.result:
  More cast tests
mysql-test/r/derived.result:
  Removed warnings
mysql-test/r/mysqldump.result:
  Update results after fixing mysqlbinlog
mysql-test/r/query_cache.result:
  Make test usable with --extern
  more tests
mysql-test/r/rpl_until.result:
  Make test repeatable under valgrind
mysql-test/r/sql_mode.result:
  Fix test result
mysql-test/r/subselect.result:
  Make test smaller. Update wrong results
mysql-test/t/cast.test:
  More cast tests
mysql-test/t/derived.test:
  Removed warnings
mysql-test/t/query_cache.test:
  Make test usable with --extern
  more tests
mysql-test/t/rpl_until.test:
  fix for valgrind.  Becasue of unknown reason one got 'Slave_SQL_Running=yes' in this setup
mysql-test/t/subselect.test:
  Make test case smaller
sql/field.cc:
  Updated need_conversion() to use new arguments
sql/ha_heap.cc:
  Moved initialization of ref_length to right place. This fixed problem that we had a ref_length of 8 for heap tables, which was not efficent.
sql/item_func.cc:
  Cleanup
sql/item_func.h:
  Fixed bug in null_handling for cast to signed/unsigned
sql/item_strfunc.cc:
  Optimized/cleaned up Item_func_conv_charset3
sql/item_sum.cc:
  Cleanup.
  Ensure that some flag variables are cleared in cleanup()
sql/item_sum.h:
  Fixed references to uninitialized memory
sql/opt_range.cc:
  Fixed spelling error
sql/sql_class.cc:
  Fixed wrong return code, which could case protocol problems
sql/sql_class.h:
  After merge fix
sql/sql_prepare.cc:
  Added comments
sql/sql_show.cc:
  Cleanup
sql/sql_string.cc:
  Optimzed usage of need_conversion().
  - Removed not used argument
  - Save diff lenght in 'offset' to not have to recalculate length several times.
  Cleaned up comment
  Optimized copy_aligned() based on the knowledge that it's only called when you have wrong data
sql/sql_string.h:
  Updated need_conversion() and copy_aligned() to use new arguments
sql/sql_update.cc:
  Fixed error handling with non-updateable tables
sql/sql_yacc.yy:
  Ensure that lex->lock_options are set correctly (to get rid of warnings from valgrind)
  Ensure that cast_type sets lex->charset and lex->length. Without these CONVERT() didn't work properly
---
 client/client_priv.h            |  33 +++++----
 client/mysqldump.c              |  47 ++++++++-----
 mysql-test/r/cast.result        |  27 ++++++++
 mysql-test/r/derived.result     |   8 +--
 mysql-test/r/mysqldump.result   |  23 ++++++-
 mysql-test/r/query_cache.result |   9 ++-
 mysql-test/r/rpl_until.result   |   2 +-
 mysql-test/r/sql_mode.result    |   2 +-
 mysql-test/r/subselect.result   |  68 +++++++-----------
 mysql-test/t/cast.test          |   9 +++
 mysql-test/t/derived.test       |   4 +-
 mysql-test/t/query_cache.test   |   8 ++-
 mysql-test/t/rpl_until.test     |   5 +-
 mysql-test/t/subselect.test     |  64 +++++------------
 sql/field.cc                    |  20 ++++--
 sql/ha_heap.cc                  |   2 +-
 sql/item_func.cc                |   5 +-
 sql/item_func.h                 |  20 ++++--
 sql/item_strfunc.cc             |  60 ++++------------
 sql/item_sum.cc                 |  18 ++++-
 sql/item_sum.h                  |   7 +-
 sql/opt_range.cc                |   2 +-
 sql/sql_class.cc                |   2 +-
 sql/sql_class.h                 |   4 --
 sql/sql_prepare.cc              |   2 +
 sql/sql_show.cc                 |   3 +-
 sql/sql_string.cc               | 118 ++++++++++++++++++--------------
 sql/sql_string.h                |   8 ++-
 sql/sql_update.cc               |   3 +
 sql/sql_yacc.yy                 |  28 ++++----
 30 files changed, 327 insertions(+), 284 deletions(-)

diff --git a/client/client_priv.h b/client/client_priv.h
index f6d766b7ef9..910de1f03e9 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -26,18 +26,21 @@
 
 /* We have to define 'enum options' identical in all files to keep OS2 happy */
 
-enum options_client { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
-	       OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE,
-	       OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS,
-	       OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE,
-	       OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES,
-	       OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_AUTO_REHASH,
-	       OPT_LINE_NUMBERS, OPT_COLUMN_NAMES, OPT_CONNECT_TIMEOUT,
-	       OPT_MAX_ALLOWED_PACKET, OPT_NET_BUFFER_LENGTH,
-	       OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL,
-               OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
-               OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE,
-	       OPT_DELETE_MASTER_LOGS,
-               OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
-               OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
-               OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH };
+enum options_client
+{
+  OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
+  OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE,
+  OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS,
+  OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE,
+  OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES,
+  OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_AUTO_REHASH,
+  OPT_LINE_NUMBERS, OPT_COLUMN_NAMES, OPT_CONNECT_TIMEOUT,
+  OPT_MAX_ALLOWED_PACKET, OPT_NET_BUFFER_LENGTH,
+  OPT_SELECT_LIMIT, OPT_MAX_JOIN_SIZE, OPT_SSL_SSL,
+  OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
+  OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE,
+  OPT_DELETE_MASTER_LOGS, OPT_COMPACT,
+  OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
+  OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
+  OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
+};
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 921ffbaab5b..0025968ae5b 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -81,7 +81,7 @@ static my_bool  verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
 	        opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_names=0,
                 opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
 	        opt_delete_master_logs=0, tty_password=0,
-		opt_single_transaction=0, opt_comments= 0;
+		opt_single_transaction=0, opt_comments= 0, opt_compact= 0;
 static MYSQL  mysql_connection,*sock=0;
 static char  insert_pat[12 * 1024],*opt_password=0,*current_user=0,
              *current_host=0,*path=0,*fields_terminated=0,
@@ -140,6 +140,10 @@ static struct my_option my_long_options[] =
    "Change the dump to be compatible with a given mode. By default tables are dumped without any restrictions. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option does a no operation on earlier server versions.",
    (gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"compact", OPT_COMPACT,
+   "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs.  Enables options --skip-add-drop-table --no-set-names --skip-disable-keys --skip-lock-tables",
+   (gptr*) &opt_compact, (gptr*) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+   0, 0},
   {"complete-insert", 'c', "Use complete insert statements.", (gptr*) &cFlag,
    (gptr*) &cFlag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"compress", 'C', "Use compression in server/client protocol.",
@@ -347,15 +351,19 @@ static void write_header(FILE *sql_file, char *db_name)
     fputs("\n", sql_file);
     fputs("\n", sql_file);
   }
-  else if (opt_comments)
+  else if (!opt_compact)
   {
-    fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
-    fprintf(sql_file, "-- Host: %s    Database: %s\n",
-	    current_host ? current_host : "localhost", db_name ? db_name : "");
-    fputs("-- ------------------------------------------------------\n",
-	  sql_file);
-    fprintf(sql_file, "-- Server version\t%s\n",
-	    mysql_get_server_info(&mysql_connection));
+    if (opt_comments)
+    {
+      fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
+      fprintf(sql_file, "-- Host: %s    Database: %s\n",
+	      current_host ? current_host : "localhost", db_name ? db_name :
+	      "");
+      fputs("-- ------------------------------------------------------\n",
+	    sql_file);
+      fprintf(sql_file, "-- Server version\t%s\n",
+	      mysql_get_server_info(&mysql_connection));
+    }
     if (!opt_set_names)
       fprintf(sql_file,"\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=%s */;\n",default_charset);
     fprintf(md_result_file,"\
@@ -371,17 +379,18 @@ static void write_header(FILE *sql_file, char *db_name)
 static void write_footer(FILE *sql_file)
 {
   if (opt_xml)
-    fputs("", sql_file);
-  else
+    fputs("\n", sql_file);
+  else if (!opt_compact)
   {
     fprintf(md_result_file,"\n\
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n\
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n\
-/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n\
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n\
-");
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n");
+    if (!opt_set_names)
+      fprintf(md_result_file,
+	      "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n");
+    fputs("\n", sql_file);
   }
-  fputs("\n", sql_file);
 } /* write_footer */
 
 
@@ -448,6 +457,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
     extended_insert= opt_drop= opt_lock= quick= create_options=
       opt_disable_keys= lock_tables= 0;
     break;
+  case (int) OPT_COMPACT:
+  if (opt_compact)
+  {
+    opt_comments= opt_drop= opt_disable_keys= opt_lock= 0;
+    opt_set_names= 1;
+  }
   case (int) OPT_TABLES:
     opt_databases=0;
     break;
@@ -1270,7 +1285,7 @@ static void dumpTable(uint numFields, char *table)
 	fprintf(md_result_file,"-- WHERE:  %s\n",where);
       strxmov(strend(query), " WHERE ",where,NullS);
     }
-    if (!opt_xml)
+    if (!opt_xml && !opt_compact)
       fputs("\n", md_result_file);
     if (mysql_query(sock, query))
     {
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 893452290b2..c60d8e19fb4 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -24,6 +24,12 @@ Note	1003	select high_priority ~(5) AS `~5`,cast(~(5) as signed) AS `cast(~5 as
 select cast(5 as unsigned) -6.0;
 cast(5 as unsigned) -6.0
 -1.0
+select cast(NULL as signed), cast(1/0 as signed);
+cast(NULL as signed)	cast(1/0 as signed)
+NULL	NULL
+select cast(NULL as unsigned), cast(1/0 as unsigned);
+cast(NULL as unsigned)	cast(1/0 as unsigned)
+NULL	NULL
 select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A";
 cast("A" as binary) = "a"	cast(BINARY "a" as CHAR) = "A"
 0	1
@@ -36,6 +42,21 @@ cast("1:2:3" as TIME)
 select CONVERT("2004-01-22 21:45:33",DATE);
 CONVERT("2004-01-22 21:45:33",DATE)
 2004-01-22
+select CONVERT(DATE "2004-01-22 21:45:33" USING latin1);
+CONVERT(DATE "2004-01-22 21:45:33" USING latin1)
+2004-01-22 21:45:33
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR);
+CONVERT(DATE "2004-01-22 21:45:33",CHAR)
+2004-01-22 21:45:33
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4));
+CONVERT(DATE "2004-01-22 21:45:33",CHAR(4))
+2004
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY);
+CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY)
+2004
+select CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY);
+CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY)
+2004
 set names binary;
 select cast(_latin1'test' as char character set latin2);
 cast(_latin1'test' as char character set latin2)
@@ -43,6 +64,12 @@ test
 select cast(_koi8r'ΤΕΣΤ' as char character set cp1251);
 cast(_koi8r'ΤΕΣΤ' as char character set cp1251)
 ςερς
+select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci");
+convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci")
+test
+select convert(_koi8r'ΤΕΣΤ', "koi8r_general_ci", "cp1251_general_ci");
+convert(_koi8r'ΤΕΣΤ', "koi8r_general_ci", "cp1251_general_ci")
+ςερς
 create table t1 select cast(_koi8r'ΤΕΣΤ' as char character set cp1251) as t;
 show create table t1;
 Table	Create Table
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 170c393524b..44d35148f87 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -252,9 +252,7 @@ drop table t1;
 CREATE TABLE `t1` (
 `N` int(11) unsigned NOT NULL default '0',
 `M` tinyint(1) default '0',
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
-Warnings:
-Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
 select * from t1;
@@ -279,9 +277,7 @@ OBJECTID int(11) NOT NULL default '0',
 SORTORDER int(11) NOT NULL auto_increment,
 KEY t1_SortIndex (SORTORDER),
 KEY t1_IdIndex (OBJECTID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
-Warnings:
-Warning	1286	'TYPE=storage_engine' is deprecated. Use 'ENGINE=storage_engine' instead.
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 CREATE TABLE t2 (
 ID int(11) default NULL,
 PARID int(11) default NULL,
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index bdcdb0532f7..0414d6fa738 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -21,6 +21,11 @@ DROP TABLE t1;
 CREATE TABLE t1 (a decimal(240, 20));
 INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"),
 ("0987654321098765432109876543210987654321");
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS `t1`;
 CREATE TABLE `t1` (
   `a` decimal(240,20) default NULL
@@ -41,6 +46,11 @@ UNLOCK TABLES;
 DROP TABLE t1;
 CREATE TABLE t1 (a double);
 INSERT INTO t1 VALUES (-9e999999);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS `t1`;
 CREATE TABLE `t1` (
   `a` double default NULL
@@ -105,6 +115,11 @@ INSERT INTO t1 VALUES ("1\""), ("\"2");
 DROP TABLE t1;
 CREATE TABLE t1 (a  VARCHAR(255)) DEFAULT CHARSET koi8r;
 INSERT INTO t1  VALUES (_koi8r x'C1C2C3C4C5');
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS `t1`;
 CREATE TABLE `t1` (
   `a` varchar(255) default NULL
@@ -125,6 +140,9 @@ UNLOCK TABLES;
 DROP TABLE t1;
 CREATE TABLE t1 (a int) ENGINE=MYISAM;
 INSERT INTO t1 VALUES (1), (2);
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS `t1`;
 CREATE TABLE `t1` (
   `a` int(11) default NULL
@@ -140,8 +158,10 @@ UNLOCK TABLES;
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
 /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS `t1`;
 CREATE TABLE `t1` (
   `a` int(11) default NULL
@@ -157,6 +177,5 @@ UNLOCK TABLES;
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
 /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 
 DROP TABLE t1;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 49ae082dead..04bcb56d48d 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -696,17 +696,22 @@ word
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
 Qcache_queries_in_cache	1
-load data infile '../../std_data/words.dat' into table t1;
+load data infile 'TEST_DIR/std_data/words.dat' into table t1;
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
 Qcache_queries_in_cache	0
+select count(*) from t1;
+count(*)
+70
 drop table t1;
 create table t1 (a int);
 insert into t1 values (1),(2),(3);
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
 Qcache_queries_in_cache	0
-select * from t1 into outfile "query_caceh.out.file";
+select * from t1 into outfile "query_cache.out.file";
+select * from t1 into outfile "query_cache.out.file";
+ERROR HY000: File 'query_cache.out.file' already exists
 select * from t1 limit 1 into dumpfile "query_cache.dump.file";
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index 82b1ed233ec..cb60ccfb1c9 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -55,7 +55,7 @@ stop slave;
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	#	master-bin.000001	Yes	No							0		0	561	#	Master	master-bin.000001	561	No						#
+#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	#	master-bin.000001	Yes	#							0		0	561	#	Master	master-bin.000001	561	No						#
 start slave until master_log_file='master-bin', master_log_pos=561;
 ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
 start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index ddc848af1ed..77fe5d06bb0 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -70,7 +70,7 @@ t1	CREATE TABLE `t1` (
   `email` varchar(60) NOT NULL default '',
   PRIMARY KEY  (`a`),
   UNIQUE KEY `email` (`email`)
-) ENGINE=HEAP ROW_FORMAT=DYNAMIC
+) TYPE=HEAP ROW_FORMAT=DYNAMIC
 set sql_mode="postgresql,oracle,mssql,db2,maxdb";
 select @@sql_mode;
 @@sql_mode
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index c06c9824b33..b5ebc8d80db 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1578,50 +1578,28 @@ select * from t1;
 a	b
 1	0.123
 drop table t1;
-CREATE TABLE t1 (
-id int(11) NOT NULL auto_increment,
-ts timestamp NOT NULL,
-id_cns tinyint(3) unsigned NOT NULL default '0',
-id_desc_nota int(11) NOT NULL default '1',
-id_publ_uff int(11) NOT NULL default '0',
-tipo enum('','UNO','DUE') NOT NULL default '',
-f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL
-default '',
-anno_dep smallint(4) unsigned zerofill NOT NULL default '0000',
-data_dep smallint(4) unsigned zerofill NOT NULL default '0000',
-particolare mediumint(8) unsigned NOT NULL default '0',
-generale mediumint(8) unsigned NOT NULL default '0',
-bis tinyint(3) unsigned NOT NULL default '0',
-PRIMARY KEY(id),
-UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
-UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
-INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
-anno_dep, data_dep, particolare, generale, bis) VALUES
-(NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
-(NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
-(NULL, NULL,  16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0),
-(NULL, NULL,  16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0),
-(NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
-(NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
-CREATE TABLE t2 (
-id tinyint(3) unsigned NOT NULL auto_increment,
-descr varchar(40) NOT NULL default '',
-f_servizi set('UNO','DUE') NOT NULL default '',
-data_uno_min int(8) unsigned NOT NULL default '0',
-data_due_min int(8) unsigned NOT NULL default '0',
-max_anno_dep smallint(6) unsigned NOT NULL default '0',
-data_agg int(8) unsigned NOT NULL default '0',
-PRIMARY KEY  (id)
+CREATE TABLE `t1` (
+`id` int(11) NOT NULL auto_increment,
+`id_cns` tinyint(3) unsigned NOT NULL default '0',
+`tipo` enum('','UNO','DUE') NOT NULL default '',
+`anno_dep` smallint(4) unsigned zerofill NOT NULL default '0000',
+`particolare` mediumint(8) unsigned NOT NULL default '0',
+`generale` mediumint(8) unsigned NOT NULL default '0',
+`bis` tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY  (`id`),
+UNIQUE KEY `idx_cns_gen_anno` (`anno_dep`,`id_cns`,`generale`,`particolare`),
+UNIQUE KEY `idx_cns_par_anno` (`id_cns`,`anno_dep`,`tipo`,`particolare`,`bis`)
 );
-INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min,
-max_anno_dep, data_agg) VALUES 
-(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
-(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
-SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE
-s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
-t2 AS cns;
-PIPPO
-1
-NULL
+INSERT INTO `t1` VALUES (1,16,'UNO',1987,2048,9681,0),(2,50,'UNO',1987,1536,13987,0),(3,16,'UNO',1987,2432,14594,0),(4,16,'UNO',1987,1792,13422,0),(5,16,'UNO',1987,1025,10240,0),(6,16,'UNO',1987,1026,7089,0);
+CREATE TABLE `t2` (
+`id` tinyint(3) unsigned NOT NULL auto_increment,
+`max_anno_dep` smallint(6) unsigned NOT NULL default '0',
+PRIMARY KEY  (`id`)
+);
+INSERT INTO `t2` VALUES (16,1987),(50,1990),(51,1990);
+SELECT cns.id, cns.max_anno_dep, cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM t2 AS cns;
+id	max_anno_dep	PIPPO
+16	1987	1
+50	1990	0
+51	1990	NULL
 DROP TABLE t1, t2;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index e1cfe5760ee..ab0242990fc 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -10,10 +10,17 @@ select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
 select ~5, cast(~5 as signed);
 explain extended select ~5, cast(~5 as signed);
 select cast(5 as unsigned) -6.0;
+select cast(NULL as signed), cast(1/0 as signed); 
+select cast(NULL as unsigned), cast(1/0 as unsigned); 
 select cast("A" as binary) = "a", cast(BINARY "a" as CHAR) = "A";
 select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
 select cast("1:2:3" as TIME);
 select CONVERT("2004-01-22 21:45:33",DATE);
+select CONVERT(DATE "2004-01-22 21:45:33" USING latin1);
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR);
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4));
+select CONVERT(DATE "2004-01-22 21:45:33",CHAR(4) BINARY);
+select CAST(DATE "2004-01-22 21:45:33" AS CHAR(4) BINARY);
 
 #
 # Character set convertion
@@ -21,6 +28,8 @@ select CONVERT("2004-01-22 21:45:33",DATE);
 set names binary;
 select cast(_latin1'test' as char character set latin2);
 select cast(_koi8r'ΤΕΣΤ' as char character set cp1251);
+select convert(_latin1'test', "latin1_german1_ci", "latin1_swedish_ci");
+select convert(_koi8r'ΤΕΣΤ', "koi8r_general_ci", "cp1251_general_ci");
 create table t1 select cast(_koi8r'ΤΕΣΤ' as char character set cp1251) as t;
 show create table t1;
 drop table t1;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 154fc4b3834..8646a98551f 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -147,7 +147,7 @@ drop table t1;
 CREATE TABLE `t1` (
   `N` int(11) unsigned NOT NULL default '0',
   `M` tinyint(1) default '0',
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 INSERT INTO `t1` (N, M) VALUES (1, 0),(1, 0),(1, 0),(2, 0),(2, 0),(3, 0);
 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
 select * from t1;
@@ -167,7 +167,7 @@ CREATE TABLE t1 (
   SORTORDER int(11) NOT NULL auto_increment,
   KEY t1_SortIndex (SORTORDER),
   KEY t1_IdIndex (OBJECTID)
-) TYPE=MyISAM DEFAULT CHARSET=latin1;
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 CREATE TABLE t2 (
   ID int(11) default NULL,
   PARID int(11) default NULL,
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index dba5619b777..5ae2039138d 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -466,8 +466,10 @@ select * from t1 where id=2;
 create table t1 (word char(20) not null);
 select * from t1;
 show status like "Qcache_queries_in_cache";
-load data infile '../../std_data/words.dat' into table t1;
+--replace_result $MYSQL_TEST_DIR TEST_DIR
+eval load data infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
 show status like "Qcache_queries_in_cache";
+select count(*) from t1;
 drop table t1;
 
 #
@@ -476,7 +478,9 @@ drop table t1;
 create table t1 (a int);
 insert into t1 values (1),(2),(3);
 show status like "Qcache_queries_in_cache";
-select * from t1 into outfile "query_caceh.out.file";
+select * from t1 into outfile "query_cache.out.file";
+--error 1086
+select * from t1 into outfile "query_cache.out.file";
 select * from t1 limit 1 into dumpfile "query_cache.dump.file";
 show status like "Qcache_queries_in_cache";
 drop table t1;
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index 4508fbea194..937a8c03f99 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -59,10 +59,11 @@ stop slave;
 
 # this should stop immideately
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
---real-sleep 2;
+# 2 is not enough when running with valgrind
+--real-sleep 4;
 # here the sql slave thread should be stopped
 --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
---replace_column 1 # 9 # 23 # 33 #
+--replace_column 1 # 9 # 12 # 23 # 33 #
 show slave status;
 
 #testing various error conditions
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index c4392186055..6c53c70c9a0 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1026,52 +1026,26 @@ drop table t1;
 # Bug 2479
 #
 
-CREATE TABLE t1 (
-id int(11) NOT NULL auto_increment,
-ts timestamp NOT NULL,
-id_cns tinyint(3) unsigned NOT NULL default '0',
-id_desc_nota int(11) NOT NULL default '1',
-id_publ_uff int(11) NOT NULL default '0',
-tipo enum('','UNO','DUE') NOT NULL default '',
-f_aggiunte set('TRE','TRETRE','QUATTRO','CINQUE','SEI','SETTE') NOT NULL
-default '',
-anno_dep smallint(4) unsigned zerofill NOT NULL default '0000',
-data_dep smallint(4) unsigned zerofill NOT NULL default '0000',
-particolare mediumint(8) unsigned NOT NULL default '0',
-generale mediumint(8) unsigned NOT NULL default '0',
-bis tinyint(3) unsigned NOT NULL default '0',
-PRIMARY KEY(id),
-UNIQUE KEY idx_cns_gen_anno (anno_dep,id_cns,generale,particolare),
-UNIQUE KEY idx_cns_par_anno (id_cns,anno_dep,tipo,particolare,bis)
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=1;
-
-INSERT INTO t1 (id, ts, id_cns, id_desc_nota, id_publ_uff, tipo, f_aggiunte,
-anno_dep, data_dep, particolare, generale, bis) VALUES
-(NULL, NULL,  16, 29, 622, 'UNO', '', 1987, 1218, 2048, 9681, 0),
-(NULL, NULL,  50, 23, 1717, 'UNO', '', 1987, 1126, 1536, 13987, 0),
-(NULL, NULL,  16, 123, 123, 'UNO', '', 1987, 1221, 2432, 14594, 0),
-(NULL, NULL,  16, 124, 124, 'UNO', '', 1987, 1201, 1792, 13422, 0),
-(NULL, NULL,  16, 125, 125, 'UNO', '', 1987, 0723, 1025, 10240, 0),
-(NULL, NULL,  16, 126, 126, 'UNO', '', 1987, 1204, 1026, 7089, 0);
-  
-CREATE TABLE t2 (
-id tinyint(3) unsigned NOT NULL auto_increment,
-descr varchar(40) NOT NULL default '',
-f_servizi set('UNO','DUE') NOT NULL default '',
-data_uno_min int(8) unsigned NOT NULL default '0',
-data_due_min int(8) unsigned NOT NULL default '0',
-max_anno_dep smallint(6) unsigned NOT NULL default '0',
-data_agg int(8) unsigned NOT NULL default '0',
-PRIMARY KEY  (id)
+CREATE TABLE `t1` (
+  `id` int(11) NOT NULL auto_increment,
+  `id_cns` tinyint(3) unsigned NOT NULL default '0',
+  `tipo` enum('','UNO','DUE') NOT NULL default '',
+  `anno_dep` smallint(4) unsigned zerofill NOT NULL default '0000',
+  `particolare` mediumint(8) unsigned NOT NULL default '0',
+  `generale` mediumint(8) unsigned NOT NULL default '0',
+  `bis` tinyint(3) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `idx_cns_gen_anno` (`anno_dep`,`id_cns`,`generale`,`particolare`),
+  UNIQUE KEY `idx_cns_par_anno` (`id_cns`,`anno_dep`,`tipo`,`particolare`,`bis`)
 );
+INSERT INTO `t1` VALUES (1,16,'UNO',1987,2048,9681,0),(2,50,'UNO',1987,1536,13987,0),(3,16,'UNO',1987,2432,14594,0),(4,16,'UNO',1987,1792,13422,0),(5,16,'UNO',1987,1025,10240,0),(6,16,'UNO',1987,1026,7089,0);
+CREATE TABLE `t2` (
+  `id` tinyint(3) unsigned NOT NULL auto_increment,
+  `max_anno_dep` smallint(6) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+);
+INSERT INTO `t2` VALUES (16,1987),(50,1990),(51,1990);
 
-INSERT INTO t2 (id, descr, f_servizi, data_uno_min, data_due_min,
-max_anno_dep, data_agg) VALUES 
-(16, 'C_UNO', 'UNO,DUE', 19000000, 30000000, 1987, 0),
-(50, 'C_TRE', 'UNO', 19000000, 30000000, 1990, 0);
-
-SELECT cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE
-s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM
-t2 AS cns;
+SELECT cns.id, cns.max_anno_dep, cns.max_anno_dep = (SELECT s.anno_dep FROM t1 AS s WHERE s.id_cns = cns.id ORDER BY s.anno_dep DESC LIMIT 1) AS PIPPO FROM t2 AS cns;
 
 DROP TABLE t1, t2;
diff --git a/sql/field.cc b/sql/field.cc
index 9f25b770ab0..f337f4ca46c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4058,10 +4058,12 @@ void Field_datetime::sql_type(String &res) const
 int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   int error= 0;
+  uint32 not_used;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
   /* Convert character set if nesessary */
-  if (String::needs_conversion(from, length, cs, field_charset))
+  if (String::needs_conversion(length, cs, field_charset, ¬_used))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -4246,10 +4248,12 @@ uint Field_string::max_packed_col_length(uint max_length)
 int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   int error= 0;
+  uint32 not_used;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
   /* Convert character set if nesessary */
-  if (String::needs_conversion(from, length, cs, field_charset))
+  if (String::needs_conversion(length, cs, field_charset, ¬_used))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -4565,10 +4569,11 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
     bool was_conversion;
     char buff[80];
     String tmpstr(buff,sizeof(buff), &my_charset_bin);
+    uint32 not_used;
 
     /* Convert character set if nesessary */
-    if ((was_conversion= String::needs_conversion(from, length,
-						  cs, field_charset)))
+    if ((was_conversion= String::needs_conversion(length, cs, field_charset,
+						  ¬_used)))
     { 
       tmpstr.copy(from, length, cs, field_charset);
       from= tmpstr.ptr();
@@ -5079,10 +5084,12 @@ void Field_enum::store_type(ulonglong value)
 int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
 {
   int err= 0;
+  uint32 not_used;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
   /* Convert character set if nesessary */
-  if (String::needs_conversion(from, length, cs, field_charset))
+  if (String::needs_conversion(length, cs, field_charset, ¬_used))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
@@ -5259,11 +5266,12 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
   int err= 0;
   char *not_used;
   uint not_used2;
+  uint32 not_used_offset;
   char buff[80];
   String tmpstr(buff,sizeof(buff), &my_charset_bin);
 
   /* Convert character set if nesessary */
-  if (String::needs_conversion(from, length, cs, field_charset))
+  if (String::needs_conversion(length, cs, field_charset, ¬_used_offset))
   { 
     tmpstr.copy(from, length, cs, field_charset);
     from= tmpstr.ptr();
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index ae0267b98f3..c1228cbd319 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -40,6 +40,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
     if (!create(name, table, &create_info))
       file= heap_open(name, mode);
   }
+  ref_length= sizeof(HEAP_PTR);
   return (file ? 0 : 1);
 }
 
@@ -335,7 +336,6 @@ int ha_heap::create(const char *name, TABLE *table_arg,
   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);
 }
 
diff --git a/sql/item_func.cc b/sql/item_func.cc
index efeb0d456ef..b1378784f92 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1068,9 +1068,8 @@ String *Item_func_min_max::val_str(String *str)
 	}
       }
     }
-    if (!res)  // If NULL
-      return 0;
-    res->set_charset(collation.collation);
+    if (res)					// If !NULL
+      res->set_charset(collation.collation);
     return res;
   }
   case ROW_RESULT:
diff --git a/sql/item_func.h b/sql/item_func.h
index be20a9b4fc7..30f817d133b 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -211,20 +211,28 @@ class Item_func_signed :public Item_int_func
 {
 public:
   Item_func_signed(Item *a) :Item_int_func(a) {}
-  double val() {  null_value=args[0]->null_value; return args[0]->val(); }
-  longlong val_int() {  null_value=args[0]->null_value; return args[0]->val_int(); }
+  double val()
+  {
+    double tmp= args[0]->val();
+    null_value= args[0]->null_value;
+    return tmp;
+  }
+  longlong val_int()
+  {
+    longlong tmp= args[0]->val_int();
+    null_value= args[0]->null_value; 
+    return tmp;
+  }
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=0; }
   void print(String *str);
 };
 
 
-class Item_func_unsigned :public Item_int_func
+class Item_func_unsigned :public Item_func_signed
 {
 public:
-  Item_func_unsigned(Item *a) :Item_int_func(a) {}
-  double val() { null_value=args[0]->null_value; return args[0]->val(); }
-  longlong val_int() { null_value=args[0]->null_value; return args[0]->val_int(); }
+  Item_func_unsigned(Item *a) :Item_func_signed(a) {}
   void fix_length_and_dec()
   { max_length=args[0]->max_length; unsigned_flag=1; }
   void print(String *str);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index f5922d03868..fd1222d5f1a 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2126,14 +2126,12 @@ void Item_func_conv_charset::print(String *str)
 
 String *Item_func_conv_charset3::val_str(String *str)
 {
-  my_wc_t wc;
-  int cnvres;
-  const uchar *s, *se;
-  uchar *d, *d0, *de;
-  uint32 dmaxlen;
+  char cs1[30], cs2[30];
+  String to_cs_buff(cs1, sizeof(cs1), default_charset_info);
+  String from_cs_buff(cs2, sizeof(cs2), default_charset_info);
   String *arg= args[0]->val_str(str);
-  String *to_cs= args[1]->val_str(str);
-  String *from_cs= args[2]->val_str(str);
+  String *to_cs= args[1]->val_str(&to_cs_buff);
+  String *from_cs= args[2]->val_str(&from_cs_buff);
   CHARSET_INFO *from_charset;
   CHARSET_INFO *to_charset;
 
@@ -2143,51 +2141,17 @@ String *Item_func_conv_charset3::val_str(String *str)
       !(from_charset=get_charset_by_name(from_cs->ptr(), MYF(MY_WME))) ||
       !(to_charset=get_charset_by_name(to_cs->ptr(), MYF(MY_WME))))
   {
-    null_value=1;
+    null_value= 1;
     return 0;
   }
 
-  s=(const uchar*)arg->ptr();
-  se=s+arg->length();
-
-  dmaxlen=arg->length()*to_charset->mbmaxlen+1;
-  str->alloc(dmaxlen);
-  d0=d=(unsigned char*)str->ptr();
-  de=d+dmaxlen;
-
-  while (1)
+  if (str_value.copy(arg->ptr(), arg->length(), from_charset, to_charset))
   {
-    cnvres=from_charset->cset->mb_wc(from_charset,&wc,s,se);
-    if (cnvres>0)
-    {
-      s+=cnvres;
-    }
-    else if (cnvres==MY_CS_ILSEQ)
-    {
-      s++;
-      wc='?';
-    }
-    else
-      break;
-
-outp:
-    cnvres=to_charset->cset->wc_mb(to_charset,wc,d,de);
-    if (cnvres>0)
-    {
-      d+=cnvres;
-    }
-    else if (cnvres==MY_CS_ILUNI && wc!='?')
-    {
-        wc='?';
-        goto outp;
-    }
-    else
-      break;
-  };
-
-  str->length((uint32) (d-d0));
-  str->set_charset(to_charset);
-  return str;
+    null_value= 1;
+    return 0;
+  }
+  null_value= 0;
+  return &str_value;
 }
 
 
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index e01f9db3463..10b50fa5b3b 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1092,15 +1092,21 @@ void Item_sum_count_distinct::cleanup()
   if (!original)
   {
     if (table)
+    {
       free_tmp_table(current_thd, table);
+      table= 0;
+    }
     delete tmp_table_param;
+    tmp_table_param= 0;
     if (use_tree)
+    {
       delete_tree(tree);
-    table= 0;
-    use_tree= 0;
+      use_tree= 0;
+    }
   }
 }
 
+
 bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
 					 Item **ref)
 {
@@ -1674,13 +1680,21 @@ void Item_func_group_concat::cleanup()
   {
     THD *thd= current_thd;
     if (table)
+    {
       free_tmp_table(thd, table);
+      table= 0;
+    }
     delete tmp_table_param;
+    tmp_table_param= 0;
     if (tree_mode)
+    {
+      tree_mode= 0;
       delete_tree(tree); 
+    }
   }
 }
 
+
 Item_func_group_concat::~Item_func_group_concat()
 {
   /*
diff --git a/sql/item_sum.h b/sql/item_sum.h
index dc84e4d4ab7..bb03f029997 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -397,12 +397,13 @@ class Item_sum_hybrid :public Item_sum
 
   public:
   Item_sum_hybrid(Item *item_par,int sign)
-    :Item_sum(item_par), hybrid_type(INT_RESULT), cmp_sign(sign),
-    used_table_cache(~(table_map) 0),
+    :Item_sum(item_par), sum(0.0), sum_int(0),
+    hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG),
+    cmp_sign(sign), used_table_cache(~(table_map) 0),
     cmp_charset(&my_charset_bin)
   {}
   Item_sum_hybrid(THD *thd, Item_sum_hybrid *item):
-    Item_sum(thd, item), value(item->value), tmp_value(item->tmp_value),
+    Item_sum(thd, item), value(item->value),
     sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type),
     hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), 
     used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 2647a0ae818..4c9f3700ef1 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1005,7 +1005,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
   }
 
   /*
-    We can't use an index when comparing stings of 
+    We can't use an index when comparing strings of 
     different collations 
   */
   if (field->result_type() == STRING_RESULT &&
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index fc042ae7918..cbac11ac42e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -744,7 +744,7 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
   if (!access(path, F_OK))
   {
     my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
-    return 1;
+    return -1;
   }
   /* Create the file world readable */
   if ((file= my_create(path, 0666, O_WRONLY, MYF(MY_WME))) < 0)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 51dc8270d09..b3135202ad6 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -993,10 +993,6 @@ public:
 
 
 class select_dump :public select_to_file {
-  sql_exchange *exchange;
-  File file;
-  IO_CACHE cache;
-  ha_rows row_count;
 public:
   select_dump(sql_exchange *ex) :select_to_file(ex) {}
   int prepare(List &list, SELECT_LEX_UNIT *u);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index de0d0c8aca8..9b8ef37757c 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1005,8 +1005,10 @@ void mysql_stmt_execute(THD *thd, char *packet)
       sl->where= sl->prep_where->copy_andor_structure(thd);
     DBUG_ASSERT(sl->join == 0);
     ORDER *order;
+    /* Fix GROUP list */
     for (order=(ORDER *)sl->group_list.first ; order ; order=order->next)
       order->item= (Item **)(order+1);
+    /* Fix ORDER list */
     for (order=(ORDER *)sl->order_list.first ; order ; order=order->next)
       order->item= (Item **)(order+1);
   }
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 5f6167f2cd1..4da2522bd3f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -519,8 +519,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
         protocol->store_null();
       // Send error to Comment field
       protocol->store(thd->net.last_error, system_charset_info);
-      thd->net.last_error[0]=0;
-      thd->net.last_errno= 0;
+      thd->clear_error();
     }
     else
     {
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 7f26a0febda..cbee67c0a4a 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -230,68 +230,86 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
 
 
 /*
-  Checks that the source string can be just copied
-  to the destination string without conversion.
-  If either character set conversion or adding leading
-  zeros (e.g. for UCS-2) must be done then return 
-  value is TRUE else FALSE.
+  Checks that the source string can be just copied to the destination string
+  without conversion.
+
+  SYNPOSIS
+
+  needs_conversion()
+  arg_length		Length of string to copy.
+  from_cs		Character set to copy from
+  to_cs			Character set to copy to
+  uint32 *offset	Returns number of unaligned characters.
+
+  RETURN
+   0  No conversion needed
+   1  Either character set conversion or adding leading  zeros
+      (e.g. for UCS-2) must be done
 */
-bool String::needs_conversion(const char *str, uint32 arg_length,
-				     CHARSET_INFO *from_cs,
-				     CHARSET_INFO *to_cs)
+
+bool String::needs_conversion(uint32 arg_length,
+			      CHARSET_INFO *from_cs,
+			      CHARSET_INFO *to_cs,
+			      uint32 *offset)
 {
+  *offset= 0;
   if ((to_cs == &my_charset_bin) || 
       (to_cs == from_cs) ||
       my_charset_same(from_cs, to_cs) ||
-      ((from_cs == &my_charset_bin) && (!(arg_length % to_cs->mbminlen))))
+      ((from_cs == &my_charset_bin) &&
+       (!(*offset=(arg_length % to_cs->mbminlen)))))
     return FALSE;
-  
   return TRUE;
 }
 
+
 /*
-** For real multi-byte, ascii incompatible charactser sets,
-** like UCS-2, add leading zeros if we have an incomplete character.
-** Thus, 
-**   SELECT _ucs2 0xAA 
-** will automatically be converted into
-**   SELECT _ucs2 0x00AA
+  Copy a multi-byte character sets with adding leading zeros.
+
+  SYNOPSIS
+
+  copy_aligned()
+  str			String to copy
+  arg_length		Length of string. This should NOT be dividable with
+			cs->mbminlen.
+  offset		arg_length % cs->mb_minlength
+  cs			Character set for 'str'
+
+  NOTES
+    For real multi-byte, ascii incompatible charactser sets,
+    like UCS-2, add leading zeros if we have an incomplete character.
+    Thus, 
+      SELECT _ucs2 0xAA 
+    will automatically be converted into
+      SELECT _ucs2 0x00AA
+
+  RETURN
+    0  ok
+    1  error
 */
 
-bool String::copy_aligned(const char *str,uint32 arg_length,
+bool String::copy_aligned(const char *str,uint32 arg_length, uint32 offset,
 			  CHARSET_INFO *cs)
 {
   /* How many bytes are in incomplete character */
-  uint32 offs= (arg_length % cs->mbminlen); 
+  offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */
+  DBUG_ASSERT(offset && offset != cs->mbmaxlen);
 
-  if (!offs) /* All characters are complete, just copy */
-  {
-    copy(str, arg_length, cs);
-    return FALSE;
-  }
-  
-  offs= cs->mbmaxlen - offs; /* How many zeros we should prepend */
-  uint32 aligned_length= arg_length + offs;
+  uint32 aligned_length= arg_length + offset;
   if (alloc(aligned_length))
     return TRUE;
   
   /*
-    Probably this condition is not really necessary
-    because if aligned_length is 0 then offs is 0 too
-    and we'll return after calling set().
+    Note, this is only safe for little-endian UCS-2.
+    If we add big-endian UCS-2 sometimes, this code
+    will be more complicated. But it's OK for now.
   */
-  if ((str_length= aligned_length))
-  {
-    /*
-      Note, this is only safe for little-endian UCS-2.
-      If we add big-endian UCS-2 sometimes, this code
-      will be more complicated. But it's OK for now.
-    */
-    bzero((char*)Ptr, offs);
-    memcpy(Ptr + offs, str, arg_length);
-  }
+  bzero((char*) Ptr, offset);
+  memcpy(Ptr + offset, str, arg_length);
   Ptr[aligned_length]=0;
-  str_charset=cs;
+  /* str_length is always >= 0 as arg_length is != 0 */
+  str_length= aligned_length;
+  str_charset= cs;
   return FALSE;
 }
 
@@ -300,14 +318,14 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
 				 CHARSET_INFO *cs)
 {
   /* How many bytes are in incomplete character */
-  uint32 offs= (arg_length % cs->mbminlen); 
+  uint32 offset= (arg_length % cs->mbminlen); 
   
-  if (!offs) /* All characters are complete, just copy */
+  if (!offset) /* All characters are complete, just copy */
   {
     set(str, arg_length, cs);
     return FALSE;
   }
-  return copy_aligned(str, arg_length, cs);
+  return copy_aligned(str, arg_length, offset, cs);
 }
 
 	/* Copy with charset convertion */
@@ -315,14 +333,11 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
 bool String::copy(const char *str, uint32 arg_length,
 		  CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 {
-  if (!needs_conversion(str, arg_length, from_cs, to_cs))
-  {
+  uint32 offset;
+  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
     return copy(str, arg_length, to_cs);
-  }
-  if ((from_cs == &my_charset_bin) && (arg_length % to_cs->mbminlen))
-  {
-    return copy_aligned(str, arg_length, to_cs);
-  }
+  if ((from_cs == &my_charset_bin) && offset)
+    return copy_aligned(str, arg_length, offset, to_cs);
   
   uint32 new_length= to_cs->mbmaxlen*arg_length;
   if (alloc(new_length))
@@ -744,7 +759,8 @@ copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
 
   while (1)
   {
-    if ((cnvres=from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from, from_end)) > 0)
+    if ((cnvres= from_cs->cset->mb_wc(from_cs, &wc, (uchar*) from,
+				      from_end)) > 0)
       from+= cnvres;
     else if (cnvres == MY_CS_ILSEQ)
     {
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 9c0900137e3..163156fdfe2 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -183,9 +183,11 @@ public:
   bool copy();					// Alloc string if not alloced
   bool copy(const String &s);			// Allocate new string
   bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs);	// Allocate new string
-  static bool needs_conversion(const char *s, uint32 arg_length,
-  			       CHARSET_INFO *cs_from, CHARSET_INFO *cs_to);
-  bool copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
+  static bool needs_conversion(uint32 arg_length,
+  			       CHARSET_INFO *cs_from, CHARSET_INFO *cs_to,
+			       uint32 *offset);
+  bool copy_aligned(const char *s, uint32 arg_length, uint32 offset,
+		    CHARSET_INFO *cs);
   bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
   bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
 	    CHARSET_INFO *csto);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c6e470fd09f..86593f5ea20 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -482,8 +482,11 @@ int mysql_multi_update(THD *thd,
     for (tl= select_lex->get_table_list() ; tl ; tl= tl->next)
     {
       if (tl->derived && (item_tables & tl->table->map))
+      {
 	my_printf_error(ER_NON_UPDATABLE_TABLE, ER(ER_NON_UPDATABLE_TABLE),
 			MYF(0), tl->alias, "UPDATE");
+	DBUG_RETURN(-1);
+      }
     }
   }
 
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f04cc9ec1dc..0dbe8981466 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -918,7 +918,7 @@ create:
 						  &tmp_table_alias :
 						  (LEX_STRING*) 0),
 						 TL_OPTION_UPDATING,
-						 ((using_update_log)?
+						 (using_update_log ?
 						  TL_READ_NO_INSERT:
 						  TL_READ)))
 	    YYABORT;
@@ -2189,10 +2189,9 @@ select_init2:
 
 select_part2:
 	{
-	  LEX *lex=Lex;
-	  SELECT_LEX * sel= lex->current_select;
-	  if (lex->current_select == &lex->select_lex)
-	    lex->lock_option= TL_READ; /* Only for global SELECT */
+	  LEX *lex= Lex;
+	  SELECT_LEX *sel= lex->current_select;
+	  lex->lock_option= TL_READ;
 	  if (sel->linkage != UNION_TYPE)
 	    mysql_init_select(lex);
 	  lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
@@ -3060,7 +3059,7 @@ opt_gorder_clause:
 	| order_clause
           {
             LEX *lex=Lex;
-            lex->gorder_list= 
+            lex->gorder_list=
 	      (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,
 				     sizeof(st_sql_list));
 	    lex->current_select->order_list.empty();
@@ -3084,16 +3083,16 @@ in_sum_expr:
 	};
 
 cast_type:
-	BINARY			{ $$=ITEM_CAST_BINARY; }
+	BINARY			{ $$=ITEM_CAST_BINARY; Lex->charset= NULL; Lex->length= (char*)0; }
 	| CHAR_SYM opt_len opt_binary	{ $$=ITEM_CAST_CHAR; }
 	| NCHAR_SYM opt_len	{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; }
-	| SIGNED_SYM		{ $$=ITEM_CAST_SIGNED_INT; }
-	| SIGNED_SYM INT_SYM	{ $$=ITEM_CAST_SIGNED_INT; }
-	| UNSIGNED		{ $$=ITEM_CAST_UNSIGNED_INT; }
-	| UNSIGNED INT_SYM	{ $$=ITEM_CAST_UNSIGNED_INT; }
-	| DATE_SYM		{ $$=ITEM_CAST_DATE; }
-	| TIME_SYM		{ $$=ITEM_CAST_TIME; }
-	| DATETIME		{ $$=ITEM_CAST_DATETIME; }
+	| SIGNED_SYM		{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
+	| SIGNED_SYM INT_SYM	{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
+	| UNSIGNED		{ $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
+	| UNSIGNED INT_SYM	{ $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->length= (char*)0; }
+	| DATE_SYM		{ $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->length= (char*)0; }
+	| TIME_SYM		{ $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->length= (char*)0; }
+	| DATETIME		{ $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->length= (char*)0; }
 	;
 
 expr_list:
@@ -3895,6 +3894,7 @@ update:
 	  LEX *lex= Lex;
 	  mysql_init_select(lex);
           lex->sql_command= SQLCOM_UPDATE;
+	  lex->lock_option= TL_UNLOCK; 	/* Will be set later */
         }
         opt_low_priority opt_ignore join_table_list
 	SET update_list where_clause opt_order_clause delete_limit_clause

From 61f0e69cb60b9db858bad3b6de6fa0b8b2f03899 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 9 Feb 2004 14:44:03 +0200
Subject: [PATCH 144/157] ufter revview fix (BUG#2120)

mysql-test/r/derived.result:
  test of error handling in derived tables with UPDATE & DELETE
mysql-test/t/derived.test:
  test of error handling in derived tables with UPDATE & DELETE
sql/mysql_priv.h:
  opened tables counter added to avoid loop of tables calculating in lock_tables
sql/sql_acl.cc:
  opened tables counter added to avoid loop of tables calculating in lock_tables, here it is just for compatibility
sql/sql_base.cc:
  removed unneeded assignment
  opened tables counter added to avoid loop of tables calculating in lock_tables
  commentary fixed
sql/sql_derived.cc:
  mysql_derived made static
  variable res moved in place where it used
  priveleges written in correct place
sql/sql_handler.cc:
  opened tables counter added to avoid loop of tables calculating in lock_tables
sql/sql_parse.cc:
  mistyping in commentary fixed
---
 mysql-test/r/derived.result |  4 +++
 mysql-test/t/derived.test   |  4 +++
 sql/mysql_priv.h            |  4 +--
 sql/sql_acl.cc              |  6 +++--
 sql/sql_base.cc             | 53 +++++++++++++++++++++++++------------
 sql/sql_derived.cc          | 16 +++++------
 sql/sql_handler.cc          |  3 ++-
 sql/sql_parse.cc            |  4 +--
 8 files changed, 62 insertions(+), 32 deletions(-)

diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index dea4dd9b4c2..6f35097e2b8 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -267,12 +267,16 @@ N	M
 3	0
 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
 ERROR HY000: The target table P2 of the UPDATE is not updatable.
+UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
+ERROR 42S22: Unknown column 'aaaa' in 'field list'
 delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
 select * from t1;
 N	M
 3	0
 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
 ERROR HY000: The target table P2 of the DELETE is not updatable.
+delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+ERROR 42S22: Unknown column 'aaa' in 'field list'
 drop table t1;
 CREATE TABLE t1 (
 OBJECTID int(11) NOT NULL default '0',
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 988ef30d1dc..0a7e3d41c73 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1)
 select * from t1;
 -- error 1287
 UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
+-- error 1054
+UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
 delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
 select * from t1;
 -- error 1287
 delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
+-- error 1054
+delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
 drop table t1;
 
 #
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 4d03feae07c..73e30e72a3c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -675,10 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
 int setup_ftfuncs(SELECT_LEX* select);
 int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
 void wait_for_refresh(THD *thd);
-int open_tables(THD *thd,TABLE_LIST *tables);
+int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
 int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
 int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
-int lock_tables(THD *thd,TABLE_LIST *tables);
+int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
 TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
 			    const char *table_name, bool link_in_list);
 bool rm_temporary_table(enum db_type base, char *path);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 8ef6a32a430..21c57d79da4 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
   tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
   tables[0].db=tables[1].db=tables[2].db=thd->db;
 
-  if (open_tables(thd,tables))
+  uint counter;
+  if (open_tables(thd, tables, &counter))
   {
     sql_print_error("Fatal error: Can't open privilege tables: %s",
 		    thd->net.last_error);
@@ -2524,7 +2525,8 @@ my_bool grant_init(THD *org_thd)
   tables[0].lock_type=tables[1].lock_type=TL_READ;
   tables[0].db=tables[1].db=thd->db;
 
-  if (open_tables(thd,tables))
+  uint counter;
+  if (open_tables(thd, tables, &counter))
     goto end;
 
   TABLE *ptr[2];				// Lock tables for quick update
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 2e8441bb23b..0ededa80ad6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1308,7 +1308,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
     bzero((char*) &table_list, sizeof(table_list)); // just for safe
     table_list.db=(char*) db;
     table_list.real_name=(char*) name;
-    table_list.next=0;
     safe_mutex_assert_owner(&LOCK_open);
 
     if ((error=lock_table_name(thd,&table_list)))
@@ -1357,24 +1356,40 @@ err:
   DBUG_RETURN(1);
 }
 
-/*****************************************************************************
-** open all tables in list
-*****************************************************************************/
+/*
+  Open all tables in list
 
-int open_tables(THD *thd,TABLE_LIST *start)
+  SYNOPSIS
+    open_tables()
+    thd - thread handler
+    start - list of tables
+    counter - number of opened tables will be return using this parameter
+
+  RETURN
+    0  - OK
+    -1 - error
+*/
+
+int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
 {
   TABLE_LIST *tables;
   bool refresh;
   int result=0;
   DBUG_ENTER("open_tables");
+  *counter= 0;
 
   thd->current_tablenr= 0;
  restart:
   thd->proc_info="Opening tables";
   for (tables=start ; tables ; tables=tables->next)
   {
+    /*
+      Ignore placeholders for derived tables. After derived tables
+      processing, link to created temporary table will be put here.
+     */
     if (tables->derived)
       continue;
+    (*counter)++;
     if (!tables->table &&
 	!(tables->table= open_table(thd,
 				    tables->db,
@@ -1533,14 +1548,19 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
     thd		- thread handler
     tables	- list of tables for open&locking
 
+  RETURN
+    0  - ok
+    -1 - error
+
   NOTE
     The lock will automaticly be freed by close_thread_tables()
 */
 
 int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
 {
-  DBUG_ENTER("open_n_lock_tables");
-  if (open_tables(thd, tables) || lock_tables(thd, tables))
+  DBUG_ENTER("simple_open_n_lock_tables");
+  uint counter;
+  if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
     DBUG_RETURN(-1);				/* purecov: inspected */
   DBUG_RETURN(0);
 }
@@ -1551,10 +1571,14 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
   tables processing.
 
   SYNOPSIS
-    simple_open_n_lock_tables()
+    open_and_lock_tables()
     thd		- thread handler
     tables	- list of tables for open&locking
 
+  RETURN
+    0  - ok
+    -1 - error
+
   NOTE
     The lock will automaticly be freed by close_thread_tables()
 */
@@ -1562,7 +1586,8 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
 int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
 {
   DBUG_ENTER("open_and_lock_tables");
-  if (open_tables(thd, tables) || lock_tables(thd, tables))
+  uint counter;
+  if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
     DBUG_RETURN(-1);				/* purecov: inspected */
   fix_tables_pointers(thd->lex->all_selects_list);
   DBUG_RETURN(mysql_handle_derived(thd->lex));
@@ -1576,6 +1601,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
     lock_tables()
     thd			Thread handler
     tables		Tables to lock
+    count		umber of opened tables
 
   NOTES
     You can't call lock_tables twice, as this would break the dead-lock-free
@@ -1587,7 +1613,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
    -1	Error
 */
 
-int lock_tables(THD *thd,TABLE_LIST *tables)
+int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
 {
   TABLE_LIST *table;
   if (!tables)
@@ -1596,12 +1622,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
   if (!thd->locked_tables)
   {
     DBUG_ASSERT(thd->lock == 0);	// You must lock everything at once
-    uint count=0;
-    for (table = tables ; table ; table=table->next)
-    {
-      if (!table->derived)
-	count++;
-    }
     TABLE **start,**ptr;
     if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
       return -1;
@@ -2207,7 +2227,6 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
       /* Ensure that we have access right to all columns */
       if (!(table->grant.privilege & SELECT_ACL) &&
-	  !tables->derived &&
 	  check_grant_all_columns(thd,SELECT_ACL,table))
 	DBUG_RETURN(-1);
 #endif
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index a307b59b525..6e70fdd46d5 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -25,7 +25,8 @@
 #include "sql_select.h"
 #include "sql_acl.h"
 
-int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
+static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
+			 TABLE_LIST *t);
 
 /*
   Resolve derived tables in all queries
@@ -39,10 +40,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
     -1	Error
     1	Error and error message given
 */
+
 int
 mysql_handle_derived(LEX *lex)
 {
-  int res= 0;
   if (lex->derived_tables)
   {
     for (SELECT_LEX *sl= lex->all_selects_list;
@@ -53,13 +54,12 @@ mysql_handle_derived(LEX *lex)
 	   cursor;
 	   cursor= cursor->next)
       {
+	int res;
 	if (cursor->derived && (res=mysql_derived(lex->thd, lex,
 						  cursor->derived,
 						  cursor)))
 	{
-	  if (res < 0 || lex->thd->net.report_error)
-	    send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0);
-	  return 1;
+	  return res;
 	}
       }
       if (lex->describe)
@@ -108,8 +108,8 @@ mysql_handle_derived(LEX *lex)
 */  
 
 
-int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
-		  TABLE_LIST *org_table_list)
+static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
+			 TABLE_LIST *org_table_list)
 {
   SELECT_LEX *first_select= unit->first_select();
   TABLE *table;
@@ -197,7 +197,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
       table->derived_select_number= first_select->select_number;
       table->tmp_table= TMP_TABLE;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
-      org_table_list->grant.privilege= SELECT_ACL;
+      table->grant.privilege= SELECT_ACL;
 #endif
       org_table_list->db= (char *)"";
       // Force read of table stats in the optimizer
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 405cfdb5bdc..897aa37ba11 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
 int mysql_ha_open(THD *thd, TABLE_LIST *tables)
 {
   HANDLER_TABLES_HACK(thd);
-  int err=open_tables(thd,tables);
+  uint counter;
+  int err=open_tables(thd, tables, &counter);
   HANDLER_TABLES_HACK(thd);
   if (err)
     return -1;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 14696ce7478..42ea6039b6c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2669,8 +2669,8 @@ mysql_execute_command(THD *thd)
     {
       auxi->table= auxi->table_list->table;
       /* 
-	 Multi-delete can't be constucted over-union => we always have
-	 single SELECT on top and have to check underlayed SELECTs of it
+	 Multi-delete can't be constructed over-union => we always have
+	 single SELECT on top and have to check underlaying SELECTs of it
       */
       for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
 	   un;

From 74b81a801785058706b46a1e75b67b026c468d04 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 9 Feb 2004 13:59:41 +0100
Subject: [PATCH 145/157] Ensure that result from date_format() is binary
 Removed warnings from test suite

mysql-test/r/ctype_utf8.result:
  Update results after fix of return argument from date_format()
mysql-test/r/date_formats.result:
  Remove unnecessary warnings
mysql-test/r/type_decimal.result:
  Remove unnecessary warnings
mysql-test/r/warnings.result:
  Remove unnecessary warnings
mysql-test/t/ctype_utf8.test:
  Fixed test
mysql-test/t/date_formats.test:
  Remove unnecessary warnings
mysql-test/t/type_decimal.test:
  Remove unnecessary warnings
mysql-test/t/warnings.test:
  Remove unnecessary warnings
sql/field.cc:
  Optimize
sql/item_timefunc.cc:
  Ensure that result from date_format() is binary
strings/ctype-simple.c:
  Better names for arguments
---
 mysql-test/r/ctype_utf8.result   |   3 +-
 mysql-test/r/date_formats.result |   2 -
 mysql-test/r/type_decimal.result | 123 -------------------------------
 mysql-test/r/warnings.result     |   3 -
 mysql-test/t/ctype_utf8.test     |   1 +
 mysql-test/t/date_formats.test   |   4 +-
 mysql-test/t/type_decimal.test   |   4 +-
 mysql-test/t/warnings.test       |   4 +-
 sql/field.cc                     |   5 +-
 sql/item_timefunc.cc             |  11 ++-
 strings/ctype-simple.c           |   6 +-
 11 files changed, 22 insertions(+), 144 deletions(-)

diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 31f26c421b6..815ab492fa4 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -73,7 +73,7 @@ create table t1 select date_format("2004-01-19 10:10:10", "%Y-%m-%d");
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
-  `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) character set utf8 default NULL
+  `date_format("2004-01-19 10:10:10", "%Y-%m-%d")` char(10) binary default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 select * from t1;
 date_format("2004-01-19 10:10:10", "%Y-%m-%d")
@@ -87,3 +87,4 @@ Warning	1264	Data truncated for column 's1' at row 1
 select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
 s1	hex(s1)	char_length(s1)	octet_length(s1)
 Α	D0B0	1	2
+drop table t1;
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index ee4fa074477..165a8d7011c 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -1,6 +1,4 @@
 drop table if exists t1;
-Warnings:
-Note	1051	Unknown table 't1'
 SHOW GLOBAL VARIABLES LIKE "%_format%";
 Variable_name	Value
 date_format	%d.%m.%Y
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 97d81d77722..fa4cd231129 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -446,39 +446,6 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,1));
 ERROR 42000: You have an error in your SQL syntax.  Check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1
 create table t1(a decimal(7,3));
 insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
-Warnings:
-Warning	1263	Data truncated, out of range for column 'a' at row 27
-Warning	1263	Data truncated, out of range for column 'a' at row 30
-Warning	1263	Data truncated, out of range for column 'a' at row 31
-Warning	1263	Data truncated, out of range for column 'a' at row 32
-Warning	1263	Data truncated, out of range for column 'a' at row 33
-Warning	1263	Data truncated, out of range for column 'a' at row 34
-Warning	1263	Data truncated, out of range for column 'a' at row 35
-Warning	1263	Data truncated, out of range for column 'a' at row 36
-Warning	1263	Data truncated, out of range for column 'a' at row 37
-Warning	1263	Data truncated, out of range for column 'a' at row 38
-Warning	1263	Data truncated, out of range for column 'a' at row 39
-Warning	1263	Data truncated, out of range for column 'a' at row 40
-Warning	1263	Data truncated, out of range for column 'a' at row 41
-Warning	1263	Data truncated, out of range for column 'a' at row 42
-Warning	1263	Data truncated, out of range for column 'a' at row 43
-Warning	1263	Data truncated, out of range for column 'a' at row 44
-Warning	1263	Data truncated, out of range for column 'a' at row 45
-Warning	1263	Data truncated, out of range for column 'a' at row 46
-Warning	1263	Data truncated, out of range for column 'a' at row 47
-Warning	1263	Data truncated, out of range for column 'a' at row 48
-Warning	1263	Data truncated, out of range for column 'a' at row 49
-Warning	1263	Data truncated, out of range for column 'a' at row 50
-Warning	1263	Data truncated, out of range for column 'a' at row 51
-Warning	1263	Data truncated, out of range for column 'a' at row 52
-Warning	1263	Data truncated, out of range for column 'a' at row 53
-Warning	1263	Data truncated, out of range for column 'a' at row 54
-Warning	1263	Data truncated, out of range for column 'a' at row 55
-Warning	1263	Data truncated, out of range for column 'a' at row 56
-Warning	1263	Data truncated, out of range for column 'a' at row 57
-Warning	1263	Data truncated, out of range for column 'a' at row 58
-Warning	1263	Data truncated, out of range for column 'a' at row 59
-Warning	1263	Data truncated, out of range for column 'a' at row 60
 select * from t1;
 a
 1.000
@@ -544,51 +511,6 @@ a
 drop table t1;
 create table t1(a decimal(7,3) unsigned);
 insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
-Warnings:
-Warning	1263	Data truncated, out of range for column 'a' at row 3
-Warning	1263	Data truncated, out of range for column 'a' at row 6
-Warning	1263	Data truncated, out of range for column 'a' at row 9
-Warning	1263	Data truncated, out of range for column 'a' at row 12
-Warning	1263	Data truncated, out of range for column 'a' at row 15
-Warning	1263	Data truncated, out of range for column 'a' at row 18
-Warning	1263	Data truncated, out of range for column 'a' at row 21
-Warning	1263	Data truncated, out of range for column 'a' at row 24
-Warning	1263	Data truncated, out of range for column 'a' at row 25
-Warning	1263	Data truncated, out of range for column 'a' at row 26
-Warning	1263	Data truncated, out of range for column 'a' at row 27
-Warning	1263	Data truncated, out of range for column 'a' at row 28
-Warning	1263	Data truncated, out of range for column 'a' at row 29
-Warning	1263	Data truncated, out of range for column 'a' at row 30
-Warning	1263	Data truncated, out of range for column 'a' at row 31
-Warning	1263	Data truncated, out of range for column 'a' at row 32
-Warning	1263	Data truncated, out of range for column 'a' at row 33
-Warning	1263	Data truncated, out of range for column 'a' at row 34
-Warning	1263	Data truncated, out of range for column 'a' at row 35
-Warning	1263	Data truncated, out of range for column 'a' at row 36
-Warning	1263	Data truncated, out of range for column 'a' at row 37
-Warning	1263	Data truncated, out of range for column 'a' at row 38
-Warning	1263	Data truncated, out of range for column 'a' at row 39
-Warning	1263	Data truncated, out of range for column 'a' at row 40
-Warning	1263	Data truncated, out of range for column 'a' at row 41
-Warning	1263	Data truncated, out of range for column 'a' at row 42
-Warning	1263	Data truncated, out of range for column 'a' at row 43
-Warning	1263	Data truncated, out of range for column 'a' at row 44
-Warning	1263	Data truncated, out of range for column 'a' at row 45
-Warning	1263	Data truncated, out of range for column 'a' at row 46
-Warning	1263	Data truncated, out of range for column 'a' at row 47
-Warning	1263	Data truncated, out of range for column 'a' at row 48
-Warning	1263	Data truncated, out of range for column 'a' at row 49
-Warning	1263	Data truncated, out of range for column 'a' at row 50
-Warning	1263	Data truncated, out of range for column 'a' at row 51
-Warning	1263	Data truncated, out of range for column 'a' at row 52
-Warning	1263	Data truncated, out of range for column 'a' at row 53
-Warning	1263	Data truncated, out of range for column 'a' at row 54
-Warning	1263	Data truncated, out of range for column 'a' at row 55
-Warning	1263	Data truncated, out of range for column 'a' at row 56
-Warning	1263	Data truncated, out of range for column 'a' at row 57
-Warning	1263	Data truncated, out of range for column 'a' at row 58
-Warning	1263	Data truncated, out of range for column 'a' at row 59
-Warning	1263	Data truncated, out of range for column 'a' at row 60
 select * from t1;
 a
 1.000
@@ -654,51 +576,6 @@ a
 drop table t1;
 create table t1(a decimal(7,3) zerofill);
 insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
-Warnings:
-Warning	1263	Data truncated, out of range for column 'a' at row 3
-Warning	1263	Data truncated, out of range for column 'a' at row 6
-Warning	1263	Data truncated, out of range for column 'a' at row 9
-Warning	1263	Data truncated, out of range for column 'a' at row 12
-Warning	1263	Data truncated, out of range for column 'a' at row 15
-Warning	1263	Data truncated, out of range for column 'a' at row 18
-Warning	1263	Data truncated, out of range for column 'a' at row 21
-Warning	1263	Data truncated, out of range for column 'a' at row 24
-Warning	1263	Data truncated, out of range for column 'a' at row 25
-Warning	1263	Data truncated, out of range for column 'a' at row 26
-Warning	1263	Data truncated, out of range for column 'a' at row 27
-Warning	1263	Data truncated, out of range for column 'a' at row 28
-Warning	1263	Data truncated, out of range for column 'a' at row 29
-Warning	1263	Data truncated, out of range for column 'a' at row 30
-Warning	1263	Data truncated, out of range for column 'a' at row 31
-Warning	1263	Data truncated, out of range for column 'a' at row 32
-Warning	1263	Data truncated, out of range for column 'a' at row 33
-Warning	1263	Data truncated, out of range for column 'a' at row 34
-Warning	1263	Data truncated, out of range for column 'a' at row 35
-Warning	1263	Data truncated, out of range for column 'a' at row 36
-Warning	1263	Data truncated, out of range for column 'a' at row 37
-Warning	1263	Data truncated, out of range for column 'a' at row 38
-Warning	1263	Data truncated, out of range for column 'a' at row 39
-Warning	1263	Data truncated, out of range for column 'a' at row 40
-Warning	1263	Data truncated, out of range for column 'a' at row 41
-Warning	1263	Data truncated, out of range for column 'a' at row 42
-Warning	1263	Data truncated, out of range for column 'a' at row 43
-Warning	1263	Data truncated, out of range for column 'a' at row 44
-Warning	1263	Data truncated, out of range for column 'a' at row 45
-Warning	1263	Data truncated, out of range for column 'a' at row 46
-Warning	1263	Data truncated, out of range for column 'a' at row 47
-Warning	1263	Data truncated, out of range for column 'a' at row 48
-Warning	1263	Data truncated, out of range for column 'a' at row 49
-Warning	1263	Data truncated, out of range for column 'a' at row 50
-Warning	1263	Data truncated, out of range for column 'a' at row 51
-Warning	1263	Data truncated, out of range for column 'a' at row 52
-Warning	1263	Data truncated, out of range for column 'a' at row 53
-Warning	1263	Data truncated, out of range for column 'a' at row 54
-Warning	1263	Data truncated, out of range for column 'a' at row 55
-Warning	1263	Data truncated, out of range for column 'a' at row 56
-Warning	1263	Data truncated, out of range for column 'a' at row 57
-Warning	1263	Data truncated, out of range for column 'a' at row 58
-Warning	1263	Data truncated, out of range for column 'a' at row 59
-Warning	1263	Data truncated, out of range for column 'a' at row 60
 select * from t1;
 a
 0001.000
diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result
index c3d9f165fed..b675d189d30 100644
--- a/mysql-test/r/warnings.result
+++ b/mysql-test/r/warnings.result
@@ -1,7 +1,4 @@
 drop table if exists t1, t2;
-Warnings:
-Note	1051	Unknown table 't1'
-Note	1051	Unknown table 't2'
 SET SQL_WARNINGS=1;
 create table t1 (a int);
 insert into t1 values (1);
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index c2ea1ed20a4..9da7b32eb6d 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -60,3 +60,4 @@ set names koi8r;
 create table t1 (s1 char(1) character set utf8);
 insert into t1 values (_koi8r'ΑΒ');
 select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
+drop table t1;
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
index 7b88c0ecf72..18af3dfb3db 100644
--- a/mysql-test/t/date_formats.test
+++ b/mysql-test/t/date_formats.test
@@ -2,9 +2,9 @@
 # Test of date format functions
 #
 
---disable-warnings
+--disable_warnings
 drop table if exists t1;
---enable-warnings
+--enable_warnings
 
 SHOW GLOBAL VARIABLES LIKE "%_format%";
 SHOW SESSION VARIABLES LIKE "%_format%";
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index cddb0347b7e..3257002ae2c 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -248,7 +248,7 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,1));
 #
 #  Zero prepend overflow bug
 #
---disable-warnings
+--disable_warnings
 create table t1(a decimal(7,3));
 insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
 select * from t1;
@@ -259,6 +259,6 @@ select * from t1;
 drop table t1;
 create table t1(a decimal(7,3) zerofill);
 insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000');
---enable-warnings
+--enable_warnings
 select * from t1;
 drop table t1;
diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test
index 0456ca8c1fe..b6042df51f1 100644
--- a/mysql-test/t/warnings.test
+++ b/mysql-test/t/warnings.test
@@ -1,9 +1,9 @@
 #
 # Test some warnings
 #
---disable-warnings
+--disable_warnings
 drop table if exists t1, t2;
---enable-warnings
+--enable_warnings
 SET SQL_WARNINGS=1;
 
 create table t1 (a int);
diff --git a/sql/field.cc b/sql/field.cc
index 6f29737e4a0..cce7446dcff 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4072,7 +4072,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
   }
 
   /* 
-    Make sure we don't break a multybite sequence
+    Make sure we don't break a multibyte sequence
     as well as don't copy a malformed data.
   */
   copy_length= field_charset->cset->wellformedlen(field_charset,
@@ -4084,8 +4084,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
     field_charset->cset->fill(field_charset,ptr+copy_length,
 			      field_length-copy_length,' ');
   
-  
-  if (current_thd->count_cuted_fields && (copy_length < length))
+  if ((copy_length < length) && current_thd->count_cuted_fields)
   {					// Check if we loosed some info
     const char *end=from+length;
     from+= copy_length;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 062e7fc7b44..32fbe192d8f 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1283,16 +1283,21 @@ longlong Item_func_sec_to_time::val_int()
 void Item_func_date_format::fix_length_and_dec()
 {
   decimals=0;
+  collation.set(&my_charset_bin);
   if (args[1]->type() == STRING_ITEM)
   {						// Optimize the normal case
     fixed_length=1;
-    max_length= format_length(((Item_string*) args[1])->const_string())*
-		collation.collation->mbmaxlen;
+    /*
+      The result is a binary string (no reason to use collation->mbmaxlen
+      This is becasue make_date_time() only returns binary strings
+    */
+    max_length= format_length(((Item_string*) args[1])->const_string());
   }
   else
   {
     fixed_length=0;
-    max_length=args[1]->max_length*10*collation.collation->mbmaxlen;
+    /* The result is a binary string (no reason to use collation->mbmaxlen */
+    max_length=args[1]->max_length*10;
     set_if_smaller(max_length,MAX_BLOB_WIDTH);
   }
   maybe_null=1;					// If wrong date
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index fb2dee99ba5..233251e16a8 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -1021,11 +1021,11 @@ uint my_charpos_8bit(CHARSET_INFO *cs __attribute__((unused)),
 }
 
 uint my_wellformedlen_8bit(CHARSET_INFO *cs __attribute__((unused)),
-			const char *b,
-			const char *e,
+			const char *start,
+			const char *end,
 			uint nchars)
 {
-  uint nbytes= e-b;
+  uint nbytes= (uint) (end-start);
   return nbytes < nchars ? nbytes : nchars;
 }
 

From c4d0631b516e62dd66bf8cc3263db133f3dc7108 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 9 Feb 2004 16:26:38 +0300
Subject: [PATCH 146/157] switch off SERVER_MORE_RESULTS_EXISTS, but don't set
 other flags: it breaks future extensions

---
 sql/protocol.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql/protocol.cc b/sql/protocol.cc
index 2d2736b20d2..bef567ad346 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -123,7 +123,7 @@ void send_error(THD *thd, uint sql_errno, const char *err)
 
   /* Abort multi-result sets */
   thd->lex->found_colon= 0;
-  thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
+  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
   DBUG_VOID_RETURN;
 }
 
@@ -356,7 +356,7 @@ send_eof(THD *thd, bool no_flush)
 	other queries (see the if test in dispatch_command / COM_QUERY)
       */
       if (thd->is_fatal_error)
-	thd->server_status= ~SERVER_MORE_RESULTS_EXISTS;
+	thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
       int2store(buff+3, thd->server_status);
       VOID(my_net_write(net,(char*) buff,5));
       VOID(net_flush(net));

From d5b3cb44b9a96d2154af4b0b7520f1e2cd3d3e58 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Mon, 9 Feb 2004 23:47:28 +0100
Subject: [PATCH 147/157] Fix for the rpl_until.test. Don't use --command in
 tests; use command.

mysql-test/r/rpl_until.result:
  result update
mysql-test/t/rpl_until.test:
  real-sleep is incorrect syntax; mysqltest knows only real_sleep.
  Tip: don't use -- before commands; if mysqltest does not recognize the command
  after -- it just says "it must be a comment", so there is no syntax error detection.
  If you don't use the -- it will report the syntax error.
  The typo caused no sleep, so the slave did not have time to stop.
  Now it has time so we needn't replace the Slave_SQL_Running
  (and it's better to not replace it, because if we don't see that it
  is running, it will trigger errors just a bit later).
---
 mysql-test/r/rpl_until.result | 2 +-
 mysql-test/t/rpl_until.test   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index cb60ccfb1c9..82b1ed233ec 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -55,7 +55,7 @@ stop slave;
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
 show slave status;
 Slave_IO_State	Master_Host	Master_User	Master_Port	Connect_Retry	Master_Log_File	Read_Master_Log_Pos	Relay_Log_File	Relay_Log_Pos	Relay_Master_Log_File	Slave_IO_Running	Slave_SQL_Running	Replicate_Do_DB	Replicate_Ignore_DB	Replicate_Do_Table	Replicate_Ignore_Table	Replicate_Wild_Do_Table	Replicate_Wild_Ignore_Table	Last_Errno	Last_Error	Skip_Counter	Exec_Master_Log_Pos	Relay_Log_Space	Until_Condition	Until_Log_File	Until_Log_Pos	Master_SSL_Allowed	Master_SSL_CA_File	Master_SSL_CA_Path	Master_SSL_Cert	Master_SSL_Cipher	Master_SSL_Key	Seconds_Behind_Master
-#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	#	master-bin.000001	Yes	#							0		0	561	#	Master	master-bin.000001	561	No						#
+#	127.0.0.1	root	MASTER_MYPORT	1	master-bin.000001	561	slave-relay-bin.000002	#	master-bin.000001	Yes	No							0		0	561	#	Master	master-bin.000001	561	No						#
 start slave until master_log_file='master-bin', master_log_pos=561;
 ERROR HY000: Wrong parameter or combination of parameters for START SLAVE UNTIL
 start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index 937a8c03f99..40d36110296 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -60,10 +60,10 @@ stop slave;
 # this should stop immideately
 start slave until master_log_file='master-bin.000001', master_log_pos=561;
 # 2 is not enough when running with valgrind
---real-sleep 4;
+real_sleep 4
 # here the sql slave thread should be stopped
 --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
---replace_column 1 # 9 # 12 # 23 # 33 #
+--replace_column 1 # 9 # 23 # 33 #
 show slave status;
 
 #testing various error conditions

From ecb11989ad22af2cdd2359dbb96705af240f1c84 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 02:18:22 +0200
Subject: [PATCH 148/157] after merge & valgrind test fixes (BUG#2120)

sql/sql_derived.cc:
  memory leack fixed
sql/sql_lex.cc:
  flag to avoid double cleaning
sql/sql_lex.h:
  flag to avoid double cleaning
sql/sql_select.cc:
  right way to cleanup JOIN_TAB
sql/sql_select.h:
  right way to cleanup JOIN_TAB
sql/sql_union.cc:
  flag to avoid double cleaning
---
 sql/sql_derived.cc |  2 ++
 sql/sql_lex.cc     |  1 +
 sql/sql_lex.h      |  3 ++-
 sql/sql_select.cc  | 66 ++++++++++++++++++++++++++--------------------
 sql/sql_select.h   |  2 ++
 sql/sql_union.cc   |  6 +++++
 6 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 6e70fdd46d5..0e04316a2e7 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -204,6 +204,8 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
       table->file->info(HA_STATUS_VARIABLE);
     }
 
+    if (!lex->describe)
+      unit->cleanup();
     if (res)
       free_tmp_table(thd, table);
     else
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 62f255ea178..65357328927 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -988,6 +988,7 @@ void st_select_lex_unit::init_query()
   union_result= 0;
   table= 0;
   fake_select_lex= 0;
+  cleaned= 0;
 }
 
 void st_select_lex::init_query()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3b1b3873706..3f56be18c4a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -305,7 +305,8 @@ protected:
   ulong found_rows_for_union;
   bool  prepared, // prepare phase already performed for UNION (unit)
     optimized, // optimize phase already performed for UNION (unit)
-    executed; // already executed
+    executed, // already executed
+    cleaned;
 
 public:
   // list of fields which points to temporary table for union
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 082a06d97de..ea5050f2550 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1510,12 +1510,7 @@ JOIN::cleanup()
       JOIN_TAB *tab, *end;
       for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
       {
-	delete tab->select;
-	delete tab->quick;
-	tab->select=0;
-	tab->quick=0;
-	x_free(tab->cache.buff);
-	tab->cache.buff= 0;
+	tab->cleanup();
       }
     }
     tmp_join->tmp_join= 0;
@@ -3759,6 +3754,41 @@ bool error_if_full_join(JOIN *join)
 }
 
 
+/*
+  cleanup JOIN_TAB
+
+  SYNOPSIS
+    JOIN_TAB::cleanup()
+*/
+
+void JOIN_TAB::cleanup()
+{
+  delete select;
+  select= 0;
+  delete quick;
+  quick= 0;
+  x_free(cache.buff);
+  cache.buff= 0;
+  if (table)
+  {
+    if (table->key_read)
+    {
+      table->key_read= 0;
+      table->file->extra(HA_EXTRA_NO_KEYREAD);
+    }
+    /* Don't free index if we are using read_record */
+    if (!read_record.table)
+      table->file->index_end();
+    /*
+      We need to reset this for next select
+      (Tested in part_of_refkey)
+    */
+    table->reginfo.join_tab= 0;
+  }
+  end_read_record(&read_record);
+}
+
+
 /*
   Free resources of given join
 
@@ -3803,29 +3833,7 @@ JOIN::join_free(bool full)
     {
       for (tab= join_tab, end= tab+tables; tab != end; tab++)
       {
-	delete tab->select;
-	delete tab->quick;
-	tab->select=0;
-	tab->quick=0;
-	x_free(tab->cache.buff);
-	tab->cache.buff= 0;
-	if (tab->table)
-	{
-	  if (tab->table->key_read)
-	  {
-	    tab->table->key_read= 0;
-	    tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
-	  }
-	  /* Don't free index if we are using read_record */
-	  if (!tab->read_record.table)
-	    tab->table->file->index_end();
-	  /*
-	    We need to reset this for next select
-	    (Tested in part_of_refkey)
-	  */
-	  tab->table->reginfo.join_tab= 0;
-	}
-	end_read_record(&tab->read_record);
+	tab->cleanup();
       }
       table= 0;
     }
diff --git a/sql/sql_select.h b/sql/sql_select.h
index a463378006b..36526bee066 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -108,6 +108,8 @@ typedef struct st_join_table {
   TABLE_REF	ref;
   JOIN_CACHE	cache;
   JOIN		*join;
+
+  void cleanup();
 } JOIN_TAB;
 
 
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 226086d0d24..75fd9be88bd 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -442,6 +442,12 @@ int st_select_lex_unit::cleanup()
   int error= 0;
   DBUG_ENTER("st_select_lex_unit::cleanup");
 
+  if (cleaned)
+  {
+    DBUG_RETURN(0);
+  }
+  cleaned= 0;
+
   if (union_result)
   {
     delete union_result;

From 102a9c6f50416b3faf79abd3ea360dd3b49b7513 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 15:42:46 +0400
Subject: [PATCH 149/157] http://bugs.mysql.com/bug.php?id=2368 Multibyte
 charsets do not check that incoming data is well-formed

---
 BUILD/compile-pentium-debug-max-no-embedded | 13 +++++
 mysql-test/r/ctype_utf8.result              | 55 +++++++++++++++++++++
 mysql-test/t/ctype_utf8.test                | 19 +++++++
 sql/field.cc                                | 32 ++++++------
 sql/field.h                                 |  9 ++++
 strings/ctype-mb.c                          | 17 ++++---
 6 files changed, 120 insertions(+), 25 deletions(-)
 create mode 100755 BUILD/compile-pentium-debug-max-no-embedded

diff --git a/BUILD/compile-pentium-debug-max-no-embedded b/BUILD/compile-pentium-debug-max-no-embedded
new file mode 100755
index 00000000000..4554e38fdc1
--- /dev/null
+++ b/BUILD/compile-pentium-debug-max-no-embedded
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-openssl --with-raid"
+
+. "$path/FINISH.sh"
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 815ab492fa4..a75b2b6065c 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -88,3 +88,58 @@ select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
 s1	hex(s1)	char_length(s1)	octet_length(s1)
 Α	D0B0	1	2
 drop table t1;
+create table t1 (s1 tinytext character set utf8);
+insert into t1 select repeat('a',300);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('Ρ',300);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('aΡ',300);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('Ρa',300);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('ΡΡ',300);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select hex(s1) from t1;
+hex(s1)
+616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161
+D18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18F
+61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F
+D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61D18F61
+D18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18FD18F
+select length(s1),char_length(s1) from t1;
+length(s1)	char_length(s1)
+255	255
+254	127
+255	170
+255	170
+254	127
+drop table t1;
+create table t1 (s1 text character set utf8);
+insert into t1 select repeat('a',66000);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('Ρ',66000);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('aΡ',66000);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('Ρa',66000);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+insert into t1 select repeat('ΡΡ',66000);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select length(s1),char_length(s1) from t1;
+length(s1)	char_length(s1)
+65535	65535
+65534	32767
+65535	43690
+65535	43690
+65534	32767
+drop table t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 9da7b32eb6d..0d42533c95f 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -61,3 +61,22 @@ create table t1 (s1 char(1) character set utf8);
 insert into t1 values (_koi8r'ΑΒ');
 select s1,hex(s1),char_length(s1),octet_length(s1) from t1;
 drop table t1;
+
+create table t1 (s1 tinytext character set utf8);
+insert into t1 select repeat('a',300);
+insert into t1 select repeat('Ρ',300);
+insert into t1 select repeat('aΡ',300);
+insert into t1 select repeat('Ρa',300);
+insert into t1 select repeat('ΡΡ',300);
+select hex(s1) from t1;
+select length(s1),char_length(s1) from t1;
+drop table t1;
+
+create table t1 (s1 text character set utf8);
+insert into t1 select repeat('a',66000);
+insert into t1 select repeat('Ρ',66000);
+insert into t1 select repeat('aΡ',66000);
+insert into t1 select repeat('Ρa',66000);
+insert into t1 select repeat('ΡΡ',66000);
+select length(s1),char_length(s1) from t1;
+drop table t1;
diff --git a/sql/field.cc b/sql/field.cc
index cce7446dcff..d26534b5ac7 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4485,19 +4485,9 @@ void Field_blob::store_length(uint32 number)
 {
   switch (packlength) {
   case 1:
-    if (number > 255)
-    {
-      number=255;
-      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
-    }
     ptr[0]= (uchar) number;
     break;
   case 2:
-    if (number > (uint16) ~0)
-    {
-      number= (uint16) ~0;
-      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
-    }
 #ifdef WORDS_BIGENDIAN
     if (table->db_low_byte_first)
     {
@@ -4508,11 +4498,6 @@ void Field_blob::store_length(uint32 number)
       shortstore(ptr,(unsigned short) number);
     break;
   case 3:
-    if (number > (uint32) (1L << 24))
-    {
-      number= (uint32) (1L << 24)-1L;
-      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
-    }
     int3store(ptr,number);
     break;
   case 4:
@@ -4573,6 +4558,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
     bool was_conversion;
     char buff[80];
     String tmpstr(buff,sizeof(buff), &my_charset_bin);
+    uint copy_length;
     uint32 not_used;
 
     /* Convert character set if nesessary */
@@ -4583,12 +4569,22 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
       from= tmpstr.ptr();
       length=  tmpstr.length();
     }
-    Field_blob::store_length(length);
-    if (was_conversion || table->copy_blobs || length <= MAX_FIELD_WIDTH)
+    
+    copy_length= max_data_length();
+    if (copy_length > length)
+      copy_length= length;
+    copy_length= field_charset->cset->wellformedlen(field_charset,
+                                                    from,from+copy_length,
+                                                    field_length);
+    if (copy_length < length)
+      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
+    
+    Field_blob::store_length(copy_length);
+    if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
     {						// Must make a copy
       if (from != value.ptr())			// For valgrind
       {
-	value.copy(from,length,charset());
+	value.copy(from,copy_length,charset());
 	from=value.ptr();
       }
     }
diff --git a/sql/field.h b/sql/field.h
index 9a12fd48e54..b62b7a7859e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -949,6 +949,15 @@ public:
   void sort_string(char *buff,uint length);
   uint32 pack_length() const
   { return (uint32) (packlength+table->blob_ptr_size); }
+  uint32 max_data_length() const
+  {
+    switch (packlength) {
+    case 1: return 255;
+    case 2: return (uint32) 0xFFFFL;
+    case 3: return (uint32) 0xFFFFFF;
+    default: return (uint32) 0xFFFFFFFF;
+    }
+  }
   void reset(void) { bzero(ptr, packlength+sizeof(char*)); }
   void reset_fields() { bzero((char*) &value,sizeof(value)); }
   void store_length(uint32 number);
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 377bf311d38..46f3e2f4fc3 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -274,18 +274,21 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
   return pos ? e+2-b0 : b-b0;
 }
 
-uint my_wellformedlen_mb(CHARSET_INFO *cs __attribute__((unused)),
-		     const char *b, const char *e, uint pos)
+uint my_wellformedlen_mb(CHARSET_INFO *cs,
+			 const char *b, const char *e, uint pos)
 {
-  uint mblen;
-  const char *b0=b;
+  my_wc_t wc;
+  int mblen;
+  const char *b0= b;
   
-  while (pos && bcset->mb_wc(cs, &wc, b, e)) <0)
+      break;
+    b+= mblen;
     pos--;
   }
-  return b-b0;
+  return b - b0;
 }
 
 

From 4138b2ac5f51e71737b025ce04342866b384edc4 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 13:11:55 +0000
Subject: [PATCH 150/157] An include was missing.

BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
---
 BitKeeper/etc/logging_ok | 1 +
 sql/sql_string.cc        | 1 +
 2 files changed, 2 insertions(+)

diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index a7eb7c81105..2eb24c49273 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -54,6 +54,7 @@ jani@janikt.pp.saunalahti.fi
 jani@rhols221.adsl.netsonic.fi
 jani@rhols221.arenanet.fi
 jani@ua126d19.elisa.omakaista.fi
+jani@ua141d10.elisa.omakaista.fi
 jani@ua167d18.elisa.omakaista.fi
 jcole@abel.spaceapes.com
 jcole@main.burghcom.com
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index cbee67c0a4a..093b85b46b7 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #ifdef HAVE_FCONVERT
 #include 
 #endif

From dc792940232f3265e21905cb939853f4db5ebd16 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 13:36:21 +0000
Subject: [PATCH 151/157] Wrong type of an argument was sent to
 my_printf_error(), which caused UDF functions to segmenation fault when they
 tried to print an error during wrong usage.

---
 sql/item_func.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sql/item_func.cc b/sql/item_func.cc
index b1378784f92..34a61ba0353 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1552,7 +1552,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
     if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
     {
       my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
-		      u_d->name,thd->net.last_error);
+		      u_d->name.str, thd->net.last_error);
       free_udf(u_d);
       DBUG_RETURN(1);
     }
@@ -1565,7 +1565,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
   if (error)
   {
     my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
-		    u_d->name, ER(ER_UNKNOWN_ERROR));
+		    u_d->name.str, ER(ER_UNKNOWN_ERROR));
     DBUG_RETURN(1);
   }
   DBUG_RETURN(0);

From 757c8c8a62b6b780f48d6f197981839ebb028fb8 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 15:14:48 +0100
Subject: [PATCH 152/157] Follow-up of a discussion on dev-docs@ : Don't show
 PSEUDO_THREAD_ID in SHOW VARIABLES because: - we don't want people to
 discover this variable as it could never do good to set it (it was designed
 for use by mysqlbinlog only, so that a thread can have several temp tables of
 the same name at the same time) - if we show it in SHOW VARIABLES, Mysql
 Administrator will display it and this will force us to put a description, so
 all MySQL Administrator user will be aware of this variable, some may have
 the idea to set it with a SET command, and then it will cause bad things. The
 variable is still settable, and still visible with SELECT @@.

sql/set_var.cc:
  Don't show PSEUDO_THREAD_ID in SHOW VARIABLES because:
  - we don't want people to discover this variable as it could never do good to
  set it (it was designed for use by mysqlbinlog only, so that a thread can have
  several temp tables of the same name at the same time)
  - if we show it in SHOW VARIABLES, Mysql Administrator will display it and
  this will force us to put a description, so all MySQL Administrator user
  will be aware of this variable, some may have the idea to set it with a SET
  command, and then it will cause bad things.
  The variable is still settable, and still visible with SELECT @@.
---
 sql/set_var.cc | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sql/set_var.cc b/sql/set_var.cc
index ecb85440068..073330e06be 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -695,7 +695,6 @@ struct show_var_st init_vars[]= {
   {"port",                    (char*) &mysqld_port,                  SHOW_INT},
   {"protocol_version",        (char*) &protocol_version,            SHOW_INT},
   {sys_preload_buff_size.name, (char*) &sys_preload_buff_size,      SHOW_SYS},
-  {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id,        SHOW_SYS},
   {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
    SHOW_SYS},
 #ifdef HAVE_QUERY_CACHE

From aaa35925ac66b00eb1fcee5e4bcc9c05472f6950 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 18:44:27 +0400
Subject: [PATCH 153/157] added skiped newline to the end of file
 mysql-test/t/mysqldump.test

mysql-test/t/mysqldump.test:
  added skiped newline to the end of file
---
 mysql-test/t/mysqldump.test | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index e6115b61bbf..eca83ce77d8 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -60,4 +60,4 @@ DROP TABLE t1;
 
 create table ```a` (i int);
 --exec $MYSQL_DUMP  --skip-comments test
-drop table ```a`;
\ No newline at end of file
+drop table ```a`;

From e4f3eb79be9dc5da27097f73e9477d9318373105 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 19:29:28 +0400
Subject: [PATCH 154/157] correcting mysql-test/r/mysqldump.result after merge

mysql-test/r/mysqldump.result:
  correcting result after merge
---
 mysql-test/r/mysqldump.result | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 37a604258d9..fd9e2a1f42b 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -180,6 +180,11 @@ UNLOCK TABLES;
 
 DROP TABLE t1;
 create table ```a` (i int);
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT, CHARACTER_SET_CLIENT=utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=NO_AUTO_VALUE_ON_ZERO */;
 DROP TABLE IF EXISTS ```a`;
 CREATE TABLE ``a` (
   `i` int(11) default NULL

From ad2c55b6ce922f9541d15b6817ce54419c462e2b Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 19:33:04 +0400
Subject: [PATCH 155/157] Bug #2368  	Multibyte charsets do not check that
 incoming data is well-formed It was together with the previous but. This test
 tends to prove it.

---
 mysql-test/r/ctype_utf8.result | 24 ++++++++++++++++++++++++
 mysql-test/t/ctype_utf8.test   | 18 ++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index a75b2b6065c..658a7b8f5f6 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -143,3 +143,27 @@ length(s1)	char_length(s1)
 65535	43690
 65534	32767
 drop table t1;
+create table t1 (s1 char(10) character set utf8);
+insert into t1 values (0x41FF);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select hex(s1) from t1;
+hex(s1)
+41
+drop table t1;
+create table t1 (s1 varchar(10) character set utf8);
+insert into t1 values (0x41FF);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select hex(s1) from t1;
+hex(s1)
+41
+drop table t1;
+create table t1 (s1 text character set utf8);
+insert into t1 values (0x41FF);
+Warnings:
+Warning	1264	Data truncated for column 's1' at row 1
+select hex(s1) from t1;
+hex(s1)
+41
+drop table t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 0d42533c95f..0615de99b7a 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -80,3 +80,21 @@ insert into t1 select repeat('
 insert into t1 select repeat('ΡΡ',66000);
 select length(s1),char_length(s1) from t1;
 drop table t1;
+
+#
+# Bug #2368 Multibyte charsets do not check that incoming data is well-formed
+#
+create table t1 (s1 char(10) character set utf8);
+insert into t1 values (0x41FF);
+select hex(s1) from t1;
+drop table t1;
+
+create table t1 (s1 varchar(10) character set utf8);
+insert into t1 values (0x41FF);
+select hex(s1) from t1;
+drop table t1;
+
+create table t1 (s1 text character set utf8);
+insert into t1 values (0x41FF);
+select hex(s1) from t1;
+drop table t1;

From f709bc18607a52d280e13aab3fb0a29ff09a214b Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 19:33:05 +0400
Subject: [PATCH 156/157] configure.in:   FreeBSD "ps" detection usually
 failed, in 90% cases,   on FreeBSD-5.1. This change should work fine under  
 5.x and 4.x, and I believe in 3.x. too.

configure.in:
  FreeBSD "ps" detection usually failed, in 90% cases. Thi
---
 configure.in | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/configure.in b/configure.in
index e607f87747b..9cdb9d209c2 100644
--- a/configure.in
+++ b/configure.in
@@ -452,6 +452,9 @@ then
   FIND_PROC="$PS \$\$PID | grep mysqld > /dev/null"
 else
   case $SYSTEM_TYPE in
+    *freebsd*)
+      FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null"
+      ;;
     *darwin*)
       FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null"
       ;;

From 98216bc9d4a65bd133d9a374fd3fe77d8c333d33 Mon Sep 17 00:00:00 2001
From: unknown 
Date: Tue, 10 Feb 2004 18:33:06 +0300
Subject: [PATCH 157/157] Another implementation of send_eof() cleanup

---
 sql/protocol.cc | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/sql/protocol.cc b/sql/protocol.cc
index bef567ad346..40adc9e8961 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -313,6 +313,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
   DBUG_VOID_RETURN;
 }
 
+static char eof_buff[1]= { (char) 254 };        /* Marker for end of fields */
 
 /*
   Send eof (= end of result set) to the client
@@ -339,12 +340,11 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
 void
 send_eof(THD *thd, bool no_flush)
 {
-  static char eof_buff[1]= { (char) 254 };	/* Marker for end of fields */
   NET *net= &thd->net;
   DBUG_ENTER("send_eof");
   if (net->vio != 0)
   {
-    if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
+    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
     {
       uchar buff[5];
       uint tmp= min(thd->total_warn_count, 65535);
@@ -384,9 +384,8 @@ send_eof(THD *thd, bool no_flush)
 
 bool send_old_password_request(THD *thd)
 {
-  static char buff[1]= { (char) 254 };
   NET *net= &thd->net;
-  return my_net_write(net, buff, 1) || net_flush(net);
+  return my_net_write(net, eof_buff, 1) || net_flush(net);
 }
 
 #endif /* EMBEDDED_LIBRARY */
@@ -585,7 +584,7 @@ bool Protocol::send_fields(List *list, uint flag)
 #endif
   }
 
-  send_eof(thd, 1);
+  my_net_write(&thd->net, eof_buff, 1);
   DBUG_RETURN(prepare_for_send(list));
 
 err: