summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc2
-rw-r--r--sql/field.cc9
-rw-r--r--sql/field.h14
-rw-r--r--sql/handler.cc140
-rw-r--r--sql/handler.h16
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_partition.cc5
-rw-r--r--sql/sql_table.cc5
-rw-r--r--sql/sql_view.cc4
-rw-r--r--sql/sql_yacc.yy21
-rw-r--r--sql/sys_vars.cc22
12 files changed, 197 insertions, 53 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 3ad546217a7..36f03e26125 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -421,7 +421,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
DBUG_RETURN(ret);
#ifdef WITH_WSREP
error:
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(true);
#endif /* WITH_WSREP */
}
diff --git a/sql/field.cc b/sql/field.cc
index 5ad1981b752..2a12a80cd70 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4677,6 +4677,15 @@ double Field_double::val_real(void)
}
+longlong Field_double::val_int_from_real(bool want_unsigned_result)
+{
+ Converter_double_to_longlong conv(val_real(), want_unsigned_result);
+ if (!want_unsigned_result && conv.error())
+ conv.push_warning(get_thd(), Field_double::val_real(), false);
+ return conv.result();
+}
+
+
my_decimal *Field_real::val_decimal(my_decimal *decimal_value)
{
ASSERT_COLUMN_MARKED_FOR_READ;
diff --git a/sql/field.h b/sql/field.h
index 7338a8ff679..2bbea486754 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -842,6 +842,10 @@ public:
}
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
+ virtual ulonglong val_uint(void)
+ {
+ return (ulonglong) val_int();
+ }
virtual bool val_bool(void)= 0;
virtual my_decimal *val_decimal(my_decimal *);
inline String *val_str(String *str) { return val_str(str, str); }
@@ -2195,6 +2199,7 @@ private:
class Field_double :public Field_real {
+ longlong val_int_from_real(bool want_unsigned_result);
public:
Field_double(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
@@ -2232,13 +2237,8 @@ public:
int store(longlong nr, bool unsigned_val);
int reset(void) { bzero(ptr,sizeof(double)); return 0; }
double val_real(void);
- longlong val_int(void)
- {
- Converter_double_to_longlong conv(Field_double::val_real(), false);
- if (conv.error())
- conv.push_warning(get_thd(), Field_double::val_real(), false);
- return conv.result();
- }
+ longlong val_int(void) { return val_int_from_real(false); }
+ ulonglong val_uint(void) { return (ulonglong) val_int_from_real(true); }
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const uchar *,const uchar *);
diff --git a/sql/handler.cc b/sql/handler.cc
index 3ea9902e57b..4a40a0256f7 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1993,6 +1993,97 @@ int ha_recover(HASH *commit_list)
}
/**
+ return the XID as it appears in the SQL function's arguments.
+ So this string can be passed to XA START, XA PREPARE etc...
+
+ @note
+ the 'buf' has to have space for at least SQL_XIDSIZE bytes.
+*/
+
+
+/*
+ 'a'..'z' 'A'..'Z', '0'..'9'
+ and '-' '_' ' ' symbols don't have to be
+ converted.
+*/
+
+static const char xid_needs_conv[128]=
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,
+ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
+ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,
+ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1
+};
+
+uint get_sql_xid(XID *xid, char *buf)
+{
+ int tot_len= xid->gtrid_length + xid->bqual_length;
+ int i;
+ const char *orig_buf= buf;
+
+ for (i=0; i<tot_len; i++)
+ {
+ uchar c= ((uchar *) xid->data)[i];
+ if (c >= 128 || xid_needs_conv[c])
+ break;
+ }
+
+ if (i >= tot_len)
+ {
+ /* No need to convert characters to hexadecimals. */
+ *buf++= '\'';
+ memcpy(buf, xid->data, xid->gtrid_length);
+ buf+= xid->gtrid_length;
+ *buf++= '\'';
+ if (xid->bqual_length > 0 || xid->formatID != 1)
+ {
+ *buf++= ',';
+ *buf++= '\'';
+ memcpy(buf, xid->data+xid->gtrid_length, xid->bqual_length);
+ buf+= xid->bqual_length;
+ *buf++= '\'';
+ }
+ }
+ else
+ {
+ *buf++= 'X';
+ *buf++= '\'';
+ for (i= 0; i < xid->gtrid_length; i++)
+ {
+ *buf++=_dig_vec_lower[((uchar*) xid->data)[i] >> 4];
+ *buf++=_dig_vec_lower[((uchar*) xid->data)[i] & 0x0f];
+ }
+ *buf++= '\'';
+ if (xid->bqual_length > 0 || xid->formatID != 1)
+ {
+ *buf++= ',';
+ *buf++= 'X';
+ *buf++= '\'';
+ for (; i < tot_len; i++)
+ {
+ *buf++=_dig_vec_lower[((uchar*) xid->data)[i] >> 4];
+ *buf++=_dig_vec_lower[((uchar*) xid->data)[i] & 0x0f];
+ }
+ *buf++= '\'';
+ }
+ }
+
+ if (xid->formatID != 1)
+ {
+ *buf++= ',';
+ buf+= my_longlong10_to_str_8bit(&my_charset_bin, buf,
+ MY_INT64_NUM_DECIMAL_DIGITS, -10, xid->formatID);
+ }
+
+ return buf - orig_buf;
+}
+
+
+/**
return the list of XID's to a client, the same way SHOW commands do.
@note
@@ -2001,7 +2092,8 @@ int ha_recover(HASH *commit_list)
It can be easily fixed later, if necessary.
*/
-static my_bool xa_recover_callback(XID_STATE *xs, Protocol *protocol)
+static my_bool xa_recover_callback(XID_STATE *xs, Protocol *protocol,
+ char *data, uint data_len, CHARSET_INFO *data_cs)
{
if (xs->xa_state == XA_PREPARED)
{
@@ -2009,8 +2101,7 @@ static my_bool xa_recover_callback(XID_STATE *xs, Protocol *protocol)
protocol->store_longlong((longlong) xs->xid.formatID, FALSE);
protocol->store_longlong((longlong) xs->xid.gtrid_length, FALSE);
protocol->store_longlong((longlong) xs->xid.bqual_length, FALSE);
- protocol->store(xs->xid.data, xs->xid.gtrid_length + xs->xid.bqual_length,
- &my_charset_bin);
+ protocol->store(data, data_len, data_cs);
if (protocol->write())
return TRUE;
}
@@ -2018,11 +2109,28 @@ static my_bool xa_recover_callback(XID_STATE *xs, Protocol *protocol)
}
+static my_bool xa_recover_callback_short(XID_STATE *xs, Protocol *protocol)
+{
+ return xa_recover_callback(xs, protocol, xs->xid.data,
+ xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin);
+}
+
+
+static my_bool xa_recover_callback_verbose(XID_STATE *xs, Protocol *protocol)
+{
+ char buf[SQL_XIDSIZE];
+ uint len= get_sql_xid(&xs->xid, buf);
+ return xa_recover_callback(xs, protocol, buf, len,
+ &my_charset_utf8_general_ci);
+}
+
+
bool mysql_xa_recover(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
MEM_ROOT *mem_root= thd->mem_root;
+ my_hash_walk_action action;
DBUG_ENTER("mysql_xa_recover");
field_list.push_back(new (mem_root)
@@ -2034,16 +2142,32 @@ bool mysql_xa_recover(THD *thd)
field_list.push_back(new (mem_root)
Item_int(thd, "bqual_length", 0,
MY_INT32_NUM_DECIMAL_DIGITS), mem_root);
- field_list.push_back(new (mem_root)
- Item_empty_string(thd, "data",
- XIDDATASIZE), mem_root);
+ {
+ uint len;
+ CHARSET_INFO *cs;
+
+ if (thd->lex->verbose)
+ {
+ len= SQL_XIDSIZE;
+ cs= &my_charset_utf8_general_ci;
+ action= (my_hash_walk_action) xa_recover_callback_verbose;
+ }
+ else
+ {
+ len= XIDDATASIZE;
+ cs= &my_charset_bin;
+ action= (my_hash_walk_action) xa_recover_callback_short;
+ }
+
+ field_list.push_back(new (mem_root)
+ Item_empty_string(thd, "data", len, cs), mem_root);
+ }
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
- if (xid_cache_iterate(thd, (my_hash_walk_action) xa_recover_callback,
- protocol))
+ if (xid_cache_iterate(thd, action, protocol))
DBUG_RETURN(1);
my_eof(thd);
DBUG_RETURN(0);
diff --git a/sql/handler.h b/sql/handler.h
index a176b45d8db..da18a8954de 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -669,6 +669,15 @@ struct xid_t {
};
typedef struct xid_t XID;
+/*
+ The size of XID string representation in the form
+ 'gtrid', 'bqual', formatID
+ see xid_t::get_sql_string() for details.
+*/
+#define SQL_XIDSIZE (XIDDATASIZE * 2 + 8 + MY_INT64_NUM_DECIMAL_DIGITS)
+/* The 'buf' has to have space for at least SQL_XIDSIZE bytes. */
+uint get_sql_xid(XID *xid, char *buf);
+
/* for recover() handlerton call */
#define MIN_XID_LIST_SIZE 128
#define MAX_XID_LIST_SIZE (1024*128)
@@ -1824,6 +1833,13 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st,
used_fields|= (HA_CREATE_USED_CHARSET | HA_CREATE_USED_DEFAULT_CHARSET);
return false;
}
+ ulong table_options_with_row_type()
+ {
+ if (row_type == ROW_TYPE_DYNAMIC || row_type == ROW_TYPE_PAGE)
+ return table_options | HA_OPTION_PACK_RECORD;
+ else
+ return table_options;
+ }
};
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 949e3bd9d17..061e313c494 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6850,8 +6850,8 @@ ER_CANT_SET_GTID_NEXT_WHEN_OWNING_GTID
eng "GTID_NEXT cannot be changed by a client that owns a GTID. The client owns %s. Ownership is released on COMMIT or ROLLBACK"
ER_UNKNOWN_EXPLAIN_FORMAT
- eng "Unknown EXPLAIN format name: '%s'"
- rus "Неизвестное имя формата команды EXPLAIN: '%s'"
+ eng "Unknown %s format name: '%s'"
+ rus "Неизвестное имя формата команды %s: '%s'"
ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION 25006
eng "Cannot execute statement in a READ ONLY transaction"
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 60ab84069b0..2842dbb9a4f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2397,11 +2397,12 @@ com_multi_end:
THD_STAGE_INFO(thd, stage_cleaning_up);
thd->reset_query();
- thd->set_examined_row_count(0); // For processlist
- thd->set_command(COM_SLEEP);
/* Performance Schema Interface instrumentation, end */
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
+ thd->set_examined_row_count(0); // For processlist
+ thd->set_command(COM_SLEEP);
+
thd->m_statement_psi= NULL;
thd->m_digest= NULL;
@@ -5103,6 +5104,9 @@ end_with_restore_list:
{
List<set_var_base> *lex_var_list= &lex->var_list;
+ if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list))
+ goto error;
+
if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
|| open_and_lock_tables(thd, all_tables, TRUE, 0)))
goto error;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index fadd7009822..e47a0e925a6 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -6560,10 +6560,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->part_info= part_info;
lpt->alter_info= alter_info;
lpt->create_info= create_info;
- lpt->db_options= create_info->table_options;
- if (create_info->row_type != ROW_TYPE_FIXED &&
- create_info->row_type != ROW_TYPE_DEFAULT)
- lpt->db_options|= HA_OPTION_PACK_RECORD;
+ lpt->db_options= create_info->table_options_with_row_type();
lpt->table= table;
lpt->key_info_buffer= 0;
lpt->key_count= 0;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5943fe2735a..60f8b5daa8d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4422,10 +4422,7 @@ handler *mysql_create_frm_image(THD *thd,
set_table_default_charset(thd, create_info, (char*) db);
- db_options= create_info->table_options;
- if (create_info->row_type == ROW_TYPE_DYNAMIC ||
- create_info->row_type == ROW_TYPE_PAGE)
- db_options|= HA_OPTION_PACK_RECORD;
+ db_options= create_info->table_options_with_row_type();
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
create_info->db_type)))
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index dd8c6b70446..e1225878905 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -430,14 +430,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
-
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
{
res= TRUE;
goto err;
}
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
/*
ignore lock specs for CREATE statement
*/
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2e51cb6da11..bd1b05c2fd1 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1692,7 +1692,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_default_time_precision
case_stmt_body opt_bin_mod
opt_if_exists_table_element opt_if_not_exists_table_element
- opt_recursive
+ opt_recursive opt_format_xid
%type <object_ddl_options>
create_or_replace
@@ -17134,9 +17134,26 @@ xa:
{
Lex->sql_command = SQLCOM_XA_ROLLBACK;
}
- | XA_SYM RECOVER_SYM
+ | XA_SYM RECOVER_SYM opt_format_xid
{
Lex->sql_command = SQLCOM_XA_RECOVER;
+ Lex->verbose= $3;
+ }
+ ;
+
+opt_format_xid:
+ /* empty */ { $$= false; }
+ | FORMAT_SYM '=' ident_or_text
+ {
+ if (!my_strcasecmp(system_charset_info, $3.str, "SQL"))
+ $$= true;
+ else if (!my_strcasecmp(system_charset_info, $3.str, "RAW"))
+ $$= false;
+ else
+ {
+ my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), "XA RECOVER", $3.str));
+ $$= false;
+ }
}
;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 79cef6a5681..4d971b2c8aa 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -35,6 +35,7 @@
#include "sql_priv.h"
#include "sql_class.h" // set_var.h: THD
#include "sys_vars.ic"
+#include "my_sys.h"
#include "events.h"
#include <thr_alarm.h>
@@ -3739,27 +3740,6 @@ static Sys_var_charptr Sys_version_source_revision(
CMD_LINE_HELP_ONLY,
IN_SYSTEM_CHARSET, DEFAULT(SOURCE_REVISION));
-static char *guess_malloc_library()
-{
- if (strcmp(MALLOC_LIBRARY, "system") == 0)
- {
-#ifdef HAVE_DLOPEN
- typedef int (*mallctl_type)(const char*, void*, size_t*, void*, size_t);
- mallctl_type mallctl_func;
- mallctl_func= (mallctl_type)dlsym(RTLD_DEFAULT, "mallctl");
- if (mallctl_func)
- {
- static char buf[128];
- char *ver;
- size_t len = sizeof(ver);
- mallctl_func("version", &ver, &len, NULL, 0);
- strxnmov(buf, sizeof(buf)-1, "jemalloc ", ver, NULL);
- return buf;
- }
-#endif
- }
- return const_cast<char*>(MALLOC_LIBRARY);
-}
static char *malloc_library;
static Sys_var_charptr Sys_malloc_library(
"version_malloc_library", "Version of the used malloc library",