mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge gbichot@213.136.52.20:/home/bk/mysql-4.1
into mysql.com:/home/mysql_src/mysql-4.1-1717
This commit is contained in:
@ -43,5 +43,6 @@ enum options_client
|
|||||||
OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
|
OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
|
||||||
OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
|
OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
|
||||||
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
|
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
|
||||||
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS
|
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
|
||||||
|
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#define MYSQL_CLIENT
|
#define MYSQL_CLIENT
|
||||||
#undef MYSQL_SERVER
|
#undef MYSQL_SERVER
|
||||||
#include "client_priv.h"
|
#include "client_priv.h"
|
||||||
#include <time.h>
|
#include <my_time.h>
|
||||||
#include "log_event.h"
|
#include "log_event.h"
|
||||||
|
|
||||||
#define BIN_LOG_HEADER_SIZE 4
|
#define BIN_LOG_HEADER_SIZE 4
|
||||||
@ -53,10 +53,18 @@ static int port = MYSQL_PORT;
|
|||||||
static const char* sock= 0;
|
static const char* sock= 0;
|
||||||
static const char* user = 0;
|
static const char* user = 0;
|
||||||
static char* pass = 0;
|
static char* pass = 0;
|
||||||
static ulonglong position = 0;
|
|
||||||
|
static ulonglong start_position, stop_position;
|
||||||
|
#define start_position_mot ((my_off_t)start_position)
|
||||||
|
#define stop_position_mot ((my_off_t)stop_position)
|
||||||
|
|
||||||
|
static char *start_datetime_str, *stop_datetime_str;
|
||||||
|
static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
|
||||||
|
static ulonglong rec_count= 0;
|
||||||
static short binlog_flags = 0;
|
static short binlog_flags = 0;
|
||||||
static MYSQL* mysql = NULL;
|
static MYSQL* mysql = NULL;
|
||||||
static const char* dirname_for_local_load= 0;
|
static const char* dirname_for_local_load= 0;
|
||||||
|
static bool stop_passed= 0;
|
||||||
|
|
||||||
static int dump_local_log_entries(const char* logname);
|
static int dump_local_log_entries(const char* logname);
|
||||||
static int dump_remote_log_entries(const char* logname);
|
static int dump_remote_log_entries(const char* logname);
|
||||||
@ -302,15 +310,36 @@ Create_file event for file_id: %u\n",ae->file_id);
|
|||||||
|
|
||||||
Load_log_processor load_processor;
|
Load_log_processor load_processor;
|
||||||
|
|
||||||
|
/*
|
||||||
|
RETURN
|
||||||
|
0 ok and continue
|
||||||
|
1 error and terminate
|
||||||
|
-1 ok and terminate
|
||||||
|
|
||||||
int process_event(ulonglong *rec_count, char *last_db, Log_event *ev,
|
TODO
|
||||||
my_off_t pos, int old_format)
|
This function returns 0 even in some error cases. This should be changed.
|
||||||
|
*/
|
||||||
|
int process_event(char *last_db, Log_event *ev, my_off_t pos, int old_format)
|
||||||
{
|
{
|
||||||
char ll_buff[21];
|
char ll_buff[21];
|
||||||
DBUG_ENTER("process_event");
|
DBUG_ENTER("process_event");
|
||||||
|
|
||||||
if ((*rec_count) >= offset)
|
if ((rec_count >= offset) &&
|
||||||
|
((my_time_t)(ev->when) >= start_datetime))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
We have found an event after start_datetime, from now on print
|
||||||
|
everything (in case the binlog has timestamps increasing and decreasing,
|
||||||
|
we do this to avoid cutting the middle).
|
||||||
|
*/
|
||||||
|
start_datetime= 0;
|
||||||
|
offset= 0; // print everything and protect against cycling rec_count
|
||||||
|
if (((my_time_t)(ev->when) >= stop_datetime)
|
||||||
|
|| (pos >= stop_position_mot))
|
||||||
|
{
|
||||||
|
stop_passed= 1; // skip all next binlogs
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
if (!short_form)
|
if (!short_form)
|
||||||
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
|
fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
|
||||||
|
|
||||||
@ -387,7 +416,7 @@ Create_file event for file_id: %u\n",exv->file_id);
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
(*rec_count)++;
|
rec_count++;
|
||||||
if (ev)
|
if (ev)
|
||||||
delete ev;
|
delete ev;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -417,13 +446,14 @@ static struct my_option my_long_options[] =
|
|||||||
{"port", 'P', "Use port to connect to the remote server.",
|
{"port", 'P', "Use port to connect to the remote server.",
|
||||||
(gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0,
|
(gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0,
|
||||||
0, 0, 0},
|
0, 0, 0},
|
||||||
{"position", 'j', "Start reading the binlog at position N.",
|
{"position", 'j', "Deprecated. Use --start-position instead.",
|
||||||
(gptr*) &position, (gptr*) &position, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0,
|
(gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL,
|
||||||
0, 0},
|
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
|
||||||
|
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
|
||||||
|
(ulonglong)(~(uint32)0), 0, 0, 0},
|
||||||
{"protocol", OPT_MYSQL_PROTOCOL,
|
{"protocol", OPT_MYSQL_PROTOCOL,
|
||||||
"The protocol of connection (tcp,socket,pipe,memory).",
|
"The protocol of connection (tcp,socket,pipe,memory).",
|
||||||
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
|
||||||
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
|
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
|
||||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"read-from-remote-server", 'R', "Read binary logs from a MySQL server",
|
{"read-from-remote-server", 'R', "Read binary logs from a MySQL server",
|
||||||
@ -439,6 +469,35 @@ static struct my_option my_long_options[] =
|
|||||||
{"socket", 'S', "Socket file to use for connection.",
|
{"socket", 'S', "Socket file to use for connection.",
|
||||||
(gptr*) &sock, (gptr*) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
|
(gptr*) &sock, (gptr*) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
|
||||||
0, 0},
|
0, 0},
|
||||||
|
{"start-datetime", OPT_START_DATETIME,
|
||||||
|
"Start reading the binlog at first event having a datetime equal or "
|
||||||
|
"posterior to the argument; the argument must be a date and time "
|
||||||
|
"in the local time zone, in any format accepted by the MySQL server "
|
||||||
|
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
|
||||||
|
"(you should probably use quotes for your shell to set it properly).",
|
||||||
|
(gptr*) &start_datetime_str, (gptr*) &start_datetime_str,
|
||||||
|
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{"stop-datetime", OPT_STOP_DATETIME,
|
||||||
|
"Stop reading the binlog at first event having a datetime equal or "
|
||||||
|
"posterior to the argument; the argument must be a date and time "
|
||||||
|
"in the local time zone, in any format accepted by the MySQL server "
|
||||||
|
"for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
|
||||||
|
"(you should probably use quotes for your shell to set it properly).",
|
||||||
|
(gptr*) &stop_datetime_str, (gptr*) &stop_datetime_str,
|
||||||
|
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{"start-position", OPT_START_POSITION,
|
||||||
|
"Start reading the binlog at position N. Applies to the first binlog "
|
||||||
|
"passed on the command line.",
|
||||||
|
(gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL,
|
||||||
|
REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
|
||||||
|
/* COM_BINLOG_DUMP accepts only 4 bytes for the position */
|
||||||
|
(ulonglong)(~(uint32)0), 0, 0, 0},
|
||||||
|
{"stop-position", OPT_STOP_POSITION,
|
||||||
|
"Stop reading the binlog at position N. Applies to the last binlog "
|
||||||
|
"passed on the command line.",
|
||||||
|
(gptr*) &stop_position, (gptr*) &stop_position, 0, GET_ULL,
|
||||||
|
REQUIRED_ARG, (ulonglong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
|
||||||
|
(ulonglong)(~(my_off_t)0), 0, 0, 0},
|
||||||
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
|
{"to-last-log", 't', "Requires -R. Will not stop at the end of the \
|
||||||
requested binlog but rather continue printing until the end of the last \
|
requested binlog but rather continue printing until the end of the last \
|
||||||
binlog of the MySQL server. If you send the output to the same MySQL server, \
|
binlog of the MySQL server. If you send the output to the same MySQL server, \
|
||||||
@ -513,6 +572,29 @@ the mysql command line client\n\n");
|
|||||||
my_print_variables(my_long_options);
|
my_print_variables(my_long_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static my_time_t convert_str_to_timestamp(const char* str)
|
||||||
|
{
|
||||||
|
int was_cut;
|
||||||
|
MYSQL_TIME l_time;
|
||||||
|
long dummy_my_timezone;
|
||||||
|
bool dummy_in_dst_time_gap;
|
||||||
|
/* We require a total specification (date AND time) */
|
||||||
|
if (str_to_datetime(str, strlen(str), &l_time, 0, &was_cut) !=
|
||||||
|
MYSQL_TIMESTAMP_DATETIME || was_cut)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Incorrect date and time argument: %s\n", str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Note that Feb 30th, Apr 31st cause no error messages and are mapped to
|
||||||
|
the next existing day, like in mysqld. Maybe this could be changed when
|
||||||
|
mysqld is changed too (with its "strict" mode?).
|
||||||
|
*/
|
||||||
|
return
|
||||||
|
my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
|
||||||
|
}
|
||||||
|
|
||||||
#include <help_end.h>
|
#include <help_end.h>
|
||||||
|
|
||||||
extern "C" my_bool
|
extern "C" my_bool
|
||||||
@ -559,7 +641,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
case OPT_START_DATETIME:
|
||||||
|
start_datetime= convert_str_to_timestamp(start_datetime_str);
|
||||||
|
break;
|
||||||
|
case OPT_STOP_DATETIME:
|
||||||
|
stop_datetime= convert_str_to_timestamp(stop_datetime_str);
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
print_version();
|
print_version();
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -604,9 +691,8 @@ static MYSQL* safe_connect()
|
|||||||
|
|
||||||
static int dump_log_entries(const char* logname)
|
static int dump_log_entries(const char* logname)
|
||||||
{
|
{
|
||||||
if (remote_opt)
|
return (remote_opt ? dump_remote_log_entries(logname) :
|
||||||
return dump_remote_log_entries(logname);
|
dump_local_log_entries(logname));
|
||||||
return dump_local_log_entries(logname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -663,21 +749,27 @@ static int dump_remote_log_entries(const char* logname)
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
char last_db[FN_REFLEN+1] = "";
|
char last_db[FN_REFLEN+1] = "";
|
||||||
uint len, logname_len;
|
uint len, logname_len;
|
||||||
NET* net = &mysql->net;
|
NET* net;
|
||||||
int old_format;
|
int old_format;
|
||||||
|
int error= 0;
|
||||||
|
my_off_t old_off= start_position_mot;
|
||||||
|
char fname[FN_REFLEN+1];
|
||||||
DBUG_ENTER("dump_remote_log_entries");
|
DBUG_ENTER("dump_remote_log_entries");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Even if we already read one binlog (case of >=2 binlogs on command line),
|
||||||
|
we cannot re-use the same connection as before, because it is now dead
|
||||||
|
(COM_BINLOG_DUMP kills the thread when it finishes).
|
||||||
|
*/
|
||||||
|
mysql= safe_connect();
|
||||||
|
net= &mysql->net;
|
||||||
old_format = check_master_version(mysql);
|
old_format = check_master_version(mysql);
|
||||||
|
|
||||||
if (!position)
|
/*
|
||||||
position = BIN_LOG_HEADER_SIZE; // protect the innocent from spam
|
COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
|
||||||
if (position < BIN_LOG_HEADER_SIZE)
|
cast to uint32.
|
||||||
{
|
*/
|
||||||
position = BIN_LOG_HEADER_SIZE;
|
int4store(buf, (uint32)start_position);
|
||||||
// warn the user
|
|
||||||
sql_print_error("Warning: The position in the binary log can't be less than %d.\nStarting from position %d\n", BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE);
|
|
||||||
}
|
|
||||||
int4store(buf, position);
|
|
||||||
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
|
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
|
||||||
logname_len = (uint) strlen(logname);
|
logname_len = (uint) strlen(logname);
|
||||||
int4store(buf + 6, 0);
|
int4store(buf + 6, 0);
|
||||||
@ -685,33 +777,32 @@ static int dump_remote_log_entries(const char* logname)
|
|||||||
if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
|
if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Got fatal error sending the log dump command\n");
|
fprintf(stderr,"Got fatal error sending the log dump command\n");
|
||||||
DBUG_RETURN(1);
|
error= 1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_off_t old_off= position;
|
|
||||||
ulonglong rec_count= 0;
|
|
||||||
char fname[FN_REFLEN+1];
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
const char *error;
|
const char *error_msg;
|
||||||
len = net_safe_read(mysql);
|
len = net_safe_read(mysql);
|
||||||
if (len == packet_error)
|
if (len == packet_error)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Got error reading packet from server: %s\n",
|
fprintf(stderr, "Got error reading packet from server: %s\n",
|
||||||
mysql_error(mysql));
|
mysql_error(mysql));
|
||||||
DBUG_RETURN(1);
|
error= 1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
if (len < 8 && net->read_pos[0] == 254)
|
if (len < 8 && net->read_pos[0] == 254)
|
||||||
break; // end of data
|
break; // end of data
|
||||||
DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n",
|
DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n",
|
||||||
len, net->read_pos[5]));
|
len, net->read_pos[5]));
|
||||||
Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 ,
|
Log_event *ev = Log_event::read_log_event((const char*) net->read_pos + 1 ,
|
||||||
len - 1, &error, old_format);
|
len - 1, &error_msg, old_format);
|
||||||
if (!ev)
|
if (!ev)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not construct log event object\n");
|
fprintf(stderr, "Could not construct log event object\n");
|
||||||
DBUG_RETURN(1);
|
error= 1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_event_type type= ev->get_type_code();
|
Log_event_type type= ev->get_type_code();
|
||||||
@ -735,22 +826,32 @@ static int dump_remote_log_entries(const char* logname)
|
|||||||
which are about the binlogs, so which would trigger the end-detection
|
which are about the binlogs, so which would trigger the end-detection
|
||||||
below.
|
below.
|
||||||
*/
|
*/
|
||||||
if ((rev->when == 0) && !to_last_remote_log)
|
if (rev->when == 0)
|
||||||
{
|
{
|
||||||
if ((rev->ident_len != logname_len) ||
|
if (!to_last_remote_log)
|
||||||
memcmp(rev->new_log_ident, logname, logname_len))
|
{
|
||||||
DBUG_RETURN(0);
|
if ((rev->ident_len != logname_len) ||
|
||||||
/*
|
memcmp(rev->new_log_ident, logname, logname_len))
|
||||||
Otherwise, this is a fake Rotate for our log, at the very beginning
|
{
|
||||||
for sure. Skip it, because it was not in the original log. If we
|
error= 0;
|
||||||
are running with to_last_remote_log, we print it, because it serves
|
goto err;
|
||||||
as a useful marker between binlogs then.
|
}
|
||||||
*/
|
/*
|
||||||
continue;
|
Otherwise, this is a fake Rotate for our log, at the very
|
||||||
|
beginning for sure. Skip it, because it was not in the original
|
||||||
|
log. If we are running with to_last_remote_log, we print it,
|
||||||
|
because it serves as a useful marker between binlogs then.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
len= 1; // fake Rotate, so don't increment old_off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (process_event(&rec_count,last_db,ev,old_off,old_format))
|
if ((error= process_event(last_db,ev,old_off,old_format)))
|
||||||
DBUG_RETURN(1);
|
{
|
||||||
|
error= ((error < 0) ? 0 : 1);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -760,29 +861,35 @@ static int dump_remote_log_entries(const char* logname)
|
|||||||
File file;
|
File file;
|
||||||
|
|
||||||
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
|
if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
|
||||||
DBUG_RETURN(1);
|
{
|
||||||
|
error= 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (process_event(&rec_count,last_db,ev,old_off,old_format))
|
if ((error= process_event(last_db,ev,old_off,old_format)))
|
||||||
{
|
{
|
||||||
my_close(file,MYF(MY_WME));
|
my_close(file,MYF(MY_WME));
|
||||||
DBUG_RETURN(1);
|
error= ((error < 0) ? 0 : 1);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
if (load_processor.load_old_format_file(net,old_fname,old_len,file))
|
if (load_processor.load_old_format_file(net,old_fname,old_len,file))
|
||||||
{
|
{
|
||||||
my_close(file,MYF(MY_WME));
|
my_close(file,MYF(MY_WME));
|
||||||
DBUG_RETURN(1);
|
error= 1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
my_close(file,MYF(MY_WME));
|
my_close(file,MYF(MY_WME));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Let's adjust offset for remote log as for local log to produce
|
Let's adjust offset for remote log as for local log to produce
|
||||||
similar text. As we don't print the fake Rotate event, all events are
|
similar text.
|
||||||
real so we can simply add the length.
|
|
||||||
*/
|
*/
|
||||||
old_off+= len-1;
|
old_off+= len-1;
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
err:
|
||||||
|
mysql_close(mysql);
|
||||||
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -817,7 +924,6 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
{
|
{
|
||||||
File fd = -1;
|
File fd = -1;
|
||||||
IO_CACHE cache,*file= &cache;
|
IO_CACHE cache,*file= &cache;
|
||||||
ulonglong rec_count = 0;
|
|
||||||
char last_db[FN_REFLEN+1];
|
char last_db[FN_REFLEN+1];
|
||||||
byte tmp_buff[BIN_LOG_HEADER_SIZE];
|
byte tmp_buff[BIN_LOG_HEADER_SIZE];
|
||||||
bool old_format = 0;
|
bool old_format = 0;
|
||||||
@ -829,7 +935,7 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
{
|
{
|
||||||
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
|
if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) position, 0,
|
if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
|
||||||
MYF(MY_WME | MY_NABP)))
|
MYF(MY_WME | MY_NABP)))
|
||||||
{
|
{
|
||||||
my_close(fd, MYF(MY_WME));
|
my_close(fd, MYF(MY_WME));
|
||||||
@ -843,12 +949,12 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
|
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
|
||||||
return 1;
|
return 1;
|
||||||
old_format = check_header(file);
|
old_format = check_header(file);
|
||||||
if (position)
|
if (start_position)
|
||||||
{
|
{
|
||||||
/* skip 'position' characters from stdout */
|
/* skip 'start_position' characters from stdout */
|
||||||
byte buff[IO_SIZE];
|
byte buff[IO_SIZE];
|
||||||
my_off_t length,tmp;
|
my_off_t length,tmp;
|
||||||
for (length= (my_off_t) position ; length > 0 ; length-=tmp)
|
for (length= start_position_mot ; length > 0 ; length-=tmp)
|
||||||
{
|
{
|
||||||
tmp=min(length,sizeof(buff));
|
tmp=min(length,sizeof(buff));
|
||||||
if (my_b_read(file, buff, (uint) tmp))
|
if (my_b_read(file, buff, (uint) tmp))
|
||||||
@ -858,11 +964,11 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file->pos_in_file=position;
|
file->pos_in_file= start_position_mot;
|
||||||
file->seek_not_done=0;
|
file->seek_not_done=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!position)
|
if (!start_position)
|
||||||
{
|
{
|
||||||
// Skip header
|
// Skip header
|
||||||
if (my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
|
if (my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
|
||||||
@ -891,9 +997,10 @@ static int dump_local_log_entries(const char* logname)
|
|||||||
// file->error == 0 means EOF, that's OK, we break in this case
|
// file->error == 0 means EOF, that's OK, we break in this case
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (process_event(&rec_count,last_db,ev,old_off,false))
|
if ((error= process_event(last_db,ev,old_off,false)))
|
||||||
{
|
{
|
||||||
error= 1;
|
if (error < 0)
|
||||||
|
error= 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -909,11 +1016,14 @@ end:
|
|||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
static char **defaults_argv;
|
static char **defaults_argv;
|
||||||
int exit_value;
|
int exit_value= 0;
|
||||||
|
ulonglong save_stop_position;
|
||||||
MY_INIT(argv[0]);
|
MY_INIT(argv[0]);
|
||||||
DBUG_ENTER("main");
|
DBUG_ENTER("main");
|
||||||
DBUG_PROCESS(argv[0]);
|
DBUG_PROCESS(argv[0]);
|
||||||
|
|
||||||
|
init_time(); // for time functions
|
||||||
|
|
||||||
parse_args(&argc, (char***)&argv);
|
parse_args(&argc, (char***)&argv);
|
||||||
defaults_argv=argv;
|
defaults_argv=argv;
|
||||||
|
|
||||||
@ -925,8 +1035,6 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
my_set_max_open_files(open_files_limit);
|
my_set_max_open_files(open_files_limit);
|
||||||
if (remote_opt)
|
|
||||||
mysql = safe_connect();
|
|
||||||
|
|
||||||
MY_TMPDIR tmpdir;
|
MY_TMPDIR tmpdir;
|
||||||
tmpdir.list= 0;
|
tmpdir.list= 0;
|
||||||
@ -944,24 +1052,26 @@ int main(int argc, char** argv)
|
|||||||
else
|
else
|
||||||
load_processor.init_by_cur_dir();
|
load_processor.init_by_cur_dir();
|
||||||
|
|
||||||
exit_value= 0;
|
|
||||||
fprintf(result_file,
|
fprintf(result_file,
|
||||||
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
|
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
|
||||||
while (--argc >= 0)
|
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
|
||||||
|
(--argc >= 0) && !stop_passed ; )
|
||||||
{
|
{
|
||||||
|
if (argc == 0) // last log, --stop-position applies
|
||||||
|
stop_position= save_stop_position;
|
||||||
if (dump_log_entries(*(argv++)))
|
if (dump_log_entries(*(argv++)))
|
||||||
{
|
{
|
||||||
exit_value=1;
|
exit_value=1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// For next log, --start-position does not apply
|
||||||
|
start_position= BIN_LOG_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmpdir.list)
|
if (tmpdir.list)
|
||||||
free_tmpdir(&tmpdir);
|
free_tmpdir(&tmpdir);
|
||||||
if (result_file != stdout)
|
if (result_file != stdout)
|
||||||
my_fclose(result_file, MYF(0));
|
my_fclose(result_file, MYF(0));
|
||||||
if (remote_opt)
|
|
||||||
mysql_close(mysql);
|
|
||||||
cleanup();
|
cleanup();
|
||||||
free_defaults(defaults_argv);
|
free_defaults(defaults_argv);
|
||||||
my_free_open_file_info();
|
my_free_open_file_info();
|
||||||
|
@ -41,6 +41,13 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
|
|||||||
bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
|
bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
|
||||||
int *was_cut);
|
int *was_cut);
|
||||||
|
|
||||||
|
long calc_daynr(uint year,uint month,uint day);
|
||||||
|
|
||||||
|
void init_time(void);
|
||||||
|
|
||||||
|
my_time_t
|
||||||
|
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap);
|
||||||
|
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
#endif /* _my_time_h_ */
|
#endif /* _my_time_h_ */
|
||||||
|
@ -34,4 +34,13 @@ typedef struct st_mysql_time
|
|||||||
enum enum_mysql_timestamp_type time_type;
|
enum enum_mysql_timestamp_type time_type;
|
||||||
} MYSQL_TIME;
|
} MYSQL_TIME;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Portable time_t replacement.
|
||||||
|
Should be signed and hold seconds for 1902-2038 range.
|
||||||
|
*/
|
||||||
|
typedef long my_time_t;
|
||||||
|
#define MY_TIME_T_MAX LONG_MAX
|
||||||
|
#define MY_TIME_T_MIN LONG_MIN
|
||||||
|
|
||||||
#endif /* _mysql_time_h_ */
|
#endif /* _mysql_time_h_ */
|
||||||
|
446
mysql-test/r/mysqlbinlog2.result
Normal file
446
mysql-test/r/mysqlbinlog2.result
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
drop table if exists t1;
|
||||||
|
reset master;
|
||||||
|
set @a=UNIX_TIMESTAMP("2020-01-21 15:32:22");
|
||||||
|
set timestamp=@a;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
set timestamp=@a+2;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
set timestamp=@a+4;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
flush logs;
|
||||||
|
set timestamp=@a+1;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- Local --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- offset --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- start-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- stop-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
|
||||||
|
--- start-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- stop-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
|
||||||
|
--- Local with 2 binlogs on command line --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- offset --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- start-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- stop-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
|
||||||
|
--- start-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- stop-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
|
||||||
|
--- Remote --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- offset --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- start-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- stop-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
|
||||||
|
--- start-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
--- stop-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
|
||||||
|
--- Remote with 2 binlogs on command line --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- offset --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- start-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- stop-position --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
|
||||||
|
--- start-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- stop-datetime --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
|
||||||
|
--- to-last-log --
|
||||||
|
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
|
||||||
|
use test;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
SET INSERT_ID=1;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
SET INSERT_ID=2;
|
||||||
|
SET TIMESTAMP=1579609942;
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
SET INSERT_ID=3;
|
||||||
|
SET TIMESTAMP=1579609944;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
SET INSERT_ID=4;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
SET INSERT_ID=5;
|
||||||
|
SET TIMESTAMP=1579609946;
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
SET INSERT_ID=6;
|
||||||
|
SET TIMESTAMP=1579609943;
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
--- end of test --
|
||||||
|
drop table t1;
|
156
mysql-test/t/mysqlbinlog2.test
Normal file
156
mysql-test/t/mysqlbinlog2.test
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# Test for the new options --start-datetime, stop-datetime,
|
||||||
|
# and a few others.
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1;
|
||||||
|
--enable_warnings
|
||||||
|
reset master;
|
||||||
|
|
||||||
|
# We need this for getting fixed timestamps inside of this test.
|
||||||
|
# I use a date in the future to keep a growing timestamp along the
|
||||||
|
# binlog (including the Start_log_event). This test will work
|
||||||
|
# unchanged everywhere, because mysql-test-run has fixed TZ, which it
|
||||||
|
# exports (so mysqlbinlog has same fixed TZ).
|
||||||
|
set @a=UNIX_TIMESTAMP("2020-01-21 15:32:22");
|
||||||
|
set timestamp=@a;
|
||||||
|
create table t1 (a int auto_increment not null primary key, b char(3));
|
||||||
|
insert into t1 values(null, "a");
|
||||||
|
insert into t1 values(null, "b");
|
||||||
|
set timestamp=@a+2;
|
||||||
|
insert into t1 values(null, "c");
|
||||||
|
set timestamp=@a+4;
|
||||||
|
insert into t1 values(null, "d");
|
||||||
|
insert into t1 values(null, "e");
|
||||||
|
|
||||||
|
flush logs;
|
||||||
|
set timestamp=@a+1; # this could happen on a slave
|
||||||
|
insert into t1 values(null, "f");
|
||||||
|
|
||||||
|
# delimiters are for easier debugging in future
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- Local --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
#
|
||||||
|
# We should use --short-form everywhere because in other case output will
|
||||||
|
# be time dependent (the Start events). Better than nothing.
|
||||||
|
#
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- offset --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --offset=2 $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --start-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --stop-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--start-datetime=2020-01-21 15:32:24" $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--stop-datetime=2020-01-21 15:32:24" $MYSQL_TEST_DIR/var/log/master-bin.000001
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- Local with 2 binlogs on command line --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
# This is to verify that some options apply only to first, or last binlog
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- offset --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --offset=2 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --start-position=497 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --stop-position=32 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--start-datetime=2020-01-21 15:32:24" $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--stop-datetime=2020-01-21 15:32:24" $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- Remote --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- offset --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --offset=2 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --start-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --stop-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--start-datetime=2020-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--stop-datetime=2020-01-21 15:32:24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- Remote with 2 binlogs on command line --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- offset --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --offset=2 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --start-position=497 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-position --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form --stop-position=32 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- start-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--start-datetime=20200121153224" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
--disable_query_log
|
||||||
|
select "--- stop-datetime --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
--exec $MYSQL_BINLOG --short-form "--stop-datetime=2020/01/21 15@32@24" --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
select "--- to-last-log --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
--exec $MYSQL_BINLOG --short-form --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --to-last-log master-bin.000001
|
||||||
|
|
||||||
|
# clean up
|
||||||
|
--disable_query_log
|
||||||
|
select "--- end of test --" as "";
|
||||||
|
--enable_query_log
|
||||||
|
drop table t1;
|
@ -35,6 +35,16 @@ static uchar internal_format_positions[]=
|
|||||||
|
|
||||||
static char time_separator=':';
|
static char time_separator=':';
|
||||||
|
|
||||||
|
static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
|
||||||
|
uchar days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Offset of system time zone from UTC in seconds used to speed up
|
||||||
|
work of my_system_gmt_sec() function.
|
||||||
|
*/
|
||||||
|
static long my_time_zone=0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert a timestamp string to a MYSQL_TIME value.
|
Convert a timestamp string to a MYSQL_TIME value.
|
||||||
|
|
||||||
@ -559,3 +569,148 @@ fractional:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepare offset of system time zone from UTC for my_system_gmt_sec() func.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
init_time()
|
||||||
|
*/
|
||||||
|
void init_time(void)
|
||||||
|
{
|
||||||
|
time_t seconds;
|
||||||
|
struct tm *l_time,tm_tmp;;
|
||||||
|
MYSQL_TIME my_time;
|
||||||
|
bool not_used;
|
||||||
|
|
||||||
|
seconds= (time_t) time((time_t*) 0);
|
||||||
|
localtime_r(&seconds,&tm_tmp);
|
||||||
|
l_time= &tm_tmp;
|
||||||
|
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;
|
||||||
|
my_system_gmt_sec(&my_time, &my_time_zone, ¬_used); /* Init my_time_zone */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Calculate nr of day since year 0 in new date-system (from 1615) */
|
||||||
|
|
||||||
|
long calc_daynr(uint year,uint month,uint day)
|
||||||
|
{
|
||||||
|
long delsum;
|
||||||
|
int temp;
|
||||||
|
DBUG_ENTER("calc_daynr");
|
||||||
|
|
||||||
|
if (year == 0 && month == 0 && day == 0)
|
||||||
|
DBUG_RETURN(0); /* Skip errors */
|
||||||
|
if (year < 200)
|
||||||
|
{
|
||||||
|
if ((year=year+1900) < 1900+YY_PART_YEAR)
|
||||||
|
year+=100;
|
||||||
|
}
|
||||||
|
delsum= (long) (365L * year+ 31*(month-1) +day);
|
||||||
|
if (month <= 2)
|
||||||
|
year--;
|
||||||
|
else
|
||||||
|
delsum-= (long) (month*4+23)/10;
|
||||||
|
temp=(int) ((year/100+1)*3)/4;
|
||||||
|
DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld",
|
||||||
|
year+(month <= 2),month,day,delsum+year/4-temp));
|
||||||
|
DBUG_RETURN(delsum+(int) year/4-temp);
|
||||||
|
} /* calc_daynr */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert time in MYSQL_TIME representation in system time zone to its
|
||||||
|
my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
my_system_gmt_sec()
|
||||||
|
t - time value to be converted
|
||||||
|
my_timezone - pointer to long where offset of system time zone
|
||||||
|
from UTC will be stored for caching
|
||||||
|
in_dst_time_gap - set to true if time falls into spring time-gap
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
The idea is to cache the time zone offset from UTC (including daylight
|
||||||
|
saving time) for the next call to make things faster. But currently we
|
||||||
|
just calculate this offset during startup (by calling init_time()
|
||||||
|
function) and use it all the time.
|
||||||
|
Time value provided should be legal time value (e.g. '2003-01-01 25:00:00'
|
||||||
|
is not allowed).
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
Time in UTC seconds since Unix Epoch representation.
|
||||||
|
*/
|
||||||
|
my_time_t
|
||||||
|
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
|
||||||
|
{
|
||||||
|
uint loop;
|
||||||
|
time_t tmp;
|
||||||
|
struct tm *l_time,tm_tmp;
|
||||||
|
long diff, current_timezone;
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 < 2 &&
|
||||||
|
(t->hour != (uint) l_time->tm_hour ||
|
||||||
|
t->minute != (uint) l_time->tm_min);
|
||||||
|
loop++)
|
||||||
|
{ /* One check should be enough ? */
|
||||||
|
/* Get difference in days */
|
||||||
|
int days= t->day - l_time->tm_mday;
|
||||||
|
if (days < -1)
|
||||||
|
days= 1; // Month has wrapped
|
||||||
|
else if (days > 1)
|
||||||
|
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)));
|
||||||
|
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 == 2 && t->hour != (uint) l_time->tm_hour)
|
||||||
|
{
|
||||||
|
int days= t->day - l_time->tm_mday;
|
||||||
|
if (days < -1)
|
||||||
|
days=1; // Month has wrapped
|
||||||
|
else if (days > 1)
|
||||||
|
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)));
|
||||||
|
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 previous hour
|
||||||
|
|
||||||
|
*in_dst_time_gap= 1;
|
||||||
|
}
|
||||||
|
*my_timezone= current_timezone;
|
||||||
|
|
||||||
|
return (my_time_t) tmp;
|
||||||
|
} /* my_system_gmt_sec */
|
||||||
|
@ -828,7 +828,7 @@ extern Gt_creator gt_creator;
|
|||||||
extern Lt_creator lt_creator;
|
extern Lt_creator lt_creator;
|
||||||
extern Ge_creator ge_creator;
|
extern Ge_creator ge_creator;
|
||||||
extern Le_creator le_creator;
|
extern Le_creator le_creator;
|
||||||
extern uchar *days_in_month;
|
extern uchar days_in_month[];
|
||||||
extern char language[LIBLEN],reg_ext[FN_EXTLEN];
|
extern char language[LIBLEN],reg_ext[FN_EXTLEN];
|
||||||
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
||||||
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
|
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
|
||||||
@ -994,12 +994,9 @@ void free_blobs(TABLE *table);
|
|||||||
int set_zone(int nr,int min_zone,int max_zone);
|
int set_zone(int nr,int min_zone,int max_zone);
|
||||||
ulong convert_period_to_month(ulong period);
|
ulong convert_period_to_month(ulong period);
|
||||||
ulong convert_month_to_period(ulong month);
|
ulong convert_month_to_period(ulong month);
|
||||||
long calc_daynr(uint year,uint month,uint day);
|
|
||||||
uint calc_days_in_year(uint year);
|
uint calc_days_in_year(uint year);
|
||||||
void get_date_from_daynr(long daynr,uint *year, uint *month,
|
void get_date_from_daynr(long daynr,uint *year, uint *month,
|
||||||
uint *day);
|
uint *day);
|
||||||
void init_time(void);
|
|
||||||
my_time_t my_system_gmt_sec(const TIME *, long *current_timezone, bool *not_exist);
|
|
||||||
my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *not_exist);
|
my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *not_exist);
|
||||||
bool str_to_time_with_warn(const char *str,uint length,TIME *l_time);
|
bool str_to_time_with_warn(const char *str,uint length,TIME *l_time);
|
||||||
timestamp_type str_to_datetime_with_warn(const char *str, uint length,
|
timestamp_type str_to_datetime_with_warn(const char *str, uint length,
|
||||||
|
157
sql/time.cc
157
sql/time.cc
@ -20,166 +20,9 @@
|
|||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
|
|
||||||
static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
|
|
||||||
uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037";
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Offset of system time zone from UTC in seconds used to speed up
|
|
||||||
work of my_system_gmt_sec() function.
|
|
||||||
*/
|
|
||||||
static long my_time_zone=0;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Prepare offset of system time zone from UTC for my_system_gmt_sec() func.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
init_time()
|
|
||||||
*/
|
|
||||||
void init_time(void)
|
|
||||||
{
|
|
||||||
time_t seconds;
|
|
||||||
struct tm *l_time,tm_tmp;;
|
|
||||||
TIME my_time;
|
|
||||||
bool not_used;
|
|
||||||
|
|
||||||
seconds= (time_t) time((time_t*) 0);
|
|
||||||
localtime_r(&seconds,&tm_tmp);
|
|
||||||
l_time= &tm_tmp;
|
|
||||||
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;
|
|
||||||
my_system_gmt_sec(&my_time, &my_time_zone, ¬_used); /* Init my_time_zone */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Convert time in TIME representation in system time zone to its
|
|
||||||
my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
my_system_gmt_sec()
|
|
||||||
t - time value to be converted
|
|
||||||
my_timezone - pointer to long where offset of system time zone
|
|
||||||
from UTC will be stored for caching
|
|
||||||
in_dst_time_gap - set to true if time falls into spring time-gap
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
The idea is to cache the time zone offset from UTC (including daylight
|
|
||||||
saving time) for the next call to make things faster. But currently we
|
|
||||||
just calculate this offset during startup (by calling init_time()
|
|
||||||
function) and use it all the time.
|
|
||||||
Time value provided should be legal time value (e.g. '2003-01-01 25:00:00'
|
|
||||||
is not allowed).
|
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
Time in UTC seconds since Unix Epoch representation.
|
|
||||||
*/
|
|
||||||
my_time_t
|
|
||||||
my_system_gmt_sec(const TIME *t, long *my_timezone, bool *in_dst_time_gap)
|
|
||||||
{
|
|
||||||
uint loop;
|
|
||||||
time_t tmp;
|
|
||||||
struct tm *l_time,tm_tmp;
|
|
||||||
long diff, current_timezone;
|
|
||||||
|
|
||||||
/*
|
|
||||||
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 < 2 &&
|
|
||||||
(t->hour != (uint) l_time->tm_hour ||
|
|
||||||
t->minute != (uint) l_time->tm_min);
|
|
||||||
loop++)
|
|
||||||
{ /* One check should be enough ? */
|
|
||||||
/* Get difference in days */
|
|
||||||
int days= t->day - l_time->tm_mday;
|
|
||||||
if (days < -1)
|
|
||||||
days= 1; // Month has wrapped
|
|
||||||
else if (days > 1)
|
|
||||||
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)));
|
|
||||||
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 == 2 && t->hour != (uint) l_time->tm_hour)
|
|
||||||
{
|
|
||||||
int days= t->day - l_time->tm_mday;
|
|
||||||
if (days < -1)
|
|
||||||
days=1; // Month has wrapped
|
|
||||||
else if (days > 1)
|
|
||||||
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)));
|
|
||||||
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 previous hour
|
|
||||||
|
|
||||||
*in_dst_time_gap= 1;
|
|
||||||
}
|
|
||||||
*my_timezone= current_timezone;
|
|
||||||
|
|
||||||
return (my_time_t) tmp;
|
|
||||||
} /* my_system_gmt_sec */
|
|
||||||
|
|
||||||
|
|
||||||
/* Some functions to calculate dates */
|
/* Some functions to calculate dates */
|
||||||
|
|
||||||
/* Calculate nr of day since year 0 in new date-system (from 1615) */
|
|
||||||
|
|
||||||
long calc_daynr(uint year,uint month,uint day)
|
|
||||||
{
|
|
||||||
long delsum;
|
|
||||||
int temp;
|
|
||||||
DBUG_ENTER("calc_daynr");
|
|
||||||
|
|
||||||
if (year == 0 && month == 0 && day == 0)
|
|
||||||
DBUG_RETURN(0); /* Skip errors */
|
|
||||||
if (year < 200)
|
|
||||||
{
|
|
||||||
if ((year=year+1900) < 1900+YY_PART_YEAR)
|
|
||||||
year+=100;
|
|
||||||
}
|
|
||||||
delsum= (long) (365L * year+ 31*(month-1) +day);
|
|
||||||
if (month <= 2)
|
|
||||||
year--;
|
|
||||||
else
|
|
||||||
delsum-= (long) (month*4+23)/10;
|
|
||||||
temp=(int) ((year/100+1)*3)/4;
|
|
||||||
DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld",
|
|
||||||
year+(month <= 2),month,day,delsum+year/4-temp));
|
|
||||||
DBUG_RETURN(delsum+(int) year/4-temp);
|
|
||||||
} /* calc_daynr */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef TESTTIME
|
#ifndef TESTTIME
|
||||||
/* Calc weekday from daynr */
|
/* Calc weekday from daynr */
|
||||||
/* Returns 0 for monday, 1 for tuesday .... */
|
/* Returns 0 for monday, 1 for tuesday .... */
|
||||||
|
@ -19,15 +19,10 @@
|
|||||||
#pragma interface /* gcc class interface */
|
#pragma interface /* gcc class interface */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#include <mysql_time.h>
|
||||||
Portable time_t replacement.
|
|
||||||
Should be signed and hold seconds for 1902-2038 range.
|
|
||||||
*/
|
|
||||||
typedef long my_time_t;
|
|
||||||
#define MY_TIME_T_MAX LONG_MAX
|
|
||||||
#define MY_TIME_T_MIN LONG_MIN
|
|
||||||
|
|
||||||
#if !defined(TESTTIME) && !defined(TZINFO2SQL)
|
#if !defined(TESTTIME) && !defined(TZINFO2SQL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This class represents abstract time zone and provides
|
This class represents abstract time zone and provides
|
||||||
basic interface for TIME <-> my_time_t conversion.
|
basic interface for TIME <-> my_time_t conversion.
|
||||||
|
Reference in New Issue
Block a user