mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
5.2 merge
This commit is contained in:
@ -780,6 +780,88 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
These events must be printed in base64 format, if printed.
|
||||||
|
base64 format requires a FD event to be safe, so if no FD
|
||||||
|
event has been printed, we give an error. Except if user
|
||||||
|
passed --short-form, because --short-form disables printing
|
||||||
|
row events.
|
||||||
|
*/
|
||||||
|
if (!print_event_info->printed_fd_event && !short_form &&
|
||||||
|
opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
|
||||||
|
{
|
||||||
|
const char* type_str= ev->get_type_str();
|
||||||
|
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
|
||||||
|
error("--base64-output=never specified, but binlog contains a "
|
||||||
|
"%s event which must be printed in base64.",
|
||||||
|
type_str);
|
||||||
|
else
|
||||||
|
error("malformed binlog: it does not contain any "
|
||||||
|
"Format_description_log_event. I now found a %s event, which "
|
||||||
|
"is not safe to process without a "
|
||||||
|
"Format_description_log_event.",
|
||||||
|
type_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ev->print(result_file, print_event_info);
|
||||||
|
return print_event_info->head_cache.error == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
||||||
|
ulong table_id, bool is_stmt_end)
|
||||||
|
{
|
||||||
|
Table_map_log_event *ignored_map=
|
||||||
|
print_event_info->m_table_map_ignored.get_table(table_id);
|
||||||
|
bool skip_event= (ignored_map != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
end of statement check:
|
||||||
|
i) destroy/free ignored maps
|
||||||
|
ii) if skip event, flush cache now
|
||||||
|
*/
|
||||||
|
if (is_stmt_end)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Now is safe to clear ignored map (clear_tables will also
|
||||||
|
delete original table map events stored in the map).
|
||||||
|
*/
|
||||||
|
if (print_event_info->m_table_map_ignored.count() > 0)
|
||||||
|
print_event_info->m_table_map_ignored.clear_tables();
|
||||||
|
|
||||||
|
/*
|
||||||
|
If there is a kept Annotate event and all corresponding
|
||||||
|
rbr-events were filtered away, the Annotate event was not
|
||||||
|
freed and it is just the time to do it.
|
||||||
|
*/
|
||||||
|
free_annotate_event();
|
||||||
|
|
||||||
|
/*
|
||||||
|
One needs to take into account an event that gets
|
||||||
|
filtered but was last event in the statement. If this is
|
||||||
|
the case, previous rows events that were written into
|
||||||
|
IO_CACHEs still need to be copied from cache to
|
||||||
|
result_file (as it would happen in ev->print(...) if
|
||||||
|
event was not skipped).
|
||||||
|
*/
|
||||||
|
if (skip_event)
|
||||||
|
{
|
||||||
|
if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) ||
|
||||||
|
copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file)))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip the event check */
|
||||||
|
if (skip_event)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return print_base64(print_event_info, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Print the given event, and either delete it or delegate the deletion
|
Print the given event, and either delete it or delegate the deletion
|
||||||
to someone else.
|
to someone else.
|
||||||
@ -1081,86 +1163,29 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
error("Could not rewrite database name");
|
error("Could not rewrite database name");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
if (print_base64(print_event_info, ev))
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case WRITE_ROWS_EVENT:
|
case WRITE_ROWS_EVENT:
|
||||||
case DELETE_ROWS_EVENT:
|
case DELETE_ROWS_EVENT:
|
||||||
case UPDATE_ROWS_EVENT:
|
case UPDATE_ROWS_EVENT:
|
||||||
|
{
|
||||||
|
Rows_log_event *e= (Rows_log_event*) ev;
|
||||||
|
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
||||||
|
e->get_flags(Rows_log_event::STMT_END_F)))
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PRE_GA_WRITE_ROWS_EVENT:
|
case PRE_GA_WRITE_ROWS_EVENT:
|
||||||
case PRE_GA_DELETE_ROWS_EVENT:
|
case PRE_GA_DELETE_ROWS_EVENT:
|
||||||
case PRE_GA_UPDATE_ROWS_EVENT:
|
case PRE_GA_UPDATE_ROWS_EVENT:
|
||||||
{
|
{
|
||||||
if (ev_type != TABLE_MAP_EVENT)
|
Old_rows_log_event *e= (Old_rows_log_event*) ev;
|
||||||
{
|
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
||||||
Rows_log_event *e= (Rows_log_event*) ev;
|
e->get_flags(Old_rows_log_event::STMT_END_F)))
|
||||||
Table_map_log_event *ignored_map=
|
|
||||||
print_event_info->m_table_map_ignored.get_table(e->get_table_id());
|
|
||||||
bool skip_event= (ignored_map != NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
end of statement check:
|
|
||||||
i) destroy/free ignored maps
|
|
||||||
ii) if skip event, flush cache now
|
|
||||||
*/
|
|
||||||
if (e->get_flags(Rows_log_event::STMT_END_F))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Now is safe to clear ignored map (clear_tables will also
|
|
||||||
delete original table map events stored in the map).
|
|
||||||
*/
|
|
||||||
if (print_event_info->m_table_map_ignored.count() > 0)
|
|
||||||
print_event_info->m_table_map_ignored.clear_tables();
|
|
||||||
|
|
||||||
/*
|
|
||||||
If there is a kept Annotate event and all corresponding
|
|
||||||
rbr-events were filtered away, the Annotate event was not
|
|
||||||
freed and it is just the time to do it.
|
|
||||||
*/
|
|
||||||
free_annotate_event();
|
|
||||||
|
|
||||||
/*
|
|
||||||
One needs to take into account an event that gets
|
|
||||||
filtered but was last event in the statement. If this is
|
|
||||||
the case, previous rows events that were written into
|
|
||||||
IO_CACHEs still need to be copied from cache to
|
|
||||||
result_file (as it would happen in ev->print(...) if
|
|
||||||
event was not skipped).
|
|
||||||
*/
|
|
||||||
if (skip_event)
|
|
||||||
{
|
|
||||||
if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) ||
|
|
||||||
copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file)))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip the event check */
|
|
||||||
if (skip_event)
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
These events must be printed in base64 format, if printed.
|
|
||||||
base64 format requires a FD event to be safe, so if no FD
|
|
||||||
event has been printed, we give an error. Except if user
|
|
||||||
passed --short-form, because --short-form disables printing
|
|
||||||
row events.
|
|
||||||
*/
|
|
||||||
if (!print_event_info->printed_fd_event && !short_form &&
|
|
||||||
opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
|
|
||||||
{
|
|
||||||
const char* type_str= ev->get_type_str();
|
|
||||||
if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
|
|
||||||
error("--base64-output=never specified, but binlog contains a "
|
|
||||||
"%s event which must be printed in base64.",
|
|
||||||
type_str);
|
|
||||||
else
|
|
||||||
error("malformed binlog: it does not contain any "
|
|
||||||
"Format_description_log_event. I now found a %s event, which "
|
|
||||||
"is not safe to process without a "
|
|
||||||
"Format_description_log_event.",
|
|
||||||
type_str);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
break;
|
||||||
/* FALL THROUGH */
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ev->print(result_file, print_event_info);
|
ev->print(result_file, print_event_info);
|
||||||
|
@ -498,7 +498,8 @@ C_MODE_END
|
|||||||
#define compile_time_assert(X) \
|
#define compile_time_assert(X) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
typedef char compile_time_assert[(X) ? 1 : -1]; \
|
typedef char compile_time_assert[(X) ? 1 : -1] \
|
||||||
|
__attribute__((unused)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -31,6 +31,31 @@
|
|||||||
#define MYSQL50_TABLE_NAME_PREFIX_LENGTH (sizeof(MYSQL50_TABLE_NAME_PREFIX)-1)
|
#define MYSQL50_TABLE_NAME_PREFIX_LENGTH (sizeof(MYSQL50_TABLE_NAME_PREFIX)-1)
|
||||||
#define SAFE_NAME_LEN (NAME_LEN + MYSQL50_TABLE_NAME_PREFIX_LENGTH)
|
#define SAFE_NAME_LEN (NAME_LEN + MYSQL50_TABLE_NAME_PREFIX_LENGTH)
|
||||||
|
|
||||||
|
/*
|
||||||
|
MDEV-4088
|
||||||
|
|
||||||
|
MySQL (and MariaDB 5.x before the fix) was using the first character of the
|
||||||
|
server version string (as sent in the first handshake protocol packet) to
|
||||||
|
decide on the replication event formats. And for 10.x the first character
|
||||||
|
is "1", which the slave thought comes from some ancient 1.x version
|
||||||
|
(ignoring the fact that the first ever MySQL version was 3.x).
|
||||||
|
|
||||||
|
To support replication to these old clients, we fake the version in the
|
||||||
|
first handshake protocol packet to start from "5.5.5-" (for example,
|
||||||
|
it might be "5.5.5-10.0.1-MariaDB-debug-log".
|
||||||
|
|
||||||
|
On the client side we remove this fake version prefix to restore the
|
||||||
|
correct server version. The version "5.5.5" did not support
|
||||||
|
pluggable authentication, so any version starting from "5.5.5-" and
|
||||||
|
claiming to support pluggable auth, must be using this fake prefix.
|
||||||
|
*/
|
||||||
|
#ifdef EMBEDDED_LIBRARY
|
||||||
|
#define RPL_VERSION_HACK ""
|
||||||
|
#else
|
||||||
|
/* this version must be the one that *does not* support pluggable auth */
|
||||||
|
#define RPL_VERSION_HACK "5.5.5-"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SERVER_VERSION_LENGTH 60
|
#define SERVER_VERSION_LENGTH 60
|
||||||
#define SQLSTATE_LENGTH 5
|
#define SQLSTATE_LENGTH 5
|
||||||
#define LIST_PROCESS_HOST_LEN 64
|
#define LIST_PROCESS_HOST_LEN 64
|
||||||
|
@ -2947,6 +2947,12 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
strmov(mysql->server_version,(char*) net->read_pos+1);
|
strmov(mysql->server_version,(char*) net->read_pos+1);
|
||||||
mysql->port=port;
|
mysql->port=port;
|
||||||
|
|
||||||
|
/* remove the rpl hack from the version string, see RPL_VERSION_HACK comment */
|
||||||
|
if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH &&
|
||||||
|
strncmp(mysql->server_version, RPL_VERSION_HACK,
|
||||||
|
sizeof(RPL_VERSION_HACK) - 1) == 0)
|
||||||
|
mysql->server_version+= sizeof(RPL_VERSION_HACK) - 1;
|
||||||
|
|
||||||
if (pkt_end >= end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1)
|
if (pkt_end >= end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -125,7 +125,12 @@
|
|||||||
|
|
||||||
static int sel_cmp(Field *f,uchar *a,uchar *b,uint8 a_flag,uint8 b_flag);
|
static int sel_cmp(Field *f,uchar *a,uchar *b,uint8 a_flag,uint8 b_flag);
|
||||||
|
|
||||||
static uchar is_null_string[2]= {1,0};
|
/*
|
||||||
|
this should be long enough so that any memcmp with a string that
|
||||||
|
starts from '\0' won't cross is_null_string boundaries, even
|
||||||
|
if the memcmp is optimized to compare 4- 8- or 16- bytes at once
|
||||||
|
*/
|
||||||
|
static uchar is_null_string[20]= {1,0};
|
||||||
|
|
||||||
class RANGE_OPT_PARAM;
|
class RANGE_OPT_PARAM;
|
||||||
/*
|
/*
|
||||||
|
19
sql/slave.cc
19
sql/slave.cc
@ -874,6 +874,7 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
|
|||||||
int err_code= 0;
|
int err_code= 0;
|
||||||
MYSQL_RES *master_res= 0;
|
MYSQL_RES *master_res= 0;
|
||||||
MYSQL_ROW master_row;
|
MYSQL_ROW master_row;
|
||||||
|
uint version= mysql_get_server_version(mysql) / 10000;
|
||||||
DBUG_ENTER("get_master_version_and_clock");
|
DBUG_ENTER("get_master_version_and_clock");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -894,20 +895,20 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi)
|
|||||||
/*
|
/*
|
||||||
Note the following switch will bug when we have MySQL branch 30 ;)
|
Note the following switch will bug when we have MySQL branch 30 ;)
|
||||||
*/
|
*/
|
||||||
switch (*mysql->server_version)
|
switch (version)
|
||||||
{
|
{
|
||||||
case '0':
|
case 0:
|
||||||
case '1':
|
case 1:
|
||||||
case '2':
|
case 2:
|
||||||
errmsg = "Master reported unrecognized MySQL version";
|
errmsg = "Master reported unrecognized MySQL version";
|
||||||
err_code= ER_SLAVE_FATAL_ERROR;
|
err_code= ER_SLAVE_FATAL_ERROR;
|
||||||
sprintf(err_buff, ER(err_code), errmsg);
|
sprintf(err_buff, ER(err_code), errmsg);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case 3:
|
||||||
mi->rli.relay_log.description_event_for_queue= new
|
mi->rli.relay_log.description_event_for_queue= new
|
||||||
Format_description_log_event(1, mysql->server_version);
|
Format_description_log_event(1, mysql->server_version);
|
||||||
break;
|
break;
|
||||||
case '4':
|
case 4:
|
||||||
mi->rli.relay_log.description_event_for_queue= new
|
mi->rli.relay_log.description_event_for_queue= new
|
||||||
Format_description_log_event(3, mysql->server_version);
|
Format_description_log_event(3, mysql->server_version);
|
||||||
break;
|
break;
|
||||||
@ -1113,10 +1114,10 @@ maybe it is a *VERY OLD MASTER*.");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* redundant with rest of code but safer against later additions */
|
/* redundant with rest of code but safer against later additions */
|
||||||
if (*mysql->server_version == '3')
|
if (version == 3)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (*mysql->server_version == '4')
|
if (version == 4)
|
||||||
{
|
{
|
||||||
master_res= NULL;
|
master_res= NULL;
|
||||||
if (!mysql_real_query(mysql,
|
if (!mysql_real_query(mysql,
|
||||||
@ -1177,7 +1178,7 @@ inconsistency if replicated data deals with collation.");
|
|||||||
This check is only necessary for 4.x masters (and < 5.0.4 masters but
|
This check is only necessary for 4.x masters (and < 5.0.4 masters but
|
||||||
those were alpha).
|
those were alpha).
|
||||||
*/
|
*/
|
||||||
if (*mysql->server_version == '4')
|
if (version == 4)
|
||||||
{
|
{
|
||||||
master_res= NULL;
|
master_res= NULL;
|
||||||
if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.TIME_ZONE")) &&
|
if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.TIME_ZONE")) &&
|
||||||
|
@ -4259,6 +4259,10 @@ static const char filename_safe_char[128]=
|
|||||||
|
|
||||||
#define MY_FILENAME_ESCAPE '@'
|
#define MY_FILENAME_ESCAPE '@'
|
||||||
|
|
||||||
|
/*
|
||||||
|
note, that we cannot trust 'e' here, it's may be fake,
|
||||||
|
see strconvert()
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
my_mb_wc_filename(CHARSET_INFO *cs __attribute__((unused)),
|
my_mb_wc_filename(CHARSET_INFO *cs __attribute__((unused)),
|
||||||
my_wc_t *pwc, const uchar *s, const uchar *e)
|
my_wc_t *pwc, const uchar *s, const uchar *e)
|
||||||
@ -4280,7 +4284,7 @@ my_mb_wc_filename(CHARSET_INFO *cs __attribute__((unused)),
|
|||||||
return MY_CS_TOOSMALL3;
|
return MY_CS_TOOSMALL3;
|
||||||
|
|
||||||
byte1= s[1];
|
byte1= s[1];
|
||||||
byte2= s[2];
|
byte2= byte1 ? s[2] : 0;
|
||||||
|
|
||||||
if (byte1 >= 0x30 && byte1 <= 0x7F &&
|
if (byte1 >= 0x30 && byte1 <= 0x7F &&
|
||||||
byte2 >= 0x30 && byte2 <= 0x7F)
|
byte2 >= 0x30 && byte2 <= 0x7F)
|
||||||
@ -4305,7 +4309,7 @@ my_mb_wc_filename(CHARSET_INFO *cs __attribute__((unused)),
|
|||||||
(byte2= hexlo(byte2)) >= 0)
|
(byte2= hexlo(byte2)) >= 0)
|
||||||
{
|
{
|
||||||
int byte3= hexlo(s[3]);
|
int byte3= hexlo(s[3]);
|
||||||
int byte4= hexlo(s[4]);
|
int byte4= hexlo(s[3] ? s[4] : 0);
|
||||||
if (byte3 >=0 && byte4 >=0)
|
if (byte3 >=0 && byte4 >=0)
|
||||||
{
|
{
|
||||||
*pwc= (byte1 << 12) + (byte2 << 8) + (byte3 << 4) + byte4;
|
*pwc= (byte1 << 12) + (byte2 << 8) + (byte3 << 4) + byte4;
|
||||||
|
@ -5599,7 +5599,7 @@ static void test_date_dt()
|
|||||||
static void test_pure_coverage()
|
static void test_pure_coverage()
|
||||||
{
|
{
|
||||||
MYSQL_STMT *stmt;
|
MYSQL_STMT *stmt;
|
||||||
MYSQL_BIND my_bind[1];
|
MYSQL_BIND my_bind[2];
|
||||||
int rc;
|
int rc;
|
||||||
ulong length;
|
ulong length;
|
||||||
|
|
||||||
@ -8275,7 +8275,7 @@ static void test_parse_error_and_bad_length()
|
|||||||
DIE_UNLESS(rc);
|
DIE_UNLESS(rc);
|
||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
||||||
rc= mysql_real_query(mysql, "SHOW DATABASES", 100);
|
rc= mysql_real_query(mysql, STRING_WITH_LEN("SHOW DATABASES\0AAAAAAAA"));
|
||||||
DIE_UNLESS(rc);
|
DIE_UNLESS(rc);
|
||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
||||||
@ -8286,7 +8286,7 @@ static void test_parse_error_and_bad_length()
|
|||||||
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
|
||||||
stmt= mysql_stmt_init(mysql);
|
stmt= mysql_stmt_init(mysql);
|
||||||
DIE_UNLESS(stmt);
|
DIE_UNLESS(stmt);
|
||||||
rc= mysql_stmt_prepare(stmt, "SHOW DATABASES", 100);
|
rc= mysql_stmt_prepare(stmt, STRING_WITH_LEN("SHOW DATABASES\0AAAAAAA"));
|
||||||
DIE_UNLESS(rc != 0);
|
DIE_UNLESS(rc != 0);
|
||||||
if (!opt_silent)
|
if (!opt_silent)
|
||||||
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
|
fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
|
||||||
@ -16272,7 +16272,8 @@ static void test_bug31669()
|
|||||||
rc= mysql_change_user(conn, "", "", "");
|
rc= mysql_change_user(conn, "", "", "");
|
||||||
DIE_UNLESS(rc);
|
DIE_UNLESS(rc);
|
||||||
|
|
||||||
memset(buff, 'a', sizeof(buff));
|
memset(buff, 'a', sizeof(buff) - 1);
|
||||||
|
buff[sizeof(buff) - 1]= 0;
|
||||||
|
|
||||||
mysql_close(conn);
|
mysql_close(conn);
|
||||||
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
|
conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
|
||||||
|
Reference in New Issue
Block a user