diff options
66 files changed, 988 insertions, 440 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 339b31543b8..44593cef0af 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -10,6 +10,7 @@ acurtis@pcgem.rdg.cyberkinetica.com administrador@light.hegel.local ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com +antony@ltantony.dsl-verizon.net antony@ltantony.rdg.cyberkinetica.homeunix.net arjen@bitbike.com arjen@co3064164-a.bitbike.com @@ -116,6 +117,7 @@ papa@gbichot.local paul@central.snake.net paul@ice.local paul@ice.snake.net +paul@kite-hub.kitebird.com paul@teton.kitebird.com pem@mysql.com peter@linux.local @@ -150,6 +152,7 @@ tfr@sarvik.tfr.cafe.ee tim@bitch.mysql.fi tim@black.box tim@hundin.mysql.fi +tim@sand.box tim@threads.polyesthetic.msg tim@white.box tim@work.mysql.com diff --git a/VC++Files/client/mysqlclient.dsp b/VC++Files/client/mysqlclient.dsp index 46a4d2c89eb..b93eab53f23 100644 --- a/VC++Files/client/mysqlclient.dsp +++ b/VC++Files/client/mysqlclient.dsp @@ -510,6 +510,10 @@ SOURCE=..\strings\strxnmov.c # End Source File # Begin Source File +SOURCE=..\strings\strxnmov.c +# End Source File +# Begin Source File + SOURCE=..\mysys\thr_mutex.c # End Source File # Begin Source File diff --git a/VC++Files/libmysqld/libmysqld.def b/VC++Files/libmysqld/libmysqld.def deleted file mode 100644 index 37a6114a6d0..00000000000 --- a/VC++Files/libmysqld/libmysqld.def +++ /dev/null @@ -1,152 +0,0 @@ -LIBRARY LIBMYSQLD -DESCRIPTION 'MySQL 4.1 Embedded Server Library' -VERSION 4.1 -EXPORTS - _dig_vec - bmove_upp - delete_dynamic - free_defaults - getopt_compare_strings - getopt_ull_limit_value - handle_options - init_dynamic_array - insert_dynamic - int2str - is_prefix - list_add - list_delete - load_defaults - max_allowed_packet - my_end - my_getopt_print_errors - my_init - my_malloc - my_memdup - my_no_flags_free - my_path - my_print_help - my_print_variables - my_realloc - my_strdup - my_thread_end - my_thread_init - myodbc_remove_escape - mysql_affected_rows - mysql_autocommit - mysql_change_user - mysql_character_set_name - mysql_close - mysql_commit - mysql_data_seek - mysql_debug - mysql_dump_debug_info - mysql_eof - mysql_errno - mysql_error - mysql_escape_string - mysql_fetch_field - mysql_fetch_field_direct - mysql_fetch_fields - mysql_fetch_lengths - mysql_fetch_row - mysql_field_count - mysql_field_seek - mysql_field_tell - mysql_free_result - mysql_get_client_info - mysql_get_host_info - mysql_get_proto_info - mysql_get_server_info - mysql_info - mysql_init - mysql_insert_id - mysql_kill - mysql_list_dbs - mysql_list_fields - mysql_list_processes - mysql_list_tables - mysql_more_results - mysql_next_result - mysql_num_fields - mysql_num_rows - mysql_odbc_escape_string - mysql_options - mysql_ping - mysql_query - mysql_read_query_result - mysql_real_connect - mysql_real_escape_string - mysql_real_query - mysql_refresh - mysql_rollback - mysql_row_seek - mysql_row_tell - mysql_select_db - mysql_send_query - mysql_shutdown - mysql_ssl_set - mysql_stat - mysql_store_result - mysql_sqlstate - mysql_thread_id - 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 - strcont - strdup_root - strfill - strinstr - strmake - strmov - strxmov - mysql_server_end - mysql_server_init - get_tty_password - sql_protocol_typelib - mysql_get_server_version - mysql_sqlstate - charsets_dir - disabled_my_option - my_charset_latin1 - init_alloc_root - my_progname - get_charset_by_csname - print_defaults - find_type - strxnmov - strend - my_fopen - my_fclose - unpack_filename - str2int - int10_to_str - longlong10_to_str - my_snprintf_8bit - alloc_root - free_root - my_read diff --git a/extra/perror.c b/extra/perror.c index d05fa2492de..10b2442de20 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -71,7 +71,7 @@ static HA_ERRORS ha_errlist[]= { 136,"No more room in index file" }, { 137,"No more records (read after end of file)" }, { 138,"Unsupported extension used for table" }, - { 139,"Too big row (>= 16 M)"}, + { 139,"Too big row"}, { 140,"Wrong create options"}, { 141,"Duplicate unique key or constraint on write or update"}, { 142,"Unknown character set used"}, diff --git a/extra/replace.c b/extra/replace.c index a44c33a4694..5a086e5ca9c 100644 --- a/extra/replace.c +++ b/extra/replace.c @@ -279,8 +279,10 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) length=(uint) strlen(name)+1; if (pa->length+length >= pa->max_length) { + pa->max_length=(pa->length+length+MALLOC_OVERHEAD+PS_MALLOC-1)/PS_MALLOC; + pa->max_length=pa->max_length*PS_MALLOC-MALLOC_OVERHEAD; if (!(new_pos= (byte*) my_realloc((gptr) pa->str, - (uint) (pa->max_length+PS_MALLOC), + (uint) pa->max_length, MYF(MY_WME)))) DBUG_RETURN(1); if (new_pos != pa->str) @@ -291,7 +293,6 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name) char*); pa->str=new_pos; } - pa->max_length+=PS_MALLOC; } if (pa->typelib.count >= pa->max_count-1) { diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9ccea5ad7a4..b1f9a10ee05 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -381,7 +381,9 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing */ + does nothing; + if LOCK_TABLE_EXP bits are set, + creates an explicit table lock */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr); /* in: query thread */ @@ -394,6 +396,14 @@ lock_is_on_table( /* out: TRUE if there are lock(s) */ dict_table_t* table); /* in: database table in dictionary cache */ /************************************************************************* +Releases a table lock. +Releases possible other transactions waiting for this lock. */ + +void +lock_table_unlock( +/*==============*/ + lock_t* lock); /* in: lock */ +/************************************************************************* Releases an auto-inc lock a transaction possibly has on a table. Releases possible other transactions waiting for this lock. */ @@ -410,6 +420,14 @@ lock_release_off_kernel( /*====================*/ trx_t* trx); /* in: transaction */ /************************************************************************* +Releases table locks, and releases possible other transactions waiting +because of these locks. */ + +void +lock_release_tables_off_kernel( +/*===========================*/ + trx_t* trx); /* in: transaction */ +/************************************************************************* Cancels a waiting lock request and releases possible other transactions waiting behind it. */ @@ -536,6 +554,7 @@ extern lock_sys_t* lock_sys; /* Lock types */ #define LOCK_TABLE 16 /* these type values should be so high that */ #define LOCK_REC 32 /* they can be ORed to the lock mode */ +#define LOCK_TABLE_EXP 80 /* explicit table lock */ #define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the type_mode field in a lock */ /* Waiting lock flag */ diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 0fb2994a414..0b9f34dda1e 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -161,6 +161,22 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL table handle */ /************************************************************************* +Unlocks a table lock possibly reserved by trx. */ + +void +row_unlock_table_for_mysql( +/*=======================*/ + trx_t* trx); /* in: transaction */ +/************************************************************************* +Sets a table lock on the table mentioned in prebuilt. */ + +int +row_lock_table_for_mysql( +/*=====================*/ + /* out: error code or DB_SUCCESS */ + row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL + table handle */ +/************************************************************************* Does an insert for MySQL. */ int diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h index 332c08fd38a..0cc48d5f299 100644 --- a/innobase/include/sync0sync.h +++ b/innobase/include/sync0sync.h @@ -218,7 +218,7 @@ void mutex_get_debug_info( /*=================*/ mutex_t* mutex, /* in: mutex */ - char** file_name, /* out: file where requested */ + const char** file_name, /* out: file where requested */ ulint* line, /* out: line where requested */ os_thread_id_t* thread_id); /* out: id of the thread which owns the mutex */ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index bb2d7e8f64d..71269cb1e4e 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -421,6 +421,8 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ + ulint n_tables_locked;/* number of table locks reserved by + the transaction, stored in trx_locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index f12389cb6b2..8805a22bb57 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -2001,7 +2001,11 @@ lock_grant( release it at the end of the SQL statement */ lock->trx->auto_inc_lock = lock; - } + } else if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + lock->trx->n_tables_locked++; + } #ifdef UNIV_DEBUG if (lock_print_waits) { @@ -2939,7 +2943,7 @@ retry: } if (ret == LOCK_VICTIM_IS_START) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { table = lock->un_member.tab_lock.table; index = NULL; } else { @@ -3015,7 +3019,7 @@ lock_deadlock_recursive( /* Look at the locks ahead of wait_lock in the lock queue */ for (;;) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); } else { @@ -3347,7 +3351,9 @@ lock_table( /* out: DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, - does nothing */ + does nothing; + if LOCK_TABLE_EXP bits are set, + creates an explicit table lock */ dict_table_t* table, /* in: database table in dictionary cache */ ulint mode, /* in: lock mode */ que_thr_t* thr) /* in: query thread */ @@ -3362,6 +3368,8 @@ lock_table( return(DB_SUCCESS); } + ut_ad(flags == 0 || flags == LOCK_TABLE_EXP); + trx = thr_get_trx(thr); lock_mutex_enter_kernel(); @@ -3390,7 +3398,12 @@ lock_table( return(err); } - lock_table_create(table, mode, trx); + lock_table_create(table, mode | flags, trx); + + if (flags) { + ut_ad(mode == LOCK_S || mode == LOCK_X); + trx->n_tables_locked++; + } lock_mutex_exit_kernel(); @@ -3471,7 +3484,8 @@ lock_table_dequeue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(lock_get_type(in_lock) == LOCK_TABLE); + ut_ad(lock_get_type(in_lock) == LOCK_TABLE || + lock_get_type(in_lock) == LOCK_TABLE_EXP); lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); @@ -3496,6 +3510,22 @@ lock_table_dequeue( /*=========================== LOCK RELEASE ==============================*/ /************************************************************************* +Releases a table lock. +Releases possible other transactions waiting for this lock. */ + +void +lock_table_unlock( +/*==============*/ + lock_t* lock) /* in: lock */ +{ + mutex_enter(&kernel_mutex); + + lock_table_dequeue(lock); + + mutex_exit(&kernel_mutex); +} + +/************************************************************************* Releases an auto-inc lock a transaction possibly has on a table. Releases possible other transactions waiting for this lock. */ @@ -3542,7 +3572,7 @@ lock_release_off_kernel( lock_rec_dequeue_from_page(lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); if (lock_get_mode(lock) != LOCK_IS && 0 != ut_dulint_cmp(trx->undo_no, @@ -3559,6 +3589,11 @@ lock_release_off_kernel( } lock_table_dequeue(lock); + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + trx->n_tables_locked--; + } } if (count == LOCK_RELEASE_KERNEL_INTERVAL) { @@ -3578,6 +3613,73 @@ lock_release_off_kernel( mem_heap_empty(trx->lock_heap); ut_a(trx->auto_inc_lock == NULL); + ut_a(trx->n_tables_locked == 0); +} + +/************************************************************************* +Releases table locks, and releases possible other transactions waiting +because of these locks. */ + +void +lock_release_tables_off_kernel( +/*===========================*/ + trx_t* trx) /* in: transaction */ +{ + dict_table_t* table; + ulint count; + lock_t* lock; + +#ifdef UNIV_SYNC_DEBUG + ut_ad(mutex_own(&kernel_mutex)); +#endif /* UNIV_SYNC_DEBUG */ + + lock = UT_LIST_GET_LAST(trx->trx_locks); + + count = 0; + + while (lock != NULL) { + + count++; + + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + ut_ad(lock_get_mode(lock) == LOCK_S + || lock_get_mode(lock) == LOCK_X); + if (trx->insert_undo || trx->update_undo) { + + /* The trx may have modified the table. + We block the use of the MySQL query + cache for all currently active + transactions. */ + + table = lock->un_member.tab_lock.table; + + table->query_cache_inv_trx_id = + trx_sys->max_trx_id; + } + + lock_table_dequeue(lock); + trx->n_tables_locked--; + lock = UT_LIST_GET_LAST(trx->trx_locks); + continue; + } + + if (count == LOCK_RELEASE_KERNEL_INTERVAL) { + /* Release the kernel mutex for a while, so that we + do not monopolize it */ + + lock_mutex_exit_kernel(); + + lock_mutex_enter_kernel(); + + count = 0; + } + + lock = UT_LIST_GET_PREV(trx_locks, lock); + } + + mem_heap_empty(trx->lock_heap); + + ut_a(trx->n_tables_locked == 0); } /************************************************************************* @@ -3597,7 +3699,7 @@ lock_cancel_waiting_and_release( lock_rec_dequeue_from_page(lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); lock_table_dequeue(lock); } @@ -3638,7 +3740,7 @@ lock_reset_all_on_table_for_trx( ut_a(!lock_get_wait(lock)); lock_rec_discard(lock); - } else if (lock_get_type(lock) == LOCK_TABLE + } else if (lock_get_type(lock) & LOCK_TABLE && lock->un_member.tab_lock.table == table) { ut_a(!lock_get_wait(lock)); @@ -3690,8 +3792,12 @@ lock_table_print( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_a(lock_get_type(lock) == LOCK_TABLE); + ut_a(lock_get_type(lock) == LOCK_TABLE || + lock_get_type(lock) == LOCK_TABLE_EXP); + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + fputs("EXPLICIT ", file); + } fputs("TABLE LOCK table ", file); ut_print_name(file, lock->un_member.tab_lock.table->name); fprintf(file, " trx id %lu %lu", @@ -4012,7 +4118,7 @@ loop: lock_rec_print(file, lock); } else { - ut_ad(lock_get_type(lock) == LOCK_TABLE); + ut_ad(lock_get_type(lock) & LOCK_TABLE); lock_table_print(file, lock); } @@ -4293,7 +4399,7 @@ lock_validate(void) lock = UT_LIST_GET_FIRST(trx->trx_locks); while (lock) { - if (lock_get_type(lock) == LOCK_TABLE) { + if (lock_get_type(lock) & LOCK_TABLE) { lock_table_queue_validate( lock->un_member.tab_lock.table); diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 92e7f1e4fc3..ff5b30bec0d 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -312,7 +312,7 @@ os_file_handle_error( /* out: TRUE if we should retry the operation */ os_file_t file, /* in: file pointer */ - char* name, /* in: name of a file or NULL */ + const char* name, /* in: name of a file or NULL */ const char* operation)/* in: operation */ { ulint err; @@ -369,6 +369,32 @@ os_file_handle_error( return(FALSE); } +#if !defined(__WIN__) && !defined(UNIV_HOTBACKUP) +/******************************************************************** +Obtain an exclusive lock on a file. */ +static +int +os_file_lock( +/*=========*/ + /* out: 0 on success */ + int fd, /* in: file descriptor */ + const char* name) /* in: file name */ +{ + struct flock lk; + lk.l_type = F_WRLCK; + lk.l_whence = SEEK_SET; + lk.l_start = lk.l_len = 0; + if (fcntl(fd, F_SETLK, &lk) == -1) { + fprintf(stderr, + "InnoDB: Unable to lock %s", name); + perror (": fcntl"); + close(fd); + return(-1); + } + return 0; +} +#endif /* !defined(__WIN__) && !defined(UNIV_HOTBACKUP) */ + /******************************************************************** Does error handling when a file operation fails. */ static @@ -781,7 +807,7 @@ try_again: } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; ibool retry; @@ -826,12 +852,17 @@ try_again: if (retry) { goto try_again; } +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /******************************************************************** @@ -902,7 +933,7 @@ os_file_create_simple_no_error_handling( } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; @@ -930,12 +961,17 @@ os_file_create_simple_no_error_handling( if (file == -1) { *success = FALSE; +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /******************************************************************** @@ -1056,7 +1092,7 @@ try_again: } return(file); -#else +#else /* __WIN__ */ os_file_t file; int create_flag; ibool retry; @@ -1136,12 +1172,17 @@ try_again: if (retry) { goto try_again; } +#ifndef UNIV_HOTBACKUP + } else if (os_file_lock(file, name)) { + *success = FALSE; + file = -1; +#endif } else { *success = TRUE; } return(file); -#endif +#endif /* __WIN__ */ } /*************************************************************************** diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c index 638571ada97..1b8c69ccc7a 100644 --- a/innobase/pars/lexyy.c +++ b/innobase/pars/lexyy.c @@ -4,6 +4,9 @@ * $Header: /home/heikki/cvsroot/ib/pars/lexyy.c,v 1.2 2003/10/30 20:27:19 heikki Exp $ */ +/* This include MUST be first to keep things portable ! */ +#include "univ.i" + #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 4da27bca1a9..5432add37f7 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -711,10 +711,94 @@ run_again: /* It may be that the current session has not yet started its transaction, or it has been committed: */ - + + trx_start_if_not_started(trx); + + err = lock_table(0, prebuilt->table, prebuilt->select_lock_type, thr); + + trx->error_state = err; + + if (err != DB_SUCCESS) { + que_thr_stop_for_mysql(thr); + + was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL); + + if (was_lock_wait) { + goto run_again; + } + + trx->op_info = (char *) ""; + + return(err); + } + + que_thr_stop_for_mysql_no_error(thr, trx); + + trx->op_info = (char *) ""; + + return((int) err); +} + +/************************************************************************* +Unlocks a table lock possibly reserved by trx. */ + +void +row_unlock_table_for_mysql( +/*=======================*/ + trx_t* trx) /* in: transaction */ +{ + if (!trx->n_tables_locked) { + + return; + } + + mutex_enter(&kernel_mutex); + lock_release_tables_off_kernel(trx); + mutex_exit(&kernel_mutex); +} +/************************************************************************* +Sets a table lock on the table mentioned in prebuilt. */ + +int +row_lock_table_for_mysql( +/*=====================*/ + /* out: error code or DB_SUCCESS */ + row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL + table handle */ +{ + trx_t* trx = prebuilt->trx; + que_thr_t* thr; + ulint err; + ibool was_lock_wait; + + ut_ad(trx); + ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); + + trx->op_info = (char *) "setting table lock"; + + if (prebuilt->sel_graph == NULL) { + /* Build a dummy select query graph */ + row_prebuild_sel_graph(prebuilt); + } + + /* We use the select query graph as the dummy graph needed + in the lock module call */ + + thr = que_fork_get_first_thr(prebuilt->sel_graph); + + que_thr_move_to_run_state_for_mysql(thr, trx); + +run_again: + thr->run_node = thr; + thr->prev_node = thr->common.parent; + + /* It may be that the current session has not yet started + its transaction, or it has been committed: */ + trx_start_if_not_started(trx); - err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); + err = lock_table(LOCK_TABLE_EXP, prebuilt->table, + prebuilt->select_lock_type, thr); trx->error_state = err; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 73bbd145517..9dffdbf2f9f 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1655,6 +1655,11 @@ loop: mutex_enter(&srv_monitor_file_mutex); rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); +#ifdef __WIN__ + chsize(fileno(srv_monitor_file), ftell(srv_monitor_file)); +#else /* __WIN__ */ + ftruncate(fileno(srv_monitor_file), ftell(srv_monitor_file)); +#endif /* __WIN__ */ mutex_exit(&srv_monitor_file_mutex); if (srv_print_innodb_tablespace_monitor diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 33d84cfaa8e..68fcb82c6d8 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1112,6 +1112,7 @@ NetWare. */ } mutex_create(&srv_monitor_file_mutex); + mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); srv_monitor_file_name = mem_alloc( strlen(fil_path_to_mysql_datadir) + 20 + sizeof "/innodb_status."); diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index 1268b22e2f8..426d7ff9f92 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -618,7 +618,6 @@ sync_array_detect_deadlock( rw_lock_t* lock; os_thread_id_t thread; ibool ret; - rw_lock_t* lock; rw_lock_debug_t*debug; ut_a(arr && start && cell); diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c index e711acbf84e..c1fb31bc966 100644 --- a/innobase/sync/sync0sync.c +++ b/innobase/sync/sync0sync.c @@ -531,7 +531,7 @@ void mutex_get_debug_info( /*=================*/ mutex_t* mutex, /* in: mutex */ - char** file_name, /* out: file where requested */ + const char** file_name, /* out: file where requested */ ulint* line, /* out: line where requested */ os_thread_id_t* thread_id) /* out: id of the thread which owns the mutex */ @@ -590,7 +590,7 @@ mutex_list_print_info(void) /*=======================*/ { mutex_t* mutex; - char* file_name; + const char* file_name; ulint line; os_thread_id_t thread_id; ulint count = 0; @@ -788,7 +788,7 @@ sync_thread_levels_g( if (mutex_get_lock_word(mutex) != 0) { #ifdef UNIV_SYNC_DEBUG - char* file_name; + const char* file_name; ulint line; os_thread_id_t thread_id; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index a69b9a96824..fc0a67278d2 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -151,6 +151,7 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; + trx->n_tables_locked = 0; trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; @@ -278,6 +279,7 @@ trx_free( ut_a(!trx->has_search_latch); ut_a(!trx->auto_inc_lock); + ut_a(!trx->n_tables_locked); ut_a(trx->dict_operation_lock_mode == 0); diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 8a87f307a67..3bbeac00754 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -154,7 +154,8 @@ enum options_mc { OPT_KEY_CACHE_BLOCK_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN, - OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT, OPT_MAX_RECORD_LENGTH + OPT_FT_MAX_WORD_LEN, OPT_FT_MAX_WORD_LEN_FOR_SORT, OPT_FT_STOPWORD_FILE, + OPT_MAX_RECORD_LENGTH }; static struct my_option my_long_options[] = @@ -328,6 +329,10 @@ static struct my_option my_long_options[] = (gptr*) &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} + { "ft_stopword_file", OPT_FT_STOPWORD_FILE, + "Use stopwords from this file instead of built-in list.", + (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, }; diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result index 7f606367f39..587c21e9129 100644 --- a/mysql-test/r/alias.result +++ b/mysql-test/r/alias.result @@ -63,7 +63,7 @@ CREATE TABLE t1 ( AUFNR varchar(12) NOT NULL default '', PLNFL varchar(6) NOT NULL default '', VORNR varchar(4) NOT NULL default '', -xstatus_vor smallint(5) unsigned NOT NULL default '0', +xstatus_vor smallint(5) unsigned NOT NULL default '0' ); INSERT INTO t1 VALUES ('40004712','000001','0010',9); INSERT INTO t1 VALUES ('40004712','000001','0020',0); diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index ce72c353d20..f2b33f2325e 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -274,6 +274,12 @@ create database `db1 `; ERROR 42000: Incorrect database name 'db1 ' create table t1(`a ` int); ERROR 42000: Incorrect column name 'a ' +create table t1 (a int,); +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 ')' at line 1 +create table t1 (a int,,b int); +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 'b int)' at line 1 +create table t1 (,b int); +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 'b int)' at line 1 create table t1 (a int, key(a)); create table t2 (b int, foreign key(b) references t1(a), key(b)); drop table if exists t1,t2; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index bdba9e4c3e4..fb0cdbbb651 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -84,9 +84,9 @@ bbbb bb bbbbbbbb aaaa bbbb select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') this is a REAL test -select soundex(''),soundex('he'),soundex('hello all folks'); -soundex('') soundex('he') soundex('hello all folks') - H000 H4142 +select soundex(''),soundex('he'),soundex('hello all folks'),soundex('#3556 in bugdb'); +soundex('') soundex('he') soundex('hello all folks') soundex('#3556 in bugdb') + H000 H4142 I51231 select 'mood' sounds like 'mud'; 'mood' sounds like 'mud' 1 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index d2ea3c4a87c..b37df0aef2c 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -352,6 +352,36 @@ extract(SECOND FROM "1999-01-02 10:11:12") select extract(MONTH FROM "2001-02-00"); extract(MONTH FROM "2001-02-00") 2 +SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; +"1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND +1968-01-20 03:14:08 +SELECT "1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND +1968-01-20 03:15:07 +SELECT "1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND +8895-03-27 22:11:40 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND; +"1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND +6255-04-08 15:04:32 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE; +"1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE +5983-01-24 02:08:00 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR; +"1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR +2019-08-15 16:00:00 +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND; +"1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE; +"1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR; +"1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR +NULL +SELECT "1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND; +"1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND +NULL create table t1 (ctime varchar(20)); insert into t1 values ('2001-01-12 12:23:40'); select ctime, hour(ctime) from t1; diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result new file mode 100644 index 00000000000..cf00adb30ae --- /dev/null +++ b/mysql-test/r/innodb-lock.result @@ -0,0 +1,22 @@ +drop table if exists t1; +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; +id x +0 0 +set autocommit=0; +lock table t1 write; +update t1 set x=1 where id = 0; +select * from t1; +id x +0 1 +commit; +update t1 set x=2 where id = 0; +commit; +unlock tables; +select * from t1; +id x +0 2 +commit; +drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 5e513061821..3c36571a8c2 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -467,7 +467,7 @@ ERROR 23000: Duplicate entry 'test2' for key 2 select * from t1; id ggid email passwd 1 this will work -3 test2 this will work +4 test2 this will work select * from t1 where id=1; id ggid email passwd 1 this will work diff --git a/mysql-test/r/raid.result b/mysql-test/r/raid.result index 690ef24d809..05013cc0d5d 100644 --- a/mysql-test/r/raid.result +++ b/mysql-test/r/raid.result @@ -4,6 +4,14 @@ create database test_$1; create table test_$1.r1 (i int) raid_type=1; create table test_$1.r2 (i int) raid_type=1 raid_chunks=32; drop database test_$1; +create database test_$1; +create table test_$1.r2 (i int) raid_type=1 raid_chunks=257; +show create table test_$1.r2; +Table Create Table +r2 CREATE TABLE `r2` ( + `i` int(11) default NULL +) TYPE=MyISAM RAID_TYPE=striped RAID_CHUNKS=255 RAID_CHUNKSIZE=256 +drop database test_$1; CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, c char(255) not null diff --git a/mysql-test/r/rpl_multi_delete2.result b/mysql-test/r/rpl_multi_delete2.result new file mode 100644 index 00000000000..8b6d87801fe --- /dev/null +++ b/mysql-test/r/rpl_multi_delete2.result @@ -0,0 +1,21 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +create table t1 (a int); +create table t2 (a int); +insert into t1 values (1); +insert into t2 values (1); +delete t1.* from t1, t2 where t1.a = t2.a; +select * from t1; +a +select * from t2; +a +1 +select * from t1; +Table 'test.t1' doesn't exist +select * from t2; +Table 'test.t2' doesn't exist +drop table t1,t2; diff --git a/mysql-test/r/rpl_multi_update.result b/mysql-test/r/rpl_multi_update.result index 65587d25f63..34f99746c7d 100644 --- a/mysql-test/r/rpl_multi_update.result +++ b/mysql-test/r/rpl_multi_update.result @@ -6,7 +6,7 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, -b int unsigned, +b int unsigned ) ENGINE=MyISAM; CREATE TABLE t2 ( a int unsigned not null auto_increment primary key, diff --git a/mysql-test/r/rpl_server_id1.result b/mysql-test/r/rpl_server_id1.result new file mode 100644 index 00000000000..d8b23b9ca41 --- /dev/null +++ b/mysql-test/r/rpl_server_id1.result @@ -0,0 +1,23 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1; +create table t1 (n int); +reset master; +stop slave; +change master to master_port=SLAVE_PORT; +show slave status; +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 Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space +127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # +start slave; +insert into t1 values (1); +show status like "slave_running"; +Variable_name Value +Slave_running ON +select * from t1; +n +1 +drop table t1; diff --git a/mysql-test/r/rpl_server_id2.result b/mysql-test/r/rpl_server_id2.result new file mode 100644 index 00000000000..5f4ec9df4c4 --- /dev/null +++ b/mysql-test/r/rpl_server_id2.result @@ -0,0 +1,21 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1; +create table t1 (n int); +reset master; +stop slave; +change master to master_port=SLAVE_PORT; +show slave status; +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 Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space +127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 # +start slave; +insert into t1 values (1); +select * from t1; +n +1 +1 +drop table t1; diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test index 852b78dd04e..986af339456 100644 --- a/mysql-test/t/alias.test +++ b/mysql-test/t/alias.test @@ -74,8 +74,7 @@ CREATE TABLE t1 ( AUFNR varchar(12) NOT NULL default '', PLNFL varchar(6) NOT NULL default '', VORNR varchar(4) NOT NULL default '', - xstatus_vor smallint(5) unsigned NOT NULL default '0', - + xstatus_vor smallint(5) unsigned NOT NULL default '0' ); INSERT INTO t1 VALUES ('40004712','000001','0010',9); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 4bd92994530..30441fb9aae 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -242,6 +242,18 @@ create database `db1 `; create table t1(`a ` int); # +# Test for Bug #3481 +# "Parser permits multiple commas without syntax error" +# + +--error 1064 +create table t1 (a int,); +--error 1064 +create table t1 (a int,,b int); +--error 1064 +create table t1 (,b int); + +# # Test create with foreign keys # diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 7efcac030af..24753c28073 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -39,7 +39,7 @@ SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),r select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; -select soundex(''),soundex('he'),soundex('hello all folks'); +select soundex(''),soundex('he'),soundex('hello all folks'),soundex('#3556 in bugdb'); select 'mood' sounds like 'mud'; select 'Glazgo' sounds like 'Liverpool'; select null sounds like 'null'; @@ -146,7 +146,7 @@ CREATE TABLE t1 ( wid int(10) unsigned NOT NULL auto_increment, data_podp date default NULL, status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy', - PRIMARY KEY(wid), + PRIMARY KEY(wid) ); INSERT INTO t1 VALUES (8,NULL,'real'); diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 4b8c26a00d8..a85f9d563e9 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -139,10 +139,27 @@ select extract(MINUTE_SECOND FROM "10:11:12"); select extract(SECOND FROM "1999-01-02 10:11:12"); select extract(MONTH FROM "2001-02-00"); +# +# Test big intervals (Bug #3498) +# +SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL "1:2147483647" MINUTE_SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL "100000000:214748364700" MINUTE_SECOND;SELECT "1900-01-01 00:00:00" + INTERVAL 1<<37 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<31 MINUTE; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<20 HOUR; + +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<38 SECOND; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<33 MINUTE; +SELECT "1900-01-01 00:00:00" + INTERVAL 1<<30 HOUR; +SELECT "1900-01-01 00:00:00" + INTERVAL "1000000000:214748364700" MINUTE_SECOND; + +# +# Bug #614 (multiple extracts in where) +# + create table t1 (ctime varchar(20)); insert into t1 values ('2001-01-12 12:23:40'); select ctime, hour(ctime) from t1; -# test bug 614 (multiple extracts in where) select ctime from t1 where extract(MONTH FROM ctime) = 1 AND extract(YEAR FROM ctime) = 2001; drop table t1; diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test new file mode 100644 index 00000000000..43a175508b4 --- /dev/null +++ b/mysql-test/t/innodb-lock.test @@ -0,0 +1,40 @@ +-- source include/have_innodb.inc + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +drop table if exists t1; + +# +# Testing of explicit table locks +# + +connection con1; +create table t1 (id integer, x integer) engine=INNODB; +insert into t1 values(0, 0); +set autocommit=0; +SELECT * from t1 where id = 0 FOR UPDATE; + +connection con2; +set autocommit=0; + +# The following statement should hang because con1 is locking the page +--send +lock table t1 write; +--sleep 2; + +connection con1; +update t1 set x=1 where id = 0; +select * from t1; +commit; + +connection con2; +reap; +update t1 set x=2 where id = 0; +commit; +unlock tables; + +connection con1; +select * from t1; +commit; + +drop table t1; diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test index 457262a8d75..14a55db0c34 100644 --- a/mysql-test/t/raid.test +++ b/mysql-test/t/raid.test @@ -21,6 +21,18 @@ create table test_$1.r1 (i int) raid_type=1; create table test_$1.r2 (i int) raid_type=1 raid_chunks=32; drop database test_$1; +# +# Bug #3182: Test using more than 257 raid chunks +# +create database test_$1; +create table test_$1.r2 (i int) raid_type=1 raid_chunks=257; +show create table test_$1.r2; +drop database test_$1; + +# +# Test that data is spread over different raid directories +# + CREATE TABLE t1 ( id int unsigned not null auto_increment primary key, c char(255) not null diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index f2ddaa273ed..4e4e79adf67 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -40,7 +40,7 @@ insert into t3 values(connection_id()); send update t2 set a = a + 1 + get_lock('crash_lock%20C', 10); connection master1; -sleep 2; +real_sleep 2; select (@id := id) - id from t3; kill @id; drop table t2,t3; diff --git a/mysql-test/t/rpl_multi_delete2-slave.opt b/mysql-test/t/rpl_multi_delete2-slave.opt new file mode 100644 index 00000000000..b828d03fafb --- /dev/null +++ b/mysql-test/t/rpl_multi_delete2-slave.opt @@ -0,0 +1 @@ +--replicate-wild-ignore-table=test.% diff --git a/mysql-test/t/rpl_multi_delete2.test b/mysql-test/t/rpl_multi_delete2.test new file mode 100644 index 00000000000..c5128833843 --- /dev/null +++ b/mysql-test/t/rpl_multi_delete2.test @@ -0,0 +1,23 @@ +source include/master-slave.inc; +create table t1 (a int); +create table t2 (a int); + +insert into t1 values (1); +insert into t2 values (1); + +delete t1.* from t1, t2 where t1.a = t2.a; + +save_master_pos; +select * from t1; +select * from t2; + +connection slave; +# BUG#3461 would cause sync to fail +sync_with_master; +error 1146; +select * from t1; +error 1146; +select * from t2; + +connection master; +drop table t1,t2; diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test index 98a199ae412..88994aa66bd 100644 --- a/mysql-test/t/rpl_multi_update.test +++ b/mysql-test/t/rpl_multi_update.test @@ -2,7 +2,7 @@ source include/master-slave.inc; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, - b int unsigned, + b int unsigned ) ENGINE=MyISAM; CREATE TABLE t2 ( diff --git a/mysql-test/t/rpl_server_id1.test b/mysql-test/t/rpl_server_id1.test new file mode 100644 index 00000000000..1bd4d9547c7 --- /dev/null +++ b/mysql-test/t/rpl_server_id1.test @@ -0,0 +1,23 @@ +# This test checks that a slave does not execute queries originating +# from itself, by default. + +source include/master-slave.inc; +connection slave; +drop table if exists t1; +create table t1 (n int); +reset master; +# replicate ourselves +stop slave; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval change master to master_port=$SLAVE_MYPORT; +--replace_result $SLAVE_MYPORT SLAVE_PORT +--replace_column 18 # +show slave status; +start slave; +insert into t1 values (1); +# can't MASTER_POS_WAIT(), it does not work in this weird setup +# (when slave is its own master without --replicate-same-server-id) +sleep 2; # enough time for the event to be replicated (it should not) +show status like "slave_running"; +select * from t1; +drop table t1; diff --git a/mysql-test/t/rpl_server_id2-slave.opt b/mysql-test/t/rpl_server_id2-slave.opt new file mode 100644 index 00000000000..302889525dd --- /dev/null +++ b/mysql-test/t/rpl_server_id2-slave.opt @@ -0,0 +1 @@ +--disable-log-slave-updates --replicate-same-server-id diff --git a/mysql-test/t/rpl_server_id2.test b/mysql-test/t/rpl_server_id2.test new file mode 100644 index 00000000000..f022ab13188 --- /dev/null +++ b/mysql-test/t/rpl_server_id2.test @@ -0,0 +1,21 @@ +# This test checks that a slave DOES execute queries originating +# from itself, if running with --replicate-same-server-id. + +source include/master-slave.inc; +connection slave; +drop table if exists t1; +create table t1 (n int); +reset master; +# replicate ourselves +stop slave; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval change master to master_port=$SLAVE_MYPORT; +--replace_result $SLAVE_MYPORT SLAVE_PORT +--replace_column 18 # +show slave status; +start slave; +insert into t1 values (1); +save_master_pos; +sync_with_master; +select * from t1; # check that indeed 2 were inserted +drop table t1; diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c index 75d9270c5af..27ab4892c57 100644 --- a/mysys/mf_soundex.c +++ b/mysys/mf_soundex.c @@ -52,7 +52,7 @@ void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr, if (remove_garbage) { - while (*in_pntr && my_isspace(cs,*in_pntr)) /* Skipp pre-space */ + while (*in_pntr && !my_isalpha(cs,*in_pntr)) /* Skipp pre-space */ in_pntr++; } *out_pntr++ = map[(uchar)*in_pntr]; /* Copy first letter */ @@ -98,7 +98,7 @@ static char get_scode(CHARSET_INFO * cs,char **ptr, pbool remove_garbage) ch=my_toupper(cs,**ptr); if (ch < 'A' || ch > 'Z') { - if (my_isalpha(cs,ch)) /* If exetended alfa (country spec) */ + if (my_isalpha(cs,ch)) /* If extended alfa (country spec) */ return '0'; /* threat as vokal */ return 0; /* Can't map */ } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 8a1f6db6f8a..efd5789968c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -342,8 +342,8 @@ int handle_options(int *argc, char ***argv, { if (!optend) /* No argument -> enable option */ *((my_bool*) value)= (my_bool) 1; - else /* If argument differs from 0, enable option, else disable */ - *((my_bool*) value)= (my_bool) atoi(optend) != 0; + else + argument= optend; } } else if (optp->arg_type == REQUIRED_ARG && !optend) @@ -398,18 +398,25 @@ int handle_options(int *argc, char ***argv, /* This is in effect a jump out of the outer loop */ optend= (char*) " "; } - else if (optp->arg_type == REQUIRED_ARG) + else { + if (optp->arg_type == OPT_ARG) + { + if (optp->var_type == GET_BOOL) + *((my_bool*) optp->value)= (my_bool) 1; + get_one_option(optp->id, optp, argument); + continue; + } /* Check if there are more arguments after this one */ - if (!*++pos) + if (!pos[1]) { - if (my_getopt_print_errors) - fprintf(stderr, - "%s: option '-%c' requires an argument\n", - my_progname, optp->id); - return EXIT_ARGUMENT_REQUIRED; + if (my_getopt_print_errors) + fprintf(stderr, + "%s: option '-%c' requires an argument\n", + my_progname, optp->id); + return EXIT_ARGUMENT_REQUIRED; } - argument= *pos; + argument= *++pos; (*argc)--; /* the other loop will break, because *optend + 1 == 0 */ } @@ -525,6 +532,9 @@ static int setval(const struct my_option *opts, gptr *value, char *argument, return EXIT_NO_PTR_TO_VARIABLE; switch ((opts->var_type & GET_TYPE_MASK)) { + case GET_BOOL: /* If argument differs from 0, enable option, else disable */ + *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0; + break; case GET_INT: case GET_UINT: /* fall through */ *((int*) result_pos)= (int) getopt_ll(argument, opts, &err); diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 0f415ccd5f0..779438e75c3 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -162,6 +162,8 @@ then echo "Please do a cd to the mysql installation directory and restart" echo "this script from there as follows:" echo "./bin/mysqld_safe". + echo "See http://dev.mysql.com/doc/mysql/en/mysqld_safe.html for more" + echo "information" exit 1 fi diff --git a/sql/field.cc b/sql/field.cc index d5499eca075..fdf314972c8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3099,9 +3099,10 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) time_t time_arg; struct tm *l_time; struct tm tm_tmp; + char *to; val_buffer->alloc(field_length+1); - char *to= (char*) val_buffer->ptr(); + to= (char*) val_buffer->ptr(); val_buffer->length(field_length); #ifdef WORDS_BIGENDIAN diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 872a6abef8b..adf3ac0d6a0 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4652,12 +4652,11 @@ the SQL statement in case of an error. */ int ha_innobase::external_lock( /*=======================*/ - /* out: 0 or error code */ + /* out: 0 */ THD* thd, /* in: handle to the user thread */ int lock_type) /* in: lock type */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - int error = 0; trx_t* trx; DBUG_ENTER("ha_innobase::external_lock"); @@ -4725,11 +4724,21 @@ ha_innobase::external_lock( } if (prebuilt->select_lock_type != LOCK_NONE) { + if (thd->in_lock_tables) { + ulint error; + error = row_lock_table_for_mysql(prebuilt); + + if (error != DB_SUCCESS) { + error = convert_error_code_to_mysql( + error, user_thd); + DBUG_RETURN(error); + } + } trx->mysql_n_tables_locked++; } - DBUG_RETURN(error); + DBUG_RETURN(0); } /* MySQL is releasing a table lock */ @@ -4737,6 +4746,9 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; + if (trx->n_tables_locked) { + row_unlock_table_for_mysql(trx); + } /* If the MySQL lock count drops to zero we know that the current SQL statement has ended */ @@ -4768,7 +4780,7 @@ ha_innobase::external_lock( } } - DBUG_RETURN(error); + DBUG_RETURN(0); } /**************************************************************************** @@ -4805,6 +4817,7 @@ innodb_show_status( rewind(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); + my_chsize(fileno(srv_monitor_file), flen, 0, MYF(0)); if(flen > 64000 - 1) { flen = 64000 - 1; } diff --git a/sql/item.cc b/sql/item.cc index e1cdfcf42c0..98e6f02efad 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1354,7 +1354,10 @@ int Item::save_in_field(Field *field, bool no_conversions) str_value.set_quick(buff, sizeof(buff), cs); result=val_str(&str_value); if (null_value) + { + str_value.set_quick(0, 0); return set_field_to_null_with_conversions(field, no_conversions); + } field->set_notnull(); error=field->store(result->ptr(),result->length(),cs); str_value.set_quick(0, 0, cs); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 933995c1d22..6b7a401c31e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1579,7 +1579,7 @@ String *Item_func_soundex::val_str(String *str) char *from= (char *) res->ptr(), *end=from+res->length(); tmp_value.set_charset(cs); - while (from != end && my_isspace(cs,*from)) // Skip pre-space + while (from != end && !my_isalpha(cs,*from)) // Skip pre-space from++; /* purecov: inspected */ if (from == end) return &my_empty_string; // No alpha characters. diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a578abc345a..f22c14c925f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -634,8 +634,8 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, For example, '1.1' -> '1.100000' */ -bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, - uint count, long *values, bool transform_msec) +static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, + uint count, long *values, bool transform_msec) { const char *end=str+length; uint i; @@ -644,10 +644,10 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, for (i=0 ; i < count ; i++) { - long value; + longlong value; const char *start= str; for (value=0; str != end && my_isdigit(cs,*str) ; str++) - value=value*10L + (long) (*str - '0'); + value= value*LL(10) + (longlong) (*str - '0'); if (transform_msec && i == count - 1) // microseconds always last { long msec_length= 6 - (str - start); @@ -662,14 +662,15 @@ bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, i++; /* Change values[0...i-1] -> values[0...count-1] */ bmove_upp((char*) (values+count), (char*) (values+i), - sizeof(long)*i); - bzero((char*) values, sizeof(long)*(count-i)); + sizeof(*values)*i); + bzero((char*) values, sizeof(*values)*(count-i)); break; } } return (str != end); } + longlong Item_func_period_add::val_int() { DBUG_ASSERT(fixed == 1); @@ -929,7 +930,8 @@ longlong Item_func_time_to_sec::val_int() static bool get_interval_value(Item *args,interval_type int_type, String *str_value, INTERVAL *interval) { - long array[5],value; + ulonglong array[5]; + longlong value; const char *str; uint32 length; CHARSET_INFO *cs=str_value->charset(); @@ -941,7 +943,7 @@ static bool get_interval_value(Item *args,interval_type int_type, bzero((char*) interval,sizeof(*interval)); if ((int) int_type <= INTERVAL_MICROSECOND) { - value=(long) args->val_int(); + value= args->val_int(); if (args->null_value) return 1; if (value < 0) @@ -971,16 +973,16 @@ static bool get_interval_value(Item *args,interval_type int_type, switch (int_type) { case INTERVAL_YEAR: - interval->year=value; + interval->year= (ulong) value; break; case INTERVAL_MONTH: - interval->month=value; + interval->month= (ulong) value; break; case INTERVAL_DAY: - interval->day=value; + interval->day= (ulong) value; break; case INTERVAL_HOUR: - interval->hour=value; + interval->hour= (ulong) value; break; case INTERVAL_MICROSECOND: interval->second_part=value; @@ -994,78 +996,78 @@ static bool get_interval_value(Item *args,interval_type int_type, case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->year=array[0]; - interval->month=array[1]; + interval->year= (ulong) array[0]; + interval->month= (ulong) array[1]; break; case INTERVAL_DAY_HOUR: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; break; case INTERVAL_DAY_MICROSECOND: if (get_interval_info(str,length,cs,5,array,1)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; - interval->second=array[3]; - interval->second_part=array[4]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; + interval->second= array[3]; + interval->second_part= array[4]; break; case INTERVAL_DAY_MINUTE: if (get_interval_info(str,length,cs,3,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; break; case INTERVAL_DAY_SECOND: if (get_interval_info(str,length,cs,4,array,0)) return (1); - interval->day=array[0]; - interval->hour=array[1]; - interval->minute=array[2]; - interval->second=array[3]; + interval->day= (ulong) array[0]; + interval->hour= (ulong) array[1]; + interval->minute= array[2]; + interval->second= array[3]; break; case INTERVAL_HOUR_MICROSECOND: if (get_interval_info(str,length,cs,4,array,1)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; - interval->second=array[2]; - interval->second_part=array[3]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; + interval->second= array[2]; + interval->second_part= array[3]; break; case INTERVAL_HOUR_MINUTE: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; break; case INTERVAL_HOUR_SECOND: if (get_interval_info(str,length,cs,3,array,0)) return (1); - interval->hour=array[0]; - interval->minute=array[1]; - interval->second=array[2]; + interval->hour= (ulong) array[0]; + interval->minute= array[1]; + interval->second= array[2]; break; case INTERVAL_MINUTE_MICROSECOND: if (get_interval_info(str,length,cs,3,array,1)) return (1); - interval->minute=array[0]; - interval->second=array[1]; - interval->second_part=array[2]; + interval->minute= array[0]; + interval->second= array[1]; + interval->second_part= array[2]; break; case INTERVAL_MINUTE_SECOND: if (get_interval_info(str,length,cs,2,array,0)) return (1); - interval->minute=array[0]; - interval->second=array[1]; + interval->minute= array[0]; + interval->second= array[1]; break; case INTERVAL_SECOND_MICROSECOND: if (get_interval_info(str,length,cs,2,array,1)) return (1); - interval->second=array[0]; - interval->second_part=array[1]; + interval->second= array[0]; + interval->second_part= array[1]; break; } return 0; @@ -1639,7 +1641,8 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) case INTERVAL_DAY_SECOND: case INTERVAL_DAY_MINUTE: case INTERVAL_DAY_HOUR: - long sec,days,daynr,microseconds,extra_sec; + { + longlong sec, days, daynr, microseconds, extra_sec; ltime->time_type=TIMESTAMP_DATETIME; // Return full date microseconds= ltime->second_part + sign*interval.second_part; extra_sec= microseconds/1000000L; @@ -1647,40 +1650,44 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+ ltime->second + - sign*(interval.day*3600*24L + - interval.hour*3600+interval.minute*60+interval.second))+ - extra_sec; - + sign* (longlong) (interval.day*3600*24L + + interval.hour*3600+interval.minute*60+ + interval.second))+ extra_sec; if (microseconds < 0) { - microseconds+= 1000000L; + microseconds+= LL(1000000); sec--; } - days=sec/(3600*24L); sec=sec-days*3600*24L; + days= sec/(3600*LL(24)); + sec-= days*3600*LL(24); if (sec < 0) { days--; - sec+=3600*24L; + sec+= 3600*LL(24); } ltime->second_part= microseconds; - ltime->second=sec % 60; - ltime->minute=sec/60 % 60; - ltime->hour=sec/3600; + ltime->second= (uint) (sec % 60); + ltime->minute= (uint) (sec/60 % 60); + ltime->hour= (uint) (sec/3600); daynr= calc_daynr(ltime->year,ltime->month,1) + days; - get_date_from_daynr(daynr,<ime->year,<ime->month,<ime->day); - if (daynr < 0 || daynr >= MAX_DAY_NUMBER) // Day number from year 0 to 9999-12-31 + /* Day number from year 0 to 9999-12-31 */ + if ((ulonglong) daynr >= MAX_DAY_NUMBER) goto null_date; + get_date_from_daynr((long) daynr, <ime->year, <ime->month, + <ime->day); break; + } case INTERVAL_DAY: - period= calc_daynr(ltime->year,ltime->month,ltime->day) + - sign*interval.day; - if (period < 0 || period >= MAX_DAY_NUMBER) // Daynumber from year 0 to 9999-12-31 + period= (calc_daynr(ltime->year,ltime->month,ltime->day) + + sign * (long) interval.day); + /* Daynumber from year 0 to 9999-12-31 */ + if ((ulong) period >= MAX_DAY_NUMBER) goto null_date; get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); break; case INTERVAL_YEAR: - ltime->year += sign*interval.year; - if ((int) ltime->year < 0 || ltime->year >= 10000L) + ltime->year+= sign * (long) interval.year; + if ((ulong) ltime->year >= 10000L) goto null_date; if (ltime->month == 2 && ltime->day == 29 && calc_days_in_year(ltime->year) != 366) @@ -1688,9 +1695,9 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) break; case INTERVAL_YEAR_MONTH: case INTERVAL_MONTH: - period= (ltime->year*12 + sign*interval.year*12 + - ltime->month-1 + sign*interval.month); - if (period < 0 || period >= 120000L) + period= (ltime->year*12 + sign * (long) interval.year*12 + + ltime->month-1 + sign * (long) interval.month); + if ((ulong) period >= 120000L) goto null_date; ltime->year= (uint) (period / 12); ltime->month= (uint) (period % 12L)+1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 207f4a51ff4..b3ec1f0fe55 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -998,11 +998,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) { slave_print_error(rli,expected_error, "\ -Query '%s' partially completed on the master (error on master: %d) \ +Query partially completed on the master (error on master: %d) \ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the \ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \ -START SLAVE; .", thd->query, expected_error); +START SLAVE; . Query: '%s'", expected_error, thd->query); thd->query_error= 1; } goto end; @@ -1021,15 +1021,14 @@ START SLAVE; .", thd->query, expected_error); { slave_print_error(rli, 0, "\ -Query '%s' caused different errors on master and slave. \ +Query caused different errors on master and slave. \ Error on master: '%s' (%d), Error on slave: '%s' (%d). \ -Default database: '%s'", - query, +Default database: '%s'. Query: '%s'", ER_SAFE(expected_error), expected_error, actual_error ? thd->net.last_error: "no error", actual_error, - print_slave_db_safe(db)); + print_slave_db_safe(db), query); thd->query_error= 1; } /* @@ -1047,11 +1046,10 @@ Default database: '%s'", else if (thd->query_error || thd->is_fatal_error) { slave_print_error(rli,actual_error, - "Error '%s' on query '%s'. Default database: '%s'", + "Error '%s' on query. Default database: '%s'. Query: '%s'", (actual_error ? thd->net.last_error : "unexpected success or fatal error"), - query, - print_slave_db_safe(db)); + print_slave_db_safe(db), query); thd->query_error= 1; } } /* End of if (db_ok(... */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a5b6bf40c71..8cae95e5070 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1042,8 +1042,7 @@ void reset_host_errors(struct in_addr *in); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); -bool get_interval_info(const char *str,uint length,uint count, - long *values); + /* sql_cache.cc */ extern bool sql_cache_init(); extern void sql_cache_free(); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b85041207bd..c231ec0e024 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2328,6 +2328,15 @@ Warning: you need to use --log-bin to make --log-slave-updates work. \ Now disabling --log-slave-updates."); } + if (opt_log_slave_updates && replicate_same_server_id) + { + sql_print_error("\ +Error: using --replicate-same-server-id in conjunction with \ +--log-slave-updates is impossible, it would lead to infinite loops in this \ +server."); + unireg_abort(1); + } + if (opt_error_log) { if (!log_error_file_ptr[0]) @@ -3616,7 +3625,7 @@ enum options_mysqld OPT_SKIP_SLAVE_START, OPT_SKIP_INNOBASE, OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE, OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE, - OPT_REPLICATE_WILD_IGNORE_TABLE, + OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID, OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_ABORT_SLAVE_EVENT_COUNT, OPT_INNODB_DATA_HOME_DIR, @@ -4090,6 +4099,13 @@ master-ssl", {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID, + "In replication, if set to 1, do not skip events having our server id. \ +Default value is 0 (to break infinite loops in circular replication). \ +Can't be set to 1 if --log-slave-updates is used.", + (gptr*) &replicate_same_server_id, + (gptr*) &replicate_same_server_id, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, // In replication, we may need to tell the other servers how to connect {"report-host", OPT_REPORT_HOST, "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.", @@ -4143,7 +4159,7 @@ relay logs.", 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, - "Show user and password in SHOW SLAVE HOSTS.", + "Show user and password in SHOW SLAVE HOSTS on this master", (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, diff --git a/sql/slave.cc b/sql/slave.cc index 61d5e956e6c..c8da53433d7 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -39,7 +39,7 @@ HASH replicate_do_table, replicate_ignore_table; DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; bool do_table_inited = 0, ignore_table_inited = 0; bool wild_do_table_inited = 0, wild_ignore_table_inited = 0; -bool table_rules_on = 0; +bool table_rules_on= 0, replicate_same_server_id; ulonglong relay_log_space_limit = 0; /* @@ -747,7 +747,16 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) Note that changing the order of the tables in the list can lead to different results. Note also the order of precedence of the do/ignore rules (see code below). For that reason, users should not set conflicting - rules because they may get unpredicted results. + rules because they may get unpredicted results (precedence order is + explained in the manual). + If no table of the list is marked "updating" (so far this can only happen + if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables" + is the tables in the FROM): then we always return 0, because there is no + reason we play this statement on this slave if it updates nothing. In the + case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(), + with tables having "updating==TRUE" (those after the DELETE), so this + second call will make the decision (because + all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)). RETURN VALUES 0 should not be logged/replicated @@ -756,6 +765,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) int tables_ok(THD* thd, TABLE_LIST* tables) { + bool some_tables_updating= 0; DBUG_ENTER("tables_ok"); for (; tables; tables = tables->next) @@ -766,6 +776,7 @@ int tables_ok(THD* thd, TABLE_LIST* tables) if (!tables->updating) continue; + some_tables_updating= 1; end= strmov(hash_key, tables->db ? tables->db : thd->db); *end++= '.'; len= (uint) (strmov(end, tables->real_name) - hash_key); @@ -788,10 +799,13 @@ int tables_ok(THD* thd, TABLE_LIST* tables) } /* + If no table was to be updated, ignore statement (no reason we play it on + slave, slave is supposed to replicate _changes_ only). If no explicit rule found and there was a do list, do not replicate. If there was no do list, go ahead */ - DBUG_RETURN(!do_table_inited && !wild_do_table_inited); + DBUG_RETURN(some_tables_updating && + !do_table_inited && !wild_do_table_inited); } @@ -1529,13 +1543,13 @@ Failed to open the existing relay log info file '%s' (errno %d)", rli->info_fd = info_fd; int relay_log_pos, master_log_pos; if (init_strvar_from_file(rli->group_relay_log_name, - sizeof(rli->group_relay_log_name), &rli->info_file, - "") || + sizeof(rli->group_relay_log_name), + &rli->info_file, "") || init_intvar_from_file(&relay_log_pos, &rli->info_file, BIN_LOG_HEADER_SIZE) || init_strvar_from_file(rli->group_master_log_name, - sizeof(rli->group_master_log_name), &rli->info_file, - "") || + sizeof(rli->group_master_log_name), + &rli->info_file, "") || init_intvar_from_file(&master_log_pos, &rli->info_file, 0)) { msg="Error reading slave log configuration"; @@ -2232,7 +2246,8 @@ st_relay_log_info::st_relay_log_info() inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), until_log_pos(0) { - group_relay_log_name[0]= event_relay_log_name[0]= group_master_log_name[0]= 0; + group_relay_log_name[0]= event_relay_log_name[0]= + group_master_log_name[0]= 0; last_slave_error[0]=0; until_log_name[0]= 0; bzero((char*) &info_file, sizeof(info_file)); @@ -2334,6 +2349,8 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, error= -2; //means improper arguments goto err; } + // Convert 0-3 to 4 + log_pos= max(log_pos, BIN_LOG_HEADER_SIZE); /* p points to '.' */ log_name_extension= strtoul(++p, &p_end, 10); /* @@ -2354,10 +2371,24 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, { bool pos_reached; int cmp_result= 0; - DBUG_ASSERT(*group_master_log_name || group_master_log_pos == 0); + + /* + group_master_log_name can be "", if we are just after a fresh + replication start or after a CHANGE MASTER TO MASTER_HOST/PORT + (before we have executed one Rotate event from the master) or + (rare) if the user is doing a weird slave setup (see next + paragraph). If group_master_log_name is "", we assume we don't + have enough info to do the comparison yet, so we just wait until + more data. In this case master_log_pos is always 0 except if + somebody (wrongly) sets this slave to be a slave of itself + without using --replicate-same-server-id (an unsupported + configuration which does nothing), then group_master_log_pos + will grow and group_master_log_name will stay "". + */ if (*group_master_log_name) { - char *basename= group_master_log_name + dirname_length(group_master_log_name); + char *basename= (group_master_log_name + + dirname_length(group_master_log_name)); /* First compare the parts before the extension. Find the dot in the master's log basename, @@ -2374,14 +2405,15 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, char *q_end; ulong group_master_log_name_extension= strtoul(q, &q_end, 10); if (group_master_log_name_extension < log_name_extension) - cmp_result = -1 ; + cmp_result= -1 ; else cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ; + + pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || + cmp_result > 0); + if (pos_reached || thd->killed) + break; } - pos_reached = ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || - cmp_result > 0); - if (pos_reached || thd->killed) - break; //wait for master update, with optional timeout. @@ -2801,7 +2833,12 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) log files themselves. */ - if (ev->server_id == (uint32) ::server_id || + /* + TODO: when this is merged into 4.1, one needs to update queue_event() to + add a similar test for replicate_same_server_id, because in 4.1 the I/O + thread is also filtering events based on the server id. + */ + if ((ev->server_id == (uint32) ::server_id && !replicate_same_server_id) || (rli->slave_skip_counter && type_code != ROTATE_EVENT)) { /* TODO: I/O thread should not even log events with the same server id */ @@ -3530,8 +3567,8 @@ static int queue_old_event(MASTER_INFO *mi, const char *buf, this end 0, which leads to segfault. */ tmp_buf[event_len++]=0; - buf = (const char*)tmp_buf; int4store(tmp_buf+EVENT_LEN_OFFSET, event_len); + buf = (const char*)tmp_buf; } /* This will transform LOAD_EVENT into CREATE_FILE_EVENT, ask the master to diff --git a/sql/slave.h b/sql/slave.h index c925831d1a5..384436fdfcc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -529,7 +529,7 @@ extern HASH replicate_do_table, replicate_ignore_table; extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table; extern bool do_table_inited, ignore_table_inited, wild_do_table_inited, wild_ignore_table_inited; -extern bool table_rules_on; +extern bool table_rules_on, replicate_same_server_id; extern int disconnect_slave_event_count, abort_slave_event_count ; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f8dca1133cc..625068e655c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -850,11 +850,11 @@ static void acl_insert_user(const char *user, const char *host, { ACL_USER acl_user; acl_user.user=*user ? strdup_root(&mem,user) : 0; - update_hostname(&acl_user.host,strdup_root(&mem,host)); + update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0); acl_user.access=privileges; acl_user.user_resource = *mqh; acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); - acl_user.hostname_length=(uint) strlen(acl_user.host.hostname); + acl_user.hostname_length=(uint) strlen(host); acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? ssl_type : SSL_TYPE_NONE); acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0; @@ -1705,107 +1705,124 @@ static byte* get_key_column(GRANT_COLUMN *buff,uint *length, class GRANT_TABLE :public Sql_alloc { public: - char *host,*db,*user,*tname, *hash_key; + char *host,*db, *user, *tname, *hash_key, *orig_host; ulong privs, cols; ulong sort; uint key_length; HASH hash_columns; - GRANT_TABLE (const char *h, const char *d,const char *u, const char *t, - ulong p, ulong c) - : privs(p), cols(c) - { - host = strdup_root(&memex,h); - db = strdup_root(&memex,d); - user = strdup_root(&memex,u); - sort= get_sort(3,host,db,user); - tname= strdup_root(&memex,t); - if (lower_case_table_names) - { - my_casedn_str(&my_charset_latin1, db); - my_casedn_str(&my_charset_latin1, tname); - } - key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; - hash_key = (char*) alloc_root(&memex,key_length); - strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,&my_charset_latin1, - 0,0,0, (hash_get_key) get_key_column,0,0); - } - - GRANT_TABLE (TABLE *form, TABLE *col_privs) - { - byte key[MAX_KEY_LENGTH]; - - host = get_field(&memex,form->field[0]); - db = get_field(&memex,form->field[1]); - user = get_field(&memex,form->field[2]); - if (!user) - user=(char*) ""; - sort= get_sort(3,host,db,user); - tname= get_field(&memex,form->field[3]); - if (!host || !db || !tname) - { - /* Wrong table row; Ignore it */ - privs = cols = 0; /* purecov: inspected */ - return; /* purecov: inspected */ - } - if (lower_case_table_names) - { - my_casedn_str(&my_charset_latin1, db); - my_casedn_str(&my_charset_latin1, tname); - } - key_length = ((uint) strlen(db) + (uint) strlen(user) + - (uint) strlen(tname) + 3); - hash_key = (char*) alloc_root(&memex,key_length); - strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - privs = (ulong) form->field[6]->val_int(); - cols = (ulong) form->field[7]->val_int(); - privs = fix_rights_for_table(privs); - cols = fix_rights_for_column(cols); - - (void) hash_init(&hash_columns,&my_charset_latin1, - 0,0,0, (hash_get_key) get_key_column,0,0); - if (cols) - { - int key_len; - col_privs->field[0]->store(host,(uint) strlen(host), &my_charset_latin1); - col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); - col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); - key_len=(col_privs->field[0]->pack_length()+ - col_privs->field[1]->pack_length()+ - col_privs->field[2]->pack_length()+ - col_privs->field[3]->pack_length()); - key_copy(key,col_privs,0,key_len); - col_privs->field[4]->store("",0, &my_charset_latin1); - col_privs->file->index_init(0); - if (col_privs->file->index_read(col_privs->record[0], - (byte*) col_privs->field[0]->ptr, - key_len, HA_READ_KEY_EXACT)) + + GRANT_TABLE(const char *h, const char *d,const char *u, + const char *t, ulong p, ulong c); + GRANT_TABLE (TABLE *form, TABLE *col_privs); + bool ok() { return privs != 0 || cols != 0; } +}; + + + +GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, + const char *t, ulong p, ulong c) + :privs(p), cols(c) +{ + /* Host given by user */ + orig_host= strdup_root(&memex,h); + /* Convert empty hostname to '%' for easy comparision */ + host= orig_host[0] ? orig_host : (char*) "%"; + db = strdup_root(&memex,d); + user = strdup_root(&memex,u); + sort= get_sort(3,host,db,user); + tname= strdup_root(&memex,t); + if (lower_case_table_names) + { + my_casedn_str(&my_charset_latin1, db); + my_casedn_str(&my_charset_latin1, tname); + } + key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; + hash_key = (char*) alloc_root(&memex,key_length); + strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); + (void) hash_init(&hash_columns,&my_charset_latin1, + 0,0,0, (hash_get_key) get_key_column,0,0); +} + + +GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) +{ + byte key[MAX_KEY_LENGTH]; + + orig_host= host= get_field(&memex, form->field[0]); + db= get_field(&memex,form->field[1]); + user= get_field(&memex,form->field[2]); + if (!user) + user= (char*) ""; + if (!orig_host) + { + orig_host= (char*) ""; + host= (char*) "%"; + } + sort= get_sort(3, orig_host, db, user); + tname= get_field(&memex,form->field[3]); + if (!db || !tname) + { + /* Wrong table row; Ignore it */ + privs = cols = 0; /* purecov: inspected */ + return; /* purecov: inspected */ + } + if (lower_case_table_names) + { + my_casedn_str(&my_charset_latin1, db); + my_casedn_str(&my_charset_latin1, tname); + } + key_length = ((uint) strlen(db) + (uint) strlen(user) + + (uint) strlen(tname) + 3); + hash_key = (char*) alloc_root(&memex,key_length); + strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); + privs = (ulong) form->field[6]->val_int(); + cols = (ulong) form->field[7]->val_int(); + privs = fix_rights_for_table(privs); + cols = fix_rights_for_column(cols); + + (void) hash_init(&hash_columns,&my_charset_latin1, + 0,0,0, (hash_get_key) get_key_column,0,0); + if (cols) + { + int key_len; + col_privs->field[0]->store(orig_host,(uint) strlen(orig_host), + &my_charset_latin1); + col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); + col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); + col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); + key_len=(col_privs->field[0]->pack_length()+ + col_privs->field[1]->pack_length()+ + col_privs->field[2]->pack_length()+ + col_privs->field[3]->pack_length()); + key_copy(key,col_privs,0,key_len); + col_privs->field[4]->store("",0, &my_charset_latin1); + col_privs->file->index_init(0); + if (col_privs->file->index_read(col_privs->record[0], + (byte*) col_privs->field[0]->ptr, + key_len, HA_READ_KEY_EXACT)) + { + cols = 0; /* purecov: deadcode */ + return; + } + do + { + String *res,column_name; + GRANT_COLUMN *mem_check; + /* As column name is a string, we don't have to supply a buffer */ + res=col_privs->field[4]->val_str(&column_name); + ulong priv= (ulong) col_privs->field[6]->val_int(); + if (!(mem_check = new GRANT_COLUMN(*res, + fix_rights_for_column(priv)))) { - cols = 0; /* purecov: deadcode */ - return; + /* Don't use this entry */ + privs = cols = 0; /* purecov: deadcode */ + return; /* purecov: deadcode */ } - do - { - String *res,column_name; - GRANT_COLUMN *mem_check; - /* As column name is a string, we don't have to supply a buffer */ - res=col_privs->field[4]->val_str(&column_name); - ulong priv= (ulong) col_privs->field[6]->val_int(); - if (!(mem_check = new GRANT_COLUMN(*res, - fix_rights_for_column(priv)))) - { - /* Don't use this entry */ - privs = cols = 0; /* purecov: deadcode */ - return; /* purecov: deadcode */ - } - my_hash_insert(&hash_columns, (byte *) mem_check); - } while (!col_privs->file->index_next(col_privs->record[0]) && - !key_cmp(col_privs,key,0,key_len)); - } + my_hash_insert(&hash_columns, (byte *) mem_check); + } while (!col_privs->file->index_next(col_privs->record[0]) && + !key_cmp(col_privs,key,0,key_len)); } - bool ok() { return privs != 0 || cols != 0; } -}; +} static byte* get_grant_table(GRANT_TABLE *buff,uint *length, @@ -2646,7 +2663,7 @@ void grant_reload(THD *thd) /**************************************************************************** - Check grants + Check table level grants All errors are written directly to the client if no_errors is given ! ****************************************************************************/ @@ -3010,9 +3027,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) const char *user,*host; acl_user=dynamic_element(&acl_users,counter,ACL_USER*); if (!(user=acl_user->user)) - user=""; + user= ""; if (!(host=acl_user->host.hostname)) - host="%"; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) break; @@ -3142,9 +3159,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user=acl_db->user)) - user=""; + user= ""; if (!(host=acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) @@ -3195,7 +3212,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) } } - /* Add column access */ + /* Add table & column access */ for (index=0 ; index < column_priv_hash.records ; index++) { const char *user,*host; @@ -3203,9 +3220,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) index); if (!(user=grant_table->user)) - user=""; - if (!(host=grant_table->host)) - host=""; + user= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) @@ -3225,6 +3240,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append("USAGE",5); else { + /* Add specific column access */ int found= 0; ulong j; @@ -3405,9 +3421,9 @@ ACL_USER *check_acl_user(LEX_USER *user_name, const char *user,*host; acl_user= dynamic_element(&acl_users, counter, ACL_USER*); if (!(user=acl_user->user)) - user=""; + user= ""; if (!(host=acl_user->host.hostname)) - host="%"; + host= "%"; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) break; @@ -3463,9 +3479,9 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) const char *user,*host; acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user= acl_db->user)) - user=""; + user= ""; if (!(host= acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) @@ -3486,9 +3502,9 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, counter); if (!(user=grant_table->user)) - user=""; + user= ""; if (!(host=grant_table->host)) - host=""; + host= ""; if (!strcmp(user_name->user.str,user) && !my_strcasecmp(system_charset_info, user_name->host.str, host)) @@ -3576,9 +3592,9 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); if (!(user=acl_db->user)) - user=""; + user= ""; if (!(host=acl_db->host.hostname)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) @@ -3595,9 +3611,9 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, counter); if (!(user=grant_table->user)) - user=""; + user= ""; if (!(host=grant_table->host)) - host=""; + host= ""; if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 75c7a779180..3a18b7eaabc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2607,9 +2607,15 @@ static void mysql_rm_tmp_tables(void) /* Remove all SQLxxx tables from directory */ - for (idx=2 ; idx < (uint) dirp->number_off_files ; idx++) + for (idx=0 ; idx < (uint) dirp->number_off_files ; idx++) { file=dirp->dir_entry+idx; + + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) { sprintf(filePath,"%s%s",tmpdir,file->name); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index a6bd1955fa5..bddaebdc0f2 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -462,7 +462,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, tot_list_next= &tot_list; - for (uint idx=2 ; + for (uint idx=0 ; idx < (uint) dirp->number_off_files && !thd->killed ; idx++) { @@ -470,6 +470,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, char *extension; DBUG_PRINT("info",("Examining: %s", file->name)); + /* skiping . and .. */ + if (file->name[0] == '.' && (!file->name[1] || + (file->name[1] == '.' && !file->name[2]))) + continue; + /* Check if file is a raid directory */ if ((my_isdigit(&my_charset_latin1, file->name[0]) || (file->name[0] >= 'a' && file->name[0] <= 'f')) && diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8185c716228..59c2999863a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -486,6 +486,7 @@ int write_record(TABLE *table,COPY_INFO *info) { int error; char *key=0; + DBUG_ENTER("write_record"); info->records++; if (info->handle_duplicates == DUP_REPLACE || @@ -593,14 +594,14 @@ int write_record(TABLE *table,COPY_INFO *info) info->copied++; if (key) my_safe_afree(key,table->max_unique_length,MAX_KEY_LENGTH); - return 0; + DBUG_RETURN(0); err: if (key) my_afree(key); info->last_errno= error; table->file->print_error(error,MYF(0)); - return 1; + DBUG_RETURN(1); } @@ -1468,24 +1469,25 @@ select_insert::~select_insert() bool select_insert::send_data(List<Item> &values) { + DBUG_ENTER("select_insert::send_data"); if (unit->offset_limit_cnt) { // using limit offset,count unit->offset_limit_cnt--; - return 0; + DBUG_RETURN(0); } if (fields->elements) fill_record(*fields, values, 1); else fill_record(table->field, values, 1); if (thd->net.report_error || write_record(table,&info)) - return 1; + DBUG_RETURN(1); if (table->next_number_field) // Clear for next record { table->next_number_field->reset(); if (! last_insert_id && thd->insert_id_used) last_insert_id=thd->insert_id(); } - return 0; + DBUG_RETURN(0); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 568a526fd58..86b4702d314 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1176,7 +1176,7 @@ field_list_item: ; column_def: - field_spec check_constraint + field_spec opt_check_constraint | field_spec references { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -1208,15 +1208,23 @@ key_def: lex->fk_match_option)); lex->col_list.empty(); /* Alloced by sql_alloc */ } + | constraint opt_check_constraint + { + Lex->col_list.empty(); /* Alloced by sql_alloc */ + } | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ } ; -check_constraint: +opt_check_constraint: /* empty */ - | CHECK_SYM expr + | check_constraint + ; + +check_constraint: + CHECK_SYM expr ; opt_constraint: diff --git a/sql/structs.h b/sql/structs.h index d9607b220f7..ee231186e1a 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -150,7 +150,8 @@ typedef struct st_time { typedef struct { - long year,month,day,hour,minute,second,second_part; + ulong year,month,day,hour; + ulonglong minute,second,second_part; bool neg; } INTERVAL; diff --git a/sql/table.cc b/sql/table.cc index 281a8c10409..73f036aed87 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1140,6 +1140,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, if (create_info->min_rows > ~(ulong) 0) create_info->min_rows= ~(ulong) 0; #endif + /* + Ensure that raid_chunks can't be larger than 255, as this would cause + problems with drop database + */ + set_if_smaller(create_info->raid_chunks, 255); if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s index 3bfd1777e18..8476bf49b75 100644 --- a/strings/longlong2str-x86.s +++ b/strings/longlong2str-x86.s @@ -142,7 +142,7 @@ longlong2str: .align 4 .globl longlong10_to_str - .type longlong10_str,@function + .type longlong10_to_str,@function longlong10_to_str: subl $80,%esp pushl %ebp diff --git a/strings/strings-x86.s b/strings/strings-x86.s index 9409657e06c..d316c34febb 100644 --- a/strings/strings-x86.s +++ b/strings/strings-x86.s @@ -412,4 +412,4 @@ next_str: movl %edx,%ebx ret .strxmov_end: - .size strxmov,strxmov_end-strxmov + .size strxmov,.strxmov_end-strxmov diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index d4ae0061a95..4650ed06dc1 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -1,8 +1,8 @@ # Example mysql config file for medium systems. # # This is for a system with little memory (32M - 64M) where MySQL plays -# a important part and systems up to 128M very MySQL is used together with -# other programs (like a web server) +# an important part, or systems up to 128M where MySQL is used together with +# other programs (such as a web server) # # You can copy this file to # /etc/my.cnf to set global options, |