summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc4
-rw-r--r--sql/item.cc18
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc386
-rw-r--r--sql/log_event.h24
-rw-r--r--sql/log_event_old.cc17
-rw-r--r--sql/partition_info.cc2
-rw-r--r--sql/rpl_tblmap.cc20
-rw-r--r--sql/rpl_tblmap.h10
-rw-r--r--sql/sql_binlog.cc91
-rw-r--r--sql/sql_class.cc23
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_lex.cc3
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_repl.cc6
-rw-r--r--sql/sql_select.cc21
-rw-r--r--sql/sql_table.cc150
-rw-r--r--sql/sql_yacc.yy19
-rw-r--r--sql/sql_yacc_ora.yy19
-rw-r--r--sql/sys_vars.cc13
-rw-r--r--sql/table.cc2
-rw-r--r--sql/table.h12
-rw-r--r--sql/wsrep_mysqld.cc1
-rw-r--r--sql/wsrep_mysqld.h1
-rw-r--r--sql/wsrep_mysqld_c.h30
27 files changed, 680 insertions, 210 deletions
diff --git a/sql/field.cc b/sql/field.cc
index bb4a0f06fc4..6fe6af2d303 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8975,7 +8975,7 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
(uint32) geom_type != wkb_type)
{
const char *db= table->s->db.str;
- const char *tab_name= table->s->error_table_name();
+ const char *tab_name= table->s->table_name.str;
if (!db)
db= "";
@@ -11022,7 +11022,7 @@ void Field::set_warning_truncated_wrong_value(const char *type_arg,
{
THD *thd= get_thd();
const char *db_name= table->s->db.str;
- const char *table_name= table->s->error_table_name();
+ const char *table_name= table->s->table_name.str;
if (!db_name)
db_name= "";
diff --git a/sql/item.cc b/sql/item.cc
index a6b4402b6ba..47e10ba4004 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1952,7 +1952,12 @@ bool Item_name_const::is_null()
Item_name_const::Item_name_const(THD *thd, Item *name_arg, Item *val):
Item_fixed_hybrid(thd), value_item(val), name_item(name_arg)
{
+ StringBuffer<128> name_buffer;
+ String *name_str;
Item::maybe_null= TRUE;
+ if (name_item->basic_const_item() &&
+ (name_str= name_item->val_str(&name_buffer))) // Can't have a NULL name
+ set_name(thd, name_str->ptr(), name_str->length(), name_str->charset());
}
@@ -1988,25 +1993,14 @@ Item::Type Item_name_const::type() const
bool Item_name_const::fix_fields(THD *thd, Item **ref)
{
- char buf[128];
- String *item_name;
- String s(buf, sizeof(buf), &my_charset_bin);
- s.length(0);
-
if (value_item->fix_fields_if_needed(thd, &value_item) ||
name_item->fix_fields_if_needed(thd, &name_item) ||
!value_item->const_item() ||
- !name_item->const_item() ||
- !(item_name= name_item->val_str(&s))) // Can't have a NULL name
+ !name_item->const_item())
{
my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST");
return TRUE;
}
- if (is_autogenerated_name)
- {
- set_name(thd, item_name->c_ptr(), (uint) item_name->length(),
- system_charset_info);
- }
if (value_item->collation.derivation == DERIVATION_NUMERIC)
collation.set_numeric();
else
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ef0dc0ba34b..e6b57750ec7 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4477,7 +4477,7 @@ bool Item_func_set_user_var::register_field_in_bitmap(void *arg)
true failure
*/
-static bool
+bool
update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
Item_result type, CHARSET_INFO *cs,
bool unsigned_arg)
diff --git a/sql/item_func.h b/sql/item_func.h
index 6408cf4dd55..e4dc1d80bf9 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -3436,4 +3436,8 @@ bool eval_const_cond(COND *cond);
extern bool volatile mqh_used;
+bool update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
+ Item_result type, CHARSET_INFO *cs,
+ bool unsigned_arg);
+
#endif /* ITEM_FUNC_INCLUDED */
diff --git a/sql/log.cc b/sql/log.cc
index a4a2b4b1e37..a89be15a0d7 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2017, MariaDB Corporation.
+/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2019, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -3994,7 +3994,7 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
// if the log entry matches, null string matching anything
if (!log_name ||
(log_name_len == fname_len &&
- !memcmp(full_fname, full_log_name, log_name_len)))
+ !strncmp(full_fname, full_log_name, log_name_len)))
{
DBUG_PRINT("info", ("Found log file entry"));
linfo->index_file_start_offset= offset;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index bbadda3167e..70f0e6c2623 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3685,9 +3685,23 @@ void free_table_map_log_event(Table_map_log_event *event)
delete event;
}
+/**
+ Encode the event, optionally per 'do_print_encoded' arg store the
+ result into the argument cache; optionally per event_info's
+ 'verbose' print into the cache a verbose representation of the event.
+ Note, no extra wrapping is done to the being io-cached data, like
+ to producing a BINLOG query. It's left for a routine that extracts from
+ the cache.
+
+ @param file pointer to IO_CACHE
+ @param print_event_info pointer to print_event_info specializing
+ what out of and how to print the event
+ @param do_print_encoded whether to store base64-encoded event
+ into @file.
+*/
bool Log_event::print_base64(IO_CACHE* file,
PRINT_EVENT_INFO* print_event_info,
- bool more)
+ bool do_print_encoded)
{
uchar *ptr= (uchar *)temp_buf;
uint32 size= uint4korr(ptr + EVENT_LEN_OFFSET);
@@ -3738,12 +3752,9 @@ bool Log_event::print_base64(IO_CACHE* file,
delete ev;
}
- if (print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
- print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
- ! print_event_info->short_form)
+ if (do_print_encoded)
{
size_t const tmp_str_sz= my_base64_needed_encoded_length((int) size);
- bool error= 0;
char *tmp_str;
if (!(tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME))))
goto err;
@@ -3753,17 +3764,8 @@ bool Log_event::print_base64(IO_CACHE* file,
DBUG_ASSERT(0);
}
- if (my_b_tell(file) == 0)
- if (unlikely(my_b_write_string(file, "\nBINLOG '\n")))
- error= 1;
- if (likely(!error) && unlikely(my_b_printf(file, "%s\n", tmp_str)))
- error= 1;
- if (!more && likely(!error))
- if (unlikely(my_b_printf(file, "'%s\n", print_event_info->delimiter)))
- error= 1;
+ my_b_printf(file, "%s\n", tmp_str);
my_free(tmp_str);
- if (unlikely(error))
- goto err;
}
#ifdef WHEN_FLASHBACK_REVIEW_READY
@@ -3877,9 +3879,22 @@ bool Log_event::print_base64(IO_CACHE* file,
}
#else
if (print_event_info->verbose)
+ {
+ /*
+ Verbose event printout can't start before encoded data
+ got enquoted. This is done at this point though multi-row
+ statement remain vulnerable.
+ TODO: fix MDEV-10362 to remove this workaround.
+ */
+ if (print_event_info->base64_output_mode !=
+ BASE64_OUTPUT_DECODE_ROWS)
+ my_b_printf(file, "'%s\n", print_event_info->delimiter);
error= ev->print_verbose(file, print_event_info);
+ }
else
+ {
ev->count_row_events(print_event_info);
+ }
#endif
delete ev;
if (unlikely(error))
@@ -5585,6 +5600,22 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
else
thd->variables.collation_database= thd->db_charset;
+ {
+ const CHARSET_INFO *cs= thd->charset();
+ /*
+ We cannot ask for parsing a statement using a character set
+ without state_maps (parser internal data).
+ */
+ if (!cs->state_map)
+ {
+ rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
+ ER_THD(thd, ER_SLAVE_FATAL_ERROR),
+ "character_set cannot be parsed");
+ thd->is_slave_error= true;
+ goto end;
+ }
+ }
+
/*
Record any GTID in the same transaction, so slave state is
transactionally consistent.
@@ -6023,11 +6054,18 @@ bool Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
!print_event_info->short_form)
{
- if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
- if (my_b_printf(&cache, "BINLOG '\n"))
- goto err;
- if (print_base64(&cache, print_event_info, FALSE))
+ /* BINLOG is matched with the delimiter below on the same level */
+ bool do_print_encoded=
+ print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS;
+ if (do_print_encoded)
+ my_b_printf(&cache, "BINLOG '\n");
+
+ if (print_base64(&cache, print_event_info, do_print_encoded))
goto err;
+
+ if (do_print_encoded)
+ my_b_printf(&cache, "'%s\n", print_event_info->delimiter);
+
print_event_info->printed_fd_event= TRUE;
}
DBUG_RETURN(cache.flush_data());
@@ -9189,12 +9227,6 @@ User_var_log_event(const char* buf, uint event_len,
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
UV_CHARSET_NUMBER_SIZE);
- if (val + val_len > buf_end)
- {
- error= true;
- goto err;
- }
-
/**
We need to check if this is from an old server
that did not pack information for flags.
@@ -10969,7 +11001,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
DBUG_VOID_RETURN;
}
size_t const data_size= event_len - read_size;
- DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu",
+ DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %lu",
m_table_id, m_flags, m_width, (ulong) data_size));
m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
@@ -11182,12 +11214,12 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
int error= 0;
/*
- If m_table_id == ~0UL, then we have a dummy event that does not
+ If m_table_id == ~0ULL, then we have a dummy event that does not
contain any data. In that case, we just remove all tables in the
tables_to_lock list, close the thread tables, and return with
success.
*/
- if (m_table_id == ~0UL)
+ if (m_table_id == ~0ULL)
{
/*
This one is supposed to be set: just an extra check so that
@@ -11453,7 +11485,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
table= m_table= rgi->m_table_map.get_table(m_table_id);
- DBUG_PRINT("debug", ("m_table:%p, m_table_id: %lu%s",
+ DBUG_PRINT("debug", ("m_table:%p, m_table_id: %llu%s",
m_table, m_table_id,
table && master_had_triggers ?
" (master had triggers)" : ""));
@@ -11819,14 +11851,14 @@ Rows_log_event::do_update_pos(rpl_group_info *rgi)
bool Rows_log_event::write_data_header()
{
uchar buf[ROWS_HEADER_LEN_V2]; // No need to init the buffer
- DBUG_ASSERT(m_table_id != ~0UL);
+ DBUG_ASSERT(m_table_id != ~0ULL);
DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
{
int4store(buf + 0, m_table_id);
int2store(buf + 4, m_flags);
return (write_data(buf, 6));
});
- int6store(buf + RW_MAPID_OFFSET, (ulonglong)m_table_id);
+ int6store(buf + RW_MAPID_OFFSET, m_table_id);
int2store(buf + RW_FLAGS_OFFSET, m_flags);
return write_data(buf, ROWS_HEADER_LEN);
}
@@ -11894,12 +11926,226 @@ void Rows_log_event::pack_info(Protocol *protocol)
char const *const flagstr=
get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
size_t bytes= my_snprintf(buf, sizeof(buf),
- "table_id: %lu%s", m_table_id, flagstr);
+ "table_id: %llu%s", m_table_id, flagstr);
protocol->store(buf, bytes, &my_charset_bin);
}
#endif
#ifdef MYSQL_CLIENT
+
+const char str_binlog[]= "\nBINLOG '\n";
+const char fmt_delim[]= "'%s\n";
+const char fmt_n_delim[]= "\n'%s";
+const char fmt_frag[]= "\nSET @binlog_fragment_%d ='\n";
+const char fmt_binlog2[]= "BINLOG @binlog_fragment_0, @binlog_fragment_1%s\n";
+
+/**
+ Print an event "body" cache to @c file possibly in two fragments.
+ Each fragement is optionally per @c do_wrap to produce an SQL statement.
+
+ @param file a file to print to
+ @param body the "body" IO_CACHE of event
+ @param do_wrap whether to wrap base64-encoded strings with
+ SQL cover.
+ @param delimiter delimiter string
+
+ @param is_verbose MDEV-10362 workraround parameter to pass
+ info on presence of verbose printout in cache encoded data
+
+ The function signals on any error through setting @c body->error to -1.
+*/
+bool copy_cache_to_file_wrapped(IO_CACHE *body,
+ FILE *file,
+ bool do_wrap,
+ const char *delimiter,
+ bool is_verbose)
+{
+ const my_off_t cache_size= my_b_tell(body);
+
+ if (reinit_io_cache(body, READ_CACHE, 0L, FALSE, FALSE))
+ goto err;
+
+ if (!do_wrap)
+ {
+ my_b_copy_to_file(body, file, SIZE_T_MAX);
+ }
+ else if (4 + sizeof(str_binlog) + cache_size + sizeof(fmt_delim) >
+ opt_binlog_rows_event_max_encoded_size)
+ {
+ /*
+ 2 fragments can always represent near 1GB row-based
+ base64-encoded event as two strings each of size less than
+ max(max_allowed_packet). Greater number of fragments does not
+ save from potential need to tweak (increase) @@max_allowed_packet
+ before to process the fragments. So 2 is safe and enough.
+
+ Split the big query when its packet size's estimation exceeds a
+ limit. The estimate includes the maximum packet header
+ contribution of non-compressed packet.
+ */
+ my_fprintf(file, fmt_frag, 0);
+ if (my_b_copy_to_file(body, file, (size_t) cache_size/2 + 1))
+ goto err;
+ my_fprintf(file, fmt_n_delim, delimiter);
+
+ my_fprintf(file, fmt_frag, 1);
+ if (my_b_copy_to_file(body, file, SIZE_T_MAX))
+ goto err;
+ if (!is_verbose)
+ my_fprintf(file, fmt_delim, delimiter);
+
+ my_fprintf(file, fmt_binlog2, delimiter);
+ }
+ else
+ {
+ my_fprintf(file, str_binlog);
+ if (my_b_copy_to_file(body, file, SIZE_T_MAX))
+ goto err;
+ if (!is_verbose)
+ my_fprintf(file, fmt_delim, delimiter);
+ }
+ reinit_io_cache(body, WRITE_CACHE, 0, FALSE, TRUE);
+
+ return false;
+
+err:
+ body->error = -1;
+ return true;
+}
+
+
+/**
+ Print an event "body" cache to @c file possibly in two fragments.
+ Each fragement is optionally per @c do_wrap to produce an SQL statement.
+
+ @param file a file to print to
+ @param body the "body" IO_CACHE of event
+ @param do_wrap whether to wrap base64-encoded strings with
+ SQL cover.
+ @param delimiter delimiter string
+
+ The function signals on any error through setting @c body->error to -1.
+*/
+bool copy_cache_to_string_wrapped(IO_CACHE *cache,
+ LEX_STRING *to,
+ bool do_wrap,
+ const char *delimiter,
+ bool is_verbose)
+{
+ const my_off_t cache_size= my_b_tell(cache);
+ // contribution to total size estimate of formating
+ const size_t fmt_size=
+ sizeof(str_binlog) + 2*(sizeof(fmt_frag) + 2 /* %d */) +
+ sizeof(fmt_delim) + sizeof(fmt_n_delim) +
+ sizeof(fmt_binlog2) +
+ 3*PRINT_EVENT_INFO::max_delimiter_size;
+
+ if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE))
+ goto err;
+
+ if (!(to->str= (char*) my_malloc((size_t)cache->end_of_file + fmt_size,
+ MYF(0))))
+ {
+ perror("Out of memory: can't allocate memory in "
+ "copy_cache_to_string_wrapped().");
+ goto err;
+ }
+
+ if (!do_wrap)
+ {
+ if (my_b_read(cache, (uchar*) to->str,
+ (to->length= (size_t)cache->end_of_file)))
+ goto err;
+ }
+ else if (4 + sizeof(str_binlog) + cache_size + sizeof(fmt_delim) >
+ opt_binlog_rows_event_max_encoded_size)
+ {
+ /*
+ 2 fragments can always represent near 1GB row-based
+ base64-encoded event as two strings each of size less than
+ max(max_allowed_packet). Greater number of fragments does not
+ save from potential need to tweak (increase) @@max_allowed_packet
+ before to process the fragments. So 2 is safe and enough.
+
+ Split the big query when its packet size's estimation exceeds a
+ limit. The estimate includes the maximum packet header
+ contribution of non-compressed packet.
+ */
+ char *str= to->str;
+ size_t add_to_len;
+
+ str += (to->length= sprintf(str, fmt_frag, 0));
+ if (my_b_read(cache, (uchar*) str, (uint32) (cache_size/2 + 1)))
+ goto err;
+ str += (add_to_len = (uint32) (cache_size/2 + 1));
+ to->length += add_to_len;
+ str += (add_to_len= sprintf(str, fmt_n_delim, delimiter));
+ to->length += add_to_len;
+
+ str += (add_to_len= sprintf(str, fmt_frag, 1));
+ to->length += add_to_len;
+ if (my_b_read(cache, (uchar*) str, uint32(cache->end_of_file - (cache_size/2 + 1))))
+ goto err;
+ str += (add_to_len= uint32(cache->end_of_file - (cache_size/2 + 1)));
+ to->length += add_to_len;
+ if (!is_verbose)
+ {
+ str += (add_to_len= sprintf(str , fmt_delim, delimiter));
+ to->length += add_to_len;
+ }
+ to->length += sprintf(str, fmt_binlog2, delimiter);
+ }
+ else
+ {
+ char *str= to->str;
+
+ str += (to->length= sprintf(str, str_binlog));
+ if (my_b_read(cache, (uchar*) str, (size_t)cache->end_of_file))
+ goto err;
+ str += cache->end_of_file;
+ to->length += (size_t)cache->end_of_file;
+ if (!is_verbose)
+ to->length += sprintf(str , fmt_delim, delimiter);
+ }
+
+ reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE);
+
+ return false;
+
+err:
+ cache->error= -1;
+ return true;
+}
+
+/**
+ The function invokes base64 encoder to run on the current
+ event string and store the result into two caches.
+ When the event ends the current statement the caches are is copied into
+ the argument file.
+ Copying is also concerned how to wrap the event, specifically to produce
+ a valid SQL syntax.
+ When the encoded data size is within max(MAX_ALLOWED_PACKET)
+ a regular BINLOG query is composed. Otherwise it is build as fragmented
+
+ SET @binlog_fragment_0='...';
+ SET @binlog_fragment_1='...';
+ BINLOG @binlog_fragment_0, @binlog_fragment_1;
+
+ where fragments are represented by a pair of indexed user
+ "one shot" variables.
+
+ @note
+ If any changes made don't forget to duplicate them to
+ Old_rows_log_event as long as it's supported.
+
+ @param file pointer to IO_CACHE
+ @param print_event_info pointer to print_event_info specializing
+ what out of and how to print the event
+ @param name the name of a table that the event operates on
+
+ The function signals on any error of cache access through setting
+ that cache's @c error to -1.
+*/
bool Rows_log_event::print_helper(FILE *file,
PRINT_EVENT_INFO *print_event_info,
char const *const name)
@@ -11909,18 +12155,24 @@ bool Rows_log_event::print_helper(FILE *file,
#ifdef WHEN_FLASHBACK_REVIEW_READY
IO_CACHE *const sql= &print_event_info->review_sql_cache;
#endif
+ bool do_print_encoded=
+ print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
+ print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
+ !print_event_info->short_form;
bool const last_stmt_event= get_flags(STMT_END_F);
if (!print_event_info->short_form)
{
+ char llbuff[22];
+
print_header(head, print_event_info, !last_stmt_event);
- if (my_b_printf(head, "\t%s: table id %lu%s\n",
- name, m_table_id,
+ if (my_b_printf(head, "\t%s: table id %s%s\n",
+ name, ullstr(m_table_id, llbuff),
last_stmt_event ? " flags: STMT_END_F" : ""))
goto err;
}
if (!print_event_info->short_form || print_event_info->print_row_count)
- if (print_base64(body, print_event_info, !last_stmt_event))
+ if (print_base64(body, print_event_info, do_print_encoded))
goto err;
if (last_stmt_event)
@@ -11928,25 +12180,31 @@ bool Rows_log_event::print_helper(FILE *file,
if (!is_flashback)
{
if (copy_event_cache_to_file_and_reinit(head, file) ||
- copy_event_cache_to_file_and_reinit(body, file))
+ copy_cache_to_file_wrapped(body, file, do_print_encoded,
+ print_event_info->delimiter,
+ print_event_info->verbose))
goto err;
}
else
{
- LEX_STRING tmp_str;
- if (copy_event_cache_to_string_and_reinit(head, &tmp_str))
- return 1;
- output_buf.append(tmp_str.str, tmp_str.length); // Not \0 terminated
- my_free(tmp_str.str);
- if (copy_event_cache_to_string_and_reinit(body, &tmp_str))
- return 1;
- output_buf.append(tmp_str.str, tmp_str.length);
- my_free(tmp_str.str);
+ LEX_STRING tmp_str;
+
+ if (copy_event_cache_to_string_and_reinit(head, &tmp_str))
+ return 1;
+ output_buf.append(tmp_str.str, tmp_str.length); // Not \0 terminated);
+ my_free(tmp_str.str);
+
+ if (copy_cache_to_string_wrapped(body, &tmp_str, do_print_encoded,
+ print_event_info->delimiter,
+ print_event_info->verbose))
+ return 1;
+ output_buf.append(tmp_str.str, tmp_str.length);
+ my_free(tmp_str.str);
#ifdef WHEN_FLASHBACK_REVIEW_READY
- if (copy_event_cache_to_string_and_reinit(sql, &tmp_str))
- return 1;
- output_buf.append(tmp_str.str, tmp_str.length);
- my_free(tmp_str.str);
+ if (copy_event_cache_to_string_and_reinit(sql, &tmp_str))
+ return 1;
+ output_buf.append(tmp_str.str, tmp_str.length);
+ my_free(tmp_str.str);
#endif
}
}
@@ -12217,7 +12475,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
uchar cbuf[MAX_INT_WIDTH];
uchar *cbuf_end;
DBUG_ENTER("Table_map_log_event::Table_map_log_event(TABLE)");
- DBUG_ASSERT(m_table_id != ~0UL);
+ DBUG_ASSERT(m_table_id != ~0ULL);
/*
In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
table.cc / alloc_table_share():
@@ -12302,7 +12560,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
#endif
m_dbnam(NULL), m_dblen(0), m_tblnam(NULL), m_tbllen(0),
m_colcnt(0), m_coltype(0),
- m_memory(NULL), m_table_id(ULONG_MAX), m_flags(0),
+ m_memory(NULL), m_table_id(ULONGLONG_MAX), m_flags(0),
m_data_size(0), m_field_metadata(0), m_field_metadata_size(0),
m_null_bits(0), m_meta_memory(NULL)
{
@@ -12339,7 +12597,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
post_start+= TM_FLAGS_OFFSET;
}
- DBUG_ASSERT(m_table_id != ~0UL);
+ DBUG_ASSERT(m_table_id != ~0ULL);
m_flags= uint2korr(post_start);
@@ -12659,7 +12917,7 @@ int Table_map_log_event::do_apply_event(rpl_group_info *rgi)
table_list->updating= 1;
table_list->required_type= TABLE_TYPE_NORMAL;
- DBUG_PRINT("debug", ("table: %s is mapped to %lu",
+ DBUG_PRINT("debug", ("table: %s is mapped to %llu",
table_list->table_name.str,
table_list->table_id));
table_list->master_had_triggers= ((m_flags & TM_BIT_HAS_TRIGGERS_F) ? 1 : 0);
@@ -12761,7 +13019,7 @@ int Table_map_log_event::do_update_pos(rpl_group_info *rgi)
#ifndef MYSQL_CLIENT
bool Table_map_log_event::write_data_header()
{
- DBUG_ASSERT(m_table_id != ~0UL);
+ DBUG_ASSERT(m_table_id != ~0ULL);
uchar buf[TABLE_MAP_HEADER_LEN];
DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
{
@@ -12769,7 +13027,7 @@ bool Table_map_log_event::write_data_header()
int2store(buf + 4, m_flags);
return (write_data(buf, 6));
});
- int6store(buf + TM_MAPID_OFFSET, (ulonglong)m_table_id);
+ int6store(buf + TM_MAPID_OFFSET, m_table_id);
int2store(buf + TM_FLAGS_OFFSET, m_flags);
return write_data(buf, TABLE_MAP_HEADER_LEN);
}
@@ -12819,7 +13077,7 @@ void Table_map_log_event::pack_info(Protocol *protocol)
{
char buf[256];
size_t bytes= my_snprintf(buf, sizeof(buf),
- "table_id: %lu (%s.%s)",
+ "table_id: %llu (%s.%s)",
m_table_id, m_dbnam, m_tblnam);
protocol->store(buf, bytes, &my_charset_bin);
}
@@ -12834,17 +13092,25 @@ bool Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info)
{
if (!print_event_info->short_form)
{
+ char llbuff[22];
+
print_header(&print_event_info->head_cache, print_event_info, TRUE);
if (my_b_printf(&print_event_info->head_cache,
- "\tTable_map: %`s.%`s mapped to number %lu%s\n",
- m_dbnam, m_tblnam, m_table_id,
+ "\tTable_map: %`s.%`s mapped to number %s%s\n",
+ m_dbnam, m_tblnam, ullstr(m_table_id, llbuff),
((m_flags & TM_BIT_HAS_TRIGGERS_F) ?
" (has triggers)" : "")))
goto err;
}
if (!print_event_info->short_form || print_event_info->print_row_count)
{
- if (print_base64(&print_event_info->body_cache, print_event_info, TRUE) ||
+ bool do_print_encoded=
+ print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
+ print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
+ !print_event_info->short_form;
+
+ if (print_base64(&print_event_info->body_cache, print_event_info,
+ do_print_encoded) ||
copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
file))
goto err;
@@ -14768,7 +15034,7 @@ err:
bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file)
{
- return (my_b_copy_to_file(cache, file) ||
+ return (my_b_copy_all_to_file(cache, file) ||
reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE));
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 38a40c90799..339db756aab 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -866,6 +866,7 @@ typedef struct st_print_event_info
bool allow_parallel_printed;
bool found_row_event;
bool print_row_count;
+ static const uint max_delimiter_size= 16;
/* Settings on how to print the events */
bool short_form;
/*
@@ -1264,7 +1265,7 @@ public:
bool print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info,
bool is_more);
bool print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info,
- bool is_more);
+ bool do_print_encoded);
#endif /* MYSQL_SERVER */
/* The following code used for Flashback */
@@ -4333,7 +4334,7 @@ public:
int rewrite_db(const char* new_name, size_t new_name_len,
const Format_description_log_event*);
#endif
- ulong get_table_id() const { return m_table_id; }
+ ulonglong get_table_id() const { return m_table_id; }
const char *get_table_name() const { return m_tblnam; }
const char *get_db_name() const { return m_dbnam; }
@@ -4377,7 +4378,7 @@ private:
uchar *m_coltype;
uchar *m_memory;
- ulong m_table_id;
+ ulonglong m_table_id;
flag_set m_flags;
size_t m_data_size;
@@ -4506,7 +4507,7 @@ public:
MY_BITMAP const *get_cols() const { return &m_cols; }
MY_BITMAP const *get_cols_ai() const { return &m_cols_ai; }
size_t get_width() const { return m_width; }
- ulong get_table_id() const { return m_table_id; }
+ ulonglong get_table_id() const { return m_table_id; }
#if defined(MYSQL_SERVER)
/*
@@ -4607,7 +4608,7 @@ protected:
#ifdef MYSQL_SERVER
TABLE *m_table; /* The table the rows belong to */
#endif
- ulong m_table_id; /* Table ID */
+ ulonglong m_table_id; /* Table ID */
MY_BITMAP m_cols; /* Bitmap denoting columns available */
ulong m_width; /* The width of the columns bitmap */
/*
@@ -5171,6 +5172,19 @@ public:
virtual int get_data_size() { return IGNORABLE_HEADER_LEN; }
};
+#ifdef MYSQL_CLIENT
+bool copy_cache_to_string_wrapped(IO_CACHE *body,
+ LEX_STRING *to,
+ bool do_wrap,
+ const char *delimiter,
+ bool is_verbose);
+bool copy_cache_to_file_wrapped(IO_CACHE *body,
+ FILE *file,
+ bool do_wrap,
+ const char *delimiter,
+ bool is_verbose);
+#endif
+
#ifdef MYSQL_SERVER
/*****************************************************************************
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 66c4c2bef42..b5381ec6d74 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1842,27 +1842,34 @@ void Old_rows_log_event::pack_info(Protocol *protocol)
#ifdef MYSQL_CLIENT
+/* Method duplicates Rows_log_event's one */
bool Old_rows_log_event::print_helper(FILE *file,
PRINT_EVENT_INFO *print_event_info,
char const *const name)
{
IO_CACHE *const head= &print_event_info->head_cache;
IO_CACHE *const body= &print_event_info->body_cache;
+ bool do_print_encoded=
+ print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
+ print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
+ !print_event_info->short_form;
+
if (!print_event_info->short_form)
{
- bool const last_stmt_event= get_flags(STMT_END_F);
- if (print_header(head, print_event_info, !last_stmt_event) ||
+ if (print_header(head, print_event_info, !do_print_encoded) ||
my_b_printf(head, "\t%s: table id %lu%s\n",
name, m_table_id,
- last_stmt_event ? " flags: STMT_END_F" : "") ||
- print_base64(body, print_event_info, !last_stmt_event))
+ do_print_encoded ? " flags: STMT_END_F" : "") ||
+ print_base64(body, print_event_info, do_print_encoded))
goto err;
}
if (get_flags(STMT_END_F))
{
if (copy_event_cache_to_file_and_reinit(head, file) ||
- copy_event_cache_to_file_and_reinit(body, file))
+ copy_cache_to_file_wrapped(body, file, do_print_encoded,
+ print_event_info->delimiter,
+ print_event_info->verbose))
goto err;
}
return 0;
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 0ac4014a669..2f021d6118c 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -878,7 +878,7 @@ void partition_info::vers_set_hist_part(THD *thd)
return;
warn:
my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
- table->s->db.str, table->s->error_table_name(),
+ table->s->db.str, table->s->table_name.str,
vers_info->hist_part->partition_name);
}
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
index 7284e4be15c..02543a429b8 100644
--- a/sql/rpl_tblmap.cc
+++ b/sql/rpl_tblmap.cc
@@ -43,7 +43,7 @@ table_mapping::table_mapping()
constructor is called at startup only.
*/
(void) my_hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
- offsetof(entry,table_id),sizeof(ulong),
+ offsetof(entry,table_id),sizeof(ulonglong),
0,0,0);
/* We don't preallocate any block, this is consistent with m_free=0 above */
init_alloc_root(&m_mem_root, "table_mapping",
@@ -60,20 +60,20 @@ table_mapping::~table_mapping()
free_root(&m_mem_root, MYF(0));
}
-TABLE* table_mapping::get_table(ulong table_id)
+TABLE* table_mapping::get_table(ulonglong table_id)
{
DBUG_ENTER("table_mapping::get_table(ulong)");
- DBUG_PRINT("enter", ("table_id: %lu", table_id));
+ DBUG_PRINT("enter", ("table_id: %llu", table_id));
entry *e= find_entry(table_id);
if (e)
{
- DBUG_PRINT("info", ("tid %lu -> table %p (%s)",
+ DBUG_PRINT("info", ("tid %llu -> table %p (%s)",
table_id, e->table,
MAYBE_TABLE_NAME(e->table)));
DBUG_RETURN(e->table);
}
- DBUG_PRINT("info", ("tid %lu is not mapped!", table_id));
+ DBUG_PRINT("info", ("tid %llu is not mapped!", table_id));
DBUG_RETURN(NULL);
}
@@ -103,11 +103,11 @@ int table_mapping::expand()
return 0;
}
-int table_mapping::set_table(ulong table_id, TABLE* table)
+int table_mapping::set_table(ulonglong table_id, TABLE* table)
{
DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)");
- DBUG_PRINT("enter", ("table_id: %lu table: %p (%s)",
- table_id,
+ DBUG_PRINT("enter", ("table_id: %llu table: %p (%s)",
+ table_id,
table, MAYBE_TABLE_NAME(table)));
entry *e= find_entry(table_id);
if (e == 0)
@@ -134,13 +134,13 @@ int table_mapping::set_table(ulong table_id, TABLE* table)
DBUG_RETURN(ERR_MEMORY_ALLOCATION);
}
- DBUG_PRINT("info", ("tid %lu -> table %p (%s)",
+ DBUG_PRINT("info", ("tid %llu -> table %p (%s)",
table_id, e->table,
MAYBE_TABLE_NAME(e->table)));
DBUG_RETURN(0); // All OK
}
-int table_mapping::remove_table(ulong table_id)
+int table_mapping::remove_table(ulonglong table_id)
{
entry *e= find_entry(table_id);
if (e)
diff --git a/sql/rpl_tblmap.h b/sql/rpl_tblmap.h
index 9fb1c4afbd7..05b298e6053 100644
--- a/sql/rpl_tblmap.h
+++ b/sql/rpl_tblmap.h
@@ -70,10 +70,10 @@ public:
table_mapping();
~table_mapping();
- TABLE* get_table(ulong table_id);
+ TABLE* get_table(ulonglong table_id);
- int set_table(ulong table_id, TABLE* table);
- int remove_table(ulong table_id);
+ int set_table(ulonglong table_id, TABLE* table);
+ int remove_table(ulonglong table_id);
void clear_tables();
ulong count() const { return m_table_ids.records; }
@@ -83,14 +83,14 @@ private:
it, which only works for PODs)
*/
struct entry {
- ulong table_id;
+ ulonglong table_id;
union {
TABLE *table;
entry *next;
};
};
- entry *find_entry(ulong table_id)
+ entry *find_entry(ulonglong table_id)
{
return (entry *) my_hash_search(&m_table_ids,
(uchar*)&table_id,
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index 1fa3cca7c27..97b8e2e4f91 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -110,6 +110,64 @@ static int check_event_type(int type, Relay_log_info *rli)
}
/**
+ Copy fragments into the standard placeholder thd->lex->comment.str.
+
+ Compute the size of the (still) encoded total,
+ allocate and then copy fragments one after another.
+ The size can exceed max(max_allowed_packet) which is not a
+ problem as no String instance is created off this char array.
+
+ @param thd THD handle
+ @return
+ 0 at success,
+ -1 otherwise.
+*/
+int binlog_defragment(THD *thd)
+{
+ user_var_entry *entry[2];
+ LEX_CSTRING name[2]= { thd->lex->comment, thd->lex->ident };
+
+ /* compute the total size */
+ thd->lex->comment.str= NULL;
+ thd->lex->comment.length= 0;
+ for (uint k= 0; k < 2; k++)
+ {
+ entry[k]=
+ (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name[k].str,
+ name[k].length);
+ if (!entry[k] || entry[k]->type != STRING_RESULT)
+ {
+ my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), name[k].str);
+ return -1;
+ }
+ thd->lex->comment.length += entry[k]->length;
+ }
+
+ thd->lex->comment.str= // to be freed by the caller
+ (char *) my_malloc(thd->lex->comment.length, MYF(MY_WME));
+ if (!thd->lex->comment.str)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1);
+ return -1;
+ }
+
+ /* fragments are merged into allocated buf while the user var:s get reset */
+ size_t gathered_length= 0;
+ for (uint k=0; k < 2; k++)
+ {
+ memcpy(const_cast<char*>(thd->lex->comment.str) + gathered_length, entry[k]->value,
+ entry[k]->length);
+ gathered_length += entry[k]->length;
+ update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0);
+ }
+
+ DBUG_ASSERT(gathered_length == thd->lex->comment.length);
+
+ return 0;
+}
+
+
+/**
Execute a BINLOG statement.
To execute the BINLOG command properly the server needs to know
@@ -134,14 +192,6 @@ void mysql_client_binlog_statement(THD* thd)
if (check_global_access(thd, SUPER_ACL))
DBUG_VOID_RETURN;
- size_t coded_len= thd->lex->comment.length;
- if (!coded_len)
- {
- my_error(ER_SYNTAX_ERROR, MYF(0));
- DBUG_VOID_RETURN;
- }
- size_t decoded_len= my_base64_needed_decoded_length((int)coded_len);
-
/*
option_bits will be changed when applying the event. But we don't expect
it be changed permanently after BINLOG statement, so backup it first.
@@ -156,6 +206,8 @@ void mysql_client_binlog_statement(THD* thd)
int err;
Relay_log_info *rli;
rpl_group_info *rgi;
+ char *buf= NULL;
+ size_t coded_len= 0, decoded_len= 0;
rli= thd->rli_fake;
if (!rli && (rli= thd->rli_fake= new Relay_log_info(FALSE)))
@@ -165,13 +217,13 @@ void mysql_client_binlog_statement(THD* thd)
rgi->thd= thd;
const char *error= 0;
- char *buf= (char *) my_malloc(decoded_len, MYF(MY_WME));
Log_event *ev = 0;
+ my_bool is_fragmented= FALSE;
/*
Out of memory check
*/
- if (!(rli && buf))
+ if (!(rli))
{
my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1); /* needed 1 bytes */
goto end;
@@ -179,6 +231,23 @@ void mysql_client_binlog_statement(THD* thd)
DBUG_ASSERT(rli->belongs_to_client());
+ if (unlikely(is_fragmented= thd->lex->comment.str && thd->lex->ident.str))
+ if (binlog_defragment(thd))
+ goto end;
+
+ if (!(coded_len= thd->lex->comment.length))
+ {
+ my_error(ER_SYNTAX_ERROR, MYF(0));
+ goto end;
+ }
+
+ decoded_len= my_base64_needed_decoded_length((int)coded_len);
+ if (!(buf= (char *) my_malloc(decoded_len, MYF(MY_WME))))
+ {
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1);
+ goto end;
+ }
+
for (char const *strptr= thd->lex->comment.str ;
strptr < thd->lex->comment.str + thd->lex->comment.length ; )
{
@@ -317,6 +386,8 @@ void mysql_client_binlog_statement(THD* thd)
my_ok(thd);
end:
+ if (unlikely(is_fragmented))
+ my_free(const_cast<char*>(thd->lex->comment.str));
thd->variables.option_bits= thd_options;
rgi->slave_close_thread_tables(thd);
my_free(buf);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 8c5cadcf5a6..7a623ce6697 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -6726,6 +6726,22 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
+ /**
+ Save a reference to the original read bitmaps
+ We will need this to restore the bitmaps at the end as
+ binlog_prepare_row_images() may change table->read_set.
+ table->read_set is used by pack_row and deep in
+ binlog_prepare_pending_events().
+ */
+ MY_BITMAP *old_read_set= table->read_set;
+
+ /**
+ This will remove spurious fields required during execution but
+ not needed for binlogging. This is done according to the:
+ binlog-row-image option.
+ */
+ binlog_prepare_row_images(table);
+
size_t const before_maxlen= max_row_length(table, table->read_set,
before_record);
size_t const after_maxlen= max_row_length(table, table->rpl_write_set,
@@ -6739,9 +6755,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
uchar *after_row= row_data.slot(1);
size_t const before_size= pack_row(table, table->read_set, before_row,
- before_record);
+ before_record);
size_t const after_size= pack_row(table, table->rpl_write_set, after_row,
- after_record);
+ after_record);
/* Ensure that all events in a GTID group are in the same cache */
if (variables.option_bits & OPTION_GTID_BEGIN)
@@ -6776,6 +6792,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
int error= ev->add_row_data(before_row, before_size) ||
ev->add_row_data(after_row, after_size);
+ /* restore read set for the rest of execution */
+ table->column_bitmaps_set_no_signal(old_read_set,
+ table->write_set);
return error;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 88494f8c169..361340ee235 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4465,7 +4465,7 @@ public:
char buff[MYSQL_ERRMSG_SIZE];
CHARSET_INFO *cs= &my_charset_latin1;
const char *db_name= s ? s->db.str : NULL;
- const char *table_name= s ? s->error_table_name() : NULL;
+ const char *table_name= s ? s->table_name.str : NULL;
if (!db_name)
db_name= "";
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index c4c141900f1..d3f4793fb67 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4131,7 +4131,8 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
inner_join->select_options|= SELECT_DESCRIBE;
}
res= inner_join->optimize();
- sl->update_used_tables();
+ if (!inner_join->cleaned)
+ sl->update_used_tables();
sl->update_correlated_cache();
is_correlated_unit|= sl->is_correlated;
inner_join->select_options= save_options;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ee4baba1134..4af0f919c91 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3038,6 +3038,10 @@ public:
String *wild; /* Wildcard in SHOW {something} LIKE 'wild'*/
sql_exchange *exchange;
select_result *result;
+ /**
+ @c the two may also hold BINLOG arguments: either comment holds a
+ base64-char string or both represent the BINLOG fragment user variables.
+ */
LEX_CSTRING comment, ident;
LEX_USER *grant_user;
XID *xid;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 59f6a45a52f..7fc3bb5926d 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2008, 2017, MariaDB Corporation
+/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2019, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -558,7 +558,7 @@ static my_bool log_in_use_callback(THD *thd, const char *log_name)
my_bool result= 0;
mysql_mutex_lock(&thd->LOCK_thd_data);
if (auto linfo= thd->current_linfo)
- result= !memcmp(log_name, linfo->log_file_name, strlen(log_name) + 1);
+ result= !strcmp(log_name, linfo->log_file_name);
mysql_mutex_unlock(&thd->LOCK_thd_data);
return result;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ef712f76031..de38cbf778d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -17864,7 +17864,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
table->no_rows_with_nulls= param->force_not_null_cols;
table->s= share;
- init_tmp_table_share(thd, share, "", 0, tmpname, tmpname);
+ init_tmp_table_share(thd, share, "", 0, "(temporary)", tmpname);
share->blob_field= blob_field;
share->table_charset= param->table_charset;
share->primary_key= MAX_KEY; // Indicate no primary key
@@ -18718,8 +18718,7 @@ bool Virtual_tmp_table::sp_set_all_fields_from_item(THD *thd, Item *value)
bool open_tmp_table(TABLE *table)
{
int error;
- if (unlikely((error= table->file->ha_open(table, table->s->table_name.str,
- O_RDWR,
+ if (unlikely((error= table->file->ha_open(table, table->s->path.str, O_RDWR,
HA_OPEN_TMP_TABLE |
HA_OPEN_INTERNAL_TABLE))))
{
@@ -18915,7 +18914,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
}
}
- if (unlikely((error= maria_create(share->table_name.str,
+ if (unlikely((error= maria_create(share->path.str,
file_type,
share->keys, &keydef,
(uint) (*recinfo-start_recinfo),
@@ -19070,12 +19069,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
bzero((char*) &create_info,sizeof(create_info));
create_info.data_file_length= table->in_use->variables.tmp_disk_table_size;
- if (unlikely((error= mi_create(share->table_name.str, share->keys, &keydef,
- (uint) (*recinfo-start_recinfo),
+ if (unlikely((error= mi_create(share->path.str, share->keys, &keydef,
+ (uint) (*recinfo-start_recinfo),
start_recinfo,
- share->uniques, &uniquedef,
+ share->uniques, &uniquedef,
&create_info,
- HA_CREATE_TMP_TABLE |
+ HA_CREATE_TMP_TABLE |
HA_CREATE_INTERNAL_TABLE |
((share->db_create_options &
HA_OPTION_PACK_RECORD) ?
@@ -19226,7 +19225,7 @@ err_killed:
(void) table->file->ha_rnd_end();
(void) new_table.file->ha_close();
err1:
- new_table.file->ha_delete_table(new_table.s->table_name.str);
+ new_table.file->ha_delete_table(new_table.s->path.str);
err2:
delete new_table.file;
thd_proc_info(thd, save_proc_info);
@@ -19255,10 +19254,10 @@ free_tmp_table(THD *thd, TABLE *entry)
entry->file->info(HA_STATUS_VARIABLE);
thd->tmp_tables_size+= (entry->file->stats.data_file_length +
entry->file->stats.index_file_length);
- entry->file->ha_drop_table(entry->s->table_name.str);
+ entry->file->ha_drop_table(entry->s->path.str);
}
else
- entry->file->ha_delete_table(entry->s->table_name.str);
+ entry->file->ha_delete_table(entry->s->path.str);
delete entry->file;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4dd9d43a7b9..a3f1f616edd 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5891,7 +5891,8 @@ static bool is_candidate_key(KEY *key)
KEY_PART_INFO *key_part;
KEY_PART_INFO *key_part_end= key->key_part + key->user_defined_key_parts;
- if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY))
+ if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY) ||
+ (key->flags & HA_KEY_HAS_PART_KEY_SEG))
return false;
for (key_part= key->key_part; key_part < key_part_end; key_part++)
@@ -6459,9 +6460,7 @@ static int compare_uint(const uint *s, const uint *t)
@retval false success
*/
-static bool fill_alter_inplace_info(THD *thd,
- TABLE *table,
- bool varchar,
+static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
Alter_inplace_info *ha_alter_info)
{
Field **f_ptr, *field, *old_field;
@@ -6469,7 +6468,6 @@ static bool fill_alter_inplace_info(THD *thd,
Create_field *new_field;
KEY_PART_INFO *key_part, *new_part;
KEY_PART_INFO *end;
- uint candidate_key_count= 0;
Alter_info *alter_info= ha_alter_info->alter_info;
DBUG_ENTER("fill_alter_inplace_info");
DBUG_PRINT("info", ("alter_info->flags: %llu", alter_info->flags));
@@ -6773,8 +6771,13 @@ static bool fill_alter_inplace_info(THD *thd,
Primary key index for the new table
*/
const KEY* const new_pk= (ha_alter_info->key_count > 0 &&
- is_candidate_key(ha_alter_info->key_info_buffer)) ?
+ (!my_strcasecmp(system_charset_info,
+ ha_alter_info->key_info_buffer->name.str,
+ primary_key_name) ||
+ is_candidate_key(ha_alter_info->key_info_buffer))) ?
ha_alter_info->key_info_buffer : NULL;
+ const KEY *const old_pk= table->s->primary_key == MAX_KEY ? NULL :
+ table->key_info + table->s->primary_key;
DBUG_PRINT("info", ("index count old: %d new: %d",
table->s->keys, ha_alter_info->key_count));
@@ -6874,8 +6877,7 @@ static bool fill_alter_inplace_info(THD *thd,
(i) Old table doesn't have primary key, new table has it and vice-versa
(ii) Primary key changed to another existing index
*/
- if ((new_key == new_pk) !=
- ((uint) (table_key - table->key_info) == table->s->primary_key))
+ if ((new_key == new_pk) != (table_key == old_pk))
goto index_changed;
/* Check that key comment is not changed. */
@@ -6937,22 +6939,6 @@ static bool fill_alter_inplace_info(THD *thd,
/* Now let us calculate flags for storage engine API. */
- /* Count all existing candidate keys. */
- for (table_key= table->key_info; table_key < table_key_end; table_key++)
- {
- /*
- Check if key is a candidate key, This key is either already primary key
- or could be promoted to primary key if the original primary key is
- dropped.
- In MySQL one is allowed to create primary key with partial fields (i.e.
- primary key which is not considered candidate). For simplicity we count
- such key as a candidate key here.
- */
- if (((uint) (table_key - table->key_info) == table->s->primary_key) ||
- is_candidate_key(table_key))
- candidate_key_count++;
- }
-
/* Figure out what kind of indexes we are dropping. */
KEY **dropped_key;
KEY **dropped_key_end= ha_alter_info->index_drop_buffer +
@@ -6965,21 +6951,10 @@ static bool fill_alter_inplace_info(THD *thd,
if (table_key->flags & HA_NOSAME)
{
- /*
- Unique key. Check for PRIMARY KEY. Also see comment about primary
- and candidate keys above.
- */
- if ((uint) (table_key - table->key_info) == table->s->primary_key)
- {
+ if (table_key == old_pk)
ha_alter_info->handler_flags|= ALTER_DROP_PK_INDEX;
- candidate_key_count--;
- }
else
- {
ha_alter_info->handler_flags|= ALTER_DROP_UNIQUE_INDEX;
- if (is_candidate_key(table_key))
- candidate_key_count--;
- }
}
else
ha_alter_info->handler_flags|= ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX;
@@ -6992,24 +6967,10 @@ static bool fill_alter_inplace_info(THD *thd,
if (new_key->flags & HA_NOSAME)
{
- bool is_pk= !my_strcasecmp(system_charset_info,
- new_key->name.str, primary_key_name);
-
- if ((!(new_key->flags & HA_KEY_HAS_PART_KEY_SEG) &&
- !(new_key->flags & HA_NULL_PART_KEY)) ||
- is_pk)
- {
- /* Candidate key or primary key! */
- if (candidate_key_count == 0 || is_pk)
- ha_alter_info->handler_flags|= ALTER_ADD_PK_INDEX;
- else
- ha_alter_info->handler_flags|= ALTER_ADD_UNIQUE_INDEX;
- candidate_key_count++;
- }
+ if (new_key == new_pk)
+ ha_alter_info->handler_flags|= ALTER_ADD_PK_INDEX;
else
- {
ha_alter_info->handler_flags|= ALTER_ADD_UNIQUE_INDEX;
- }
}
else
ha_alter_info->handler_flags|= ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX;
@@ -8432,7 +8393,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
if (!drop)
{
- check->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param);
+ if (alter_info->flags & ALTER_RENAME_COLUMN)
+ {
+ check->expr->walk(&Item::rename_fields_processor, 1,
+ &column_rename_param);
+ table->m_needs_reopen= 1; // because new column name is on thd->mem_root
+ }
new_constraint_list.push_back(check, thd->mem_root);
}
}
@@ -9315,6 +9281,64 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
THD_STAGE_INFO(thd, stage_setup);
+ if (alter_info->flags & ALTER_DROP_CHECK_CONSTRAINT)
+ {
+ /*
+ ALTER TABLE DROP CONSTRAINT
+ should be replaced with ... DROP [FOREIGN] KEY
+ if the constraint is the FOREIGN KEY or UNIQUE one.
+ */
+
+ List_iterator<Alter_drop> drop_it(alter_info->drop_list);
+ Alter_drop *drop;
+ List <FOREIGN_KEY_INFO> fk_child_key_list;
+ table->file->get_foreign_key_list(thd, &fk_child_key_list);
+
+ alter_info->flags&= ~ALTER_DROP_CHECK_CONSTRAINT;
+
+ while ((drop= drop_it++))
+ {
+ if (drop->type == Alter_drop::CHECK_CONSTRAINT)
+ {
+ {
+ /* Test if there is a FOREIGN KEY with this name. */
+ FOREIGN_KEY_INFO *f_key;
+ List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
+
+ while ((f_key= fk_key_it++))
+ {
+ if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
+ drop->name) == 0)
+ {
+ drop->type= Alter_drop::FOREIGN_KEY;
+ alter_info->flags|= ALTER_DROP_FOREIGN_KEY;
+ goto do_continue;
+ }
+ }
+ }
+
+ {
+ /* Test if there is an UNIQUE with this name. */
+ uint n_key;
+
+ for (n_key=0; n_key < table->s->keys; n_key++)
+ {
+ if ((table->key_info[n_key].flags & HA_NOSAME) &&
+ my_strcasecmp(system_charset_info,
+ drop->name, table->key_info[n_key].name.str) == 0) // Merge todo: review '.str'
+ {
+ drop->type= Alter_drop::KEY;
+ alter_info->flags|= ALTER_DROP_INDEX;
+ goto do_continue;
+ }
+ }
+ }
+ }
+ alter_info->flags|= ALTER_DROP_CHECK_CONSTRAINT;
+do_continue:;
+ }
+ }
+
handle_if_exists_options(thd, table, alter_info);
/*
@@ -9639,7 +9663,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
thd->create_and_open_tmp_table(new_db_type, &frm,
alter_ctx.get_tmp_path(),
alter_ctx.new_db.str,
- alter_ctx.tmp_name.str,
+ alter_ctx.new_name.str,
false, true)))
goto err_new_table_cleanup;
@@ -9755,7 +9779,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
goto err_new_table_cleanup;
if (ha_create_table(thd, alter_ctx.get_tmp_path(),
- alter_ctx.new_db.str, alter_ctx.tmp_name.str,
+ alter_ctx.new_db.str, alter_ctx.new_name.str,
create_info, &frm))
goto err_new_table_cleanup;
@@ -9763,11 +9787,11 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
no_ha_table= false;
/* Open the table since we need to copy the data. */
- new_table= thd->create_and_open_tmp_table(new_db_type, &frm,
- alter_ctx.get_tmp_path(),
- alter_ctx.new_db.str,
- alter_ctx.tmp_name.str,
- true, true);
+ new_table=
+ thd->create_and_open_tmp_table(new_db_type, &frm, alter_ctx.get_tmp_path(),
+ alter_ctx.new_db.str,
+ alter_ctx.new_name.str,
+ true, true);
if (!new_table)
goto err_new_table_cleanup;
@@ -9827,7 +9851,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
goto err_new_table_cleanup;
}
}
- new_table->s->orig_table_name= table->s->table_name.str;
/*
Note: In case of MERGE table, we do not attach children. We do not
@@ -10687,7 +10710,10 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
{
/* calculating table's checksum */
ha_checksum crc= 0;
- uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
+ DBUG_ASSERT(t->s->last_null_bit_pos < 8);
+ uchar null_mask= (t->s->last_null_bit_pos ?
+ (256 - (1 << t->s->last_null_bit_pos)):
+ 0);
t->use_all_stored_columns();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 00566c463e8..bdc1893637d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2073,6 +2073,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
opt_lock_wait_timeout
opt_delete_gtid_domain
asrow_attribute
+ opt_constraint_no_id
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -6659,6 +6660,11 @@ check_constraint:
}
;
+opt_constraint_no_id:
+ /* Empty */ {}
+ | CONSTRAINT {}
+ ;
+
opt_constraint:
/* empty */ { $$= null_clex_str; }
| constraint { $$= $1; }
@@ -8374,7 +8380,7 @@ alter_list_item:
lex->alter_info.drop_list.push_back(ad, thd->mem_root);
lex->alter_info.flags|= ALTER_DROP_FOREIGN_KEY;
}
- | DROP PRIMARY_SYM KEY_SYM
+ | DROP opt_constraint_no_id PRIMARY_SYM KEY_SYM
{
LEX *lex=Lex;
Alter_drop *ad= (new (thd->mem_root)
@@ -8886,8 +8892,17 @@ binlog_base64_event:
{
Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
Lex->comment= $2;
+ Lex->ident.str= NULL;
+ Lex->ident.length= 0;
}
- ;
+ |
+ BINLOG_SYM '@' ident_or_text ',' '@' ident_or_text
+ {
+ Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
+ Lex->comment= $3;
+ Lex->ident= $6;
+ }
+ ;
check_view_or_table:
table_or_tables table_list opt_mi_check_type
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 025241f8e93..6a6c901c197 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -1580,6 +1580,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
set_assign
sf_tail_standalone
sp_tail_standalone
+ opt_constraint_no_id
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -6597,6 +6598,11 @@ check_constraint:
}
;
+opt_constraint_no_id:
+ /* Empty */ {}
+ | CONSTRAINT {}
+ ;
+
opt_constraint:
/* empty */ { $$= null_clex_str; }
| constraint { $$= $1; }
@@ -8401,7 +8407,7 @@ alter_list_item:
lex->alter_info.drop_list.push_back(ad, thd->mem_root);
lex->alter_info.flags|= ALTER_DROP_FOREIGN_KEY;
}
- | DROP PRIMARY_SYM KEY_SYM
+ | DROP opt_constraint_no_id PRIMARY_SYM KEY_SYM
{
LEX *lex=Lex;
Alter_drop *ad= (new (thd->mem_root)
@@ -8913,8 +8919,17 @@ binlog_base64_event:
{
Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
Lex->comment= $2;
+ Lex->ident.str= NULL;
+ Lex->ident.length= 0;
}
- ;
+ |
+ BINLOG_SYM '@' ident_or_text ',' '@' ident_or_text
+ {
+ Lex->sql_command = SQLCOM_BINLOG_BASE64_EVENT;
+ Lex->comment= $3;
+ Lex->ident= $6;
+ }
+ ;
check_view_or_table:
table_or_tables table_list opt_mi_check_type
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 766e655b20a..64a8b0c17b5 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5484,6 +5484,19 @@ static Sys_var_mybool Sys_wsrep_certify_nonPK(
GLOBAL_VAR(wsrep_certify_nonPK),
CMD_LINE(OPT_ARG), DEFAULT(TRUE));
+static const char *wsrep_certification_rules_names[]= { "strict", "optimized", NullS };
+static Sys_var_enum Sys_wsrep_certification_rules(
+ "wsrep_certification_rules",
+ "Certification rules to use in the cluster. Possible values are: "
+ "\"strict\": stricter rules that could result in more certification "
+ "failures. "
+ "\"optimized\": relaxed rules that allow more concurrency and "
+ "cause less certification failures.",
+ GLOBAL_VAR(wsrep_certification_rules), CMD_LINE(REQUIRED_ARG),
+ wsrep_certification_rules_names, DEFAULT(WSREP_CERTIFICATION_RULES_STRICT),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(0));
+
static Sys_var_mybool Sys_wsrep_causal_reads(
"wsrep_causal_reads", "Setting this variable is equivalent "
"to setting wsrep_sync_wait READ flag",
diff --git a/sql/table.cc b/sql/table.cc
index 7682119c241..75f5a464186 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5450,7 +5450,7 @@ int TABLE::verify_constraints(bool ignore_failure)
field_error.append((*chk)->name.str);
my_error(ER_CONSTRAINT_FAILED,
MYF(ignore_failure ? ME_WARNING : 0), field_error.c_ptr(),
- s->db.str, s->error_table_name());
+ s->db.str, s->table_name.str);
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
}
diff --git a/sql/table.h b/sql/table.h
index 914f4dc15c2..82fefe60e0b 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -646,16 +646,6 @@ struct TABLE_SHARE
LEX_CSTRING normalized_path; /* unpack_filename(path) */
LEX_CSTRING connect_string;
- const char* orig_table_name; /* Original table name for this tmp table */
- const char* error_table_name() const /* Get table name for error messages */
- {
- return tmp_table ? (
- orig_table_name ?
- orig_table_name :
- "(temporary)") :
- table_name.str;
- }
-
/*
Set of keys in use, implemented as a Bitmap.
Excludes keys disabled by ALTER TABLE ... DISABLE KEYS.
@@ -2100,7 +2090,7 @@ struct TABLE_LIST
/* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
List<Index_hint> *index_hints;
TABLE *table; /* opened table */
- ulong table_id; /* table id (from binlog) for opened table */
+ ulonglong table_id; /* table id (from binlog) for opened table */
/*
select_result for derived table to pass it from table creation to table
filling procedure
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 18c2e7072e2..0b31c361abc 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -90,6 +90,7 @@ my_bool wsrep_convert_LOCK_to_trx; // Convert locking sessions to t
my_bool wsrep_auto_increment_control; // Control auto increment variables
my_bool wsrep_drupal_282555_workaround; // Retry autoinc insert after dupkey
my_bool wsrep_certify_nonPK; // Certify, even when no primary key
+ulong wsrep_certification_rules = WSREP_CERTIFICATION_RULES_STRICT;
my_bool wsrep_recovery; // Recovery
my_bool wsrep_replicate_myisam; // Enable MyISAM replication
my_bool wsrep_log_conflicts;
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index dc2793c384d..d12cc835136 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -32,6 +32,7 @@ typedef struct st_mysql_show_var SHOW_VAR;
#include <sql_priv.h>
#include "mdl.h"
#include "sql_table.h"
+#include "wsrep_mysqld_c.h"
#include "wsrep/provider.hpp"
#include "wsrep/streaming_context.hpp"
diff --git a/sql/wsrep_mysqld_c.h b/sql/wsrep_mysqld_c.h
new file mode 100644
index 00000000000..235a871c113
--- /dev/null
+++ b/sql/wsrep_mysqld_c.h
@@ -0,0 +1,30 @@
+/* Copyright 2018-2018 Codership Oy <http://www.codership.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef WSREP_MYSQLD_C_H
+#define WSREP_MYSQLD_C_H
+
+enum enum_wsrep_certification_rules {
+ WSREP_CERTIFICATION_RULES_STRICT,
+ WSREP_CERTIFICATION_RULES_OPTIMIZED
+};
+
+/* This is intentionally declared as a weak global symbol, so that
+the same ha_innodb.so can be used with the embedded server
+(which does not link to the definition of this variable)
+and with the regular server built WITH_WSREP. */
+extern ulong wsrep_certification_rules __attribute__((weak));
+
+#endif /* WSREP_MYSQLD_C_H */