summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@narttu.mysql.fi>2003-06-04 19:21:51 +0300
committerunknown <monty@narttu.mysql.fi>2003-06-04 19:21:51 +0300
commit13f7e49494559bba3195ccf3abdb349fbe79b6dc (patch)
tree6b8e47374bf313429416a26678bc409946f34772 /sql
parentb388eb004df7112b2ae0986457fc9d01131b71ea (diff)
parentb5860aed7b1d11f2d3ac909cde1438c86af26cb5 (diff)
downloadmariadb-git-13f7e49494559bba3195ccf3abdb349fbe79b6dc.tar.gz
Merge with 4.0.13
BitKeeper/etc/logging_ok: auto-union BUILD/SETUP.sh: Auto merged BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43: Auto merged client/mysqltest.c: Auto merged include/config-win.h: Auto merged include/my_global.h: Auto merged include/mysql_com.h: Auto merged innobase/include/srv0srv.h: Auto merged innobase/log/log0log.c: Auto merged innobase/os/os0file.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/ut/ut0mem.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/errors.result: Auto merged mysql-test/r/loaddata.result: Auto merged mysql-test/r/rpl_insert_id.result: Auto merged mysql-test/r/rpl_loaddata.result: Auto merged mysql-test/std_data/rpl_loaddata2.dat: Auto merged mysql-test/t/alter_table.test: Auto merged mysql-test/t/loaddata.test: Auto merged mysql-test/t/query_cache.test: Auto merged mysql-test/t/raid.test: Auto merged mysql-test/t/rpl_insert_id.test: Auto merged mysql-test/t/rpl_loaddata.test: Auto merged sql/field.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_update.cc: Auto merged sql/time.cc: Auto merged configure.in: No changes libmysqld/lib_sql.cc: No changes
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc3
-rw-r--r--sql/log.cc51
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/mysqld.cc52
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/slave.cc27
-rw-r--r--sql/sql_cache.cc16
-rw-r--r--sql/sql_insert.cc24
-rw-r--r--sql/sql_table.cc133
-rw-r--r--sql/sql_update.cc1
-rw-r--r--sql/sql_yacc.yy3
-rw-r--r--sql/time.cc56
12 files changed, 244 insertions, 128 deletions
diff --git a/sql/field.cc b/sql/field.cc
index a61654ed8f4..f610f95ae0e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2755,6 +2755,7 @@ int Field_timestamp::store(longlong nr)
if ((nr=fix_datetime(nr)))
{
+ long not_used;
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
l_time.year= (int) (part1/10000L); part1%=10000L;
@@ -2763,7 +2764,7 @@ int Field_timestamp::store(longlong nr)
l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
- timestamp=my_gmt_sec(&l_time);
+ timestamp=my_gmt_sec(&l_time, &not_used);
}
else
timestamp=0;
diff --git a/sql/log.cc b/sql/log.cc
index c05d52bdc5d..0ccb40c5246 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1200,6 +1200,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
No check for auto events flag here - this write method should
never be called if auto-events are enabled
*/
+
+ /*
+ 1. Write first log events which describe the 'run environment'
+ of the SQL command
+ */
+
if (thd)
{
if (thd->last_insert_id_used)
@@ -1245,7 +1251,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
}
-#if 0
+#ifdef TO_BE_REMOVED
if (thd->variables.convert_set)
{
char buf[256], *p;
@@ -1257,12 +1263,39 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
#endif
+
+ /*
+ If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
+ command in the binlog inside:
+ SET FOREIGN_KEY_CHECKS=0;
+ <command>;
+ SET FOREIGN_KEY_CHECKS=1;
+ */
+
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
}
+
+ /* Write the SQL command */
+
event_info->set_log_pos(this);
- if (event_info->write(file) ||
- file == &log_file && flush_io_cache(file))
+ if (event_info->write(file))
goto err;
- error=0;
+
+ /* Write log events to reset the 'run environment' of the SQL command */
+
+ if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
/*
Tell for transactional table handlers up to which position in the
@@ -1283,6 +1316,9 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file) // we are writing to the real log (disk)
{
+ if (flush_io_cache(file))
+ goto err;
+
if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
/*
@@ -1292,8 +1328,8 @@ bool MYSQL_LOG::write(Log_event* event_info)
handler if the log event type is appropriate.
*/
- if (event_info->get_type_code() == QUERY_EVENT
- || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ if (event_info->get_type_code() == QUERY_EVENT ||
+ event_info->get_type_code() == EXEC_LOAD_EVENT)
{
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
@@ -1303,6 +1339,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
+ error=0;
err:
if (error)
@@ -1329,7 +1366,7 @@ err:
Flush the transactional handler log file now that we have released
LOCK_log; the flush is placed here to eliminate the bottleneck on the
group commit
- */
+ */
if (called_handler_commit)
ha_commit_complete(thd);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 97158191111..b7e8c0bd0ab 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -461,7 +461,6 @@ bool mysql_rename_table(enum db_type base,
const char * old_name,
const char *new_db,
const char * new_name);
-bool close_cached_table(THD *thd,TABLE *table);
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
@@ -501,6 +500,7 @@ Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
+#include <openssl/des.h>
struct st_des_keyblock
{
des_cblock key1, key2, key3;
@@ -837,7 +837,7 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
void init_time(void);
-long my_gmt_sec(TIME *);
+long my_gmt_sec(TIME *, long *current_timezone);
time_t str_to_timestamp(const char *str,uint length);
bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 019a3388341..c6922edb674 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -566,7 +566,7 @@ static void close_connections(void)
unix_sock= INVALID_SOCKET;
}
#endif
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(0); // Abort old alarms.
end_slave();
/* First signal all threads that it's time to die */
@@ -875,6 +875,7 @@ void clean_up(bool print_message)
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
+ end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
#endif
@@ -940,7 +941,6 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_crypt);
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received);
- (void) pthread_mutex_destroy(&LOCK_timezone);
(void) pthread_mutex_destroy(&LOCK_user_conn);
#ifdef HAVE_REPLICATION
(void) pthread_mutex_destroy(&LOCK_rpl_status);
@@ -1501,7 +1501,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
- fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
@@ -1509,7 +1508,7 @@ and this may fail.\n\n");
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) keybuff_size +
(global_system_variables.read_buff_size +
- thd->variables.sortbuff_size) *
+ global_system_variables.sortbuff_size) *
max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
@@ -1538,14 +1537,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
- fprintf(stderr, "\n\
-Successfully dumped variables, if you ran with --log, take a look at the\n\
-details of what thread %ld did to cause the crash. In some cases of really\n\
-bad corruption, the values shown above may be invalid.\n\n",
- thd->thread_id);
}
fprintf(stderr, "\
-The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
+The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
information that should help you find out what is causing the crash.\n");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
@@ -1569,6 +1563,7 @@ information that should help you find out what is causing the crash.\n");
static void init_signals(void)
{
sigset_t set;
+ struct sigaction sa;
DBUG_ENTER("init_signals");
sigset(THR_KILL_SIGNAL,end_thread_signal);
@@ -1576,7 +1571,6 @@ static void init_signals(void)
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{
- struct sigaction sa;
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
@@ -1618,15 +1612,23 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
- sigset(SIGTERM, print_signal_warning); // If it's blocked by parent
- sigset(SIGHUP, print_signal_warning); // If it's blocked by parent
+
+ /* Fix signals if blocked by parents (can happen on Mac OS X) */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGTERM, &sa, (struct sigaction*) 0);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGHUP, &sa, (struct sigaction*) 0);
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
sigaddset(&set,THR_SERVER_ALARM);
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
sigdelset(&set,THR_CLIENT_ALARM); // For alarms
- (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
+ sigprocmask(SIG_SETMASK,&set,NULL);
+ pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN;
}
@@ -1894,7 +1896,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= { "mysqld","server",0 };
+const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 };
bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
@@ -1951,19 +1953,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
}
#endif
#ifdef HAVE_TZNAME
-#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
{
struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp);
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
}
-#else
- {
- struct tm *start_tm;
- start_tm=localtime(&start_time);
- strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
- }
-#endif
#endif
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
@@ -2075,7 +2069,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
@@ -2441,14 +2434,14 @@ The server will not act as a slave.");
if (opt_bootstrap)
{
int error=bootstrap(stdin);
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(error ? 1 : 0);
}
if (opt_init_file)
{
if (read_init_file(opt_init_file))
{
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(1);
}
}
@@ -2620,9 +2613,12 @@ int main(int argc, char **argv)
return 0;
if (Service.IsService(argv[2]))
{
- /* start an optional service */
+ /*
+ mysqld was started as
+ mysqld --defaults-file=my_path\my.ini service-name
+ */
use_opt_args=1;
- opt_argc=argc;
+ opt_argc= 2; // Skip service-name
opt_argv=argv;
start_mode= 1;
Service.Init(argv[2], mysql_service);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 42ea92825d1..b772f6410f7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -209,6 +209,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size);
+sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
#ifdef HAVE_REPLICATION
@@ -596,6 +597,7 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
+ {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
#ifdef HAVE_REPLICATION
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},
diff --git a/sql/slave.cc b/sql/slave.cc
index be95cc16d90..21674d9ece2 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1388,9 +1388,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)) &&
!rli->ignore_log_space_limit)
- {
pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
- }
thd->proc_info = save_proc_info;
pthread_mutex_unlock(&rli->log_space_lock);
DBUG_RETURN(slave_killed);
@@ -2101,7 +2099,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
Log_event * ev = next_event(rli);
DBUG_ASSERT(rli->sql_thd==thd);
if (sql_slave_killed(thd,rli))
+ {
+ /* do not forget to free ev ! */
+ if (ev) delete ev;
return 1;
+ }
if (ev)
{
int type_code = ev->get_type_code();
@@ -2376,6 +2378,18 @@ reconnect done to recover from failed read");
goto err;
}
flush_master_info(mi);
+ /*
+ See if the relay logs take too much space.
+ We don't lock mi->rli.log_space_lock here; this dirty read saves time
+ and does not introduce any problem:
+ - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so
+ the clean value is 0), then we are reading only one more event as we
+ should, and we'll block only at the next event. No big deal.
+ - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so
+ the clean value is 1), then we are going into wait_for_relay_log_space()
+ for no reason, but this function will do a clean read, notice the clean
+ value and exit immediately.
+ */
if (mi->rli.log_space_limit && mi->rli.log_space_limit <
mi->rli.log_space_total &&
!mi->rli.ignore_log_space_limit)
@@ -2489,7 +2503,9 @@ slave_begin:
pthread_cond_broadcast(&rli->start_cond);
//tell the I/O thread to take relay_log_space_limit into account from now on
+ pthread_mutex_lock(&rli->log_space_lock);
rli->ignore_log_space_limit= 0;
+ pthread_mutex_unlock(&rli->log_space_lock);
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
@@ -3221,7 +3237,12 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
pthread_mutex_lock(&rli->log_space_lock);
// prevent the I/O thread from blocking next times
rli->ignore_log_space_limit= 1;
- // If the I/O thread is blocked, unblock it
+ /*
+ If the I/O thread is blocked, unblock it.
+ Ok to broadcast after unlock, because the mutex is only destroyed in
+ ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
+ destroyed before we exit the present function.
+ */
pthread_mutex_unlock(&rli->log_space_lock);
pthread_cond_broadcast(&rli->log_space_cond);
// Note that wait_for_update unlocks lock_log !
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7a154d206ef..ac6471e794c 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -739,7 +739,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size_arg));
free_cache(0);
query_cache_size= query_cache_size_arg;
- DBUG_RETURN(init_cache());
+ DBUG_RETURN(::query_cache_size= init_cache());
}
@@ -1318,6 +1318,12 @@ ulong Query_cache::init_cache()
mem_bin_steps = 1;
mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
prev_size = 0;
+ if (mem_bin_size <= min_allocation_unit)
+ {
+ DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
+ // TODO here (and above) should be warning in 4.1
+ goto err;
+ }
while (mem_bin_size > min_allocation_unit)
{
mem_bin_num += mem_bin_count;
@@ -1344,14 +1350,6 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
- if (max_mem_bin_size <= min_allocation_unit)
- {
- DBUG_PRINT("qcache",
- (" max bin size (%lu) <= min_allocation_unit => cache disabled",
- max_mem_bin_size));
- STRUCT_UNLOCK(&structure_guard_mutex);
- goto err;
- }
if (!(cache = (byte *)
my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 1908f898a27..69382b2db95 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1421,6 +1421,24 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(thd,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
+ /*
+ If at least one row has been inserted/modified and will stay in the table
+ (the table doesn't have transactions) (example: we got a duplicate key
+ error while inserting into a MyISAM table) we must write to the binlog (and
+ the error code will make the slave stop).
+ */
+ if ((info.copied || info.deleted) && !table->file->has_transactions())
+ {
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ table->file->has_transactions());
+ mysql_bin_log.write(&qinfo);
+ }
+ }
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
ha_rollback_stmt(thd);
@@ -1442,7 +1460,10 @@ bool select_insert::send_eof()
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */
+ mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
@@ -1467,10 +1488,7 @@ bool select_insert::send_eof()
else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields);
- if (last_insert_id)
- thd->insert_id(last_insert_id); // For update log
::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
- mysql_update_log.write(thd,thd->query,thd->query_length);
return 0;
}
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7cadf187181..c15c824f843 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1081,58 +1081,76 @@ mysql_rename_table(enum db_type base,
}
/*
- close table in this thread and force close + reopen in other threads
- This assumes that the calling thread has lock on LOCK_open
- Win32 clients must also have a WRITE LOCK on the table !
+ Force all other threads to stop using the table
+
+ SYNOPSIS
+ wait_while_table_is_used()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ When returning, the table will be unusable for other threads until
+ the table is closed.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
*/
-static void safe_remove_from_cache(THD *thd,TABLE *table)
+static void wait_while_table_is_used(THD *thd,TABLE *table)
{
- DBUG_ENTER("safe_remove_from_cache");
- if (table)
- {
- DBUG_PRINT("enter",("table: %s", table->real_name));
- VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
- /* Mark all tables that are in use as 'old' */
- mysql_lock_abort(thd,table); // end threads waiting on lock
+ DBUG_PRINT("enter",("table: %s", table->real_name));
+ DBUG_ENTER("wait_while_table_is_used");
+ safe_mutex_assert_owner(&LOCK_open);
-#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
- /* Wait until all there are no other threads that has this table open */
- while (remove_table_from_cache(thd,table->table_cache_key,
- table->real_name))
- {
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
- }
-#else
- (void) remove_table_from_cache(thd,table->table_cache_key,
- table->real_name);
-#endif
- /* When lock on LOCK_open is freed other threads can continue */
- pthread_cond_broadcast(&COND_refresh);
+ VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
+ /* Mark all tables that are in use as 'old' */
+ mysql_lock_abort(thd, table); // end threads waiting on lock
+
+ /* Wait until all there are no other threads that has this table open */
+ while (remove_table_from_cache(thd,table->table_cache_key,
+ table->real_name))
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
}
DBUG_VOID_RETURN;
}
+/*
+ Close a cached table
-bool close_cached_table(THD *thd,TABLE *table)
+ SYNOPSIS
+ clsoe_cached_table()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ Function ends by signaling threads waiting for the table to try to
+ reopen the table.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
+*/
+
+static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
- safe_mutex_assert_owner(&LOCK_open);
-
- if (table)
+
+ wait_while_table_is_used(thd,table);
+ /* Close lock if this is not got with LOCK TABLES */
+ if (thd->lock)
{
- safe_remove_from_cache(thd,table);
- /* Close lock if this is not got with LOCK TABLES */
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0; // Start locked threads
- }
- /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
- thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0; // Start locked threads
}
+ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
+ thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+
+ /* When lock on LOCK_open is freed other threads can continue */
+ pthread_cond_broadcast(&COND_refresh);
DBUG_RETURN(0);
}
@@ -1261,10 +1279,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
- pthread_mutex_lock(&LOCK_open);
- close_cached_table(thd,table_list->table);
- pthread_mutex_unlock(&LOCK_open);
-
+ /* If we could open the table, close it */
+ if (table_list->table)
+ {
+ pthread_mutex_lock(&LOCK_open);
+ close_cached_table(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
+ }
if (lock_and_wait_for_table_name(thd,table_list))
{
error= -1;
@@ -1794,11 +1815,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
- close_cached_table(thd,table);
+ close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
- VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -1807,12 +1827,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- safe_remove_from_cache(thd,table);
- error= table->file->activate_all_index(thd);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->activate_all_index(thd);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- safe_remove_from_cache(thd,table);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
@@ -2247,7 +2273,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
- if (close_cached_table(thd,table))
+ if (close_cached_table(thd, table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2281,7 +2307,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by
closing the locked table.
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
@@ -2291,7 +2318,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename
free locks and remove old table
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
else
@@ -2311,7 +2339,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0))
{ // This shouldn't happen
- close_cached_table(thd,table); // Remove lock for table
+ if (table)
+ close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 1f6364ec427..989d17b006b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -200,7 +200,6 @@ int mysql_update(THD *thd,
*/
uint length;
SORT_FIELD *sortorder;
- List<Item> fields;
ha_rows examined_rows;
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index efb5e42626d..e96c87b3f43 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4324,6 +4324,7 @@ keyword:
| SHARE_SYM {}
| SHUTDOWN {}
| SLAVE {}
+ | SOUNDS_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
@@ -4348,8 +4349,8 @@ keyword:
| VARIABLES {}
| VALUE_SYM {}
| WORK_SYM {}
+ | X509_SYM {}
| YEAR_SYM {}
- | SOUNDS_SYM {}
;
/* Option functions */
diff --git a/sql/time.cc b/sql/time.cc
index eba664a690d..b6ca306e523 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Currently only my_time_zone is inited */
static long my_time_zone=0;
-pthread_mutex_t LOCK_timezone;
void init_time(void)
{
@@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
l_time= &tm_tmp;
- my_time_zone=0;
+ my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */
my_time.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min;
- my_time.second= (uint) l_time->tm_sec;
- VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */
+ my_time.second= (uint) l_time->tm_sec;
+ my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
}
/*
@@ -57,26 +56,39 @@ void init_time(void)
*/
-long my_gmt_sec(TIME *t)
+long my_gmt_sec(TIME *t, long *my_timezone)
{
uint loop;
time_t tmp;
struct tm *l_time,tm_tmp;
- long diff;
+ long diff, current_timezone;
if (t->hour >= 24)
{ /* Fix for time-loop */
t->day+=t->hour/24;
t->hour%=24;
}
- pthread_mutex_lock(&LOCK_timezone);
- tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
- (long) days_at_timestart)*86400L + (long) t->hour*3600L +
- (long) (t->minute*60 + t->second)) + (time_t) my_time_zone;
+
+ /*
+ Calculate the gmt time based on current time and timezone
+ The -1 on the end is to ensure that if have a date that exists twice
+ (like 2002-10-27 02:00:0 MET), we will find the initial date.
+
+ By doing -3600 we will have to call localtime_r() several times, but
+ I couldn't come up with a better way to get a repeatable result :(
+
+ We can't use mktime() as it's buggy on many platforms and not thread safe.
+ */
+ tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
+ (long) days_at_timestart)*86400L + (long) t->hour*3600L +
+ (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
+ 3600);
+ current_timezone= my_time_zone;
+
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
for (loop=0;
- loop < 3 &&
+ loop < 2 &&
(t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min);
loop++)
@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min)));
- my_time_zone+=diff;
- tmp+=(time_t) diff;
+ current_timezone+= diff+3600; // Compensate for -3600 above
+ tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
}
- /* Fix that if we are in the not existing daylight saving time hour
- we move the start of the next real hour */
- if (loop == 3 && t->hour != (uint) l_time->tm_hour)
+ /*
+ Fix that if we are in the not existing daylight saving time hour
+ we move the start of the next real hour
+ */
+ if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{
int days= t->day - l_time->tm_mday;
if (days < -1)
@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600)
- tmp-=t->minute*60 + t->second; // Move to next hour
+ tmp-=t->minute*60 + t->second; // Move to previous hour
}
- if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12)
- my_time_zone=0; /* Wrong date */
- pthread_mutex_unlock(&LOCK_timezone);
+ *my_timezone= current_timezone;
return (long) tmp;
} /* my_gmt_sec */
@@ -428,6 +440,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
time_t str_to_timestamp(const char *str,uint length)
{
TIME l_time;
+ long not_used;
+
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
@@ -435,7 +449,7 @@ time_t str_to_timestamp(const char *str,uint length)
current_thd->cuted_fields++;
return(0);
}
- return(my_gmt_sec(&l_time));
+ return(my_gmt_sec(&l_time, &not_used));
}