diff options
author | unknown <monty@mishka.local> | 2004-04-26 15:53:31 +0300 |
---|---|---|
committer | unknown <monty@mishka.local> | 2004-04-26 15:53:31 +0300 |
commit | 1065f2bbd66ac4b1161f5c188171a54cbad5b422 (patch) | |
tree | 25e3315af05fa92d20d2ad1d812882957c400337 /sql | |
parent | 0ba6cb48d84f1ff951d09871a96be6cdef3f2c3c (diff) | |
parent | 6366a9090c7fc24f0e13b5b9d73d6777dcda9d9e (diff) | |
download | mariadb-git-1065f2bbd66ac4b1161f5c188171a54cbad5b422.tar.gz |
Merge with 4.0
innobase/dict/dict0boot.c:
Auto merged
innobase/dict/dict0load.c:
Auto merged
innobase/dict/dict0mem.c:
Auto merged
innobase/fut/fut0lst.c:
Auto merged
innobase/include/buf0lru.h:
Auto merged
innobase/include/dict0mem.h:
Auto merged
innobase/include/fsp0fsp.h:
Auto merged
innobase/include/ha0ha.h:
Auto merged
innobase/include/ibuf0ibuf.h:
Auto merged
innobase/include/lock0lock.h:
Auto merged
innobase/include/log0log.h:
Auto merged
innobase/include/mem0pool.h:
Auto merged
innobase/include/mtr0mtr.h:
Auto merged
innobase/include/os0file.h:
Auto merged
innobase/include/rem0rec.h:
Auto merged
innobase/include/rem0rec.ic:
Auto merged
innobase/include/srv0srv.h:
Auto merged
innobase/include/sync0sync.h:
Auto merged
innobase/include/trx0sys.h:
Auto merged
innobase/include/ut0byte.h:
Auto merged
innobase/include/ut0ut.h:
Auto merged
innobase/mem/mem0pool.c:
Auto merged
innobase/mtr/mtr0mtr.c:
Auto merged
innobase/os/os0proc.c:
Auto merged
innobase/pars/lexyy.c:
Auto merged
innobase/pars/pars0opt.c:
Auto merged
innobase/row/row0ins.c:
Auto merged
innobase/row/row0purge.c:
Auto merged
innobase/row/row0uins.c:
Auto merged
innobase/row/row0umod.c:
Auto merged
innobase/row/row0undo.c:
Auto merged
innobase/row/row0upd.c:
Auto merged
innobase/trx/trx0purge.c:
Auto merged
innobase/trx/trx0roll.c:
Auto merged
innobase/trx/trx0sys.c:
Auto merged
innobase/trx/trx0undo.c:
Auto merged
innobase/ut/ut0byte.c:
Auto merged
pstack/bucomm.h:
Auto merged
pstack/budbg.h:
Auto merged
sql/item_sum.h:
Auto merged
sql/slave.cc:
Auto merged
sql/sql_db.cc:
Auto merged
support-files/mysql.spec.sh:
Auto merged
tests/insert_test.c:
Auto merged
mysql-test/t/func_group.test:
Merge with 4.0
Put 4.1 tests lasts
sql/ha_innodb.cc:
Merge with 4.0
Added checking of results from my_malloc()
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_innodb.cc | 294 | ||||
-rw-r--r-- | sql/item_sum.h | 1 | ||||
-rw-r--r-- | sql/log_event.cc | 37 | ||||
-rw-r--r-- | sql/slave.cc | 62 | ||||
-rw-r--r-- | sql/sql_db.cc | 7 |
5 files changed, 264 insertions, 137 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index a5dc6719182..b6b2123fd66 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -15,7 +15,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This file defines the InnoDB handler: the interface between MySQL and -InnoDB */ +InnoDB +NOTE: You can only use noninlined InnoDB functions in this file, because we +have disables the InnoDB inlining in this file. */ /* TODO list for the InnoDB handler in 4.1: - Check if the query_id is now right also in prepared and executed stats @@ -74,6 +76,7 @@ extern "C" { #include "../innobase/include/btr0cur.h" #include "../innobase/include/btr0btr.h" #include "../innobase/include/fsp0fsp.h" +#include "../innobase/include/sync0sync.h" #include "../innobase/include/fil0fil.h" } @@ -321,70 +324,49 @@ convert_error_code_to_mysql( } } -extern "C" { /***************************************************************** Prints info of a THD object (== user session thread) to the standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for this function! */ - +extern "C" void innobase_mysql_print_thd( /*=====================*/ - char* buf, /* in/out: buffer where to print, must be at least - 400 bytes */ + FILE* f, /* in: output stream */ void* input_thd)/* in: pointer to a MySQL THD object */ { THD* thd; - char* old_buf = buf; thd = (THD*) input_thd; - /* We cannot use the return value of normal sprintf() as this is - not portable to some old non-Posix Unixes, e.g., some old SCO - Unixes */ - - buf += my_sprintf(buf, - (buf, "MySQL thread id %lu, query id %lu", - thd->thread_id, thd->query_id)); - if (thd->host) { - *buf = ' '; - buf++; - buf = strnmov(buf, thd->host, 30); - } + fprintf(f, "MySQL thread id %lu, query id %lu", + thd->thread_id, thd->query_id); + if (thd->host) { + putc(' ', f); + fputs(thd->host, f); + } - if (thd->ip) { - *buf = ' '; - buf++; - buf=strnmov(buf, thd->ip, 20); - } + if (thd->ip) { + putc(' ', f); + fputs(thd->ip, f); + } if (thd->user) { - *buf = ' '; - buf++; - buf=strnmov(buf, thd->user, 20); - } - - if (thd->proc_info) { - *buf = ' '; - buf++; - buf=strnmov(buf, thd->proc_info, 50); + putc(' ', f); + fputs(thd->user, f); } - if (thd->query) { - *buf = '\n'; - buf++; - buf=strnmov(buf, thd->query, 150); - } - - buf[0] = '\n'; - buf[1] = '\0'; /* Note that we must put a null character here to end - the printed string */ + if (thd->proc_info) { + putc(' ', f); + fputs(thd->proc_info, f); + } - /* We test the printed length did not overrun the buffer length of - 400 bytes */ + if (thd->query) { + putc(' ', f); + fputs(thd->query, f); + } - ut_a(strlen(old_buf) < 400); -} + putc('\n', f); } /************************************************************************* @@ -627,12 +609,11 @@ innobase_query_caching_of_table_permitted( return((my_bool)FALSE); } -extern "C" { /********************************************************************* Invalidates the MySQL query cache for the table. NOTE that the exact prototype of this function has to be in /innobase/row/row0ins.c! */ - +extern "C" void innobase_invalidate_query_cache( /*============================*/ @@ -652,6 +633,17 @@ innobase_invalidate_query_cache( TRUE); #endif } + +/********************************************************************* +Get the quote character to be used in SQL identifiers. */ +extern "C" +char +mysql_get_identifier_quote_char(void) +/*=================================*/ + /* out: quote character to be + used in SQL identifiers */ +{ + return '`'; } /********************************************************************* @@ -2102,24 +2094,20 @@ ha_innobase::write_row( if (prebuilt->trx != (trx_t*) current_thd->transaction.all.innobase_tid) { - char err_buf[2000]; - fprintf(stderr, "InnoDB: Error: the transaction object for the table handle is at\n" -"InnoDB: %lx, but for the current thread it is at %lx\n", - (ulong)prebuilt->trx, - (ulong)current_thd->transaction.all.innobase_tid); - - ut_sprintf_buf(err_buf, ((byte*)prebuilt) - 100, 200); - fprintf(stderr, -"InnoDB: Dump of 200 bytes around prebuilt: %.1000s\n", err_buf); - - ut_sprintf_buf(err_buf, +"InnoDB: %p, but for the current thread it is at %p\n", + prebuilt->trx, + current_thd->transaction.all.innobase_tid); + fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr); + ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200); + fputs("\n" + "InnoDB: Dump of 200 bytes around transaction.all: ", + stderr); + ut_print_buf(stderr, ((byte*)(&(current_thd->transaction.all))) - 100, 200); - fprintf(stderr, -"InnoDB: Dump of 200 bytes around transaction.all: %.1000s\n", err_buf); - - ut_a(0); + putc('\n', stderr); + ut_error; } statistic_increment(ha_write_count, &LOCK_status); @@ -3390,12 +3378,9 @@ create_index( field = form->field[j]; - if (strlen(field->field_name) - == strlen(key_part->field->field_name) - && 0 == ut_cmp_in_lower_case( + if (0 == ut_cmp_in_lower_case( (char*)field->field_name, - (char*)key_part->field->field_name, - strlen(field->field_name))) { + (char*)key_part->field->field_name)) { /* Found the corresponding column */ break; @@ -3762,7 +3747,8 @@ ha_innobase::delete_table( /* Drop the table in InnoDB */ - error = row_drop_table_for_mysql(norm_name, trx); + error = row_drop_table_for_mysql(norm_name, trx, + thd->lex.sql_command == SQLCOM_DROP_DB); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3801,7 +3787,7 @@ innobase_drop_database( trx_t* trx; char* ptr; int error; - char namebuf[10000]; + char* namebuf; /* Get the transaction associated with the current thd, or create one if not yet created */ @@ -3821,6 +3807,7 @@ innobase_drop_database( } ptr++; + namebuf = my_malloc(len + 2, MYF(0)); memcpy(namebuf, ptr, len); namebuf[len] = '/'; @@ -3837,6 +3824,7 @@ innobase_drop_database( } error = row_drop_database_for_mysql(namebuf, trx); + my_free(namebuf, MYF(0)); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -4361,15 +4349,18 @@ ha_innobase::update_table_comment( info on foreign keys */ const char* comment)/* in: table comment defined by user */ { - row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; - uint length = strlen(comment); - char* str = my_malloc(length + 16500, MYF(0)); - char* pos; + uint length = strlen(comment); + char* str; + row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table handle. */ + if(length > 64000 - 3) { + return((char*)comment); /* string too long */ + } + update_thd(current_thd); prebuilt->trx->op_info = (char*)"returning table comment"; @@ -4378,37 +4369,47 @@ ha_innobase::update_table_comment( possible adaptive hash latch to avoid deadlocks of threads */ trx_search_latch_release_if_reserved(prebuilt->trx); - - if (!str) { - prebuilt->trx->op_info = (char*)""; + str = NULL; - return((char*)comment); - } + if (FILE* file = tmpfile()) { + long flen; - pos = str; - if (length) { - pos=strmov(str, comment); - *pos++=';'; - *pos++=' '; - } + /* output the data to a temporary file */ + fprintf(file, "InnoDB free: %lu kB", + (ulong) fsp_get_available_space_in_free_extents( + prebuilt->table->space)); + + dict_print_info_on_foreign_keys(FALSE, file, prebuilt->table); + flen = ftell(file); + if(length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - pos += my_sprintf(pos, - (pos,"InnoDB free: %lu kB", - (ulong) fsp_get_available_space_in_free_extents( - prebuilt->table->space))); + ut_ad(flen > 0); - /* We assume 16000 - length bytes of space to print info; the limit - 16000 bytes is arbitrary, and MySQL could handle at least 64000 - bytes */ - - if (length < 16000) { - dict_print_info_on_foreign_keys(FALSE, pos, 16000 - length, - prebuilt->table); + /* allocate buffer for the full string, and + read the contents of the temporary file */ + + str = my_malloc(length + flen + 3, MYF(0)); + + if (str) { + char* pos = str + length; + if(length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; + } + rewind(file); + flen = fread(pos, 1, flen, file); + pos[flen] = 0; + } + + fclose(file); } prebuilt->trx->op_info = (char*)""; - return(str); + return(str ? str : (char*) comment); } /*********************************************************************** @@ -4422,7 +4423,7 @@ ha_innobase::get_foreign_key_create_info(void) MUST be freed with ::free_foreign_key_create_info */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; - char* str; + char* str = 0; ut_a(prebuilt != NULL); @@ -4432,23 +4433,47 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + if (FILE* file = tmpfile()) { + long flen; - /* In case MySQL calls this in the middle of a SELECT query, release - possible adaptive hash latch to avoid deadlocks of threads */ + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; - trx_search_latch_release_if_reserved(prebuilt->trx); - - str = (char*)ut_malloc(10000); + /* In case MySQL calls this in the middle of a SELECT query, + release possible adaptive hash latch to avoid + deadlocks of threads */ - str[0] = '\0'; - - dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table); + trx_search_latch_release_if_reserved(prebuilt->trx); - prebuilt->trx->op_info = (char*)""; + /* output the data to a temporary file */ + dict_print_info_on_foreign_keys(TRUE, file, prebuilt->table); + prebuilt->trx->op_info = (char*)""; + + flen = ftell(file); + if(flen > 64000 - 1) { + flen = 64000 - 1; + } + + ut_ad(flen >= 0); + + /* allocate buffer for the string, and + read the contents of the temporary file */ + + str = my_malloc(flen + 1, MYF(0)); + + if (str) { + rewind(file); + flen = fread(str, 1, flen, file); + str[flen] = 0; + } + + fclose(file); + } else { + /* unable to create temporary file */ + str = my_malloc(1, MYF(MY_ZEROFILL)); + } return(str); -} +} /*********************************************************************** Checks if a table is referenced by a foreign key. The MySQL manual states that @@ -4481,7 +4506,7 @@ ha_innobase::free_foreign_key_create_info( char* str) /* in, own: create info string to free */ { if (str) { - ut_free(str); + my_free(str, MYF(0)); } } @@ -4772,34 +4797,55 @@ innodb_show_status( innobase_release_stat_resources(trx); - /* We let the InnoDB Monitor to output at most 60 kB of text, add - a safety margin of 100 kB for buffer overruns */ + /* We let the InnoDB Monitor to output at most 64000 bytes of text. */ - buf = (char*)ut_malloc(160 * 1024); + long flen; + char* str; - srv_sprintf_innodb_monitor(buf, 60 * 1024); + mutex_enter_noninline(&srv_monitor_file_mutex); + rewind(srv_monitor_file); + srv_printf_innodb_monitor(srv_monitor_file); + flen = ftell(srv_monitor_file); + if(flen > 64000 - 1) { + flen = 64000 - 1; + } - List<Item> field_list; + ut_ad(flen > 0); - field_list.push_back(new Item_empty_string("Status", strlen(buf))); + /* allocate buffer for the string, and + read the contents of the temporary file */ - if (protocol->send_fields(&field_list, 1)) + if (!(str = my_malloc(flen + 1, MYF(0)))) { - ut_free(buf); - DBUG_RETURN(-1); + mutex_exit_noninline(&srv_monitor_file_mutex); + DBUG_RETURN(-1); } - protocol->prepare_for_resend(); - protocol->store(buf, strlen(buf), system_charset_info); + rewind(srv_monitor_file); + flen = fread(str, 1, flen, srv_monitor_file); + + mutex_exit_noninline(&srv_monitor_file_mutex); + + List<Item> field_list; - ut_free(buf); + field_list.push_back(new Item_empty_string("Status", flen)); + + if (protocol->send_fields(field_list, 1)) { + + my_free(str, MYF(0)); + + DBUG_RETURN(-1); + } + + protocol->prepare_for_resend(); + protocol->store(str, flen, system_charset_info); + my_free(str, MYF(0)); if (protocol->write()) DBUG_RETURN(-1); - send_eof(thd); - - DBUG_RETURN(0); + send_eof(&thd->net); + DBUG_RETURN(0); } /**************************************************************************** diff --git a/sql/item_sum.h b/sql/item_sum.h index 107c19b7d85..9593c8ddbba 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -298,6 +298,7 @@ class Item_sum_avg :public Item_sum_num void update_field(); Item *result_item(Field *field) { return new Item_avg_field(this); } + void no_rows_in_result() {} const char *func_name() const { return "avg"; } Item *copy_or_same(THD* thd); }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 3b92e0956ba..207f4a51ff4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -923,15 +923,15 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db) (ulong) thread_id, (ulong) exec_time, error_code); } - bool same_db = 0; + bool different_db= 1; if (db && last_db) { - if (!(same_db = !memcmp(last_db, db, db_len + 1))) + if (different_db= memcmp(last_db, db, db_len + 1)) memcpy(last_db, db, db_len + 1); } - if (db && db[0] && !same_db) + if (db && db[0] && different_db) fprintf(file, "use %s;\n", db); end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); *end++=';'; @@ -960,8 +960,10 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) position to store is of the END of the current log event. */ #if MYSQL_VERSION_ID < 50000 - rli->future_group_master_log_pos= log_pos + get_event_len(); + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); #else + /* In 5.0 we store the end_log_pos in the relay log so no problem */ rli->future_group_master_log_pos= log_pos; #endif clear_all_errors(thd, rli); @@ -1165,6 +1167,11 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli) { DBUG_ENTER("Start_log_event::exec_event"); + /* + If the I/O thread has not started, mi->old_format is BINLOG_FORMAT_CURRENT + (that's what the MASTER_INFO constructor does), so the test below is not + perfect at all. + */ switch (rli->mi->old_format) { case BINLOG_FORMAT_CURRENT: /* @@ -1542,14 +1549,21 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db, thread_id, exec_time); } - bool same_db = 0; + bool different_db= 1; if (db && last_db) { - if (!(same_db = !memcmp(last_db, db, db_len + 1))) + /* + If the database is different from the one of the previous statement, we + need to print the "use" command, and we update the last_db. + But if commented, the "use" is going to be commented so we should not + update the last_db. + */ + if ((different_db= memcmp(last_db, db, db_len + 1)) && + !commented) memcpy(last_db, db, db_len + 1); } - if (db && db[0] && !same_db) + if (db && db[0] && different_db) fprintf(file, "%suse %s;\n", commented ? "# " : "", db); @@ -1667,7 +1681,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, if (!use_rli_only_for_errors) { #if MYSQL_VERSION_ID < 50000 - rli->future_group_master_log_pos= log_pos + get_event_len(); + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); #else rli->future_group_master_log_pos= log_pos; #endif @@ -3138,9 +3153,11 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) */ #if MYSQL_VERSION_ID < 40100 - rli->future_master_log_pos= log_pos + get_event_len(); + rli->future_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); #elif MYSQL_VERSION_ID < 50000 - rli->future_group_master_log_pos= log_pos + get_event_len(); + rli->future_group_master_log_pos= log_pos + get_event_len() - + (rli->mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); #else rli->future_group_master_log_pos= log_pos; #endif diff --git a/sql/slave.cc b/sql/slave.cc index 67b9c7515e1..d3af72f78bd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -361,6 +361,52 @@ void init_slave_skip_errors(const char* arg) } } +void st_relay_log_info::inc_pending(ulonglong val) +{ + pending += val; +} + +/* TODO: this probably needs to be fixed */ +void st_relay_log_info::inc_pos(ulonglong val, ulonglong log_pos, bool skip_lock) +{ + if (!skip_lock) + pthread_mutex_lock(&data_lock); + relay_log_pos += val+pending; + pending = 0; + if (log_pos) +#if MYSQL_VERSION_ID < 50000 + /* + If the event was converted from a 3.23 format, get_event_len() has + grown by 6 bytes (at least for most events, except LOAD DATA INFILE + which is already a big problem for 3.23->4.0 replication); 6 bytes is + the difference between the header's size in 4.0 (LOG_EVENT_HEADER_LEN) + and the header's size in 3.23 (OLD_HEADER_LEN). Note that using + mi->old_format will not help if the I/O thread has not started yet. + Yes this is a hack but it's just to make 3.23->4.x replication work; + 3.23->5.0 replication is working much better. + + The line "mi->old_format ? : " below should NOT BE MERGED to 5.0 which + already works. But it SHOULD be merged to 4.1. + */ + master_log_pos= log_pos + val - + (mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); +#endif + pthread_cond_broadcast(&data_cond); + if (!skip_lock) + pthread_mutex_unlock(&data_lock); +} + +/* + thread safe read of position - not needed if we are in the slave thread, + but required otherwise as var is a longlong +*/ +void st_relay_log_info::read_pos(ulonglong& var) +{ + pthread_mutex_lock(&data_lock); + var = relay_log_pos; + pthread_mutex_unlock(&data_lock); +} + void st_relay_log_info::close_temporary_tables() { TABLE *table,*next; @@ -3473,8 +3519,16 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, DBUG_RETURN(1); } memcpy(tmp_buf,buf,event_len); - tmp_buf[event_len]=0; // Create_file constructor wants null-term buffer + /* + Create_file constructor wants a 0 as last char of buffer, this 0 will + serve as the string-termination char for the file's name (which is at the + end of the buffer) + We must increment event_len, otherwise the event constructor will not see + this end 0, which leads to segfault. + */ + tmp_buf[event_len++]=0; buf = (const char*)tmp_buf; + int4store(buf+EVENT_LEN_OFFSET, event_len); } /* This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to @@ -3520,7 +3574,11 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, DBUG_ASSERT(tmp_buf); int error = process_io_create_file(mi,(Create_file_log_event*)ev); delete ev; - mi->master_log_pos += event_len; + /* + We had incremented event_len, but now when it is used to calculate the + position in the master's log, we must use the original value. + */ + mi->master_log_pos += --event_len; DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos)); pthread_mutex_unlock(&mi->data_lock); my_free((char*)tmp_buf, MYF(0)); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 51b875385f1..a6bd1955fa5 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -551,7 +551,12 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, If the directory is a symbolic link, remove the link first, then remove the directory the symbolic link pointed at */ - if (!found_other_files) + if (found_other_files) + { + my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST); + DBUG_RETURN(-1); + } + else { char tmp_path[FN_REFLEN], *pos; char *path= tmp_path; |