summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-09-21 10:14:42 +0200
committerSergei Golubchik <sergii@pisem.net>2013-09-21 10:14:42 +0200
commit9af177042ed0e297b8f26f2c2f8ae00b3a814a90 (patch)
tree0d8d2fab7ebeb02f3c25c00ac1543754b625bde8 /sql
parenta6add4ff43a905cee1bfd00b2ec2d276018866ce (diff)
parent2fe0836eed16ce5809c34064893681f12c77da9f (diff)
downloadmariadb-git-9af177042ed0e297b8f26f2c2f8ae00b3a814a90.tar.gz
10.0-base merge.
Partitioning/InnoDB changes are *not* merged (they'll come from 5.6) TokuDB does not compile (not updated to 10.0 SE API)
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt4
-rw-r--r--sql/datadict.cc81
-rw-r--r--sql/debug_sync.cc4
-rw-r--r--sql/field.cc8
-rw-r--r--sql/field.h30
-rw-r--r--sql/handler.cc6
-rw-r--r--sql/handler.h18
-rw-r--r--sql/item.cc26
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_cmpfunc.cc255
-rw-r--r--sql/item_cmpfunc.h57
-rw-r--r--sql/item_func.cc254
-rw-r--r--sql/item_func.h162
-rw-r--r--sql/item_subselect.cc9
-rw-r--r--sql/item_timefunc.cc73
-rw-r--r--sql/item_timefunc.h40
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log.cc56
-rw-r--r--sql/log.h6
-rw-r--r--sql/log_event.cc400
-rw-r--r--sql/log_event.h16
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/opt_range.cc28
-rw-r--r--sql/opt_subselect.cc48
-rw-r--r--sql/opt_subselect.h1
-rw-r--r--sql/opt_table_elimination.cc9
-rw-r--r--sql/records.cc10
-rw-r--r--sql/rpl_gtid.cc151
-rw-r--r--sql/rpl_gtid.h15
-rw-r--r--sql/rpl_rli.cc2
-rw-r--r--sql/rpl_rli.h2
-rw-r--r--sql/rpl_utility.cc4
-rw-r--r--sql/share/errmsg-utf8.txt10
-rw-r--r--sql/signal_handler.cc2
-rw-r--r--sql/slave.cc187
-rw-r--r--sql/sp_head.cc11
-rw-r--r--sql/spatial.cc91
-rw-r--r--sql/spatial.h5
-rw-r--r--sql/sql_acl.cc49
-rw-r--r--sql/sql_audit.cc4
-rw-r--r--sql/sql_audit.h16
-rw-r--r--sql/sql_bitmap.h1
-rw-r--r--sql/sql_cache.cc12
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_cursor.cc2
-rw-r--r--sql/sql_delete.cc45
-rw-r--r--sql/sql_delete.h7
-rw-r--r--sql/sql_lex.cc18
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_load.cc3
-rw-r--r--sql/sql_parse.cc59
-rw-r--r--sql/sql_partition.cc349
-rw-r--r--sql/sql_plugin.cc68
-rw-r--r--sql/sql_plugin_services.h13
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_reload.cc2
-rw-r--r--sql/sql_rename.cc5
-rw-r--r--sql/sql_repl.cc225
-rw-r--r--sql/sql_repl.h2
-rw-r--r--sql/sql_select.cc644
-rw-r--r--sql/sql_select.h10
-rw-r--r--sql/sql_show.cc4
-rw-r--r--sql/sql_show.h2
-rw-r--r--sql/sql_table.cc22
-rw-r--r--sql/sql_table.h4
-rw-r--r--sql/sql_time.cc2
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_yacc.yy949
-rw-r--r--sql/sys_vars.cc120
-rw-r--r--sql/sys_vars.h57
-rw-r--r--sql/table.cc400
-rw-r--r--sql/table.h17
74 files changed, 3519 insertions, 1712 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index d6ebd19fe90..488dd527744 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -109,8 +109,8 @@ ADD_LIBRARY(sql STATIC ${SQL_SOURCE})
ADD_DEPENDENCIES(sql GenServerSource)
DTRACE_INSTRUMENT(sql)
TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS}
- mysys mysys_ssl dbug strings vio regex
- ${LIBWRAP} ${LIBCRYPT} ${LIBDL}
+ mysys mysys_ssl dbug strings vio regex ${LIBJEMALLOC}
+ ${LIBWRAP} ${LIBCRYPT} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT}
${SSL_LIBRARIES})
IF(WIN32)
diff --git a/sql/datadict.cc b/sql/datadict.cc
index 4bc74af7bdb..deeedcd512d 100644
--- a/sql/datadict.cc
+++ b/sql/datadict.cc
@@ -18,6 +18,22 @@
#include "sql_class.h"
#include "sql_table.h"
+static int read_string(File file, uchar**to, size_t length)
+{
+ DBUG_ENTER("read_string");
+
+ my_free(*to);
+ if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) ||
+ mysql_file_read(file, *to, length, MYF(MY_NABP)))
+ {
+ my_free(*to);
+ *to= 0;
+ DBUG_RETURN(1);
+ }
+ *((char*) *to+length)= '\0'; // C-style safety
+ DBUG_RETURN (0);
+}
+
/**
Check type of .frm if we are not going to parse it.
@@ -36,6 +52,7 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
File file;
uchar header[10]; //"TYPE=VIEW\n" it is 10 characters
size_t error;
+ frm_type_enum type= FRMTYPE_ERROR;
DBUG_ENTER("dd_frm_type");
*dbt= DB_TYPE_UNKNOWN;
@@ -43,12 +60,16 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
if ((file= mysql_file_open(key_file_frm, path, O_RDONLY | O_SHARE, MYF(0))) < 0)
DBUG_RETURN(FRMTYPE_ERROR);
error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP));
- mysql_file_close(file, MYF(MY_WME));
if (error)
- DBUG_RETURN(FRMTYPE_ERROR);
+ goto err;
if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header)))
- DBUG_RETURN(FRMTYPE_VIEW);
+ {
+ type= FRMTYPE_VIEW;
+ goto err;
+ }
+
+ type= FRMTYPE_TABLE;
/*
This is just a check for DB_TYPE. We'll return default unknown type
@@ -56,17 +77,57 @@ frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
on return value from this function (default FRMTYPE_TABLE)
*/
if (!is_binary_frm_header(header))
- DBUG_RETURN(FRMTYPE_TABLE);
+ goto err;
- /*
- XXX this is a bug.
- if header[3] is > DB_TYPE_FIRST_DYNAMIC, then the complete
- storage engine name must be read from the frm
- */
*dbt= (enum legacy_db_type) (uint) *(header + 3);
+ if (*dbt >= DB_TYPE_FIRST_DYNAMIC) /* read the true engine name */
+ {
+ MY_STAT state;
+ uchar *frm_image= 0;
+ uint n_length;
+
+ if (mysql_file_fstat(file, &state, MYF(MY_WME)))
+ goto err;
+
+ if (mysql_file_seek(file, 0, SEEK_SET, MYF(MY_WME)))
+ goto err;
+
+ if (read_string(file, &frm_image, state.st_size))
+ goto err;
+
+ if ((n_length= uint4korr(frm_image+55)))
+ {
+ uint record_offset= uint2korr(frm_image+6)+
+ ((uint2korr(frm_image+14) == 0xffff ?
+ uint4korr(frm_image+47) : uint2korr(frm_image+14)));
+ uint reclength= uint2korr(frm_image+16);
+
+ uchar *next_chunk= frm_image + record_offset + reclength;
+ uchar *buff_end= next_chunk + n_length;
+ uint connect_string_length= uint2korr(next_chunk);
+ next_chunk+= connect_string_length + 2;
+ if (next_chunk + 2 < buff_end)
+ {
+ uint str_db_type_length= uint2korr(next_chunk);
+ LEX_STRING name;
+ name.str= (char*) next_chunk + 2;
+ name.length= str_db_type_length;
+ plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);
+ if (tmp_plugin)
+ *dbt= plugin_data(tmp_plugin, handlerton *)->db_type;
+ else
+ *dbt= DB_TYPE_UNKNOWN;
+ }
+ }
+
+ my_free(frm_image);
+ }
+
/* Probably a table. */
- DBUG_RETURN(FRMTYPE_TABLE);
+err:
+ mysql_file_close(file, MYF(MY_WME));
+ DBUG_RETURN(type);
}
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 750f770552e..35b838d7c3d 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2011, Oracle and/or its affiliates.
+/* Copyright (c) 2009, 2013, Oracle and/or its affiliates.
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
@@ -1394,7 +1394,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
if (action->wait_for.length())
{
mysql_mutex_t *old_mutex;
- mysql_cond_t *UNINIT_VAR(old_cond);
+ mysql_cond_t *old_cond= NULL;
int error= 0;
struct timespec abstime;
diff --git a/sql/field.cc b/sql/field.cc
index 81b5a66d908..06744541fcc 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2008, 2013, Monty Program Ab
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2013, Monty Program Ab.
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
@@ -7274,7 +7274,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
{
Field_blob::store_length(length);
- bmove(ptr+packlength,(char*) &from,sizeof(char*));
+ bmove(ptr+packlength, &from, sizeof(char*));
return 0;
}
if (tmpstr.copy(from, length, cs))
@@ -7793,7 +7793,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
value.copy(from, length, cs);
from= value.ptr();
}
- bmove(ptr + packlength, (char*) &from, sizeof(char*));
+ bmove(ptr + packlength, &from, sizeof(char*));
}
return 0;
diff --git a/sql/field.h b/sql/field.h
index e6a3b9c530b..cb8495cee8b 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -126,6 +126,36 @@ inline enum_field_types real_type_to_type(enum_field_types real_type)
}
+static inline enum enum_mysql_timestamp_type
+mysql_type_to_time_type(enum enum_field_types mysql_type)
+{
+ switch(mysql_type) {
+ case MYSQL_TYPE_TIME2:
+ case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME;
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME2:
+ case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
+ case MYSQL_TYPE_NEWDATE:
+ case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
+ default: return MYSQL_TIMESTAMP_ERROR;
+ }
+}
+
+
+/**
+ Tests if field type is temporal, i.e. represents
+ DATE, TIME, DATETIME or TIMESTAMP types in SQL.
+
+ @param type Field type, as returned by field->type().
+ @retval true If field type is temporal
+ @retval false If field type is not temporal
+*/
+inline bool is_temporal_type(enum_field_types type)
+{
+ return mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_ERROR;
+}
+
/*
Virtual_column_info is the class to contain additional
characteristics that is specific for a virtual/computed
diff --git a/sql/handler.cc b/sql/handler.cc
index 38a9fff9921..9fca0a5d133 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -527,6 +527,12 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
{
uint tmp;
ulong fslot;
+
+ DBUG_EXECUTE_IF("unstable_db_type", {
+ static int i= (int) DB_TYPE_FIRST_DYNAMIC;
+ hton->db_type= (enum legacy_db_type)++i;
+ });
+
/* now check the db_type for conflict */
if (hton->db_type <= DB_TYPE_UNKNOWN ||
hton->db_type >= DB_TYPE_DEFAULT ||
diff --git a/sql/handler.h b/sql/handler.h
index c0ff5402e6c..8c787b50127 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -429,7 +429,8 @@ enum legacy_db_type
DB_TYPE_PBXT=23,
DB_TYPE_PERFORMANCE_SCHEMA=28,
DB_TYPE_ARIA=42,
- DB_TYPE_FIRST_DYNAMIC=43,
+ DB_TYPE_TOKUDB=43,
+ DB_TYPE_FIRST_DYNAMIC=44,
DB_TYPE_DEFAULT=127 // Must be last
};
/*
@@ -886,8 +887,8 @@ enum ha_option_type { HA_OPTION_TYPE_ULL, /* unsigned long long */
HA_xOPTION_STRING(name, ha_index_option_struct, field)
#define HA_IOPTION_ENUM(name, field, values, def) \
HA_xOPTION_ENUM(name, ha_index_option_struct, field, values, def)
-#define HA_IOPTION_BOOL(name, field, values, def) \
- HA_xOPTION_BOOL(name, ha_index_option_struct, field, values, def)
+#define HA_IOPTION_BOOL(name, field, def) \
+ HA_xOPTION_BOOL(name, ha_index_option_struct, field, def)
#define HA_IOPTION_SYSVAR(name, field, sysvar) \
HA_xOPTION_SYSVAR(name, ha_index_option_struct, field, sysvar)
#define HA_IOPTION_END HA_xOPTION_END
@@ -1366,6 +1367,7 @@ static inline sys_var *find_hton_sysvar(handlerton *hton, st_mysql_sys_var *var)
Schema which have no meaning for replication.
*/
#define HTON_NO_BINLOG_ROW_OPT (1 << 9)
+#define HTON_EXTENDED_KEYS (1 <<10) //supports extended keys
class Ha_trx_info;
@@ -2547,6 +2549,16 @@ public:
}
/* This is called after index_init() if we need to do a index scan */
virtual int prepare_index_scan() { return 0; }
+ virtual int prepare_index_key_scan_map(const uchar * key, key_part_map keypart_map)
+ {
+ uint key_len= calculate_key_len(table, active_index, key, keypart_map);
+ return prepare_index_key_scan(key, key_len);
+ }
+ virtual int prepare_index_key_scan( const uchar * key, uint key_len )
+ { return 0; }
+ virtual int prepare_range_scan(const key_range *start_key, const key_range *end_key)
+ { return 0; }
+
int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result))
{
DBUG_EXECUTE_IF("ha_rnd_init_fail", return HA_ERR_TABLE_DEF_CHANGED;);
diff --git a/sql/item.cc b/sql/item.cc
index 441470a0df1..b04290f1af0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -297,7 +297,9 @@ String *Item::val_string_from_decimal(String *str)
String *Item::val_string_from_date(String *str)
{
MYSQL_TIME ltime;
- if (get_date(&ltime, sql_mode_for_dates(current_thd)) ||
+ if (get_date(&ltime, field_type() == MYSQL_TYPE_TIME
+ ? TIME_TIME_ONLY
+ : sql_mode_for_dates(current_thd)) ||
str->alloc(MAX_DATE_STRING_REP_LENGTH))
{
null_value= 1;
@@ -555,6 +557,28 @@ uint Item::decimal_precision() const
}
+uint Item::temporal_precision(enum_field_types type)
+{
+ if (const_item() && result_type() == STRING_RESULT &&
+ !is_temporal_type(field_type()))
+ {
+ MYSQL_TIME ltime;
+ String buf, *tmp;
+ MYSQL_TIME_STATUS status;
+ DBUG_ASSERT(fixed);
+ if ((tmp= val_str(&buf)) &&
+ (type == MYSQL_TYPE_TIME ?
+ str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_TIME_ONLY, &status) :
+ str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
+ &ltime, TIME_FUZZY_DATES, &status)) >
+ MYSQL_TIMESTAMP_ERROR)
+ return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
+ }
+ return MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
+}
+
+
void Item::print_item_w_name(String *str, enum_query_type query_type)
{
print(str, query_type);
diff --git a/sql/item.h b/sql/item.h
index e0f2d26ba14..fc8cb58df7a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1022,6 +1022,10 @@ public:
virtual uint decimal_precision() const;
inline int decimal_int_part() const
{ return my_decimal_int_part(decimal_precision(), decimals); }
+ /**
+ TIME or DATETIME precision of the item: 0..6
+ */
+ uint temporal_precision(enum_field_types type);
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 53d33353e65..256cae2e384 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2006,7 +2006,7 @@ void Item_func_interval::fix_length_and_dec()
for (uint i= 1; not_null_consts && i < rows; i++)
{
Item *el= row->element_index(i);
- not_null_consts&= el->const_item() & !el->is_null();
+ not_null_consts&= el->const_item() && !el->is_null();
}
if (not_null_consts &&
@@ -2416,12 +2416,13 @@ void
Item_func_ifnull::fix_length_and_dec()
{
uint32 char_length;
- agg_result_type(&hybrid_type, args, 2);
+ agg_result_type(&cached_result_type, args, 2);
+ cached_field_type= agg_field_type(args, 2);
maybe_null=args[1]->maybe_null;
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
- if (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT)
+ if (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT)
{
int len0= args[0]->max_char_length() - args[0]->decimals
- (args[0]->unsigned_flag ? 0 : 1);
@@ -2434,9 +2435,9 @@ Item_func_ifnull::fix_length_and_dec()
else
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
- switch (hybrid_type) {
+ switch (cached_result_type) {
case STRING_RESULT:
- if (agg_arg_charsets_for_comparison(collation, args, arg_count))
+ if (count_string_result_length(cached_field_type, args, arg_count))
return;
break;
case DECIMAL_RESULT:
@@ -2451,7 +2452,6 @@ Item_func_ifnull::fix_length_and_dec()
DBUG_ASSERT(0);
}
fix_char_length(char_length);
- cached_field_type= agg_field_type(args, 2);
}
@@ -2465,11 +2465,6 @@ uint Item_func_ifnull::decimal_precision() const
}
-enum_field_types Item_func_ifnull::field_type() const
-{
- return cached_field_type;
-}
-
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
{
return tmp_table_field_from_field_type(table, 0);
@@ -2543,6 +2538,18 @@ Item_func_ifnull::str_op(String *str)
}
+bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
+{
+ DBUG_ASSERT(fixed == 1);
+ if (!args[0]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
+ return (null_value= false);
+ if (!args[1]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES))
+ return (null_value= false);
+ bzero((char*) ltime,sizeof(*ltime));
+ return null_value= !(fuzzydate & TIME_FUZZY_DATES);
+}
+
+
/**
Perform context analysis of an IF item tree.
@@ -2637,20 +2644,20 @@ Item_func_if::fix_length_and_dec()
}
agg_result_type(&cached_result_type, args + 1, 2);
+ cached_field_type= agg_field_type(args + 1, 2);
maybe_null= args[1]->maybe_null || args[2]->maybe_null;
decimals= MY_MAX(args[1]->decimals, args[2]->decimals);
unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag;
if (cached_result_type == STRING_RESULT)
{
- if (agg_arg_charsets_for_string_result(collation, args + 1, 2))
- return;
+ count_string_result_length(cached_field_type, args + 1, 2);
+ return;
}
else
{
collation.set_numeric(); // Number
}
- cached_field_type= agg_field_type(args + 1, 2);
uint32 char_length;
if ((cached_result_type == DECIMAL_RESULT )
@@ -2680,7 +2687,7 @@ uint Item_func_if::decimal_precision() const
double
-Item_func_if::val_real()
+Item_func_if::real_op()
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2];
@@ -2690,7 +2697,7 @@ Item_func_if::val_real()
}
longlong
-Item_func_if::val_int()
+Item_func_if::int_op()
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2];
@@ -2700,7 +2707,7 @@ Item_func_if::val_int()
}
String *
-Item_func_if::val_str(String *str)
+Item_func_if::str_op(String *str)
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2];
@@ -2713,7 +2720,7 @@ Item_func_if::val_str(String *str)
my_decimal *
-Item_func_if::val_decimal(my_decimal *decimal_value)
+Item_func_if::decimal_op(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_bool() ? args[1] : args[2];
@@ -2723,6 +2730,14 @@ Item_func_if::val_decimal(my_decimal *decimal_value)
}
+bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate)
+{
+ DBUG_ASSERT(fixed == 1);
+ Item *arg= args[0]->val_bool() ? args[1] : args[2];
+ return (null_value= arg->get_date(ltime, fuzzydate));
+}
+
+
void
Item_func_nullif::fix_length_and_dec()
{
@@ -2881,7 +2896,7 @@ Item *Item_func_case::find_item(String *str)
}
-String *Item_func_case::val_str(String *str)
+String *Item_func_case::str_op(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res;
@@ -2899,7 +2914,7 @@ String *Item_func_case::val_str(String *str)
}
-longlong Item_func_case::val_int()
+longlong Item_func_case::int_op()
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
@@ -2917,7 +2932,7 @@ longlong Item_func_case::val_int()
return res;
}
-double Item_func_case::val_real()
+double Item_func_case::real_op()
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
@@ -2936,7 +2951,7 @@ double Item_func_case::val_real()
}
-my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
+my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
@@ -2956,6 +2971,18 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value)
}
+bool Item_func_case::date_op(MYSQL_TIME *ltime, uint fuzzydate)
+{
+ DBUG_ASSERT(fixed == 1);
+ char buff[MAX_FIELD_WIDTH];
+ String dummy_str(buff, sizeof(buff), default_charset());
+ Item *item= find_item(&dummy_str);
+ if (!item)
+ return (null_value= true);
+ return (null_value= item->get_date(ltime, fuzzydate));
+}
+
+
bool Item_func_case::fix_fields(THD *thd, Item **ref)
{
/*
@@ -3023,7 +3050,10 @@ void Item_func_case::fix_length_and_dec()
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
return;
-
+
+ if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
+ maybe_null= 1;
+
/*
Aggregate all THEN and ELSE expression types
and collations when string result
@@ -3036,9 +3066,11 @@ void Item_func_case::fix_length_and_dec()
agg[nagg++]= args[else_expr_num];
agg_result_type(&cached_result_type, agg, nagg);
+ cached_field_type= agg_field_type(agg, nagg);
+
if (cached_result_type == STRING_RESULT)
{
- if (agg_arg_charsets_for_string_result(collation, agg, nagg))
+ if (count_string_result_length(cached_field_type, agg, nagg))
return;
/*
Copy all THEN and ELSE items back to args[] array.
@@ -3051,11 +3083,22 @@ void Item_func_case::fix_length_and_dec()
change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
}
else
+ {
collation.set_numeric();
+ max_length=0;
+ decimals=0;
+ unsigned_flag= TRUE;
+ for (uint i= 0; i < ncases; i+= 2)
+ agg_num_lengths(args[i + 1]);
+ if (else_expr_num != -1)
+ agg_num_lengths(args[else_expr_num]);
+ max_length= my_decimal_precision_to_length_no_truncation(max_length +
+ decimals, decimals,
+ unsigned_flag);
+ }
- cached_field_type= agg_field_type(agg, nagg);
/*
- Aggregate first expression and all THEN expression types
+ Aggregate first expression and all WHEN expression types
and collations when string comparison
*/
if (first_expr_num != -1)
@@ -3141,30 +3184,6 @@ void Item_func_case::fix_length_and_dec()
args[i]->cmp_context= item_cmp_type(left_result_type,
args[i]->result_type());
}
-
- if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
- maybe_null=1;
-
- max_length=0;
- decimals=0;
- unsigned_flag= TRUE;
- if (cached_result_type == STRING_RESULT)
- {
- for (uint i= 0; i < ncases; i+= 2)
- agg_str_lengths(args[i + 1]);
- if (else_expr_num != -1)
- agg_str_lengths(args[else_expr_num]);
- }
- else
- {
- for (uint i= 0; i < ncases; i+= 2)
- agg_num_lengths(args[i + 1]);
- if (else_expr_num != -1)
- agg_num_lengths(args[else_expr_num]);
- max_length= my_decimal_precision_to_length_no_truncation(max_length +
- decimals, decimals,
- unsigned_flag);
- }
}
@@ -3272,18 +3291,18 @@ double Item_func_coalesce::real_op()
}
-bool Item_func_coalesce::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
+bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
null_value= 0;
for (uint i= 0; i < arg_count; i++)
{
- bool res= args[i]->get_date(ltime, fuzzydate);
+ bool res= args[i]->get_date(ltime, fuzzydate & ~TIME_FUZZY_DATES);
if (!args[i]->null_value)
return res;
}
- null_value=1;
- return 1;
+ bzero((char*) ltime,sizeof(*ltime));
+ return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
}
@@ -3305,21 +3324,11 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec()
{
cached_field_type= agg_field_type(args, arg_count);
- agg_result_type(&hybrid_type, args, arg_count);
- Item_result cmp_type;
- agg_cmp_type(&cmp_type, args, arg_count);
- ///< @todo let result_type() return TIME_RESULT and remove this special case
- if (cmp_type == TIME_RESULT)
- {
- count_real_length();
- return;
- }
- switch (hybrid_type) {
+ agg_result_type(&cached_result_type, args, arg_count);
+ switch (cached_result_type) {
case STRING_RESULT:
- decimals= NOT_FIXED_DEC;
- if (agg_arg_charsets_for_string_result(collation, args, arg_count))
- return;
- count_only_length();
+ if (count_string_result_length(cached_field_type, args, arg_count))
+ return;
break;
case DECIMAL_RESULT:
count_decimal_length();
@@ -3328,7 +3337,7 @@ void Item_func_coalesce::fix_length_and_dec()
count_real_length();
break;
case INT_RESULT:
- count_only_length();
+ count_only_length(args, arg_count);
decimals= 0;
break;
case ROW_RESULT:
@@ -4341,12 +4350,32 @@ Item_cond::fix_fields(THD *thd, Item **ref)
return TRUE; /* purecov: inspected */
used_tables_cache|= item->used_tables();
if (item->const_item())
- and_tables_cache= (table_map) 0;
+ {
+ if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
+ item->val_int() == 0)
+ {
+ /*
+ This is "... OR false_cond OR ..."
+ In this case, false_cond has no effect on cond_or->not_null_tables()
+ */
+ }
+ else
+ {
+ /*
+ This is "... OR const_cond OR ..."
+ In this case, cond_or->not_null_tables()=0, because the condition
+ const_cond might evaluate to true (regardless of whether some tables
+ were NULL-complemented).
+ */
+ and_tables_cache= (table_map) 0;
+ }
+ }
else
{
table_map tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
and_tables_cache&= tmp_table_map;
+
const_item_cache= FALSE;
}
@@ -4374,7 +4403,26 @@ Item_cond::eval_not_null_tables(uchar *opt_arg)
{
table_map tmp_table_map;
if (item->const_item())
- and_tables_cache= (table_map) 0;
+ {
+ if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
+ item->val_int() == 0)
+ {
+ /*
+ This is "... OR false_cond OR ..."
+ In this case, false_cond has no effect on cond_or->not_null_tables()
+ */
+ }
+ else
+ {
+ /*
+ This is "... OR const_cond OR ..."
+ In this case, cond_or->not_null_tables()=0, because the condition
+ some_cond_or might be true regardless of what tables are
+ NULL-complemented.
+ */
+ and_tables_cache= (table_map) 0;
+ }
+ }
else
{
tmp_table_map= item->not_null_tables();
@@ -4752,6 +4800,8 @@ Item *and_expressions(Item *a, Item *b, Item **org_item)
longlong Item_func_isnull::val_int()
{
DBUG_ASSERT(fixed == 1);
+ if (const_item() && !args[0]->maybe_null)
+ return 0;
return args[0]->is_null() ? 1: 0;
}
@@ -4759,6 +4809,8 @@ longlong Item_is_not_null_test::val_int()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_is_not_null_test::val_int");
+ if (const_item() && !args[0]->maybe_null)
+ DBUG_RETURN(1);
if (args[0]->is_null())
{
DBUG_PRINT("info", ("null"));
@@ -5751,10 +5803,12 @@ void Item_equal::merge(Item_equal *item)
@brief
Merge members of another Item_equal object into this one
- @param item multiple equality whose members are to be merged
+ @param item multiple equality whose members are to be merged
+ @param save_merged keep the list of equalities in 'item' intact
+ (e.g. for other merges)
@details
- If the Item_equal 'item' happened to have some elements of the list
+ If the Item_equal 'item' happens to have some elements of the list
of equal items belonging to 'this' object then the function merges
the equal items from 'item' into this list.
If both lists contains constants and they are different then
@@ -5769,24 +5823,45 @@ void Item_equal::merge(Item_equal *item)
The method 'merge' just joins the list of equal items belonging to 'item'
to the list of equal items belonging to this object assuming that the lists
are disjoint. It would be more correct to call the method 'join'.
- The method 'merge_with_check' really merges two lists of equal items if they
- have common members.
+ The method 'merge_into_with_check' really merges two lists of equal items if
+ they have common members.
*/
-bool Item_equal::merge_with_check(Item_equal *item)
+bool Item_equal::merge_with_check(Item_equal *item, bool save_merged)
{
bool intersected= FALSE;
- Item_equal_fields_iterator_slow fi(*this);
+ Item_equal_fields_iterator_slow fi(*item);
+
while (fi++)
{
- if (item->contains(fi.get_curr_field()))
+ if (contains(fi.get_curr_field()))
{
- fi.remove();
intersected= TRUE;
+ if (!save_merged)
+ fi.remove();
}
}
if (intersected)
- item->merge(this);
+ {
+ if (!save_merged)
+ merge(item);
+ else
+ {
+ Item *c= item->get_const();
+ if (c)
+ add_const(c);
+ if (!cond_false)
+ {
+ Item *item;
+ fi.rewind();
+ while ((item= fi++))
+ {
+ if (!contains(fi.get_curr_field()))
+ add(item);
+ }
+ }
+ }
+ }
return intersected;
}
@@ -5795,17 +5870,25 @@ bool Item_equal::merge_with_check(Item_equal *item)
@brief
Merge this object into a list of Item_equal objects
- @param list the list of Item_equal objects to merge into
+ @param list the list of Item_equal objects to merge into
+ @param save_merged keep the list of equalities in 'this' intact
+ (e.g. for other merges)
+ @param only_intersected do not merge if there are no common members
+ in any of Item_equal objects from the list
+ and this Item_equal
@details
If the list of equal items from 'this' object contains common members
with the lists of equal items belonging to Item_equal objects from 'list'
then all involved Item_equal objects e1,...,ek are merged into one
- Item equal that replaces e1,...,ek in the 'list'. Otherwise this
+ Item equal that replaces e1,...,ek in the 'list'. Otherwise, in the case
+ when the value of the parameter only_if_intersected is false, this
Item_equal is joined to the 'list'.
*/
-void Item_equal::merge_into_list(List<Item_equal> *list)
+void Item_equal::merge_into_list(List<Item_equal> *list,
+ bool save_merged,
+ bool only_intersected)
{
Item_equal *item;
List_iterator<Item_equal> it(*list);
@@ -5814,16 +5897,16 @@ void Item_equal::merge_into_list(List<Item_equal> *list)
{
if (!merge_into)
{
- if (merge_with_check(item))
+ if (item->merge_with_check(this, save_merged))
merge_into= item;
}
else
{
- if (item->merge_with_check(merge_into))
+ if (merge_into->merge_with_check(item, false))
it.remove();
}
}
- if (!merge_into)
+ if (!only_intersected && !merge_into)
list->push_back(this);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 47c61215ab5..34c665556d0 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -737,24 +737,19 @@ public:
};
-class Item_func_coalesce :public Item_func_numhybrid
+class Item_func_coalesce :public Item_func_hybrid_field_type
{
-protected:
- enum_field_types cached_field_type;
- Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
public:
- Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
+ Item_func_coalesce(Item *a, Item *b) :Item_func_hybrid_field_type(a, b) {}
+ Item_func_coalesce(List<Item> &list) :Item_func_hybrid_field_type(list) {}
double real_op();
longlong int_op();
String *str_op(String *);
my_decimal *decimal_op(my_decimal *);
+ bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec();
- void find_num_type() {}
- enum Item_result result_type () const { return hybrid_type; }
const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; }
- enum_field_types field_type() const { return cached_field_type; }
- bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
};
@@ -768,7 +763,7 @@ public:
longlong int_op();
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
- enum_field_types field_type() const;
+ bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
void fix_length_and_dec();
void update_used_tables()
{
@@ -781,20 +776,17 @@ public:
};
-class Item_func_if :public Item_func
+class Item_func_if :public Item_func_hybrid_field_type
{
- enum Item_result cached_result_type;
- enum_field_types cached_field_type;
public:
Item_func_if(Item *a,Item *b,Item *c)
- :Item_func(a,b,c), cached_result_type(INT_RESULT)
+ :Item_func_hybrid_field_type(a,b,c)
{}
- double val_real();
- longlong val_int();
- String *val_str(String *str);
- my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return cached_result_type; }
- enum_field_types field_type() const { return cached_field_type; }
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
+ longlong int_op();
+ double real_op();
+ my_decimal *decimal_op(my_decimal *);
+ String *str_op(String *);
bool fix_fields(THD *, Item **);
void fix_length_and_dec();
void update_used_tables()
@@ -1231,21 +1223,20 @@ public:
function and only comparators for there result types are used.
*/
-class Item_func_case :public Item_func
+class Item_func_case :public Item_func_hybrid_field_type
{
int first_expr_num, else_expr_num;
- enum Item_result cached_result_type, left_result_type;
+ enum Item_result left_result_type;
String tmp_value;
uint ncases;
Item_result cmp_type;
DTCollation cmp_collation;
- enum_field_types cached_field_type;
cmp_item *cmp_items[6]; /* For all result types */
cmp_item *case_item;
public:
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
- :Item_func(), first_expr_num(-1), else_expr_num(-1),
- cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0)
+ :Item_func_hybrid_field_type(), first_expr_num(-1), else_expr_num(-1),
+ left_result_type(INT_RESULT), case_item(0)
{
ncases= list.elements;
if (first_expr_arg)
@@ -1261,10 +1252,11 @@ public:
set_arguments(list);
bzero(&cmp_items, sizeof(cmp_items));
}
- double val_real();
- longlong val_int();
- String *val_str(String *);
- my_decimal *val_decimal(my_decimal *);
+ double real_op();
+ longlong int_op();
+ String *str_op(String *);
+ my_decimal *decimal_op(my_decimal *);
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
void update_used_tables()
@@ -1275,8 +1267,6 @@ public:
}
uint decimal_precision() const;
table_map not_null_tables() const { return 0; }
- enum Item_result result_type () const { return cached_result_type; }
- enum_field_types field_type() const { return cached_field_type; }
const char *func_name() const { return "case"; }
virtual void print(String *str, enum_query_type query_type);
Item *find_item(String *str);
@@ -1762,8 +1752,9 @@ public:
/** Get number of field items / references to field items in this object */
uint n_field_items() { return equal_items.elements-test(with_const); }
void merge(Item_equal *item);
- bool merge_with_check(Item_equal *equal_item);
- void merge_into_list(List<Item_equal> *list);
+ bool merge_with_check(Item_equal *equal_item, bool save_merged);
+ void merge_into_list(List<Item_equal> *list, bool save_merged,
+ bool only_intersected);
void update_const();
enum Functype functype() const { return MULT_EQUAL_FUNC; }
longlong val_int();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 69b53871f9f..5af74b0116b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -618,6 +618,30 @@ void Item_func_numhybrid::fix_num_length_and_dec()
{}
+
+/**
+ Count max_length and decimals for temporal functions.
+
+ @param item Argument array
+ @param nitems Number of arguments in the array.
+
+ @retval False on success, true on error.
+*/
+void Item_func::count_datetime_length(Item **item, uint nitems)
+{
+ unsigned_flag= 0;
+ decimals= 0;
+ if (field_type() != MYSQL_TYPE_DATE)
+ {
+ for (uint i= 0; i < nitems; i++)
+ set_if_bigger(decimals, item[i]->decimals);
+ }
+ set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
+ uint len= decimals ? (decimals + 1) : 0;
+ len+= mysql_temporal_int_part_length(field_type());
+ fix_char_length(len);
+}
+
/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
@@ -645,14 +669,14 @@ void Item_func::count_decimal_length()
Set max_length of if it is maximum length of its arguments.
*/
-void Item_func::count_only_length()
+void Item_func::count_only_length(Item **item, uint nitems)
{
uint32 char_length= 0;
unsigned_flag= 0;
- for (uint i=0 ; i < arg_count ; i++)
+ for (uint i= 0; i < nitems ; i++)
{
- set_if_bigger(char_length, args[i]->max_char_length());
- set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
+ set_if_bigger(char_length, item[i]->max_char_length());
+ set_if_bigger(unsigned_flag, item[i]->unsigned_flag);
}
fix_char_length(char_length);
}
@@ -689,6 +713,30 @@ void Item_func::count_real_length()
}
+/**
+ Calculate max_length and decimals for STRING_RESULT functions.
+
+ @param field_type Field type.
+ @param items Argument array.
+ @param nitems Number of arguments.
+
+ @retval False on success, true on error.
+*/
+bool Item_func::count_string_result_length(enum_field_types field_type,
+ Item **items, uint nitems)
+{
+ if (agg_arg_charsets(collation, items, nitems, MY_COLL_ALLOW_CONV, 1))
+ return true;
+ if (is_temporal_type(field_type))
+ count_datetime_length(items, nitems);
+ else
+ {
+ decimals= NOT_FIXED_DEC;
+ count_only_length(items, nitems);
+ }
+ return false;
+}
+
void Item_func::signal_divide_by_null()
{
@@ -761,26 +809,26 @@ void Item_num_op::find_num_type(void)
{
count_real_length();
max_length= float_length(decimals);
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
}
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
r0 == TIME_RESULT || r1 == TIME_RESULT)
{
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
result_precision();
fix_decimals();
}
else
{
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
- hybrid_type=INT_RESULT;
+ cached_result_type=INT_RESULT;
result_precision();
decimals= 0;
}
DBUG_PRINT("info", ("Type: %s",
- (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
- hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- hybrid_type == INT_RESULT ? "INT_RESULT" :
+ (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
+ cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ cached_result_type == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
}
@@ -796,17 +844,17 @@ void Item_func_num1::find_num_type()
{
DBUG_ENTER("Item_func_num1::find_num_type");
DBUG_PRINT("info", ("name %s", func_name()));
- switch (hybrid_type= args[0]->cast_to_int_type()) {
+ switch (cached_result_type= args[0]->cast_to_int_type()) {
case INT_RESULT:
unsigned_flag= args[0]->unsigned_flag;
break;
case STRING_RESULT:
case REAL_RESULT:
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
max_length= float_length(decimals);
break;
case TIME_RESULT:
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
case DECIMAL_RESULT:
break;
case ROW_RESULT:
@@ -814,9 +862,9 @@ void Item_func_num1::find_num_type()
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
- (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
- hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- hybrid_type == INT_RESULT ? "INT_RESULT" :
+ (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
+ cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ cached_result_type == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
}
@@ -836,10 +884,10 @@ void Item_func_numhybrid::fix_length_and_dec()
}
-String *Item_func_numhybrid::val_str(String *str)
+String *Item_func_hybrid_result_type::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- switch (hybrid_type) {
+ switch (cached_result_type) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -867,6 +915,21 @@ String *Item_func_numhybrid::val_str(String *str)
break;
}
case STRING_RESULT:
+ if (is_temporal_type(field_type()))
+ {
+ MYSQL_TIME ltime;
+ if (date_op(&ltime,
+ field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0) ||
+ str->alloc(MAX_DATE_STRING_REP_LENGTH))
+ {
+ null_value= 1;
+ return (String *) 0;
+ }
+ ltime.time_type= mysql_type_to_time_type(field_type());
+ str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
+ str->set_charset(&my_charset_bin);
+ return str;
+ }
return str_op(&str_value);
case TIME_RESULT:
case ROW_RESULT:
@@ -877,10 +940,10 @@ String *Item_func_numhybrid::val_str(String *str)
}
-double Item_func_numhybrid::val_real()
+double Item_func_hybrid_result_type::val_real()
{
DBUG_ASSERT(fixed == 1);
- switch (hybrid_type) {
+ switch (cached_result_type) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -899,6 +962,18 @@ double Item_func_numhybrid::val_real()
return real_op();
case STRING_RESULT:
{
+ if (is_temporal_type(field_type()))
+ {
+ MYSQL_TIME ltime;
+ if (date_op(&ltime,
+ field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0 ))
+ {
+ null_value= 1;
+ return 0;
+ }
+ ltime.time_type= mysql_type_to_time_type(field_type());
+ return TIME_to_double(&ltime);
+ }
char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
@@ -914,10 +989,10 @@ double Item_func_numhybrid::val_real()
}
-longlong Item_func_numhybrid::val_int()
+longlong Item_func_hybrid_result_type::val_int()
{
DBUG_ASSERT(fixed == 1);
- switch (hybrid_type) {
+ switch (cached_result_type) {
case DECIMAL_RESULT:
{
my_decimal decimal_value, *val;
@@ -933,6 +1008,18 @@ longlong Item_func_numhybrid::val_int()
return (longlong) rint(real_op());
case STRING_RESULT:
{
+ if (is_temporal_type(field_type()))
+ {
+ MYSQL_TIME ltime;
+ if (date_op(&ltime,
+ field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0))
+ {
+ null_value= 1;
+ return 0;
+ }
+ ltime.time_type= mysql_type_to_time_type(field_type());
+ return TIME_to_ulonglong(&ltime);
+ }
int err_not_used;
String *res;
if (!(res= str_op(&str_value)))
@@ -951,11 +1038,11 @@ longlong Item_func_numhybrid::val_int()
}
-my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
+my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
{
my_decimal *val= decimal_value;
DBUG_ASSERT(fixed == 1);
- switch (hybrid_type) {
+ switch (cached_result_type) {
case DECIMAL_RESULT:
val= decimal_op(decimal_value);
break;
@@ -973,6 +1060,19 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
}
case STRING_RESULT:
{
+ if (is_temporal_type(field_type()))
+ {
+ MYSQL_TIME ltime;
+ if (date_op(&ltime,
+ field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0))
+ {
+ my_decimal_set_zero(decimal_value);
+ null_value= 1;
+ return 0;
+ }
+ ltime.time_type= mysql_type_to_time_type(field_type());
+ return date2my_decimal(&ltime, decimal_value);
+ }
String *res;
if (!(res= str_op(&str_value)))
return NULL;
@@ -990,6 +1090,63 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
}
+bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime,
+ ulonglong fuzzydate)
+{
+ DBUG_ASSERT(fixed == 1);
+ switch (cached_result_type) {
+ case DECIMAL_RESULT:
+ {
+ my_decimal value, *res;
+ if (!(res= decimal_op(&value)) ||
+ decimal_to_datetime_with_warn(res, ltime, fuzzydate,
+ field_name_or_null()))
+ goto err;
+ break;
+ }
+ case INT_RESULT:
+ {
+ longlong value= int_op();
+ if (null_value || int_to_datetime_with_warn(value, ltime, fuzzydate,
+ field_name_or_null()))
+ goto err;
+ break;
+ }
+ case REAL_RESULT:
+ {
+ double value= real_op();
+ if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
+ field_name_or_null()))
+ goto err;
+ break;
+ }
+ case STRING_RESULT:
+ {
+ if (is_temporal_type(field_type()))
+ return date_op(ltime, fuzzydate);
+ char buff[40];
+ String tmp(buff,sizeof(buff), &my_charset_bin),*res;
+ if (!(res= str_op(&tmp)) ||
+ str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
+ ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
+ goto err;
+ break;
+ break;
+ }
+ case ROW_RESULT:
+ case TIME_RESULT:
+ case IMPOSSIBLE_RESULT:
+ DBUG_ASSERT(0);
+ }
+
+ return (null_value= 0);
+
+err:
+ bzero(ltime, sizeof(*ltime));
+ return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+}
+
+
void Item_func_signed::print(String *str, enum_query_type query_type)
{
str->append(STRING_WITH_LEN("cast("));
@@ -1684,7 +1841,7 @@ void Item_func_div::fix_length_and_dec()
DBUG_ENTER("Item_func_div::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
Item_num_op::fix_length_and_dec();
- switch (hybrid_type) {
+ switch (cached_result_type) {
case REAL_RESULT:
{
decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
@@ -1700,7 +1857,7 @@ void Item_func_div::fix_length_and_dec()
break;
}
case INT_RESULT:
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
result_precision();
break;
@@ -1952,7 +2109,7 @@ void Item_func_neg::fix_length_and_dec()
Use val() to get value as arg_type doesn't mean that item is
Item_int or Item_real due to existence of Item_param.
*/
- if (hybrid_type == INT_RESULT && args[0]->const_item())
+ if (cached_result_type == INT_RESULT && args[0]->const_item())
{
longlong val= args[0]->val_int();
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
@@ -1963,7 +2120,7 @@ void Item_func_neg::fix_length_and_dec()
Ensure that result is converted to DECIMAL, as longlong can't hold
the negated number
*/
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
}
@@ -2267,11 +2424,11 @@ void Item_func_int_val::find_num_type()
{
DBUG_ENTER("Item_func_int_val::find_num_type");
DBUG_PRINT("info", ("name %s", func_name()));
- switch (hybrid_type= args[0]->cast_to_int_type())
+ switch (cached_result_type= args[0]->cast_to_int_type())
{
case STRING_RESULT:
case REAL_RESULT:
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
max_length= float_length(decimals);
break;
case INT_RESULT:
@@ -2284,12 +2441,12 @@ void Item_func_int_val::find_num_type()
if ((args[0]->max_length - args[0]->decimals) >=
(DECIMAL_LONGLONG_DIGITS - 2))
{
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
}
else
{
unsigned_flag= args[0]->unsigned_flag;
- hybrid_type= INT_RESULT;
+ cached_result_type= INT_RESULT;
}
break;
case ROW_RESULT:
@@ -2297,9 +2454,9 @@ void Item_func_int_val::find_num_type()
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s",
- (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
- hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- hybrid_type == INT_RESULT ? "INT_RESULT" :
+ (cached_result_type == REAL_RESULT ? "REAL_RESULT" :
+ cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
+ cached_result_type == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--")));
DBUG_VOID_RETURN;
@@ -2414,10 +2571,10 @@ void Item_func_round::fix_length_and_dec()
if (args[0]->result_type() == DECIMAL_RESULT)
{
max_length++;
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
}
else
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
return;
}
@@ -2435,14 +2592,14 @@ void Item_func_round::fix_length_and_dec()
{
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
max_length= float_length(decimals);
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
return;
}
switch (args[0]->result_type()) {
case REAL_RESULT:
case STRING_RESULT:
- hybrid_type= REAL_RESULT;
+ cached_result_type= REAL_RESULT;
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
max_length= float_length(decimals);
break;
@@ -2452,14 +2609,14 @@ void Item_func_round::fix_length_and_dec()
int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
max_length= args[0]->max_length + length_can_increase;
/* Here we can keep INT_RESULT */
- hybrid_type= INT_RESULT;
+ cached_result_type= INT_RESULT;
decimals= 0;
break;
}
/* fall through */
case DECIMAL_RESULT:
{
- hybrid_type= DECIMAL_RESULT;
+ cached_result_type= DECIMAL_RESULT;
decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
int decimals_delta= args[0]->decimals - decimals_to_set;
int precision= args[0]->decimal_precision();
@@ -2787,6 +2944,13 @@ bool Item_func_min_max::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
ltime->time_type= MYSQL_TIMESTAMP_DATE;
ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
}
+ else if (compare_as_dates->field_type() == MYSQL_TYPE_TIME)
+ {
+ ltime->time_type= MYSQL_TIMESTAMP_TIME;
+ ltime->hour+= (ltime->month * 32 + ltime->day) * 24;
+ ltime->month= ltime->day= 0;
+ }
+
return (null_value= 0);
}
@@ -4063,9 +4227,7 @@ longlong Item_func_get_lock::val_int()
if (!ull_name_ok(res))
DBUG_RETURN(0);
-
- DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
- (long) thd->real_id));
+ DBUG_PRINT("enter", ("lock: %.*s", res->length(), res->ptr()));
/* HASH entries are of type User_level_lock. */
if (! my_hash_inited(&thd->ull_hash) &&
my_hash_init(&thd->ull_hash, &my_charset_bin,
@@ -4086,6 +4248,7 @@ longlong Item_func_get_lock::val_int()
/* Recursive lock */
ull->refs++;
null_value = 0;
+ DBUG_PRINT("info", ("recursive lock, ref-count: %d", (int) ull->refs));
DBUG_RETURN(1);
}
@@ -4142,7 +4305,7 @@ longlong Item_func_release_lock::val_int()
if (!ull_name_ok(res))
DBUG_RETURN(0);
- DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
+ DBUG_PRINT("enter", ("lock: %.*s", res->length(), res->ptr()));
MDL_key ull_key;
ull_key.mdl_key_init(MDL_key::USER_LOCK, res->c_ptr_safe(), "");
@@ -4156,6 +4319,7 @@ longlong Item_func_release_lock::val_int()
null_value= thd->mdl_context.get_lock_owner(&ull_key) == 0;
DBUG_RETURN(0);
}
+ DBUG_PRINT("info", ("ref count: %d", (int) ull->refs));
null_value= 0;
if (--ull->refs == 0)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 68a64fef3cb..8d4b507fe28 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -44,7 +44,14 @@ protected:
String *val_str_from_val_str_ascii(String *str, String *str2);
public:
uint arg_count;
- table_map used_tables_cache, not_null_tables_cache;
+ /*
+ In some cases used_tables_cache is not what used_tables() return
+ so the method should be used where one need used tables bit map
+ (even internally in Item_func_* code).
+ */
+ table_map used_tables_cache;
+ table_map not_null_tables_cache;
+
bool const_item_cache;
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
GE_FUNC,GT_FUNC,FT_FUNC,
@@ -150,13 +157,16 @@ public:
void print_op(String *str, enum_query_type query_type);
void print_args(String *str, uint from, enum_query_type query_type);
virtual void fix_num_length_and_dec();
- void count_only_length();
+ void count_only_length(Item **item, uint nitems);
void count_real_length();
void count_decimal_length();
inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
return (null_value=args[0]->get_date(ltime, fuzzy_date));
}
+ void count_datetime_length(Item **item, uint nitems);
+ bool count_string_result_length(enum_field_types field_type,
+ Item **item, uint nitems);
inline bool get_arg0_time(MYSQL_TIME *ltime)
{
return (null_value=args[0]->get_time(ltime));
@@ -411,38 +421,33 @@ public:
};
-class Item_func_numhybrid: public Item_func
+class Item_func_hybrid_result_type: public Item_func
{
protected:
- Item_result hybrid_type;
+ Item_result cached_result_type;
+
public:
- Item_func_numhybrid() :Item_func(), hybrid_type(REAL_RESULT)
- {}
- Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT)
+ Item_func_hybrid_result_type() :Item_func(), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); }
- Item_func_numhybrid(Item *a,Item *b)
- :Item_func(a,b), hybrid_type(REAL_RESULT)
+ Item_func_hybrid_result_type(Item *a) :Item_func(a), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); }
- Item_func_numhybrid(List<Item> &list)
- :Item_func(list), hybrid_type(REAL_RESULT)
+ Item_func_hybrid_result_type(Item *a,Item *b)
+ :Item_func(a,b), cached_result_type(REAL_RESULT)
+ { collation.set_numeric(); }
+ Item_func_hybrid_result_type(Item *a,Item *b,Item *c)
+ :Item_func(a,b,c), cached_result_type(REAL_RESULT)
+ { collation.set_numeric(); }
+ Item_func_hybrid_result_type(List<Item> &list)
+ :Item_func(list), cached_result_type(REAL_RESULT)
{ collation.set_numeric(); }
- enum Item_result result_type () const { return hybrid_type; }
- void fix_length_and_dec();
- void fix_num_length_and_dec();
- virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
-
- inline void fix_decimals()
- {
- DBUG_ASSERT(result_type() == DECIMAL_RESULT);
- if (decimals == NOT_FIXED_DEC)
- set_if_smaller(decimals, max_length - 1);
- }
+ enum Item_result result_type () const { return cached_result_type; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
String *val_str(String*str);
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
/**
@brief Performs the operation that this functions implements when the
@@ -479,9 +484,75 @@ public:
@return The result of the operation.
*/
virtual String *str_op(String *)= 0;
- bool is_null() { update_null_value(); return null_value; }
+
+ /**
+ @brief Performs the operation that this functions implements when
+ field type is a temporal type.
+ @return The result of the operation.
+ */
+ virtual bool date_op(MYSQL_TIME *res, uint fuzzy_date)= 0;
+
+};
+
+
+
+class Item_func_hybrid_field_type :public Item_func_hybrid_result_type
+{
+protected:
+ enum_field_types cached_field_type;
+public:
+ Item_func_hybrid_field_type()
+ :Item_func_hybrid_result_type(), cached_field_type(MYSQL_TYPE_DOUBLE)
+ {}
+ Item_func_hybrid_field_type(Item *a, Item *b)
+ :Item_func_hybrid_result_type(a, b), cached_field_type(MYSQL_TYPE_DOUBLE)
+ {}
+ Item_func_hybrid_field_type(Item *a, Item *b, Item *c)
+ :Item_func_hybrid_result_type(a, b, c),
+ cached_field_type(MYSQL_TYPE_DOUBLE)
+ {}
+ Item_func_hybrid_field_type(List<Item> &list)
+ :Item_func_hybrid_result_type(list),
+ cached_field_type(MYSQL_TYPE_DOUBLE)
+ {}
+ enum_field_types field_type() const { return cached_field_type; }
+};
+
+
+
+class Item_func_numhybrid: public Item_func_hybrid_result_type
+{
+protected:
+
+ inline void fix_decimals()
+ {
+ DBUG_ASSERT(result_type() == DECIMAL_RESULT);
+ if (decimals == NOT_FIXED_DEC)
+ set_if_smaller(decimals, max_length - 1);
+ }
+
+public:
+ Item_func_numhybrid() :Item_func_hybrid_result_type()
+ { }
+ Item_func_numhybrid(Item *a) :Item_func_hybrid_result_type(a)
+ { }
+ Item_func_numhybrid(Item *a,Item *b)
+ :Item_func_hybrid_result_type(a,b)
+ { }
+ Item_func_numhybrid(Item *a,Item *b,Item *c)
+ :Item_func_hybrid_result_type(a,b,c)
+ { }
+ Item_func_numhybrid(List<Item> &list)
+ :Item_func_hybrid_result_type(list)
+ { }
+ void fix_length_and_dec();
+ void fix_num_length_and_dec();
+ virtual void find_num_type()= 0; /* To be called from fix_length_and_dec */
+ String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
};
+
/* function where type of result detected by first argument */
class Item_func_num1: public Item_func_numhybrid
{
@@ -491,7 +562,6 @@ public:
void fix_num_length_and_dec();
void find_num_type();
- String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
};
@@ -508,7 +578,6 @@ class Item_num_op :public Item_func_numhybrid
}
void find_num_type();
- String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
};
@@ -1270,11 +1339,11 @@ public:
Item_func_sleep(Item *a) :Item_int_func(a) {}
bool const_item() const { return 0; }
const char *func_name() const { return "sleep"; }
- void update_used_tables()
+ table_map used_tables() const
{
- Item_int_func::update_used_tables();
- used_tables_cache|= RAND_TABLE_BIT;
+ return Item_int_func::used_tables() | RAND_TABLE_BIT;
}
+ bool is_expensive() { return 1; }
longlong val_int();
bool check_vcol_func_processor(uchar *int_arg)
{
@@ -1524,6 +1593,12 @@ class Item_func_get_lock :public Item_int_func
longlong val_int();
const char *func_name() const { return "get_lock"; }
void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);}
+ table_map used_tables() const
+ {
+ return Item_int_func::used_tables() | RAND_TABLE_BIT;
+ }
+ bool const_item() const { return 0; }
+ bool is_expensive() { return 1; }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1538,6 +1613,12 @@ public:
longlong val_int();
const char *func_name() const { return "release_lock"; }
void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);}
+ table_map used_tables() const
+ {
+ return Item_int_func::used_tables() | RAND_TABLE_BIT;
+ }
+ bool const_item() const { return 0; }
+ bool is_expensive() { return 1; }
bool check_vcol_func_processor(uchar *int_arg)
{
return trace_unsupported_by_check_vcol_func_processor(func_name());
@@ -1600,15 +1681,14 @@ public:
:Item_func(b), cached_result_type(INT_RESULT),
entry(NULL), entry_thread_id(0), name(a)
{}
- Item_func_set_user_var(Item_func_set_user_var *item)
- :Item_func(item), cached_result_type(item->cached_result_type),
- entry(item->entry), entry_thread_id(item->entry_thread_id),
- value(item->value), decimal_buff(item->decimal_buff),
- null_item(item->null_item), save_result(item->save_result),
- name(item->name)
- {
- //fixed= 1;
- }
+ Item_func_set_user_var(THD *thd, Item_func_set_user_var *item)
+ :Item_func(thd, item), cached_result_type(item->cached_result_type),
+ entry(item->entry), entry_thread_id(item->entry_thread_id),
+ value(item->value), decimal_buff(item->decimal_buff),
+ null_item(item->null_item), save_result(item->save_result),
+ name(item->name)
+ {}
+
enum Functype functype() const { return SUSERVAR_FUNC; }
double val_real();
longlong val_int();
@@ -1630,6 +1710,12 @@ public:
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
+ table_map used_tables() const
+ {
+ return Item_func::used_tables() | RAND_TABLE_BIT;
+ }
+ bool const_item() const { return 0; }
+ bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
void print_as_stmt(String *str, enum_query_type query_type);
const char *func_name() const { return "set_user_var"; }
@@ -1749,6 +1835,8 @@ public:
double val_real();
longlong val_int();
String* val_str(String*);
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ { return val_decimal_from_real(dec_buf); }
/* TODO: fix to support views */
const char *func_name() const { return "get_system_var"; }
/**
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 87fa8147411..2bdcf919131 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1752,6 +1752,15 @@ Item_in_subselect::single_value_transformer(JOIN *join)
*/
where_item->walk(&Item::remove_dependence_processor, 0,
(uchar *) select_lex->outer_select());
+ /*
+ fix_field of substitution item will be done in time of
+ substituting.
+ Note that real_item() should be used instead of
+ original left expression because left_expr can be
+ runtime created Ref item which is deleted at the end
+ of the statement. Thus one of 'substitution' arguments
+ can be broken in case of PS.
+ */
substitution= func->create(left_expr, where_item);
have_to_be_excluded= 1;
if (thd->lex->describe)
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 483620bd2fa..bb7d28d1e18 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1290,7 +1290,19 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
String str_value(buf, sizeof(buf), &my_charset_bin);
bzero((char*) interval,sizeof(*interval));
- if ((int) int_type <= INTERVAL_MICROSECOND)
+ if (int_type == INTERVAL_SECOND && args->decimals)
+ {
+ my_decimal decimal_value, *val;
+ ulonglong second;
+ ulong second_part;
+ if (!(val= args->val_decimal(&decimal_value)))
+ return true;
+ interval->neg= my_decimal2seconds(val, &second, &second_part);
+ interval->second= second;
+ interval->second_part= second_part;
+ return false;
+ }
+ else if ((int) int_type <= INTERVAL_MICROSECOND)
{
value= args->val_int();
if (args->null_value)
@@ -1435,11 +1447,11 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval)
void Item_temporal_func::fix_length_and_dec()
{
- static const uint max_time_type_width[5]=
- { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
- MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
- uint char_length= max_time_type_width[mysql_type_to_time_type(field_type())+2];
-
+ uint char_length= mysql_temporal_int_part_length(field_type());
+ /*
+ We set maybe_null to 1 as default as any bad argument with date or
+ time can get us to return NULL.
+ */
set_persist_maybe_null(1);
if (decimals)
{
@@ -1949,7 +1961,7 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime,
void Item_func_convert_tz::fix_length_and_dec()
{
- decimals= args[0]->decimals;
+ decimals= args[0]->temporal_precision(MYSQL_TYPE_DATETIME);
Item_temporal_func::fix_length_and_dec();
}
@@ -2020,28 +2032,40 @@ void Item_date_add_interval::fix_length_and_dec()
*/
cached_field_type= MYSQL_TYPE_STRING;
arg0_field_type= args[0]->field_type();
+ uint interval_dec= 0;
+ if (int_type == INTERVAL_MICROSECOND ||
+ (int_type >= INTERVAL_DAY_MICROSECOND &&
+ int_type <= INTERVAL_SECOND_MICROSECOND))
+ interval_dec= TIME_SECOND_PART_DIGITS;
+ else if (int_type == INTERVAL_SECOND && args[1]->decimals > 0)
+ interval_dec= MY_MIN(args[1]->decimals, TIME_SECOND_PART_DIGITS);
+
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ {
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
cached_field_type= MYSQL_TYPE_DATETIME;
+ }
else if (arg0_field_type == MYSQL_TYPE_DATE)
{
if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH)
cached_field_type= arg0_field_type;
else
+ {
+ decimals= interval_dec;
cached_field_type= MYSQL_TYPE_DATETIME;
+ }
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
cached_field_type= arg0_field_type;
else
cached_field_type= MYSQL_TYPE_DATETIME;
}
- if (int_type == INTERVAL_MICROSECOND || int_type >= INTERVAL_DAY_MICROSECOND)
- decimals= 6;
else
- decimals= args[0]->decimals;
-
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
Item_temporal_func::fix_length_and_dec();
}
@@ -2052,7 +2076,9 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
INTERVAL interval;
- if (args[0]->get_date(ltime, 0) ||
+ if (args[0]->get_date(ltime,
+ cached_field_type == MYSQL_TYPE_TIME ?
+ TIME_TIME_ONLY : 0) ||
get_interval_value(args[1], int_type, &interval))
return (null_value=1);
@@ -2443,7 +2469,9 @@ bool Item_time_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
if (ltime->time_type != MYSQL_TIMESTAMP_TIME)
ltime->year= ltime->month= ltime->day= 0;
ltime->time_type= MYSQL_TIMESTAMP_TIME;
- return 0;
+ return (fuzzy_date & TIME_TIME_ONLY) ? 0 :
+ (null_value= check_date_with_warn(ltime, fuzzy_date,
+ MYSQL_TIMESTAMP_ERROR));
}
@@ -2551,10 +2579,19 @@ void Item_func_add_time::fix_length_and_dec()
arg0_field_type= args[0]->field_type();
if (arg0_field_type == MYSQL_TYPE_DATE ||
arg0_field_type == MYSQL_TYPE_DATETIME ||
- arg0_field_type == MYSQL_TYPE_TIMESTAMP)
+ arg0_field_type == MYSQL_TYPE_TIMESTAMP ||
+ is_date)
+ {
cached_field_type= MYSQL_TYPE_DATETIME;
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME),
+ args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ }
else if (arg0_field_type == MYSQL_TYPE_TIME)
+ {
cached_field_type= MYSQL_TYPE_TIME;
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
+ args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ }
Item_temporal_func::fix_length_and_dec();
}
@@ -2735,13 +2772,14 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{
DBUG_ASSERT(fixed == 1);
bool overflow= 0;
-
longlong hour= args[0]->val_int();
longlong minute= args[1]->val_int();
- longlong second= args[2]->val_int();
+ ulonglong second;
+ ulong microsecond;
+ bool neg= args[2]->get_seconds(&second, &microsecond);
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
- minute < 0 || minute > 59 || second < 0 || second > 59)
+ minute < 0 || minute > 59 || neg || second > 59)
return (null_value= 1);
bzero(ltime, sizeof(*ltime));
@@ -2763,6 +2801,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
ltime->hour= (uint) ((hour < 0 ? -hour : hour));
ltime->minute= (uint) minute;
ltime->second= (uint) second;
+ ltime->second_part= microsecond;
}
else
{
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 029e3b17cf1..dc3e368be8d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -30,19 +30,17 @@ enum date_time_format_types
TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND
};
-static inline enum enum_mysql_timestamp_type
-mysql_type_to_time_type(enum enum_field_types mysql_type)
+
+static inline uint
+mysql_temporal_int_part_length(enum enum_field_types mysql_type)
{
- switch(mysql_type) {
- case MYSQL_TYPE_TIME: return MYSQL_TIMESTAMP_TIME;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME: return MYSQL_TIMESTAMP_DATETIME;
- case MYSQL_TYPE_NEWDATE:
- case MYSQL_TYPE_DATE: return MYSQL_TIMESTAMP_DATE;
- default: return MYSQL_TIMESTAMP_ERROR;
- }
+ static uint max_time_type_width[5]=
+ { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
+ MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
+ return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
}
+
bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
class Item_func_period_add :public Item_int_func
@@ -410,26 +408,32 @@ class Item_func_dayname :public Item_func_weekday
class Item_func_seconds_hybrid: public Item_func_numhybrid
{
+protected:
+ virtual enum_field_types arg0_expected_type() const = 0;
public:
Item_func_seconds_hybrid() :Item_func_numhybrid() {}
Item_func_seconds_hybrid(Item *a) :Item_func_numhybrid(a) {}
void fix_num_length_and_dec()
{
if (arg_count)
- decimals= args[0]->decimals;
+ decimals= args[0]->temporal_precision(arg0_expected_type());
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
max_length=17 + (decimals ? decimals + 1 : 0);
set_persist_maybe_null(1);
}
- void find_num_type() { hybrid_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
+ void find_num_type()
+ { cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT; }
double real_op() { DBUG_ASSERT(0); return 0; }
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
+ bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
};
class Item_func_unix_timestamp :public Item_func_seconds_hybrid
{
bool get_timestamp_value(my_time_t *seconds, ulong *second_part);
+protected:
+ enum_field_types arg0_expected_type() const { return MYSQL_TYPE_DATETIME; }
public:
Item_func_unix_timestamp() :Item_func_seconds_hybrid() {}
Item_func_unix_timestamp(Item *a) :Item_func_seconds_hybrid(a) {}
@@ -461,6 +465,8 @@ public:
class Item_func_time_to_sec :public Item_func_seconds_hybrid
{
+protected:
+ enum_field_types arg0_expected_type() const { return MYSQL_TYPE_TIME; }
public:
Item_func_time_to_sec(Item *item) :Item_func_seconds_hybrid(item) {}
const char *func_name() const { return "time_to_sec"; }
@@ -896,7 +902,7 @@ public:
void fix_length_and_dec()
{
if (decimals == NOT_FIXED_DEC)
- decimals= args[0]->decimals;
+ decimals= args[0]->temporal_precision(field_type());
Item_temporal_func::fix_length_and_dec();
}
};
@@ -968,7 +974,8 @@ public:
const char *func_name() const { return "timediff"; }
void fix_length_and_dec()
{
- decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
+ decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
+ args[1]->temporal_precision(MYSQL_TYPE_TIME));
Item_timefunc::fix_length_and_dec();
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
@@ -980,6 +987,11 @@ public:
Item_func_maketime(Item *a, Item *b, Item *c)
:Item_timefunc(a, b, c)
{}
+ void fix_length_and_dec()
+ {
+ decimals= MY_MIN(args[2]->decimals, TIME_SECOND_PART_DIGITS);
+ Item_timefunc::fix_length_and_dec();
+ }
const char *func_name() const { return "maketime"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
};
diff --git a/sql/lex.h b/sql/lex.h
index c5229beb653..470d55876f7 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -266,6 +266,7 @@ static SYMBOL symbols[] = {
{ "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM)},
{ "HOUR_MINUTE", SYM(HOUR_MINUTE_SYM)},
{ "HOUR_SECOND", SYM(HOUR_SECOND_SYM)},
+ { "ID", SYM(ID_SYM)},
{ "IDENTIFIED", SYM(IDENTIFIED_SYM)},
{ "IF", SYM(IF)},
{ "IGNORE", SYM(IGNORE_SYM)},
@@ -491,6 +492,7 @@ static SYMBOL symbols[] = {
{ "RESUME", SYM(RESUME_SYM)},
{ "RETURNED_SQLSTATE",SYM(RETURNED_SQLSTATE_SYM)},
{ "RETURN", SYM(RETURN_SYM)},
+ { "RETURNING", SYM(RETURNING_SYM)},
{ "RETURNS", SYM(RETURNS_SYM)},
{ "REVOKE", SYM(REVOKE)},
{ "RIGHT", SYM(RIGHT)},
diff --git a/sql/log.cc b/sql/log.cc
index 1295dc087fd..94e5c45f135 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3719,7 +3719,8 @@ err:
1 error
*/
-bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
+bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log,
+ rpl_gtid *init_state, uint32 init_state_len)
{
LOG_INFO linfo;
bool error=0;
@@ -3738,6 +3739,14 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
if (!is_relay_log)
{
+ if (init_state && !is_empty_state())
+ {
+ my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
+ mysql_mutex_unlock(&LOCK_index);
+ mysql_mutex_unlock(&LOCK_log);
+ DBUG_RETURN(1);
+ }
+
/*
Mark that a RESET MASTER is in progress.
This ensures that a binlog checkpoint will not try to write binlog
@@ -3855,7 +3864,10 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log)
if (!is_relay_log)
{
- rpl_global_gtid_binlog_state.reset();
+ if (init_state)
+ rpl_global_gtid_binlog_state.load(init_state, init_state_len);
+ else
+ rpl_global_gtid_binlog_state.reset();
}
/* Start logging with a new file */
@@ -4810,12 +4822,23 @@ end:
}
-bool MYSQL_BIN_LOG::append(Log_event* ev)
+bool
+MYSQL_BIN_LOG::append(Log_event *ev)
{
- bool error = 0;
+ bool res;
mysql_mutex_lock(&LOCK_log);
+ res= append_no_lock(ev);
+ mysql_mutex_unlock(&LOCK_log);
+ return res;
+}
+
+
+bool MYSQL_BIN_LOG::append_no_lock(Log_event* ev)
+{
+ bool error = 0;
DBUG_ENTER("MYSQL_BIN_LOG::append");
+ mysql_mutex_assert_owner(&LOCK_log);
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
/*
Log_event::write() is smart enough to use my_b_write() or
@@ -4833,7 +4856,6 @@ bool MYSQL_BIN_LOG::append(Log_event* ev)
if (my_b_append_tell(&log_file) > max_size)
error= new_file_without_locking();
err:
- mysql_mutex_unlock(&LOCK_log);
signal_update(); // Safe as we don't call close
DBUG_RETURN(error);
}
@@ -5541,6 +5563,30 @@ MYSQL_BIN_LOG::append_state_pos(String *str)
bool
+MYSQL_BIN_LOG::append_state(String *str)
+{
+ bool err;
+
+ mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ err= rpl_global_gtid_binlog_state.append_state(str);
+ mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ return err;
+}
+
+
+bool
+MYSQL_BIN_LOG::is_empty_state()
+{
+ bool res;
+
+ mysql_mutex_lock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ res= (rpl_global_gtid_binlog_state.count() == 0);
+ mysql_mutex_unlock(&rpl_global_gtid_binlog_state.LOCK_binlog_state);
+ return res;
+}
+
+
+bool
MYSQL_BIN_LOG::find_in_binlog_state(uint32 domain_id, uint32 server_id,
rpl_gtid *out_gtid)
{
diff --git a/sql/log.h b/sql/log.h
index 018ac64eff7..051ee8ea068 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -712,6 +712,7 @@ public:
*/
bool appendv(const char* buf,uint len,...);
bool append(Log_event* ev);
+ bool append_no_lock(Log_event* ev);
void mark_xids_active(ulong cookie, uint xid_count);
void mark_xid_done(ulong cookie, bool write_checkpoint);
@@ -751,7 +752,8 @@ public:
int register_create_index_entry(const char* entry);
int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
bool need_mutex);
- bool reset_logs(THD* thd, bool create_new_log);
+ bool reset_logs(THD* thd, bool create_new_log,
+ rpl_gtid *init_state, uint32 init_state_len);
void close(uint exiting);
void clear_inuse_flag_when_closing(File file);
@@ -780,6 +782,8 @@ public:
int write_state_to_file();
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
bool append_state_pos(String *str);
+ bool append_state(String *str);
+ bool is_empty_state();
bool find_in_binlog_state(uint32 domain_id, uint32 server_id,
rpl_gtid *out_gtid);
bool lookup_domain_in_binlog_state(uint32 domain_id, rpl_gtid *out_gtid);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b1fe6a8cf64..5094e47219f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1750,6 +1750,165 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
#ifdef MYSQL_CLIENT
+static void hexdump_minimal_header_to_io_cache(IO_CACHE *file,
+ my_off_t offset,
+ uchar *ptr)
+{
+ DBUG_ASSERT(LOG_EVENT_MINIMAL_HEADER_LEN == 19);
+
+ /*
+ Pretty-print the first LOG_EVENT_MINIMAL_HEADER_LEN (19) bytes of the
+ common header, which contains the basic information about the log event.
+ Every event will have at least this much header, but events could contain
+ more headers (which must be printed by other methods, if desired).
+ */
+ char emit_buf[120]; // Enough for storing one line
+ my_b_printf(file,
+ "# "
+ "|Timestamp "
+ "|Type "
+ "|Master ID "
+ "|Size "
+ "|Master Pos "
+ "|Flags\n");
+ size_t const emit_buf_written=
+ my_snprintf(emit_buf, sizeof(emit_buf),
+ "# %8llx " /* Position */
+ "|%02x %02x %02x %02x " /* Timestamp */
+ "|%02x " /* Type */
+ "|%02x %02x %02x %02x " /* Master ID */
+ "|%02x %02x %02x %02x " /* Size */
+ "|%02x %02x %02x %02x " /* Master Pos */
+ "|%02x %02x\n", /* Flags */
+ (ulonglong) offset, /* Position */
+ ptr[0], ptr[1], ptr[2], ptr[3], /* Timestamp */
+ ptr[4], /* Type */
+ ptr[5], ptr[6], ptr[7], ptr[8], /* Master ID */
+ ptr[9], ptr[10], ptr[11], ptr[12], /* Size */
+ ptr[13], ptr[14], ptr[15], ptr[16], /* Master Pos */
+ ptr[17], ptr[18]); /* Flags */
+
+ DBUG_ASSERT(static_cast<size_t>(emit_buf_written) < sizeof(emit_buf));
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buf), emit_buf_written);
+ my_b_write(file, "#\n", 2);
+}
+
+
+/*
+ The number of bytes to print per line. Should be an even number,
+ and "hexdump -C" uses 16, so we'll duplicate that here.
+*/
+#define HEXDUMP_BYTES_PER_LINE 16
+
+static void format_hex_line(char *emit_buff)
+{
+ memset(emit_buff + 1, ' ',
+ 1 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE);
+ emit_buff[0]= '#';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 1]= '|';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE]= '|';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 1]= '\n';
+ emit_buff[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 2]= '\0';
+}
+
+static void hexdump_data_to_io_cache(IO_CACHE *file,
+ my_off_t offset,
+ uchar *ptr,
+ my_off_t size)
+{
+ /*
+ 2 = '# '
+ 8 = address
+ 2 = ' '
+ (HEXDUMP_BYTES_PER_LINE * 3 + 1) = Each byte prints as two hex digits,
+ plus a space
+ 2 = ' |'
+ HEXDUMP_BYTES_PER_LINE = text representation
+ 2 = '|\n'
+ 1 = '\0'
+ */
+ char emit_buffer[2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2 +
+ HEXDUMP_BYTES_PER_LINE + 2 + 1 ];
+ char *h,*c;
+ my_off_t i;
+
+ if (size == 0)
+ return;
+
+ format_hex_line(emit_buffer);
+ /*
+ Print the rest of the event (without common header)
+ */
+ my_off_t starting_offset = offset;
+ for (i= 0,
+ c= emit_buffer + 2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2,
+ h= emit_buffer + 2 + 8 + 2;
+ i < size;
+ i++, ptr++)
+ {
+ my_snprintf(h, 4, "%02x ", *ptr);
+ h+= 3;
+
+ *c++= my_isprint(&my_charset_bin, *ptr) ? *ptr : '.';
+
+ /* Print in groups of HEXDUMP_BYTES_PER_LINE characters. */
+ if ((i % HEXDUMP_BYTES_PER_LINE) == (HEXDUMP_BYTES_PER_LINE - 1))
+ {
+ /* remove \0 left after printing hex byte representation */
+ *h= ' ';
+ /* prepare space to print address */
+ memset(emit_buffer + 2, ' ', 8);
+ /* print address */
+ size_t const emit_buf_written= my_snprintf(emit_buffer + 2, 9, "%8llx",
+ (ulonglong) starting_offset);
+ /* remove \0 left after printing address */
+ emit_buffer[2 + emit_buf_written]= ' ';
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buffer),
+ sizeof(emit_buffer) - 1);
+ c= emit_buffer + 2 + 8 + 2 + (HEXDUMP_BYTES_PER_LINE * 3 + 1) + 2;
+ h= emit_buffer + 2 + 8 + 2;
+ format_hex_line(emit_buffer);
+ starting_offset+= HEXDUMP_BYTES_PER_LINE;
+ }
+ else if ((i % (HEXDUMP_BYTES_PER_LINE / 2))
+ == ((HEXDUMP_BYTES_PER_LINE / 2) - 1))
+ {
+ /*
+ In the middle of the group of HEXDUMP_BYTES_PER_LINE, emit an extra
+ space in the hex string, to make two groups.
+ */
+ *h++= ' ';
+ }
+
+ }
+
+ /*
+ There is still data left in our buffer, which means that the previous
+ line was not perfectly HEXDUMP_BYTES_PER_LINE characters, so write an
+ incomplete line, with spaces to pad out to the same length as a full
+ line would be, to make things more readable.
+ */
+ if (h != emit_buffer + 2 + 8 + 2)
+ {
+ *h= ' ';
+ *c++= '|'; *c++= '\n';
+ memset(emit_buffer + 2, ' ', 8);
+ size_t const emit_buf_written= my_snprintf(emit_buffer + 2, 9, "%8llx",
+ (ulonglong) starting_offset);
+ emit_buffer[2 + emit_buf_written]= ' ';
+ /* pad unprinted area */
+ memset(h, ' ',
+ (HEXDUMP_BYTES_PER_LINE * 3 + 1) - (h - (emit_buffer + 2 + 8 + 2)));
+ my_b_write(file, reinterpret_cast<uchar*>(emit_buffer),
+ c - emit_buffer);
+ }
+ my_b_write(file, "#\n", 2);
+}
+
/*
Log_event::print_header()
*/
@@ -1784,86 +1943,27 @@ void Log_event::print_header(IO_CACHE* file,
{
my_b_write_byte(file, '\n');
uchar *ptr= (uchar*)temp_buf;
- my_off_t size=
- uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
- my_off_t i;
-
- /* Header len * 4 >= header len * (2 chars + space + extra space) */
- char *h, hex_string[LOG_EVENT_MINIMAL_HEADER_LEN*4]= {0};
- char *c, char_string[16+1]= {0};
-
- /* Pretty-print event common header if header is exactly 19 bytes */
- if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
- {
- char emit_buf[256]; // Enough for storing one line
- my_b_printf(file, "# Position Timestamp Type Master ID "
- "Size Master Pos Flags \n");
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x\n",
- (unsigned long) hexdump_from,
- ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
- ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
- ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
- hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
- }
-
- /* Rest of event (without common header) */
- for (i= 0, c= char_string, h=hex_string;
- i < size;
- i++, ptr++)
- {
- my_snprintf(h, 4, "%02x ", *ptr);
- h += 3;
-
- *c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
-
- if (i % 16 == 15)
- {
- /*
- my_b_printf() does not support full printf() formats, so we
- have to do it this way.
+ my_off_t size= uint4korr(ptr + EVENT_LEN_OFFSET);
+ my_off_t hdr_len= get_header_len(print_event_info->common_header_len);
- TODO: Rewrite my_b_printf() to support full printf() syntax.
- */
- char emit_buf[256];
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %-48.48s |%16s|\n",
- (unsigned long) (hexdump_from + (i & 0xfffffff0)),
- hex_string, char_string);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- hex_string[0]= 0;
- char_string[0]= 0;
- c= char_string;
- h= hex_string;
- }
- else if (i % 8 == 7) *h++ = ' ';
- }
- *c= '\0';
+ size-= hdr_len;
+
+ my_b_printf(file, "# Position\n");
+
+ /* Write the header, nicely formatted by field. */
+ hexdump_minimal_header_to_io_cache(file, hexdump_from, ptr);
+
+ ptr+= hdr_len;
+ hexdump_from+= hdr_len;
+
+ /* Print the rest of the data, mimicking "hexdump -C" output. */
+ hexdump_data_to_io_cache(file, hexdump_from, ptr, size);
- if (hex_string[0])
- {
- char emit_buf[256];
- size_t const bytes_written=
- my_snprintf(emit_buf, sizeof(emit_buf),
- "# %8.8lx %-48.48s |%s|\n",
- (unsigned long) (hexdump_from + (i & 0xfffffff0)),
- hex_string, char_string);
- DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
- my_b_write(file, (uchar*) emit_buf, bytes_written);
- }
/*
- need a # to prefix the rest of printouts for example those of
- Rows_log_event::print_helper().
+ Prefix the next line so that the output from print_helper()
+ will appear as a comment.
*/
- my_b_write(file, reinterpret_cast<const uchar*>("# "), 2);
+ my_b_write(file, "# Event: ", 9);
}
DBUG_VOID_RETURN;
}
@@ -4454,7 +4554,7 @@ Start_log_event_v3::Start_log_event_v3(const char* buf,
*description_event)
:Log_event(buf, description_event)
{
- buf+= description_event->common_header_len;
+ buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
ST_SERVER_VER_LEN);
@@ -4801,16 +4901,15 @@ bool Format_description_log_event::write(IO_CACHE* file)
We don't call Start_log_event_v3::write() because this would make 2
my_b_safe_write().
*/
- uchar buff[FORMAT_DESCRIPTION_HEADER_LEN + BINLOG_CHECKSUM_ALG_DESC_LEN];
- size_t rec_size= sizeof(buff);
+ uchar buff[START_V3_HEADER_LEN+1];
+ size_t rec_size= sizeof(buff) + BINLOG_CHECKSUM_ALG_DESC_LEN +
+ number_of_event_types;
int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
if (!dont_set_created)
created= get_time();
int4store(buff + ST_CREATED_OFFSET,created);
- buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN;
- memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET + 1, (uchar*) post_header_len,
- LOG_EVENT_TYPES);
+ buff[ST_COMMON_HEADER_LEN_OFFSET]= common_header_len;
/*
if checksum is requested
record the checksum-algorithm descriptor next to
@@ -4823,7 +4922,7 @@ bool Format_description_log_event::write(IO_CACHE* file)
#ifndef DBUG_OFF
data_written= 0; // to prepare for need_checksum assert
#endif
- buff[FORMAT_DESCRIPTION_HEADER_LEN]= need_checksum() ?
+ uchar checksum_byte= need_checksum() ?
checksum_alg : (uint8) BINLOG_CHECKSUM_ALG_OFF;
/*
FD of checksum-aware server is always checksum-equipped, (V) is in,
@@ -4843,7 +4942,10 @@ bool Format_description_log_event::write(IO_CACHE* file)
checksum_alg= BINLOG_CHECKSUM_ALG_CRC32; // Forcing (V) room to fill anyway
}
ret= (write_header(file, rec_size) ||
- wrapper_my_b_safe_write(file, buff, rec_size) ||
+ wrapper_my_b_safe_write(file, buff, sizeof(buff)) ||
+ wrapper_my_b_safe_write(file, (uchar*)post_header_len,
+ number_of_event_types) ||
+ wrapper_my_b_safe_write(file, &checksum_byte, sizeof(checksum_byte)) ||
write_footer(file));
if (no_checksum)
checksum_alg= BINLOG_CHECKSUM_ALG_OFF;
@@ -5034,9 +5136,9 @@ uint8 get_checksum_alg(const char* buf, ulong len)
DBUG_ENTER("get_checksum_alg");
DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT);
- memcpy(version, buf +
- buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET]
- + ST_SERVER_VER_OFFSET, ST_SERVER_VER_LEN);
+ memcpy(version,
+ buf + LOG_EVENT_MINIMAL_HEADER_LEN + ST_SERVER_VER_OFFSET,
+ ST_SERVER_VER_LEN);
version[ST_SERVER_VER_LEN - 1]= 0;
do_server_version_split(version, &version_split);
@@ -5909,16 +6011,14 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
{
DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
- uint8 header_size= description_event->common_header_len;
uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1];
uint ident_offset;
- if (event_len < header_size)
+ if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN)
DBUG_VOID_RETURN;
- buf += header_size;
- pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
- ident_len = (uint)(event_len -
- (header_size+post_header_len));
- ident_offset = post_header_len;
+ buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
+ pos= post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
+ ident_len= (uint)(event_len - (LOG_EVENT_MINIMAL_HEADER_LEN + post_header_len));
+ ident_offset= post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
new_log_ident= my_strndup(buf + ident_offset, (uint) ident_len, MYF(MY_WME));
DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
@@ -6173,7 +6273,7 @@ bool
Gtid_log_event::peek(const char *event_start, size_t event_len,
uint8 checksum_alg,
uint32 *domain_id, uint32 *server_id, uint64 *seq_no,
- uchar *flags2)
+ uchar *flags2, const Format_description_log_event *fdev)
{
const char *p;
@@ -6188,10 +6288,10 @@ Gtid_log_event::peek(const char *event_start, size_t event_len,
DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF ||
checksum_alg == BINLOG_CHECKSUM_ALG_OFF);
- if (event_len < LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN)
+ if (event_len < (uint32)fdev->common_header_len + GTID_HEADER_LEN)
return true;
*server_id= uint4korr(event_start + SERVER_ID_OFFSET);
- p= event_start + LOG_EVENT_HEADER_LEN;
+ p= event_start + fdev->common_header_len;
*seq_no= uint8korr(p);
p+= 8;
*domain_id= uint4korr(p);
@@ -6382,7 +6482,7 @@ Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info)
Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len,
const Format_description_log_event *description_event)
- : Log_event(buf, description_event), count(0), list(0)
+ : Log_event(buf, description_event), count(0), list(0), sub_id_list(0)
{
uint32 i;
uint32 val;
@@ -6411,6 +6511,31 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len,
list[i].seq_no= uint8korr(buf);
buf+= 8;
}
+
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+ if ((gl_flags & FLAG_IGN_GTIDS))
+ {
+ uint32 i;
+ if (!(sub_id_list= (uint64 *)my_malloc(count*sizeof(uint64), MYF(MY_WME))))
+ {
+ my_free(list);
+ list= NULL;
+ return;
+ }
+ for (i= 0; i < count; ++i)
+ {
+ if (!(sub_id_list[i]=
+ rpl_global_gtid_slave_state.next_sub_id(list[i].domain_id)))
+ {
+ my_free(list);
+ my_free(sub_id_list);
+ list= NULL;
+ sub_id_list= NULL;
+ return;
+ }
+ }
+ }
+#endif
}
@@ -6418,7 +6543,7 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len,
Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set,
uint32 gl_flags_)
- : count(gtid_set->count()), gl_flags(gl_flags_), list(0)
+ : count(gtid_set->count()), gl_flags(gl_flags_), list(0), sub_id_list(0)
{
cache_type= EVENT_NO_CACHE;
/* Failure to allocate memory will be caught by is_valid() returning false. */
@@ -6429,6 +6554,47 @@ Gtid_list_log_event::Gtid_list_log_event(rpl_binlog_state *gtid_set,
}
+Gtid_list_log_event::Gtid_list_log_event(slave_connection_state *gtid_set,
+ uint32 gl_flags_)
+ : count(gtid_set->count()), gl_flags(gl_flags_), list(0), sub_id_list(0)
+{
+ cache_type= EVENT_NO_CACHE;
+ /* Failure to allocate memory will be caught by is_valid() returning false. */
+ if (count < (1<<28) &&
+ (list = (rpl_gtid *)my_malloc(count * sizeof(*list) + (count == 0),
+ MYF(MY_WME))))
+ {
+ gtid_set->get_gtid_list(list, count);
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+ if (gl_flags & FLAG_IGN_GTIDS)
+ {
+ uint32 i;
+
+ if (!(sub_id_list= (uint64 *)my_malloc(count * sizeof(uint64),
+ MYF(MY_WME))))
+ {
+ my_free(list);
+ list= NULL;
+ return;
+ }
+ for (i= 0; i < count; ++i)
+ {
+ if (!(sub_id_list[i]=
+ rpl_global_gtid_slave_state.next_sub_id(list[i].domain_id)))
+ {
+ my_free(list);
+ my_free(sub_id_list);
+ list= NULL;
+ sub_id_list= NULL;
+ return;
+ }
+ }
+ }
+#endif
+ }
+}
+
+
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
bool
Gtid_list_log_event::to_packet(String *packet)
@@ -6480,7 +6646,20 @@ Gtid_list_log_event::write(IO_CACHE *file)
int
Gtid_list_log_event::do_apply_event(Relay_log_info const *rli)
{
- int ret= Log_event::do_apply_event(rli);
+ int ret;
+ if (gl_flags & FLAG_IGN_GTIDS)
+ {
+ uint32 i;
+ for (i= 0; i < count; ++i)
+ {
+ if ((ret= rpl_global_gtid_slave_state.record_gtid(thd, &list[i],
+ sub_id_list[i],
+ false, false)))
+ return ret;
+ rpl_global_gtid_slave_state.update_state_hash(sub_id_list[i], &list[i]);
+ }
+ }
+ ret= Log_event::do_apply_event(rli);
if (rli->until_condition == Relay_log_info::UNTIL_GTID &&
(gl_flags & FLAG_UNTIL_REACHED))
{
@@ -6550,7 +6729,8 @@ Gtid_list_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info)
bool
Gtid_list_log_event::peek(const char *event_start, uint32 event_len,
uint8 checksum_alg,
- rpl_gtid **out_gtid_list, uint32 *out_list_len)
+ rpl_gtid **out_gtid_list, uint32 *out_list_len,
+ const Format_description_log_event *fdev)
{
const char *p;
uint32 count_field, count;
@@ -6567,13 +6747,13 @@ Gtid_list_log_event::peek(const char *event_start, uint32 event_len,
DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF ||
checksum_alg == BINLOG_CHECKSUM_ALG_OFF);
- if (event_len < LOG_EVENT_HEADER_LEN + GTID_LIST_HEADER_LEN)
+ if (event_len < (uint32)fdev->common_header_len + GTID_LIST_HEADER_LEN)
return true;
- p= event_start + LOG_EVENT_HEADER_LEN;
+ p= event_start + fdev->common_header_len;
count_field= uint4korr(p);
p+= 4;
count= count_field & ((1<<28)-1);
- if (event_len < LOG_EVENT_HEADER_LEN + GTID_LIST_HEADER_LEN +
+ if (event_len < (uint32)fdev->common_header_len + GTID_LIST_HEADER_LEN +
16 * count)
return true;
if (!(gtid_list= (rpl_gtid *)my_malloc(sizeof(rpl_gtid)*count + (count == 0),
@@ -6709,6 +6889,7 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
{
+ DBUG_ENTER("Intvar_log_event::do_apply_event");
/*
We are now in a statement until the associated query log event has
been processed.
@@ -6716,18 +6897,23 @@ int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
if (rli->deferred_events_collecting)
- return rli->deferred_events->add(this);
+ {
+ DBUG_PRINT("info",("deferring event"));
+ DBUG_RETURN(rli->deferred_events->add(this));
+ }
switch (type) {
case LAST_INSERT_ID_EVENT:
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
- thd->first_successful_insert_id_in_prev_stmt= val;
+ thd->first_successful_insert_id_in_prev_stmt_for_binlog=
+ thd->first_successful_insert_id_in_prev_stmt= val;
+ DBUG_PRINT("info",("last_insert_id_event: %ld", (long) val));
break;
case INSERT_ID_EVENT:
thd->force_one_auto_inc_interval(val);
break;
}
- return 0;
+ DBUG_RETURN(0);
}
int Intvar_log_event::do_update_pos(Relay_log_info *rli)
diff --git a/sql/log_event.h b/sql/log_event.h
index b73c0e71f77..623169914b1 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -41,7 +41,6 @@
#include "rpl_utility.h"
#include "hash.h"
#include "rpl_tblmap.h"
-#include "rpl_tblmap.cc"
#endif
#ifdef MYSQL_SERVER
@@ -1253,6 +1252,7 @@ public:
#endif
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() const = 0;
+ virtual my_off_t get_header_len(my_off_t len) { return len; }
void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; }
void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; }
bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; }
@@ -2469,6 +2469,8 @@ public:
const Format_description_log_event* description_event);
~Start_log_event_v3() {}
Log_event_type get_type_code() { return START_EVENT_V3;}
+ my_off_t get_header_len(my_off_t l __attribute__((unused)))
+ { return LOG_EVENT_MINIMAL_HEADER_LEN; }
#ifdef MYSQL_SERVER
bool write(IO_CACHE* file);
#endif
@@ -2984,6 +2986,8 @@ public:
my_free((void*) new_log_ident);
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
+ my_off_t get_header_len(my_off_t l __attribute__((unused)))
+ { return LOG_EVENT_MINIMAL_HEADER_LEN; }
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() const { return new_log_ident != 0; }
#ifdef MYSQL_SERVER
@@ -3118,7 +3122,7 @@ public:
static bool peek(const char *event_start, size_t event_len,
uint8 checksum_alg,
uint32 *domain_id, uint32 *server_id, uint64 *seq_no,
- uchar *flags2);
+ uchar *flags2, const Format_description_log_event *fdev);
#endif
};
@@ -3197,12 +3201,15 @@ public:
uint32 count;
uint32 gl_flags;
struct rpl_gtid *list;
+ uint64 *sub_id_list;
static const uint element_size= 4+4+8;
static const uint32 FLAG_UNTIL_REACHED= (1<<28);
+ static const uint32 FLAG_IGN_GTIDS= (1<<29);
#ifdef MYSQL_SERVER
Gtid_list_log_event(rpl_binlog_state *gtid_set, uint32 gl_flags);
+ Gtid_list_log_event(slave_connection_state *gtid_set, uint32 gl_flags);
#ifdef HAVE_REPLICATION
void pack_info(THD *thd, Protocol *protocol);
#endif
@@ -3211,7 +3218,7 @@ public:
#endif
Gtid_list_log_event(const char *buf, uint event_len,
const Format_description_log_event *description_event);
- ~Gtid_list_log_event() { my_free(list); }
+ ~Gtid_list_log_event() { my_free(list); my_free(sub_id_list); }
Log_event_type get_type_code() { return GTID_LIST_EVENT; }
int get_data_size() {
/*
@@ -3229,7 +3236,8 @@ public:
#endif
static bool peek(const char *event_start, uint32 event_len,
uint8 checksum_alg,
- rpl_gtid **out_gtid_list, uint32 *out_list_len);
+ rpl_gtid **out_gtid_list, uint32 *out_list_len,
+ const Format_description_log_event *fdev);
};
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 904dc6211ff..eca6e37da15 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -598,7 +598,6 @@ key_map key_map_full(0); // Will be initialized later
DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
Time_zone *default_tz;
-char *mysql_data_home= const_cast<char*>(".");
const char *mysql_real_data_home_ptr= mysql_real_data_home;
char server_version[SERVER_VERSION_LENGTH];
char *mysqld_unix_port, *opt_mysql_tmpdir;
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 8aff25f60be..4d3411754f9 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -465,7 +465,6 @@ extern uint mysql_data_home_len;
extern uint mysql_real_data_home_len;
extern const char *mysql_real_data_home_ptr;
extern ulong thread_handling;
-extern MYSQL_PLUGIN_IMPORT char *mysql_data_home;
extern "C" MYSQL_PLUGIN_IMPORT char server_version[SERVER_VERSION_LENGTH];
extern MYSQL_PLUGIN_IMPORT char mysql_real_data_home[];
extern char mysql_unpacked_real_data_home[];
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 8d959e8028a..dfbcac9aa55 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -11811,6 +11811,26 @@ int QUICK_SELECT_DESC::get_next()
if (!(last_range= rev_it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
+ key_range start_key;
+ start_key.key= (const uchar*) last_range->min_key;
+ start_key.length= last_range->min_length;
+ start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
+ (last_range->flag & EQ_RANGE) ?
+ HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
+ start_key.keypart_map= last_range->min_keypart_map;
+ key_range end_key;
+ end_key.key= (const uchar*) last_range->max_key;
+ end_key.length= last_range->max_length;
+ end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
+ HA_READ_AFTER_KEY);
+ end_key.keypart_map= last_range->max_keypart_map;
+ result= file->prepare_range_scan((last_range->flag & NO_MIN_RANGE) ? NULL : &start_key,
+ (last_range->flag & NO_MAX_RANGE) ? NULL : &end_key);
+ if (result)
+ {
+ DBUG_RETURN(result);
+ }
+
if (last_range->flag & NO_MAX_RANGE) // Read last record
{
int local_error;
@@ -12437,8 +12457,12 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
uchar cur_key_infix[MAX_KEY_LENGTH];
uint cur_used_key_parts;
- /* Check (B1) - if current index is covering. */
- if (!table->covering_keys.is_set(cur_index))
+ /*
+ Check (B1) - if current index is covering. Exclude UNIQUE indexes, because
+ loose scan may still be chosen for them due to imperfect cost calculations.
+ */
+ if (!table->covering_keys.is_set(cur_index) ||
+ cur_index_info->flags & HA_NOSAME)
goto next_index;
/*
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 7d6d58a3414..ac262e1110e 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5223,10 +5223,12 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
{
eq_cond= new Item_func_eq(subq_pred->left_expr->element_index(i),
new_sink->row[i]);
- if (!eq_cond || eq_cond->fix_fields(join->thd, &eq_cond))
+ if (!eq_cond)
DBUG_RETURN(1);
- (*join_where)= and_items(*join_where, eq_cond);
+ if (!((*join_where)= and_items(*join_where, eq_cond)) ||
+ (*join_where)->fix_fields(join->thd, join_where))
+ DBUG_RETURN(1);
}
}
else
@@ -5241,6 +5243,12 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
DBUG_RETURN(1);
table->table= dummy_table;
table->table->pos_in_table_list= table;
+ /*
+ Note: the table created above may be freed by:
+ 1. JOIN_TAB::cleanup(), when the parent join is a regular join.
+ 2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
+ degenerate join (e.g. one with "Impossible where").
+ */
setup_table_map(table->table, table, table->jtbm_table_no);
}
else
@@ -5273,6 +5281,42 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
}
+/*
+ Cleanup non-merged semi-joins (JBMs) that have empty.
+
+ This function is to cleanups for a special case:
+ Consider a query like
+
+ select * from t1 where 1=2 AND t1.col IN (select max(..) ... having 1=2)
+
+ For this query, optimization of subquery will short-circuit, and
+ setup_jtbm_semi_joins() will call create_dummy_tmp_table() so that we have
+ empty, constant temp.table to stand in as materialized temp. table.
+
+ Now, suppose that the upper join is also found to be degenerate. In that
+ case, no JOIN_TAB array will be produced, and hence, JOIN::cleanup() will
+ have a problem with cleaning up empty JTBMs (non-empty ones are cleaned up
+ through Item::cleanup() calls).
+*/
+
+void cleanup_empty_jtbm_semi_joins(JOIN *join)
+{
+ List_iterator<TABLE_LIST> li(*join->join_list);
+ TABLE_LIST *table;
+ while ((table= li++))
+ {
+ if ((table->jtbm_subselect && table->jtbm_subselect->is_jtbm_const_tab))
+ {
+ if (table->table)
+ {
+ free_tmp_table(join->thd, table->table);
+ table->table= NULL;
+ }
+ }
+ }
+}
+
+
/**
Choose an optimal strategy to execute an IN/ALL/ANY subquery predicate
based on cost.
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 01da437504b..044e2dce3ee 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -28,6 +28,7 @@ int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
Item **join_where);
+void cleanup_empty_jtbm_semi_joins(JOIN *join);
// used by Loose_scan_opt
ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest,
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 7454e756416..e50a9b0b42d 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -892,8 +892,11 @@ bool Dep_analysis_context::run_wave(List<Dep_module> *new_bound_modules)
iter= module->init_unbound_values_iter(iter_buf);
while ((value= module->get_next_unbound_value(this, iter)))
{
- value->make_bound();
- new_bound_values.push_back(value);
+ if (!value->is_bound())
+ {
+ value->make_bound();
+ new_bound_values.push_back(value);
+ }
}
}
new_bound_modules->empty();
@@ -1740,7 +1743,7 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac,
- have this field as a part of them
*/
while (key_dep && (key_dep->is_applicable() ||
- !field->part_of_key.is_set(key_dep->keyno)))
+ !field->part_of_key_not_clustered.is_set(key_dep->keyno)))
{
key_dep= key_dep->next_table_key;
}
diff --git a/sql/records.cc b/sql/records.cc
index d28799ea9d2..e534c04935a 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -371,7 +371,15 @@ static int rr_quick(READ_RECORD *info)
static int rr_index_first(READ_RECORD *info)
{
- int tmp= info->table->file->ha_index_first(info->record);
+ int tmp;
+ // tell handler that we are doing an index scan
+ if ((tmp = info->table->file->prepare_index_scan()))
+ {
+ tmp= rr_handle_error(info, tmp);
+ return tmp;
+ }
+
+ tmp= info->table->file->ha_index_first(info->record);
info->read_record= rr_index;
if (tmp)
tmp= rr_handle_error(info, tmp);
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 05ac79a8f64..ef760a9444f 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -721,6 +721,45 @@ gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid)
}
+rpl_gtid *
+gtid_parse_string_to_list(const char *str, size_t str_len, uint32 *out_len)
+{
+ char *p= const_cast<char *>(str);
+ char *end= p + str_len;
+ uint32 len= 0, alloc_len= 5;
+ rpl_gtid *list= NULL;
+
+ for (;;)
+ {
+ rpl_gtid gtid;
+
+ if (len >= (((uint32)1 << 28)-1) || gtid_parser_helper(&p, end, &gtid))
+ {
+ my_free(list);
+ return NULL;
+ }
+ if ((!list || len >= alloc_len) &&
+ !(list=
+ (rpl_gtid *)my_realloc(list,
+ (alloc_len= alloc_len*2) * sizeof(rpl_gtid),
+ MYF(MY_FREE_ON_ERROR|MY_ALLOW_ZERO_PTR))))
+ return NULL;
+ list[len++]= gtid;
+
+ if (p == end)
+ break;
+ if (*p != ',')
+ {
+ my_free(list);
+ return NULL;
+ }
+ ++p;
+ }
+ *out_len= len;
+ return list;
+}
+
+
/*
Update the slave replication state with the GTID position obtained from
master when connecting with old-style (filename,offset) position.
@@ -1236,11 +1275,46 @@ rpl_binlog_state::append_pos(String *str)
}
+bool
+rpl_binlog_state::append_state(String *str)
+{
+ uint32 i, j;
+ bool first= true;
+
+ for (i= 0; i < hash.records; ++i)
+ {
+ element *e= (element *)my_hash_element(&hash, i);
+ if (!e->last_gtid)
+ {
+ DBUG_ASSERT(e->hash.records==0);
+ continue;
+ }
+ for (j= 0; j <= e->hash.records; ++j)
+ {
+ const rpl_gtid *gtid;
+ if (j < e->hash.records)
+ {
+ gtid= (rpl_gtid *)my_hash_element(&e->hash, j);
+ if (gtid == e->last_gtid)
+ continue;
+ }
+ else
+ gtid= e->last_gtid;
+
+ if (rpl_slave_state_tostring_helper(str, gtid, &first))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
slave_connection_state::slave_connection_state()
{
my_hash_init(&hash, &my_charset_bin, 32,
- offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, my_free,
- HASH_UNIQUE);
+ offsetof(entry, gtid) + offsetof(rpl_gtid, domain_id),
+ sizeof(uint32), NULL, my_free, HASH_UNIQUE);
}
@@ -1274,7 +1348,7 @@ slave_connection_state::load(char *slave_request, size_t len)
char *p, *end;
uchar *rec;
rpl_gtid *gtid;
- const rpl_gtid *gtid2;
+ const entry *e;
reset();
p= slave_request;
@@ -1283,27 +1357,28 @@ slave_connection_state::load(char *slave_request, size_t len)
return 0;
for (;;)
{
- if (!(rec= (uchar *)my_malloc(sizeof(*gtid), MYF(MY_WME))))
+ if (!(rec= (uchar *)my_malloc(sizeof(entry), MYF(MY_WME))))
{
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*gtid));
return 1;
}
- gtid= (rpl_gtid *)rec;
+ gtid= &((entry *)rec)->gtid;
if (gtid_parser_helper(&p, end, gtid))
{
my_free(rec);
my_error(ER_INCORRECT_GTID_STATE, MYF(0));
return 1;
}
- if ((gtid2= (const rpl_gtid *)
+ if ((e= (const entry *)
my_hash_search(&hash, (const uchar *)(&gtid->domain_id), 0)))
{
my_error(ER_DUPLICATE_GTID_DOMAIN, MYF(0), gtid->domain_id,
- gtid->server_id, (ulonglong)gtid->seq_no, gtid2->domain_id,
- gtid2->server_id, (ulonglong)gtid2->seq_no, gtid->domain_id);
+ gtid->server_id, (ulonglong)gtid->seq_no, e->gtid.domain_id,
+ e->gtid.server_id, (ulonglong)e->gtid.seq_no, gtid->domain_id);
my_free(rec);
return 1;
}
+ ((entry *)rec)->flags= 0;
if (my_hash_insert(&hash, rec))
{
my_free(rec);
@@ -1359,30 +1434,42 @@ slave_connection_state::load(rpl_slave_state *state,
}
+slave_connection_state::entry *
+slave_connection_state::find_entry(uint32 domain_id)
+{
+ return (entry *) my_hash_search(&hash, (const uchar *)(&domain_id), 0);
+}
+
+
rpl_gtid *
slave_connection_state::find(uint32 domain_id)
{
- return (rpl_gtid *) my_hash_search(&hash, (const uchar *)(&domain_id), 0);
+ entry *e= find_entry(domain_id);
+ if (!e)
+ return NULL;
+ return &e->gtid;
}
int
slave_connection_state::update(const rpl_gtid *in_gtid)
{
- rpl_gtid *new_gtid;
+ entry *e;
uchar *rec= my_hash_search(&hash, (const uchar *)(&in_gtid->domain_id), 0);
if (rec)
{
- memcpy(rec, in_gtid, sizeof(*in_gtid));
+ e= (entry *)rec;
+ e->gtid= *in_gtid;
return 0;
}
- if (!(new_gtid= (rpl_gtid *)my_malloc(sizeof(*new_gtid), MYF(MY_WME))))
+ if (!(e= (entry *)my_malloc(sizeof(*e), MYF(MY_WME))))
return 1;
- memcpy(new_gtid, in_gtid, sizeof(*new_gtid));
- if (my_hash_insert(&hash, (uchar *)new_gtid))
+ e->gtid= *in_gtid;
+ e->flags= 0;
+ if (my_hash_insert(&hash, (uchar *)e))
{
- my_free(new_gtid);
+ my_free(e);
return 1;
}
@@ -1396,7 +1483,7 @@ slave_connection_state::remove(const rpl_gtid *in_gtid)
uchar *rec= my_hash_search(&hash, (const uchar *)(&in_gtid->domain_id), 0);
#ifndef DBUG_OFF
bool err;
- rpl_gtid *slave_gtid= (rpl_gtid *)rec;
+ rpl_gtid *slave_gtid= &((entry *)rec)->gtid;
DBUG_ASSERT(rec /* We should never try to remove not present domain_id. */);
DBUG_ASSERT(slave_gtid->server_id == in_gtid->server_id);
DBUG_ASSERT(slave_gtid->seq_no == in_gtid->seq_no);
@@ -1408,6 +1495,15 @@ slave_connection_state::remove(const rpl_gtid *in_gtid)
}
+void
+slave_connection_state::remove_if_present(const rpl_gtid *in_gtid)
+{
+ uchar *rec= my_hash_search(&hash, (const uchar *)(&in_gtid->domain_id), 0);
+ if (rec)
+ my_hash_delete(&hash, rec);
+}
+
+
int
slave_connection_state::to_string(String *out_str)
{
@@ -1425,9 +1521,28 @@ slave_connection_state::append_to_string(String *out_str)
first= true;
for (i= 0; i < hash.records; ++i)
{
- const rpl_gtid *gtid= (const rpl_gtid *)my_hash_element(&hash, i);
- if (rpl_slave_state_tostring_helper(out_str, gtid, &first))
+ const entry *e= (const entry *)my_hash_element(&hash, i);
+ if (rpl_slave_state_tostring_helper(out_str, &e->gtid, &first))
return 1;
}
return 0;
}
+
+
+int
+slave_connection_state::get_gtid_list(rpl_gtid *gtid_list, uint32 list_size)
+{
+ uint32 i, pos;
+
+ pos= 0;
+ for (i= 0; i < hash.records; ++i)
+ {
+ entry *e;
+ if (pos >= list_size)
+ return 1;
+ e= (entry *)my_hash_element(&hash, i);
+ memcpy(&gtid_list[pos++], &e->gtid, sizeof(e->gtid));
+ }
+
+ return 0;
+}
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index 1a94ee76eca..d6da2295abe 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -163,6 +163,7 @@ struct rpl_binlog_state
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
bool append_pos(String *str);
+ bool append_state(String *str);
rpl_gtid *find(uint32 domain_id, uint32 server_id);
rpl_gtid *find_most_recent(uint32 domain_id);
};
@@ -174,7 +175,14 @@ struct rpl_binlog_state
*/
struct slave_connection_state
{
- /* Mapping from domain_id to the GTID requested for that domain. */
+ struct entry {
+ rpl_gtid gtid;
+ uint32 flags;
+ };
+ static const uint32 START_OWN_SLAVE_POS= 0x1;
+ static const uint32 START_ON_EMPTY_DOMAIN= 0x2;
+
+ /* Mapping from domain_id to the entry with GTID requested for that domain. */
HASH hash;
slave_connection_state();
@@ -185,15 +193,20 @@ struct slave_connection_state
int load(const rpl_gtid *gtid_list, uint32 count);
int load(rpl_slave_state *state, rpl_gtid *extra_gtids, uint32 num_extra);
rpl_gtid *find(uint32 domain_id);
+ entry *find_entry(uint32 domain_id);
int update(const rpl_gtid *in_gtid);
void remove(const rpl_gtid *gtid);
+ void remove_if_present(const rpl_gtid *in_gtid);
ulong count() const { return hash.records; }
int to_string(String *out_str);
int append_to_string(String *out_str);
+ int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
};
extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid,
bool *first);
extern int gtid_check_rpl_slave_state_table(TABLE *table);
+extern rpl_gtid *gtid_parse_string_to_list(const char *p, size_t len,
+ uint32 *out_len);
#endif /* RPL_GTID_H */
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 3a6bb4c33dc..70d6033cebc 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1012,7 +1012,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
rli->cur_log_fd= -1;
}
- if (rli->relay_log.reset_logs(thd, !just_reset))
+ if (rli->relay_log.reset_logs(thd, !just_reset, NULL, 0))
{
*errmsg = "Failed during log reset";
error=1;
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 6dd757343fd..9ab5dcb30a5 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -303,6 +303,8 @@ public:
*/
char ign_master_log_name_end[FN_REFLEN];
ulonglong ign_master_log_pos_end;
+ /* Similar for ignored GTID events. */
+ slave_connection_state ign_gtids;
/*
Indentifies where the SQL Thread should create temporary files for the
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index db47c3c164a..614f18a6dff 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -1186,7 +1186,7 @@ bool Deferred_log_events::is_empty()
bool Deferred_log_events::execute(Relay_log_info *rli)
{
bool res= false;
-
+ DBUG_ENTER("Deferred_log_events::execute");
DBUG_ASSERT(rli->deferred_events_collecting);
rli->deferred_events_collecting= false;
@@ -1197,7 +1197,7 @@ bool Deferred_log_events::execute(Relay_log_info *rli)
res= ev->apply_event(rli);
}
rli->deferred_events_collecting= true;
- return res;
+ DBUG_RETURN(res);
}
void Deferred_log_events::rewind()
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 35f2cfb330c..75004bba351 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7022,7 +7022,7 @@ ER_SQL_DISCOVER_ERROR
ER_FAILED_GTID_STATE_INIT
eng "Failed initializing replication GTID state"
ER_INCORRECT_GTID_STATE
- eng "Could not parse GTID list for GTID_POS"
+ eng "Could not parse GTID list"
ER_CANNOT_UPDATE_GTID_STATE
eng "Could not update replication slave gtid state"
ER_DUPLICATE_GTID_DOMAIN
@@ -7050,3 +7050,11 @@ ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
eng "Cannot modify @@session.gtid_domain_id or @@session.gtid_seq_no inside a transaction"
ER_STORED_FUNCTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
eng "Cannot modify @@session.gtid_domain_id or @@session.gtid_seq_no inside a stored function or trigger"
+ER_GTID_POSITION_NOT_FOUND_IN_BINLOG2
+ eng "Connecting slave requested to start from GTID %u-%u-%llu, which is not in the master's binlog. Since the master's binlog contains GTIDs with higher sequence numbers, it probably means that the slave has diverged due to executing extra errorneous transactions"
+ER_BINLOG_MUST_BE_EMPTY
+ eng "This operation is not allowed if any GTID has been logged to the binary log. Run RESET MASTER first to erase the log"
+ER_NO_SUCH_QUERY
+ eng "Unknown query id: %lld"
+ ger "Unbekannte Abfrage-ID: %lld"
+ rus "Неизвестный номер запроса: %lld"
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 9437db6c318..c50072f5159 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -12,7 +12,7 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "my_global.h"
#include <signal.h>
diff --git a/sql/slave.cc b/sql/slave.cc
index d46be570b5e..332a4a9669a 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2238,34 +2238,66 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi)
DBUG_ASSERT(thd == mi->io_thd);
mysql_mutex_lock(log_lock);
- if (rli->ign_master_log_name_end[0])
- {
- DBUG_PRINT("info",("writing a Rotate event to track down ignored events"));
- Rotate_log_event *ev= new Rotate_log_event(rli->ign_master_log_name_end,
- 0, rli->ign_master_log_pos_end,
- Rotate_log_event::DUP_NAME);
- rli->ign_master_log_name_end[0]= 0;
- /* can unlock before writing as slave SQL thd will soon see our Rotate */
+ if (rli->ign_master_log_name_end[0] || rli->ign_gtids.count())
+ {
+ Rotate_log_event *rev= NULL;
+ Gtid_list_log_event *glev= NULL;
+ if (rli->ign_master_log_name_end[0])
+ {
+ rev= new Rotate_log_event(rli->ign_master_log_name_end,
+ 0, rli->ign_master_log_pos_end,
+ Rotate_log_event::DUP_NAME);
+ rli->ign_master_log_name_end[0]= 0;
+ if (unlikely(!(bool)rev))
+ mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE,
+ ER(ER_SLAVE_CREATE_EVENT_FAILURE),
+ "Rotate_event (out of memory?),"
+ " SHOW SLAVE STATUS may be inaccurate");
+ }
+ if (rli->ign_gtids.count())
+ {
+ glev= new Gtid_list_log_event(&rli->ign_gtids,
+ Gtid_list_log_event::FLAG_IGN_GTIDS);
+ rli->ign_gtids.reset();
+ if (unlikely(!(bool)glev))
+ mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE,
+ ER(ER_SLAVE_CREATE_EVENT_FAILURE),
+ "Gtid_list_event (out of memory?),"
+ " gtid_slave_pos may be inaccurate");
+ }
+
+ /* Can unlock before writing as slave SQL thd will soon see our event. */
mysql_mutex_unlock(log_lock);
- if (likely((bool)ev))
+ if (rev)
{
- ev->server_id= 0; // don't be ignored by slave SQL thread
- if (unlikely(rli->relay_log.append(ev)))
+ DBUG_PRINT("info",("writing a Rotate event to track down ignored events"));
+ rev->server_id= 0; // don't be ignored by slave SQL thread
+ if (unlikely(rli->relay_log.append(rev)))
mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
"failed to write a Rotate event"
" to the relay log, SHOW SLAVE STATUS may be"
" inaccurate");
+ delete rev;
+ }
+ if (glev)
+ {
+ DBUG_PRINT("info",("writing a Gtid_list event to track down ignored events"));
+ glev->server_id= 0; // don't be ignored by slave SQL thread
+ glev->set_artificial_event(); // Don't mess up Exec_Master_Log_Pos
+ if (unlikely(rli->relay_log.append(glev)))
+ mi->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_WRITE_FAILURE,
+ ER(ER_SLAVE_RELAY_LOG_WRITE_FAILURE),
+ "failed to write a Gtid_list event to the relay log, "
+ "gtid_slave_pos may be inaccurate");
+ delete glev;
+ }
+ if (likely (rev || glev))
+ {
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
if (flush_master_info(mi, TRUE, TRUE))
sql_print_error("Failed to flush master info file");
- delete ev;
}
- else
- mi->report(ERROR_LEVEL, ER_SLAVE_CREATE_EVENT_FAILURE,
- ER(ER_SLAVE_CREATE_EVENT_FAILURE),
- "Rotate_event (out of memory?),"
- " SHOW SLAVE STATUS may be inaccurate");
}
else
mysql_mutex_unlock(log_lock);
@@ -3121,6 +3153,12 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli)
rli->slave_skip_counter--;
}
mysql_mutex_unlock(&rli->data_lock);
+ DBUG_EXECUTE_IF("inject_slave_sql_before_apply_event",
+ {
+ DBUG_ASSERT(!debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR continue")));
+ DBUG_SET_INITIAL("-d,inject_slave_sql_before_apply_event");
+ };);
if (reason == Log_event::EVENT_SKIP_NOT)
exec_res= ev->apply_event(rli);
@@ -3184,6 +3222,14 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli)
DBUG_RETURN(2);
}
}
+ else
+ {
+ /*
+ Make sure we do not errorneously update gtid_slave_pos with a lingering
+ GTID from this failed event group (MDEV-4906).
+ */
+ rli->gtid_sub_id= 0;
+ }
DBUG_RETURN(exec_res ? 1 : 0);
}
@@ -4119,6 +4165,7 @@ pthread_handler_t handle_slave_sql(void *arg)
rli->trans_retries= 0; // start from "no error"
DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries));
+ rli->gtid_sub_id= 0;
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
rli->group_relay_log_pos,
@@ -4840,6 +4887,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
ulong s_id;
bool unlock_data_lock= TRUE;
bool gtid_skip_enqueue= false;
+ bool got_gtid_event= false;
+ rpl_gtid event_gtid;
/*
FD_q must have been prepared for the first R_a event
@@ -4903,8 +4952,6 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
goto err;
}
- LINT_INIT(inc_pos);
-
if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
(uchar)buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT /* a way to escape */)
DBUG_RETURN(queue_old_event(mi,buf,event_len));
@@ -5158,6 +5205,15 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
{
uchar dummy_flag;
+ if (Gtid_log_event::peek(buf, event_len, checksum_alg,
+ &event_gtid.domain_id, &event_gtid.server_id,
+ &event_gtid.seq_no, &dummy_flag,
+ rli->relay_log.description_event_for_queue))
+ {
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ goto err;
+ }
+ got_gtid_event= true;
if (mi->using_gtid == Master_info::USE_GTID_NO)
goto default_action;
if (unlikely(!mi->gtid_event_seen))
@@ -5165,8 +5221,6 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
mi->gtid_event_seen= true;
if (mi->gtid_reconnect_event_skip_count)
{
- rpl_gtid gtid;
-
/*
If we are reconnecting, and we need to skip a partial event group
already queued to the relay log before the reconnect, then we check
@@ -5175,21 +5229,14 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
The only way we should be able to receive a different GTID than what
we expect is if the binlog on the master (or more likely the whole
- master server) was replaced with a different one, one the same IP
+ master server) was replaced with a different one, on the same IP
address, _and_ the new master happens to have domains in a different
order so we get the GTID from a different domain first. Still, it is
best to protect against this case.
*/
- if (Gtid_log_event::peek(buf, event_len, checksum_alg,
- &gtid.domain_id, &gtid.server_id,
- &gtid.seq_no, &dummy_flag))
- {
- error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
- goto err;
- }
- if (gtid.domain_id != mi->last_queued_gtid.domain_id ||
- gtid.server_id != mi->last_queued_gtid.server_id ||
- gtid.seq_no != mi->last_queued_gtid.seq_no)
+ if (event_gtid.domain_id != mi->last_queued_gtid.domain_id ||
+ event_gtid.server_id != mi->last_queued_gtid.server_id ||
+ event_gtid.seq_no != mi->last_queued_gtid.seq_no)
{
bool first;
error= ER_SLAVE_UNEXPECTED_MASTER_SWITCH;
@@ -5199,7 +5246,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
&first);
error_msg.append(STRING_WITH_LEN(", received: "));
first= true;
- rpl_slave_state_tostring_helper(&error_msg, &gtid, &first);
+ rpl_slave_state_tostring_helper(&error_msg, &event_gtid, &first);
goto err;
}
}
@@ -5219,15 +5266,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
mi->gtid_current_pos.update(&mi->last_queued_gtid);
mi->events_queued_since_last_gtid= 0;
}
- if (Gtid_log_event::peek(buf, event_len, checksum_alg,
- &mi->last_queued_gtid.domain_id,
- &mi->last_queued_gtid.server_id,
- &mi->last_queued_gtid.seq_no, &dummy_flag))
- {
- error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
- goto err;
- }
+ mi->last_queued_gtid= event_gtid;
++mi->events_queued_since_last_gtid;
+ inc_pos= event_len;
}
break;
@@ -5279,6 +5320,36 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
mysql_mutex_lock(log_lock);
s_id= uint4korr(buf + SERVER_ID_OFFSET);
+ /*
+ Write the event to the relay log, unless we reconnected in the middle
+ of an event group and now need to skip the initial part of the group that
+ we already wrote before reconnecting.
+ */
+ if (unlikely(gtid_skip_enqueue))
+ {
+ mi->master_log_pos+= inc_pos;
+ if ((uchar)buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT &&
+ s_id == mi->master_id)
+ {
+ /*
+ If we write this master's description event in the middle of an event
+ group due to GTID reconnect, SQL thread will think that master crashed
+ in the middle of the group and roll back the first half, so we must not.
+
+ But we still have to write an artificial copy of the masters description
+ event, to override the initial slave-version description event so that
+ SQL thread has the right information for parsing the events it reads.
+ */
+ rli->relay_log.description_event_for_queue->created= 0;
+ rli->relay_log.description_event_for_queue->set_artificial_event();
+ if (rli->relay_log.append_no_lock
+ (rli->relay_log.description_event_for_queue))
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ else
+ rli->relay_log.harvest_bytes_written(&rli->log_space_total);
+ }
+ }
+ else
if ((s_id == global_system_variables.server_id &&
!mi->rli.replicate_same_server_id) ||
/*
@@ -5321,6 +5392,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN);
DBUG_ASSERT(rli->ign_master_log_name_end[0]);
rli->ign_master_log_pos_end= mi->master_log_pos;
+ if (got_gtid_event)
+ rli->ign_gtids.update(&event_gtid);
}
rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
DBUG_PRINT("info", ("master_log_pos: %lu, event originating from %u server, ignored",
@@ -5328,16 +5401,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
}
else
{
- /*
- Write the event to the relay log, unless we reconnected in the middle
- of an event group and now need to skip the initial part of the group that
- we already wrote before reconnecting.
- */
- if (unlikely(gtid_skip_enqueue))
- {
- mi->master_log_pos+= inc_pos;
- }
- else if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
+ if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
@@ -5348,6 +5412,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
}
rli->ign_master_log_name_end[0]= 0; // last event is not ignored
+ if (got_gtid_event)
+ rli->ign_gtids.remove_if_present(&event_gtid);
if (save_buf != NULL)
buf= save_buf;
}
@@ -5954,6 +6020,25 @@ static Log_event* next_event(Relay_log_info* rli)
DBUG_RETURN(ev);
}
+ if (rli->ign_gtids.count())
+ {
+ /* We generate and return a Gtid_list, to update gtid_slave_pos. */
+ DBUG_PRINT("info",("seeing ignored end gtids"));
+ ev= new Gtid_list_log_event(&rli->ign_gtids,
+ Gtid_list_log_event::FLAG_IGN_GTIDS);
+ rli->ign_gtids.reset();
+ mysql_mutex_unlock(log_lock);
+ if (unlikely(!ev))
+ {
+ errmsg= "Slave SQL thread failed to create a Gtid_list event "
+ "(out of memory?), gtid_slave_pos may be inaccurate";
+ goto err;
+ }
+ ev->server_id= 0; // don't be ignored by slave SQL thread
+ ev->set_artificial_event(); // Don't mess up Exec_Master_Log_Pos
+ DBUG_RETURN(ev);
+ }
+
/*
We can, and should release data_lock while we are waiting for
update. If we do not, show slave status will block
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 510bce21093..c0be41e0f3c 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -312,6 +312,17 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_UNINSTALL_PLUGIN:
flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
break;
+ case SQLCOM_DELETE:
+ {
+ if (lex->select_lex.item_list.is_empty())
+ flags= 0;
+ else
+ {
+ /* This is DELETE ... RETURNING ... */
+ flags= sp_head::MULTI_RESULTS;
+ }
+ break;
+ }
default:
flags= 0;
break;
diff --git a/sql/spatial.cc b/sql/spatial.cc
index a01d2c59a49..32a2012a49d 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -447,19 +447,18 @@ const char *Geometry::append_points(String *txt, uint32 n_points,
const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
uint offset) const
{
- uint32 n_points;
+ uint32 points;
/* read number of points */
if (no_data(data, 4))
return 0;
- n_points= uint4korr(data);
+ points= uint4korr(data);
data+= 4;
- if (n_points > max_n_points ||
- no_data(data, (POINT_DATA_SIZE + offset) * n_points))
+ if (not_enough_points(data, points, offset))
return 0;
/* Calculate MBR for points */
- while (n_points--)
+ while (points--)
{
data+= offset;
mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
@@ -563,12 +562,16 @@ const Geometry::Class_info *Gis_point::get_class_info() const
uint32 Gis_line_string::get_data_size() const
{
- uint32 n_points, size;
- if (no_data(m_data, 4) ||
- (n_points= uint4korr(m_data)) > max_n_points ||
- no_data(m_data, (size= 4 + n_points * POINT_DATA_SIZE)))
+ uint32 n_points;
+ if (no_data(m_data, 4))
return GET_SIZE_ERROR;
- return size;
+
+ n_points= uint4korr(m_data);
+
+ if (not_enough_points(m_data + 4, n_points))
+ return GET_SIZE_ERROR;
+
+ return 4 + n_points * POINT_DATA_SIZE;
}
@@ -607,9 +610,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
const char *wkb_end;
Gis_point p;
- if (len < 4 ||
- (n_points= wkb_get_uint(wkb, bo)) < 1 ||
- n_points > max_n_points)
+ if (len < 4 || (n_points= wkb_get_uint(wkb, bo)) < 1 ||
+ ((len - 4) / POINT_DATA_SIZE) < n_points)
return 0;
proper_length= 4 + n_points * POINT_DATA_SIZE;
@@ -638,8 +640,8 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
n_points= uint4korr(data);
data += 4;
- if (n_points < 1 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points) ||
+ if (n_points < 1 ||
+ not_enough_points(data, n_points) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
@@ -676,8 +678,7 @@ int Gis_line_string::geom_length(double *len, const char **end) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (n_points < 1 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (n_points < 1 || not_enough_points(data, n_points))
return 1;
get_point(&prev_x, &prev_y, data);
@@ -725,8 +726,7 @@ int Gis_line_string::is_closed(int *closed) const
return 0;
}
data+= 4;
- if (n_points == 0 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (n_points == 0 || not_enough_points(data, n_points))
return 1;
/* Get first point */
@@ -761,8 +761,7 @@ int Gis_line_string::end_point(String *result) const
if (no_data(m_data, 4))
return 1;
n_points= uint4korr(m_data);
- if (n_points == 0 || n_points > max_n_points ||
- no_data(m_data, POINT_DATA_SIZE * n_points))
+ if (n_points == 0 || not_enough_points(m_data+4, n_points))
return 1;
return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
}
@@ -775,9 +774,7 @@ int Gis_line_string::point_n(uint32 num, String *result) const
return 1;
num--;
n_points= uint4korr(m_data);
- if (num >= n_points ||
- num > max_n_points || // means (num > n_points || num < 1)
- no_data(m_data, num * POINT_DATA_SIZE))
+ if (num >= n_points || not_enough_points(m_data+4, n_points))
return 1;
return create_point(result, m_data + 4 + num*POINT_DATA_SIZE);
@@ -796,8 +793,7 @@ int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (n_points < 1 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
return 1;
trn->start_line();
@@ -840,7 +836,7 @@ uint32 Gis_polygon::get_data_size() const
while (n_linear_rings--)
{
if (no_data(data, 4) ||
- (n_points= uint4korr(data)) > max_n_points)
+ not_enough_points(data+4, n_points= uint4korr(data)))
return GET_SIZE_ERROR;
data+= 4 + n_points*POINT_DATA_SIZE;
}
@@ -986,7 +982,7 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (n_points > max_n_points || no_data(data, POINT_DATA_SIZE * n_points) ||
+ if (not_enough_points(data, n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
@@ -1040,8 +1036,8 @@ int Gis_polygon::area(double *ar, const char **end_of_data) const
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- if (n_points == 0 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (n_points == 0 ||
+ not_enough_points(data, n_points))
return 1;
get_point(&prev_x, &prev_y, data+4);
data+= (4+POINT_DATA_SIZE);
@@ -1077,8 +1073,7 @@ int Gis_polygon::exterior_ring(String *result) const
n_points= uint4korr(data);
data+= 4;
length= n_points * POINT_DATA_SIZE;
- if (n_points > max_n_points ||
- no_data(data, length) || result->reserve(1 + 4 + 4 + length))
+ if (not_enough_points(data, n_points) || result->reserve(1+4+4+ length))
return 1;
result->q_append((char) wkb_ndr);
@@ -1124,8 +1119,7 @@ int Gis_polygon::interior_ring_n(uint32 num, String *result) const
n_points= uint4korr(data);
points_size= n_points * POINT_DATA_SIZE;
data+= 4;
- if (n_points > max_n_points ||
- no_data(data, points_size) || result->reserve(1 + 4 + 4 + points_size))
+ if (not_enough_points(data, n_points) || result->reserve(1+4+4+ points_size))
return 1;
result->q_append((char) wkb_ndr);
@@ -1162,8 +1156,7 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
return 1;
org_n_points= n_points= uint4korr(data);
data+= 4;
- if (n_points == 0 || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (n_points == 0 || not_enough_points(data, n_points))
return 1;
get_point(&prev_x, &prev_y, data);
data+= POINT_DATA_SIZE;
@@ -1237,8 +1230,7 @@ int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (!n_points || n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points))
+ if (!n_points || no_data(data, POINT_DATA_SIZE * n_points))
return 1;
trn->start_ring();
@@ -1292,13 +1284,12 @@ const Geometry::Class_info *Gis_polygon::get_class_info() const
uint32 Gis_multi_point::get_data_size() const
{
uint32 n_points;
- uint32 size;
if (no_data(m_data, 4) ||
- (n_points= uint4korr(m_data)) > max_n_points ||
- no_data(m_data, (size= 4 + n_points*(POINT_DATA_SIZE + WKB_HEADER_SIZE))))
+ not_enough_points(m_data+4, (n_points= uint4korr(m_data)),
+ WKB_HEADER_SIZE))
return GET_SIZE_ERROR;
- return size;
+ return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
@@ -1393,7 +1384,7 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
n_points= uint4korr(m_data);
if (n_points > max_n_points ||
- no_data(m_data+4, n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE)) ||
+ not_enough_points(m_data+4, n_points, WKB_HEADER_SIZE) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
@@ -1485,7 +1476,8 @@ uint32 Gis_multi_line_string::get_data_size() const
while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4) ||
- (n_points= uint4korr(data + WKB_HEADER_SIZE)) > max_n_points)
+ not_enough_points(data + WKB_HEADER_SIZE+4,
+ (n_points= uint4korr(data + WKB_HEADER_SIZE))))
return GET_SIZE_ERROR;
data+= (WKB_HEADER_SIZE + 4 + n_points*POINT_DATA_SIZE);
}
@@ -1614,7 +1606,7 @@ bool Gis_multi_line_string::get_data_as_wkt(String *txt,
return 1;
n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- if (n_points > max_n_points || no_data(data, n_points * POINT_DATA_SIZE) ||
+ if (not_enough_points(data, n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
@@ -1675,7 +1667,7 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const
return 1;
n_points= uint4korr(data + WKB_HEADER_SIZE);
length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
- if (n_points > max_n_points || no_data(data, length))
+ if (not_enough_points(data+WKB_HEADER_SIZE+4, n_points))
return 1;
if (!--num)
break;
@@ -1806,7 +1798,7 @@ uint32 Gis_multi_polygon::get_data_size() const
while (n_linear_rings--)
{
if (no_data(data, 4) ||
- (n_points= uint4korr(data)) > max_n_points)
+ not_enough_points(data+4, (n_points= uint4korr(data))))
return GET_SIZE_ERROR;
data+= 4 + n_points * POINT_DATA_SIZE;
}
@@ -1940,8 +1932,7 @@ bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
- if (n_points > max_n_points ||
- no_data(data, POINT_DATA_SIZE * n_points) ||
+ if (not_enough_points(data, n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
512))
return 1;
@@ -2024,7 +2015,7 @@ int Gis_multi_polygon::geometry_n(uint32 num, String *result) const
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- if (n_points > max_n_points)
+ if (not_enough_points(data + 4, n_points))
return 1;
data+= 4 + POINT_DATA_SIZE * n_points;
}
diff --git a/sql/spatial.h b/sql/spatial.h
index b0e4b83bf6a..3a6055add06 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -214,11 +214,6 @@ struct Geometry_buffer;
class Geometry
{
public:
- // Maximum number of points in feature that can fit into String
- static const uint32 max_n_points=
- (uint32) (INT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
- POINT_DATA_SIZE;
-
Geometry() {} /* Remove gcc warning */
virtual ~Geometry() {} /* Remove gcc warning */
static void *operator new(size_t size, void *buffer)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 80e7d405a04..67d14b9b965 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -6111,8 +6111,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
LEX_USER *user_from, LEX_USER *user_to)
{
int result= 0;
- uint idx;
- uint elements;
+ int idx;
+ int elements;
const char *user;
const char *host;
ACL_USER *acl_user= NULL;
@@ -6161,8 +6161,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
struct_no, user_from->user.str, user_from->host.str));
#endif
- /* Loop over all elements. */
- for (idx= 0; idx < elements; idx++)
+ /* Loop over all elements *backwards* (see the comment below). */
+ for (idx= elements - 1; idx >= 0; idx--)
{
/*
Get a pointer to the element.
@@ -6213,6 +6213,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
result= 1; /* At least one element found. */
if ( drop )
{
+ elements--;
switch ( struct_no ) {
case USER_ACL:
delete_dynamic_element(&acl_users, idx);
@@ -6226,6 +6227,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
case PROC_PRIVILEGES_HASH:
case FUNC_PRIVILEGES_HASH:
my_hash_delete(grant_name_hash, (uchar*) grant_name);
+ /*
+ In our HASH implementation on deletion one elements
+ is moved into a place where a deleted element was,
+ and the last element is moved into the empty space.
+ Thus we need to re-examine the current element, but
+ we don't have to restart the search from the beginning.
+ */
+ if (idx != elements)
+ idx++;
break;
case PROXY_USERS_ACL:
@@ -6233,21 +6243,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
break;
}
- elements--;
- /*
- - If we are iterating through an array then we just have moved all
- elements after the current element one position closer to its head.
- This means that we have to take another look at the element at
- current position as it is a new element from the array's tail.
- - If we are iterating through a hash the current element was replaced
- with one of elements from the tail. So we also have to take a look
- at the new element in current position.
- Note that in our HASH implementation hash_delete() won't move any
- elements with position after current one to position before the
- current (i.e. from the tail to the head), so it is safe to continue
- iteration without re-starting.
- */
- idx--;
}
else if ( user_to )
{
@@ -6288,15 +6283,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
old_key_length);
/*
- hash_update() operation could have moved element from the tail
- of the hash to the current position. So we need to take a look
- at the element in current position once again.
- Thanks to the fact that hash_update() for our HASH implementation
- won't move any elements from the tail of the hash to the positions
- before the current one (a.k.a. head) it is safe to continue
- iteration without restarting.
+ hash_update() operation could have moved element from the tail or
+ the head of the hash to the current position. But it can never
+ move an element from the head to the tail or from the tail to the
+ head over the current element.
+ So we need to examine the current element once again, but
+ we don't need to restart the search from the beginning.
*/
- idx--;
+ if (idx != elements)
+ idx++;
break;
}
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 07a5243e836..f0e35cb022f 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -82,6 +82,9 @@ static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
event.general_query_length= va_arg(ap, unsigned int);
event.general_charset= va_arg(ap, struct charset_info_st *);
event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
+ event.database= va_arg(ap, const char *);
+ event.database_length= va_arg(ap, unsigned int);
+ event.query_id= (unsigned long long) thd->query_id;
event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
}
@@ -131,6 +134,7 @@ static void table_class_handler(THD *thd, uint event_subclass, va_list ap)
event.new_database_length= va_arg(ap, unsigned int);
event.new_table= va_arg(ap, const char *);
event.new_table_length= va_arg(ap, unsigned int);
+ event.query_id= (unsigned long long) thd->query_id;
event_class_dispatch(thd, MYSQL_AUDIT_TABLE_CLASS, &event);
}
diff --git a/sql/sql_audit.h b/sql/sql_audit.h
index 1c7d6a1c224..bf8d837580a 100644
--- a/sql/sql_audit.h
+++ b/sql/sql_audit.h
@@ -99,7 +99,8 @@ void mysql_audit_general_log(THD *thd, time_t time,
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG,
0, time, user, userlen, cmd, cmdlen,
- query, querylen, clientcs, 0);
+ query, querylen, clientcs, (ha_rows) 0,
+ thd->db, thd->db_length);
}
}
@@ -145,7 +146,8 @@ void mysql_audit_general(THD *thd, uint event_subtype,
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype,
error_code, time, user, userlen, msg, msglen,
- query.str(), query.length(), query.charset(), rows);
+ query.str(), query.length(), query.charset(), rows,
+ thd->db, thd->db_length);
}
}
@@ -176,10 +178,18 @@ void mysql_audit_notify_connection_disconnect(THD *thd, int errcode)
{
if (mysql_audit_connection_enabled())
{
+ const Security_context *sctx= thd->security_ctx;
mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS,
MYSQL_AUDIT_CONNECTION_DISCONNECT,
errcode, thd->thread_id,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ sctx->user, sctx->user ? strlen(sctx->user) : 0,
+ sctx->priv_user, strlen(sctx->priv_user),
+ sctx->external_user,
+ sctx->external_user ? strlen(sctx->external_user) : 0,
+ sctx->proxy_user, strlen(sctx->proxy_user),
+ sctx->host, sctx->host ? strlen(sctx->host) : 0,
+ sctx->ip, sctx->ip ? strlen(sctx->ip) : 0,
+ thd->db, thd->db ? strlen(thd->db) : 0);
}
}
diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h
index 5e86a889053..7e163b0dbcc 100644
--- a/sql/sql_bitmap.h
+++ b/sql/sql_bitmap.h
@@ -72,6 +72,7 @@ public:
bool is_subset(const Bitmap& map2) const { return bitmap_is_subset(&map, &map2.map); }
bool is_overlapping(const Bitmap& map2) const { return bitmap_is_overlapping(&map, &map2.map); }
bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); }
+ bool operator!=(const Bitmap& map2) const { return !(*this == map2); }
char *print(char *buf) const
{
char *s=buf;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index d70113c28e4..35285501fba 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1320,17 +1320,17 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
{
BLOCK_LOCK_WR(block);
Query_cache_query *query= block->query();
- if (query && query->writer())
+ if (query->writer())
{
/*
- Drop the writer; this will cancel any attempts to store
+ Drop the writer; this will cancel any attempts to store
the processed statement associated with this writer.
*/
query->writer()->first_query_block= NULL;
query->writer(0);
refused++;
}
- BLOCK_UNLOCK_WR(block);
+ query->unlock_n_destroy();
block= block->next;
} while (block != queries_blocks);
}
@@ -4307,11 +4307,11 @@ my_bool Query_cache::move_by_type(uchar **border,
size_t key_length;
key=query_cache_query_get_key((uchar*) block, &key_length, 0);
my_hash_first(&queries, (uchar*) key, key_length, &record_idx);
- // Move table of used tables
- memmove((char*) new_block->table(0), (char*) block->table(0),
- ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
block->query()->unlock_n_destroy();
block->destroy();
+ // Move table of used tables
+ memmove((char*) new_block->table(0), (char*) block->table(0),
+ ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
new_block->init(len);
new_block->type=Query_cache_block::QUERY;
new_block->used=used;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f215073ef15..bc0e9b792b5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2479,7 +2479,8 @@ int select_send::send_data(List<Item> &items)
Protocol *protocol= thd->protocol;
DBUG_ENTER("select_send::send_data");
- if (unit->offset_limit_cnt)
+ /* unit is not set when using 'delete ... returning' */
+ if (unit && unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
DBUG_RETURN(FALSE);
@@ -3636,7 +3637,8 @@ select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long,
- bool create_table)
+ bool create_table,
+ bool keep_row_order)
{
DBUG_ASSERT(table == 0);
tmp_table_param.field_count= column_types->elements;
@@ -3644,7 +3646,8 @@ create_result_table(THD *thd_arg, List<Item> *column_types,
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
- options, HA_POS_ERROR, (char*) table_alias)))
+ options, HA_POS_ERROR, (char*) table_alias,
+ keep_row_order)))
return TRUE;
col_stat= (Column_statistics*) table->in_use->alloc(table->s->fields *
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a6613ec23c1..900b5f91f32 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -456,7 +456,8 @@ extern int killed_errno(killed_state killed);
enum killed_type
{
KILL_TYPE_ID,
- KILL_TYPE_USER
+ KILL_TYPE_USER,
+ KILL_TYPE_QUERY
};
#include "sql_lex.h" /* Must be here */
@@ -3944,7 +3945,8 @@ public:
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
- bool create_table);
+ bool create_table,
+ bool keep_row_order= FALSE);
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
};
@@ -4014,7 +4016,8 @@ public:
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
- bool create_table);
+ bool create_table,
+ bool keep_row_order= FALSE);
bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items);
void cleanup();
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index c1820c0187e..a38077c40cb 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -393,7 +393,7 @@ bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
if (create_result_table(unit->thd, unit->get_unit_column_types(),
FALSE,
thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS,
- "", FALSE, TRUE))
+ "", FALSE, TRUE, TRUE))
return TRUE;
materialized_cursor= new (&table->mem_root)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 300f12c5971..1e0789aab12 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -49,7 +49,8 @@
*/
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order_list, ha_rows limit, ulonglong options)
+ SQL_I_List<ORDER> *order_list, ha_rows limit,
+ ulonglong options, select_result *result)
{
bool will_batch;
int error, loc_error;
@@ -67,6 +68,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SELECT_LEX *select_lex= &thd->lex->select_lex;
killed_state killed_status= NOT_KILLED;
THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
+ bool with_select= !select_lex->item_list.is_empty();
DBUG_ENTER("mysql_delete");
if (open_and_lock_tables(thd, table_list, TRUE, 0))
@@ -91,9 +93,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
THD_STAGE_INFO(thd, stage_init);
table->map=1;
- if (mysql_prepare_delete(thd, table_list, &conds))
+ if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
+ select_lex->item_list, &conds))
DBUG_RETURN(TRUE);
+ (void) result->prepare(select_lex->item_list, NULL);
+
if (thd->lex->current_select->first_cond_optimization)
{
thd->lex->current_select->save_leaf_tables(thd);
@@ -155,9 +160,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- We should not be binlogging this statement in row-based, and
- there should be no delete triggers associated with the table.
*/
- if (!using_limit && const_cond_result &&
- (!thd->is_current_stmt_binlog_format_row() &&
- !(table->triggers && table->triggers->has_delete_triggers())))
+ if (!with_select && !using_limit && const_cond_result &&
+ (!thd->is_current_stmt_binlog_format_row() &&
+ !(table->triggers && table->triggers->has_delete_triggers())))
{
/* Update the table->file->stats.records number */
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -326,9 +331,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
will_batch= !table->file->start_bulk_delete();
-
table->mark_columns_needed_for_delete();
+ if (with_select)
+ {
+ if (result->send_result_set_metadata(select_lex->item_list,
+ Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ goto cleanup;
+ }
+
while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error())
{
@@ -348,6 +360,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
break;
}
+ if (with_select && result->send_data(select_lex->item_list) < 0)
+ {
+ error=1;
+ break;
+ }
+
if (!(error= table->file->ha_delete_row(table->record[0])))
{
deleted++;
@@ -454,7 +472,10 @@ cleanup:
if (error < 0 ||
(thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
{
- my_ok(thd, deleted);
+ if (!with_select)
+ my_ok(thd, deleted);
+ else
+ result->send_eof();
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
}
DBUG_RETURN(error >= 0 || thd->is_error());
@@ -468,13 +489,16 @@ cleanup:
mysql_prepare_delete()
thd - thread handler
table_list - global/local table list
+ wild_num - number of wildcards used in optional SELECT clause
+ field_list - list of items in optional SELECT clause
conds - conditions
RETURN VALUE
FALSE OK
TRUE error
*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
+ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
+ uint wild_num, List<Item> &field_list, Item **conds)
{
Item *fake_conds= 0;
SELECT_LEX *select_lex= &thd->lex->select_lex;
@@ -486,7 +510,10 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
&thd->lex->select_lex.top_join_list,
table_list,
select_lex->leaf_tables, FALSE,
- DELETE_ACL, SELECT_ACL, TRUE) ||
+ DELETE_ACL, SELECT_ACL, TRUE))
+ DBUG_RETURN(TRUE);
+ if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) ||
+ setup_fields(thd, NULL, field_list, MARK_COLUMNS_READ, NULL, 0) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_delete.h b/sql/sql_delete.h
index 6147e0ea367..9cd09dc5722 100644
--- a/sql/sql_delete.h
+++ b/sql/sql_delete.h
@@ -21,12 +21,15 @@
class THD;
struct TABLE_LIST;
class Item;
+class select_result;
typedef class Item COND;
template <typename T> class SQL_I_List;
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
+int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
+ uint wild_num, List<Item> &field_list, Item **conds);
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_I_List<ORDER> *order, ha_rows rows, ulonglong options);
+ SQL_I_List<ORDER> *order, ha_rows rows,
+ ulonglong options, select_result *result);
#endif /* SQL_DELETE_INCLUDED */
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1bf0d49214e..28a380175d6 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -30,7 +30,7 @@
#include "sp.h"
#include "sql_select.h"
-static int lex_one_token(void *arg, void *yythd);
+static int lex_one_token(void *arg, THD *thd);
/*
We are using pointer to this variable for distinguishing between assignment
@@ -961,9 +961,8 @@ bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
(which can't be followed by a signed number)
*/
-int MYSQLlex(void *arg, void *yythd)
+int MYSQLlex(void *arg, THD *thd)
{
- THD *thd= (THD *)yythd;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
YYSTYPE *yylval=(YYSTYPE*) arg;
int token;
@@ -982,7 +981,7 @@ int MYSQLlex(void *arg, void *yythd)
return token;
}
- token= lex_one_token(arg, yythd);
+ token= lex_one_token(arg, thd);
switch(token) {
case WITH:
@@ -993,7 +992,7 @@ int MYSQLlex(void *arg, void *yythd)
to transform the grammar into a LALR(1) grammar,
which sql_yacc.yy can process.
*/
- token= lex_one_token(arg, yythd);
+ token= lex_one_token(arg, thd);
switch(token) {
case CUBE_SYM:
lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, WITH_CUBE_SYM,
@@ -1022,14 +1021,13 @@ int MYSQLlex(void *arg, void *yythd)
return token;
}
-int lex_one_token(void *arg, void *yythd)
+int lex_one_token(void *arg, THD *thd)
{
reg1 uchar c;
bool comment_closed;
int tokval, result_state;
uint length;
enum my_lex_states state;
- THD *thd= (THD *)yythd;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
LEX *lex= thd->lex;
YYSTYPE *yylval=(YYSTYPE*) arg;
@@ -3754,10 +3752,7 @@ void SELECT_LEX::mark_as_belong_to_derived(TABLE_LIST *derived)
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
- {
- tl->open_type= OT_BASE_ONLY;
tl->belong_to_derived= derived;
- }
}
@@ -4052,7 +4047,8 @@ void SELECT_LEX::increase_derived_records(ha_rows records)
void SELECT_LEX::mark_const_derived(bool empty)
{
TABLE_LIST *derived= master_unit()->derived;
- if (!join->thd->lex->describe && derived)
+ /* join == NULL in DELETE ... RETURNING */
+ if (!(join && join->thd->lex->describe) && derived)
{
if (!empty)
increase_derived_records(1);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 59f7c122646..5b520980953 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -2812,7 +2812,7 @@ extern void lex_start(THD *thd);
extern void lex_end(LEX *lex);
void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex);
int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex);
-extern int MYSQLlex(void *arg, void *yythd);
+extern int MYSQLlex(void *arg, THD *thd);
extern void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 0d0efb0c21f..436e4681c13 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2013, Monty Progrm Ab
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
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index bd765cebb6c..4663146674c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -119,7 +119,7 @@
"FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
-static void sql_kill(THD *thd, ulong id, killed_state state);
+static void sql_kill(THD *thd, longlong id, killed_state state, killed_type type);
static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state);
static bool execute_show_status(THD *, TABLE_LIST *);
static bool execute_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
@@ -1632,7 +1632,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
status_var_increment(thd->status_var.com_stat[SQLCOM_KILL]);
ulong id=(ulong) uint4korr(packet);
- sql_kill(thd,id, KILL_CONNECTION_HARD);
+ sql_kill(thd, id, KILL_CONNECTION_HARD, KILL_TYPE_ID);
break;
}
case COM_SET_OPTION:
@@ -3499,6 +3499,7 @@ end_with_restore_list:
}
case SQLCOM_DELETE:
{
+ select_result *sel_result=lex->result;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= delete_precheck(thd, all_tables)))
break;
@@ -3506,9 +3507,13 @@ end_with_restore_list:
unit->set_limit(select_lex);
MYSQL_DELETE_START(thd->query());
- res = mysql_delete(thd, all_tables, select_lex->where,
- &select_lex->order_list,
- unit->select_limit_cnt, select_lex->options);
+ if (!(sel_result= lex->result) && !(sel_result= new select_send()))
+ return 1;
+ res = mysql_delete(thd, all_tables,
+ select_lex->where, &select_lex->order_list,
+ unit->select_limit_cnt, select_lex->options,
+ sel_result);
+ delete sel_result;
MYSQL_DELETE_DONE(res, (ulong) thd->get_row_count_func());
break;
}
@@ -4178,7 +4183,7 @@ end_with_restore_list:
break;
}
- if (lex->kill_type == KILL_TYPE_ID)
+ if (lex->kill_type == KILL_TYPE_ID || lex->kill_type == KILL_TYPE_QUERY)
{
Item *it= (Item *)lex->value_list.head();
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
@@ -4187,7 +4192,7 @@ end_with_restore_list:
MYF(0));
goto error;
}
- sql_kill(thd, (ulong) it->val_int(), lex->kill_signal);
+ sql_kill(thd, it->val_int(), lex->kill_signal, lex->kill_type);
}
else
sql_kill_user(thd, get_current_user(thd, lex->users_list.head()),
@@ -7113,12 +7118,13 @@ void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
Find a thread by id and return it, locking it LOCK_thd_data
@param id Identifier of the thread we're looking for
+ @param query_id If true, search by query_id instead of thread_id
@return NULL - not found
pointer - thread found, and its LOCK_thd_data is locked.
*/
-THD *find_thread_by_id(ulong id)
+THD *find_thread_by_id(longlong id, bool query_id)
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
@@ -7127,7 +7133,7 @@ THD *find_thread_by_id(ulong id)
{
if (tmp->get_command() == COM_DAEMON)
continue;
- if (tmp->thread_id == id)
+ if (id == (query_id ? tmp->query_id : (longlong) tmp->thread_id))
{
mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
break;
@@ -7139,24 +7145,26 @@ THD *find_thread_by_id(ulong id)
/**
- kill on thread.
+ kill one thread.
@param thd Thread class
- @param id Thread id
- @param only_kill_query Should it kill the query or the connection
+ @param id Thread id or query id
+ @param kill_signal Should it kill the query or the connection
+ @param type Type of id: thread id or query id
@note
This is written such that we have a short lock on LOCK_thread_count
*/
-uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal)
+uint
+kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type type)
{
THD *tmp;
- uint error=ER_NO_SUCH_THREAD;
+ uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD);
DBUG_ENTER("kill_one_thread");
- DBUG_PRINT("enter", ("id: %lu signal: %u", id, (uint) kill_signal));
+ DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal));
- if ((tmp= find_thread_by_id(id)))
+ if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY)))
{
/*
If we're SUPER, we can KILL anything, including system-threads.
@@ -7274,21 +7282,20 @@ static uint kill_threads_for_user(THD *thd, LEX_USER *user,
}
-/*
- kills a thread and sends response
+/**
+ kills a thread and sends response.
- SYNOPSIS
- sql_kill()
- thd Thread class
- id Thread id
- only_kill_query Should it kill the query or the connection
+ @param thd Thread class
+ @param id Thread id or query id
+ @param state Should it kill the query or the connection
+ @param type Type of id: thread id or query id
*/
static
-void sql_kill(THD *thd, ulong id, killed_state state)
+void sql_kill(THD *thd, longlong id, killed_state state, killed_type type)
{
uint error;
- if (!(error= kill_one_thread(thd, id, state)))
+ if (!(error= kill_one_thread(thd, id, state, type)))
{
if ((!thd->killed))
my_ok(thd);
@@ -8210,7 +8217,7 @@ bool check_host_name(LEX_STRING *str)
}
-extern int MYSQLparse(void *thd); // from sql_yacc.cc
+extern int MYSQLparse(THD *thd); // from sql_yacc.cc
/**
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 9e4c48b47ff..87bfcfcdfc2 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -177,7 +177,8 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec);
static int cmp_rec_and_tuple_prune(part_column_list_val *val,
uint32 n_vals_in_rec,
- bool tail_is_min);
+ bool is_left_endpoint,
+ bool include_endpoint);
/*
Convert constants in VALUES definition to the character set the
@@ -3102,44 +3103,6 @@ notfound:
}
-/*
- Find the sub-array part_info->list_array that corresponds to given interval
-
- SYNOPSIS
- get_list_array_idx_for_endpoint()
- part_info Partitioning info (partitioning type must be LIST)
- left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
- FALSE - the interval is (-inf; a] or (-inf; a)
- include_endpoint TRUE iff the interval includes the endpoint
-
- DESCRIPTION
- This function finds the sub-array of part_info->list_array where values of
- list_array[idx].list_value are contained within the specifed interval.
- list_array is ordered by list_value, so
- 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
- sought sub-array starts at some index idx and continues till array end.
- The function returns first number idx, such that
- list_array[idx].list_value is contained within the passed interval.
-
- 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
- sought sub-array starts at array start and continues till some last
- index idx.
- The function returns first number idx, such that
- list_array[idx].list_value is NOT contained within the passed interval.
- If all array elements are contained, part_info->num_list_values is
- returned.
-
- NOTE
- The caller will call this function and then will run along the sub-array of
- list_array to collect partition ids. If the number of list values is
- significantly higher then number of partitions, this could be slow and
- we could invent some other approach. The "run over list array" part is
- already wrapped in a get_next()-like function.
-
- RETURN
- The edge of corresponding sub-array of part_info->list_array
-*/
-
uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
bool left_endpoint,
bool include_endpoint,
@@ -3147,37 +3110,81 @@ uint32 get_partition_id_cols_list_for_endpoint(partition_info *part_info,
{
part_column_list_val *list_col_array= part_info->list_col_array;
uint num_columns= part_info->part_field_list.elements;
- int list_index, cmp;
+ uint list_index;
uint min_list_index= 0;
- uint max_list_index= part_info->num_list_values - 1;
- bool tailf= !(left_endpoint ^ include_endpoint);
+ uint max_list_index= part_info->num_list_values;
DBUG_ENTER("get_partition_id_cols_list_for_endpoint");
+ /* Find the matching partition (including taking endpoint into account). */
do
{
+ /* Midpoint, adjusted down, so it can never be > last index. */
list_index= (max_list_index + min_list_index) >> 1;
- cmp= cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
- nparts, tailf);
- if (cmp > 0)
+ if (cmp_rec_and_tuple_prune(list_col_array + list_index*num_columns,
+ nparts, left_endpoint, include_endpoint) > 0)
min_list_index= list_index + 1;
- else if (cmp < 0)
- {
- if (!list_index)
- goto notfound;
- max_list_index= list_index - 1;
- }
- else
- {
- DBUG_RETURN(list_index + test(!tailf));
- }
- } while (max_list_index >= min_list_index);
- if (cmp > 0)
- list_index++;
-notfound:
+ else
+ max_list_index= list_index;
+ } while (max_list_index > min_list_index);
+ list_index= max_list_index;
+
+ /* Given value must be LESS THAN or EQUAL to the found partition. */
+ DBUG_ASSERT(list_index == part_info->num_list_values ||
+ (0 >= cmp_rec_and_tuple_prune(list_col_array +
+ list_index*num_columns,
+ nparts, left_endpoint,
+ include_endpoint)));
+ /* Given value must be GREATER THAN the previous partition. */
+ DBUG_ASSERT(list_index == 0 ||
+ (0 < cmp_rec_and_tuple_prune(list_col_array +
+ (list_index - 1)*num_columns,
+ nparts, left_endpoint,
+ include_endpoint)));
+
+ if (!left_endpoint)
+ {
+ /* Set the end after this list tuple if not already after the last. */
+ if (list_index < part_info->num_parts)
+ list_index++;
+ }
+
DBUG_RETURN(list_index);
}
+/**
+ Find the sub-array part_info->list_array that corresponds to given interval.
+
+ @param part_info Partitioning info (partitioning type must be LIST)
+ @param left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
+ FALSE - the interval is (-inf; a] or (-inf; a)
+ @param include_endpoint TRUE iff the interval includes the endpoint
+
+ This function finds the sub-array of part_info->list_array where values of
+ list_array[idx].list_value are contained within the specifed interval.
+ list_array is ordered by list_value, so
+ 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
+ sought sub-array starts at some index idx and continues till array end.
+ The function returns first number idx, such that
+ list_array[idx].list_value is contained within the passed interval.
+
+ 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
+ sought sub-array starts at array start and continues till some last
+ index idx.
+ The function returns first number idx, such that
+ list_array[idx].list_value is NOT contained within the passed interval.
+ If all array elements are contained, part_info->num_list_values is
+ returned.
+
+ @note The caller will call this function and then will run along the
+ sub-array of list_array to collect partition ids. If the number of list
+ values is significantly higher then number of partitions, this could be slow
+ and we could invent some other approach. The "run over list array" part is
+ already wrapped in a get_next()-like function.
+
+ @return The index of corresponding sub-array of part_info->list_array.
+*/
+
uint32 get_list_array_idx_for_endpoint_charset(partition_info *part_info,
bool left_endpoint,
bool include_endpoint)
@@ -7427,15 +7434,17 @@ uint32 store_tuple_to_record(Field **pfield,
return nparts;
}
-/*
- RANGE(columns) partitioning: compare value bound and probe tuple.
+/**
+ RANGE(columns) partitioning: compare partition value bound and probe tuple.
- The value bound always is a full tuple (but may include the MAXVALUE
- special value).
+ @param val Partition column values.
+ @param nvals_in_rec Number of (prefix) fields to compare.
- The probe tuple may be a prefix of partitioning tuple. The tail_is_min
- parameter specifies whether the suffix components should be assumed to
- hold MAXVALUE
+ @return Less than/Equal to/Greater than 0 if the record is L/E/G than val.
+
+ @note The partition value bound is always a full tuple (but may include the
+ MAXVALUE special value). The probe tuple may be a prefix of partitioning
+ tuple.
*/
static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec)
@@ -7465,25 +7474,73 @@ static int cmp_rec_and_tuple(part_column_list_val *val, uint32 nvals_in_rec)
}
+/**
+ Compare record and columns partition tuple including endpoint handling.
+
+ @param val Columns partition tuple
+ @param n_vals_in_rec Number of columns to compare
+ @param is_left_endpoint True if left endpoint (part_tuple < rec or
+ part_tuple <= rec)
+ @param include_endpoint If endpoint is included (part_tuple <= rec or
+ rec <= part_tuple)
+
+ @return Less than/Equal to/Greater than 0 if the record is L/E/G than
+ the partition tuple.
+
+ @see get_list_array_idx_for_endpoint() and
+ get_partition_id_range_for_endpoint().
+*/
+
static int cmp_rec_and_tuple_prune(part_column_list_val *val,
uint32 n_vals_in_rec,
- bool tail_is_min)
+ bool is_left_endpoint,
+ bool include_endpoint)
{
int cmp;
Field **field;
- partition_info *part_info;
if ((cmp= cmp_rec_and_tuple(val, n_vals_in_rec)))
return cmp;
- part_info= val->part_info;
- field= part_info->part_field_array + n_vals_in_rec;
- for (; *field; field++, val++)
+ field= val->part_info->part_field_array + n_vals_in_rec;
+ if (!(*field))
{
- if (tail_is_min)
- return -1;
- if (!tail_is_min && !val->max_value)
- return +1;
+ /*
+ Full match, if right endpoint and not including the endpoint,
+ (rec < part) return lesser.
+ */
+ if (!is_left_endpoint && !include_endpoint)
+ return -4;
+
+ /* Otherwise they are equal! */
+ return 0;
}
- return 0;
+ /*
+ The prefix is equal and there are more partition columns to compare.
+
+ If including left endpoint or not including right endpoint
+ then the record is considered lesser compared to the partition.
+
+ i.e:
+ part(10, x) <= rec(10, unknown) and rec(10, unknown) < part(10, x)
+ part <= rec -> lesser (i.e. this or previous partitions)
+ rec < part -> lesser (i.e. this or previous partitions)
+ */
+ if (is_left_endpoint == include_endpoint)
+ return -2;
+
+ /*
+ If right endpoint and the first additional partition value
+ is MAXVALUE, then the record is lesser.
+ */
+ if (!is_left_endpoint && (val + n_vals_in_rec)->max_value)
+ return -3;
+
+ /*
+ Otherwise the record is considered greater.
+
+ rec <= part -> greater (i.e. does not match this partition, seek higher).
+ part < rec -> greater (i.e. does not match this partition, seek higher).
+ */
+ return 2;
}
@@ -7494,91 +7551,65 @@ typedef uint32 (*get_col_endpoint_func)(partition_info*, bool left_endpoint,
bool include_endpoint,
uint32 num_parts);
-/*
- Partitioning Interval Analysis: Initialize the iterator for "mapping" case
+/**
+ Get partition for RANGE COLUMNS endpoint.
- SYNOPSIS
- get_part_iter_for_interval_via_mapping()
- part_info Partition info
- is_subpart TRUE - act for subpartitioning
- FALSE - act for partitioning
- min_value minimum field value, in opt_range key format.
- max_value minimum field value, in opt_range key format.
- flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
- NO_MAX_RANGE.
- part_iter Iterator structure to be initialized
+ @param part_info Partitioning metadata.
+ @param is_left_endpoint True if left endpoint (const <=/< cols)
+ @param include_endpoint True if range includes the endpoint (<=/>=)
+ @param nparts Total number of partitions
- DESCRIPTION
- Initialize partition set iterator to walk over the interval in
- ordered-array-of-partitions (for RANGE partitioning) or
- ordered-array-of-list-constants (for LIST partitioning) space.
+ @return Partition id of matching partition.
- IMPLEMENTATION
- This function is used when partitioning is done by
- <RANGE|LIST>(ascending_func(t.field)), and we can map an interval in
- t.field space into a sub-array of partition_info::range_int_array or
- partition_info::list_array (see get_partition_id_range_for_endpoint,
- get_list_array_idx_for_endpoint for details).
-
- The function performs this interval mapping, and sets the iterator to
- traverse the sub-array and return appropriate partitions.
-
- RETURN
- 0 - No matching partitions (iterator not initialized)
- 1 - Ok, iterator intialized for traversal of matching partitions.
- -1 - All partitions would match (iterator not initialized)
+ @see get_partition_id_cols_list_for_endpoint and
+ get_partition_id_range_for_endpoint.
*/
uint32 get_partition_id_cols_range_for_endpoint(partition_info *part_info,
- bool left_endpoint,
+ bool is_left_endpoint,
bool include_endpoint,
uint32 nparts)
{
- uint max_partition= part_info->num_parts - 1;
- uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
+ uint min_part_id= 0, max_part_id= part_info->num_parts, loc_part_id;
part_column_list_val *range_col_array= part_info->range_col_array;
uint num_columns= part_info->part_field_list.elements;
- bool tailf= !(left_endpoint ^ include_endpoint);
DBUG_ENTER("get_partition_id_cols_range_for_endpoint");
- /* Get the partitioning function value for the endpoint */
- while (max_part_id > min_part_id)
+ /* Find the matching partition (including taking endpoint into account). */
+ do
{
- loc_part_id= (max_part_id + min_part_id + 1) >> 1;
- if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
- nparts, tailf) >= 0)
+ /* Midpoint, adjusted down, so it can never be > last partition. */
+ loc_part_id= (max_part_id + min_part_id) >> 1;
+ if (0 <= cmp_rec_and_tuple_prune(range_col_array +
+ loc_part_id * num_columns,
+ nparts,
+ is_left_endpoint,
+ include_endpoint))
min_part_id= loc_part_id + 1;
else
- max_part_id= loc_part_id - 1;
- }
+ max_part_id= loc_part_id;
+ } while (max_part_id > min_part_id);
loc_part_id= max_part_id;
- if (loc_part_id < max_partition &&
- cmp_rec_and_tuple_prune(range_col_array + (loc_part_id+1)*num_columns,
- nparts, tailf) >= 0
- )
- {
- loc_part_id++;
- }
- if (left_endpoint)
- {
- if (cmp_rec_and_tuple_prune(range_col_array + loc_part_id*num_columns,
- nparts, tailf) >= 0)
+
+ /* Given value must be LESS THAN the found partition. */
+ DBUG_ASSERT(loc_part_id == part_info->num_parts ||
+ (0 > cmp_rec_and_tuple_prune(range_col_array +
+ loc_part_id * num_columns,
+ nparts, is_left_endpoint,
+ include_endpoint)));
+ /* Given value must be GREATER THAN or EQUAL to the previous partition. */
+ DBUG_ASSERT(loc_part_id == 0 ||
+ (0 <= cmp_rec_and_tuple_prune(range_col_array +
+ (loc_part_id - 1) * num_columns,
+ nparts, is_left_endpoint,
+ include_endpoint)));
+
+ if (!is_left_endpoint)
+ {
+ /* Set the end after this partition if not already after the last. */
+ if (loc_part_id < part_info->num_parts)
loc_part_id++;
}
- else
- {
- if (loc_part_id < max_partition)
- {
- int res= cmp_rec_and_tuple_prune(range_col_array +
- loc_part_id * num_columns,
- nparts, tailf);
- if (!res)
- loc_part_id += test(include_endpoint);
- else if (res > 0)
- loc_part_id++;
- }
- loc_part_id++;
- }
DBUG_RETURN(loc_part_id);
}
@@ -7650,6 +7681,40 @@ int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
}
+/**
+ Partitioning Interval Analysis: Initialize the iterator for "mapping" case
+
+ @param part_info Partition info
+ @param is_subpart TRUE - act for subpartitioning
+ FALSE - act for partitioning
+ @param store_length_array Ignored.
+ @param min_value minimum field value, in opt_range key format.
+ @param max_value minimum field value, in opt_range key format.
+ @param min_len Ignored.
+ @param max_len Ignored.
+ @param flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
+ NO_MAX_RANGE.
+ @param part_iter Iterator structure to be initialized
+
+ @details Initialize partition set iterator to walk over the interval in
+ ordered-array-of-partitions (for RANGE partitioning) or
+ ordered-array-of-list-constants (for LIST partitioning) space.
+
+ This function is used when partitioning is done by
+ <RANGE|LIST>(ascending_func(t.field)), and we can map an interval in
+ t.field space into a sub-array of partition_info::range_int_array or
+ partition_info::list_array (see get_partition_id_range_for_endpoint,
+ get_list_array_idx_for_endpoint for details).
+
+ The function performs this interval mapping, and sets the iterator to
+ traverse the sub-array and return appropriate partitions.
+
+ @return Status of iterator
+ @retval 0 No matching partitions (iterator not initialized)
+ @retval 1 Ok, iterator intialized for traversal of matching partitions.
+ @retval -1 All partitions would match (iterator not initialized)
+*/
+
int get_part_iter_for_interval_via_mapping(partition_info *part_info,
bool is_subpart,
uint32 *store_length_array, /* ignored */
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 6d2a33450de..0ece0e1967d 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -176,8 +176,7 @@ static struct
/* we disable few other plugins by default */
{ "ndbcluster", PLUGIN_OFF },
- { "feedback", PLUGIN_OFF },
- { "pbxt", PLUGIN_OFF }
+ { "feedback", PLUGIN_OFF }
};
/* support for Services */
@@ -691,6 +690,8 @@ static my_bool read_maria_plugin_info(struct st_plugin_dl *plugin_dl,
sym= cur;
plugin_dl->allocated= true;
}
+ else
+ sym= ptr;
}
plugin_dl->plugins= (struct st_maria_plugin *)sym;
@@ -2437,6 +2438,7 @@ typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_longlong_t, longlong);
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_uint_t, uint);
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulong_t, ulong);
typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_ulonglong_t, ulonglong);
+typedef DECLARE_MYSQL_SYSVAR_SIMPLE(sysvar_double_t, double);
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_int_t, int);
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_long_t, long);
@@ -2444,6 +2446,7 @@ typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_longlong_t, longlong);
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint);
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong);
typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong);
+typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_double_t, double);
/****************************************************************************
@@ -2659,6 +2662,20 @@ err:
return 1;
}
+static int check_func_double(THD *thd, struct st_mysql_sys_var *var,
+ void *save, st_mysql_value *value)
+{
+ double v;
+ my_bool fixed;
+ struct my_option option;
+
+ value->val_real(value, &v);
+ plugin_opt_set_limits(&option, var);
+ *(double *) save= getopt_double_limit_value(v, &option, &fixed);
+
+ return throw_bounds_warning(thd, var->name, fixed, v);
+}
+
static void update_func_bool(THD *thd, struct st_mysql_sys_var *var,
void *tgt, const void *save)
@@ -2697,12 +2714,19 @@ static void update_func_str(THD *thd, struct st_mysql_sys_var *var,
char *old= *(char**) tgt;
if (value)
*(char**) tgt= my_strdup(value, MYF(0));
+ else
+ *(char**) tgt= 0;
my_free(old);
}
else
*(char**) tgt= value;
}
+static void update_func_double(THD *thd, struct st_mysql_sys_var *var,
+ void *tgt, const void *save)
+{
+ *(double *) tgt= *(double *) save;
+}
/****************************************************************************
System Variables support
@@ -2817,6 +2841,9 @@ static st_bookmark *register_var(const char *plugin, const char *name,
case PLUGIN_VAR_STR:
size= sizeof(char*);
break;
+ case PLUGIN_VAR_DOUBLE:
+ size= sizeof(double);
+ break;
default:
DBUG_ASSERT(0);
return NULL;
@@ -3029,6 +3056,11 @@ static char **mysql_sys_var_str(THD* thd, int offset)
return (char **) intern_sys_var_ptr(thd, offset, true);
}
+static double *mysql_sys_var_double(THD* thd, int offset)
+{
+ return (double *) intern_sys_var_ptr(thd, offset, true);
+}
+
void plugin_thdvar_init(THD *thd)
{
plugin_ref old_table_plugin= thd->variables.table_plugin;
@@ -3181,6 +3213,8 @@ static SHOW_TYPE pluginvar_show_type(st_mysql_sys_var *plugin_var)
case PLUGIN_VAR_ENUM:
case PLUGIN_VAR_SET:
return SHOW_CHAR;
+ case PLUGIN_VAR_DOUBLE:
+ return SHOW_DOUBLE;
default:
DBUG_ASSERT(0);
return SHOW_UNDEF;
@@ -3201,6 +3235,8 @@ bool sys_var_pluginvar::check_update_type(Item_result type)
case PLUGIN_VAR_BOOL:
case PLUGIN_VAR_SET:
return type != STRING_RESULT && type != INT_RESULT;
+ case PLUGIN_VAR_DOUBLE:
+ return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT;
default:
return true;
}
@@ -3319,6 +3355,9 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
case PLUGIN_VAR_STR:
src= &((sysvar_str_t*) plugin_var)->def_val;
break;
+ case PLUGIN_VAR_DOUBLE:
+ src= &((sysvar_double_t*) plugin_var)->def_val;
+ break;
case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
src= &((thdvar_uint_t*) plugin_var)->def_val;
break;
@@ -3340,6 +3379,9 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
src= &((thdvar_str_t*) plugin_var)->def_val;
break;
+ case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL:
+ src= &((thdvar_double_t*) plugin_var)->def_val;
+ break;
default:
DBUG_ASSERT(0);
}
@@ -3357,6 +3399,13 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
options->max_value= (opt)->max_val; \
options->block_size= (long) (opt)->blk_sz
+#define OPTION_SET_LIMITS_DOUBLE(options, opt) \
+ options->var_type= GET_DOUBLE; \
+ options->def_value= (longlong) getopt_double2ulonglong((opt)->def_val); \
+ options->min_value= (longlong) getopt_double2ulonglong((opt)->min_val); \
+ options->max_value= getopt_double2ulonglong((opt)->max_val); \
+ options->block_size= (long) (opt)->blk_sz;
+
void plugin_opt_set_limits(struct my_option *options,
const struct st_mysql_sys_var *opt)
@@ -3407,6 +3456,9 @@ void plugin_opt_set_limits(struct my_option *options,
GET_STR_ALLOC : GET_STR);
options->def_value= (intptr) ((sysvar_str_t*) opt)->def_val;
break;
+ case PLUGIN_VAR_DOUBLE:
+ OPTION_SET_LIMITS_DOUBLE(options, (sysvar_double_t*) opt);
+ break;
/* threadlocal variables */
case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
OPTION_SET_LIMITS(GET_INT, options, (thdvar_int_t*) opt);
@@ -3426,6 +3478,9 @@ void plugin_opt_set_limits(struct my_option *options,
case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL:
OPTION_SET_LIMITS(GET_ULL, options, (thdvar_ulonglong_t*) opt);
break;
+ case PLUGIN_VAR_DOUBLE | PLUGIN_VAR_THDLOCAL:
+ OPTION_SET_LIMITS_DOUBLE(options, (thdvar_double_t*) opt);
+ break;
case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL:
options->var_type= GET_ENUM;
options->typelib= ((thdvar_enum_t*) opt)->typelib;
@@ -3577,6 +3632,9 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
case PLUGIN_VAR_SET:
((thdvar_set_t *) opt)->resolve= mysql_sys_var_ulonglong;
break;
+ case PLUGIN_VAR_DOUBLE:
+ ((thdvar_double_t *) opt)->resolve= mysql_sys_var_double;
+ break;
default:
sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
opt->flags, plugin_name);
@@ -3640,6 +3698,12 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
if (!opt->update)
opt->update= update_func_longlong;
break;
+ case PLUGIN_VAR_DOUBLE:
+ if (!opt->check)
+ opt->check= check_func_double;
+ if (!opt->update)
+ opt->update= update_func_double;
+ break;
default:
sql_print_error("Unknown variable type code 0x%x in plugin '%s'.",
opt->flags, plugin_name);
diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h
index 6b70048345a..362252eee8a 100644
--- a/sql/sql_plugin_services.h
+++ b/sql/sql_plugin_services.h
@@ -64,6 +64,16 @@ static struct my_sha1_service_st my_sha1_handler = {
my_sha1_multi
};
+static struct logger_service_st logger_service_handler= {
+ logger_init_mutexes,
+ logger_open,
+ logger_close,
+ logger_vprintf,
+ logger_printf,
+ logger_write,
+ logger_rotate
+};
+
static struct st_service_ref list_of_services[]=
{
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
@@ -73,6 +83,7 @@ static struct st_service_ref list_of_services[]=
{ "debug_sync_service", VERSION_debug_sync, 0 }, // updated in plugin_init()
{ "thd_kill_statement_service", VERSION_kill_statement, &thd_kill_statement_handler },
{ "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler },
- { "my_sha1_service", VERSION_my_sha1, &my_sha1_handler}
+ { "my_sha1_service", VERSION_my_sha1, &my_sha1_handler},
+ { "logger_service", VERSION_logger, &logger_service_handler },
};
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4465da6eeac..494f603cd8e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1471,7 +1471,10 @@ static bool mysql_test_delete(Prepared_statement *stmt,
goto error;
}
- DBUG_RETURN(mysql_prepare_delete(thd, table_list, &lex->select_lex.where));
+ DBUG_RETURN(mysql_prepare_delete(thd, table_list,
+ lex->select_lex.with_wild,
+ lex->select_lex.item_list,
+ &lex->select_lex.where));
error:
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index f3eab6b84cf..5df5b0ab3f7 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -322,7 +322,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
{
DBUG_ASSERT(thd);
tmp_write_to_binlog= 0;
- if (reset_master(thd))
+ if (reset_master(thd, NULL, 0))
{
/* NOTE: my_error() has been already called by reset_master(). */
result= 1;
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 78acb4a519f..6babdd7c636 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2013, Monty Program Ab.
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
@@ -296,7 +297,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
and handler's data and report about failure to rename table.
*/
(void) mysql_rename_table(hton, new_db, new_alias,
- ren_table->db, old_alias, 0);
+ ren_table->db, old_alias, NO_FK_CHECKS);
}
}
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 5a93f3b819a..5d508b56dac 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -884,6 +884,28 @@ contains_all_slave_gtid(slave_connection_state *st, Gtid_list_log_event *glev)
}
+static void
+give_error_start_pos_missing_in_binlog(int *err, const char **errormsg,
+ rpl_gtid *error_gtid)
+{
+ rpl_gtid binlog_gtid;
+
+ if (mysql_bin_log.lookup_domain_in_binlog_state(error_gtid->domain_id,
+ &binlog_gtid) &&
+ binlog_gtid.seq_no >= error_gtid->seq_no)
+ {
+ *errormsg= "Requested slave GTID state not found in binlog. The slave has "
+ "probably diverged due to executing errorneous transactions";
+ *err= ER_GTID_POSITION_NOT_FOUND_IN_BINLOG2;
+ }
+ else
+ {
+ *errormsg= "Requested slave GTID state not found in binlog";
+ *err= ER_GTID_POSITION_NOT_FOUND_IN_BINLOG;
+ }
+}
+
+
/*
Check the start GTID state requested by the slave against our binlog state.
@@ -894,43 +916,51 @@ contains_all_slave_gtid(slave_connection_state *st, Gtid_list_log_event *glev)
static int
check_slave_start_position(THD *thd, slave_connection_state *st,
const char **errormsg, rpl_gtid *error_gtid,
- slave_connection_state *until_gtid_state,
- HASH *fake_gtid_hash)
+ slave_connection_state *until_gtid_state)
{
uint32 i;
int err;
- rpl_gtid **delete_list= NULL;
+ slave_connection_state::entry **delete_list= NULL;
uint32 delete_idx= 0;
- bool slave_state_loaded= false;
+
+ if (rpl_load_gtid_slave_state(thd))
+ {
+ *errormsg= "Failed to load replication slave GTID state";
+ err= ER_CANNOT_LOAD_SLAVE_GTID_STATE;
+ goto end;
+ }
for (i= 0; i < st->hash.records; ++i)
{
- rpl_gtid *slave_gtid= (rpl_gtid *)my_hash_element(&st->hash, i);
+ slave_connection_state::entry *slave_gtid_entry=
+ (slave_connection_state::entry *)my_hash_element(&st->hash, i);
+ rpl_gtid *slave_gtid= &slave_gtid_entry->gtid;
rpl_gtid master_gtid;
rpl_gtid master_replication_gtid;
rpl_gtid start_gtid;
+ bool start_at_own_slave_pos=
+ rpl_global_gtid_slave_state.domain_to_gtid(slave_gtid->domain_id,
+ &master_replication_gtid) &&
+ slave_gtid->server_id == master_replication_gtid.server_id &&
+ slave_gtid->seq_no == master_replication_gtid.seq_no;
if (mysql_bin_log.find_in_binlog_state(slave_gtid->domain_id,
slave_gtid->server_id,
&master_gtid) &&
master_gtid.seq_no >= slave_gtid->seq_no)
- continue;
-
- if (!slave_state_loaded)
{
- if (rpl_load_gtid_slave_state(thd))
- {
- *errormsg= "Failed to load replication slave GTID state";
- err= ER_CANNOT_LOAD_SLAVE_GTID_STATE;
- goto end;
- }
- slave_state_loaded= true;
+ /*
+ If connecting slave requests to start at the GTID we last applied when
+ we were ourselves a slave, then this GTID may not exist in our binlog
+ (in case of --log-slave-updates=0). So set the flag to disable the
+ error about missing GTID in the binlog in this case.
+ */
+ if (start_at_own_slave_pos)
+ slave_gtid_entry->flags|= slave_connection_state::START_OWN_SLAVE_POS;
+ continue;
}
- if (!rpl_global_gtid_slave_state.domain_to_gtid(slave_gtid->domain_id,
- &master_replication_gtid) ||
- slave_gtid->server_id != master_replication_gtid.server_id ||
- slave_gtid->seq_no != master_replication_gtid.seq_no)
+ if (!start_at_own_slave_pos)
{
rpl_gtid domain_gtid;
rpl_gtid *until_gtid;
@@ -942,7 +972,12 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
We do not have anything in this domain, neither in the binlog nor
in the slave state. So we are probably one master in a multi-master
setup, and this domain is served by a different master.
+
+ But set a flag so that if we then ever _do_ happen to encounter
+ anything in this domain, then we will re-check that the requested
+ slave position exists, and give the error at that time if not.
*/
+ slave_gtid_entry->flags|= slave_connection_state::START_ON_EMPTY_DOMAIN;
continue;
}
@@ -966,9 +1001,8 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
continue;
}
- *errormsg= "Requested slave GTID state not found in binlog";
*error_gtid= *slave_gtid;
- err= ER_GTID_POSITION_NOT_FOUND_IN_BINLOG;
+ give_error_start_pos_missing_in_binlog(&err, errormsg, error_gtid);
goto end;
}
@@ -999,7 +1033,6 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
&start_gtid) &&
start_gtid.seq_no > slave_gtid->seq_no)
{
- rpl_gtid *fake_gtid;
/*
Start replication within this domain at the first GTID that we logged
ourselves after becoming a master.
@@ -1009,20 +1042,7 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
--gtid-strict-mode.
*/
slave_gtid->server_id= global_system_variables.server_id;
- if (!(fake_gtid= (rpl_gtid *)my_malloc(sizeof(*fake_gtid), MYF(0))))
- {
- *errormsg= "Out of memory while checking slave start position";
- err= ER_OUT_OF_RESOURCES;
- goto end;
- }
- *fake_gtid= *slave_gtid;
- if (my_hash_insert(fake_gtid_hash, (uchar *)fake_gtid))
- {
- my_free(fake_gtid);
- *errormsg= "Out of memory while checking slave start position";
- err= ER_OUT_OF_RESOURCES;
- goto end;
- }
+ slave_gtid_entry->flags|= slave_connection_state::START_OWN_SLAVE_POS;
}
else if (mysql_bin_log.lookup_domain_in_binlog_state(slave_gtid->domain_id,
&start_gtid))
@@ -1042,7 +1062,7 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
*/
if (!delete_list)
{
- if (!(delete_list= (rpl_gtid **)
+ if (!(delete_list= (slave_connection_state::entry **)
my_malloc(sizeof(*delete_list) * st->hash.records, MYF(MY_WME))))
{
*errormsg= "Out of memory while checking slave start position";
@@ -1050,7 +1070,7 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
goto end;
}
}
- delete_list[delete_idx++]= slave_gtid;
+ delete_list[delete_idx++]= slave_gtid_entry;
}
}
@@ -1058,7 +1078,7 @@ check_slave_start_position(THD *thd, slave_connection_state *st,
if (delete_list)
{
for (i= 0; i < delete_idx; ++i)
- st->remove(delete_list[i]);
+ st->remove(&(delete_list[i]->gtid));
}
err= 0;
@@ -1249,6 +1269,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
int err;
String packet;
+ Format_description_log_event *fdev= NULL;
if (gtid_state->load((const rpl_gtid *)NULL, 0))
{
@@ -1260,6 +1281,13 @@ gtid_state_from_pos(const char *name, uint32 offset,
if ((file= open_binlog(&cache, name, &errormsg)) == (File)-1)
return errormsg;
+ if (!(fdev= new Format_description_log_event(3)))
+ {
+ errormsg= "Out of memory initializing format_description event "
+ "while scanning binlog to find start position";
+ goto end;
+ }
+
/*
First we need to find the initial GTID_LIST_EVENT. We need this even
if the offset is at the very start of the binlog file.
@@ -1295,6 +1323,8 @@ gtid_state_from_pos(const char *name, uint32 offset,
typ= (Log_event_type)(uchar)packet[EVENT_TYPE_OFFSET];
if (typ == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
if (found_format_description_event)
{
errormsg= "Duplicate format description log event found while "
@@ -1304,6 +1334,15 @@ gtid_state_from_pos(const char *name, uint32 offset,
current_checksum_alg= get_checksum_alg(packet.ptr(), packet.length());
found_format_description_event= true;
+ if (!(tmp= new Format_description_log_event(packet.ptr(), packet.length(),
+ fdev)))
+ {
+ errormsg= "Corrupt Format_description event found or out-of-memory "
+ "while searching for old-style position in binlog";
+ goto end;
+ }
+ delete fdev;
+ fdev= tmp;
}
else if (typ != FORMAT_DESCRIPTION_EVENT && !found_format_description_event)
{
@@ -1328,7 +1367,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
}
status= Gtid_list_log_event::peek(packet.ptr(), packet.length(),
current_checksum_alg,
- &gtid_list, &list_len);
+ &gtid_list, &list_len, fdev);
if (status)
{
errormsg= "Error reading Gtid_list_log_event while searching "
@@ -1356,7 +1395,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
uchar flags2;
if (Gtid_log_event::peek(packet.ptr(), packet.length(),
current_checksum_alg, &gtid.domain_id,
- &gtid.server_id, &gtid.seq_no, &flags2))
+ &gtid.server_id, &gtid.seq_no, &flags2, fdev))
{
errormsg= "Corrupt gtid_log_event found while scanning binlog to find "
"initial slave position";
@@ -1379,6 +1418,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
}
end:
+ delete fdev;
end_io_cache(&cache);
mysql_file_close(file, MYF(MY_WME));
@@ -1482,7 +1522,8 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
enum_gtid_until_state *gtid_until_group,
rpl_binlog_state *until_binlog_state,
bool slave_gtid_strict_mode, rpl_gtid *error_gtid,
- bool *send_fake_gtid_list, HASH *fake_gtid_hash)
+ bool *send_fake_gtid_list,
+ Format_description_log_event *fdev)
{
my_off_t pos;
size_t len= packet->length();
@@ -1496,7 +1537,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
if (ev_offset > len ||
Gtid_list_log_event::peek(packet->ptr()+ev_offset, len - ev_offset,
current_checksum_alg,
- &gtid_list, &list_len))
+ &gtid_list, &list_len, fdev))
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
return "Failed to read Gtid_list_log_event: corrupt binlog";
@@ -1514,6 +1555,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
if (event_type == GTID_EVENT && using_gtid_state)
{
uchar flags2;
+ slave_connection_state::entry *gtid_entry;
rpl_gtid *gtid;
if (gtid_state->count() > 0 || until_gtid_state)
@@ -1524,7 +1566,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
Gtid_log_event::peek(packet->ptr()+ev_offset, len - ev_offset,
current_checksum_alg,
&event_gtid.domain_id, &event_gtid.server_id,
- &event_gtid.seq_no, &flags2))
+ &event_gtid.seq_no, &flags2, fdev))
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
return "Failed to read Gtid_log_event: corrupt binlog";
@@ -1551,9 +1593,28 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
if (gtid_state->count() > 0)
{
- gtid= gtid_state->find(event_gtid.domain_id);
- if (gtid != NULL)
+ gtid_entry= gtid_state->find_entry(event_gtid.domain_id);
+ if (gtid_entry != NULL)
{
+ gtid= &gtid_entry->gtid;
+ if (gtid_entry->flags & slave_connection_state::START_ON_EMPTY_DOMAIN)
+ {
+ rpl_gtid master_gtid;
+ if (!mysql_bin_log.find_in_binlog_state(gtid->domain_id,
+ gtid->server_id,
+ &master_gtid) ||
+ master_gtid.seq_no < gtid->seq_no)
+ {
+ int err;
+ const char *errormsg;
+ *error_gtid= *gtid;
+ give_error_start_pos_missing_in_binlog(&err, &errormsg, error_gtid);
+ my_errno= err;
+ return errormsg;
+ }
+ gtid_entry->flags&= ~(uint32)slave_connection_state::START_ON_EMPTY_DOMAIN;
+ }
+
/* Skip this event group if we have not yet reached slave start pos. */
if (event_gtid.server_id != gtid->server_id ||
event_gtid.seq_no <= gtid->seq_no)
@@ -1563,8 +1624,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
event_gtid.seq_no >= gtid->seq_no)
{
if (slave_gtid_strict_mode && event_gtid.seq_no > gtid->seq_no &&
- !my_hash_search(fake_gtid_hash,
- (const uchar *)&event_gtid.domain_id, 0))
+ !(gtid_entry->flags & slave_connection_state::START_OWN_SLAVE_POS))
{
/*
In strict mode, it is an error if the slave requests to start
@@ -1839,10 +1899,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
rpl_binlog_state until_binlog_state;
bool slave_gtid_strict_mode= false;
bool send_fake_gtid_list= false;
- HASH fake_gtid_hash;
uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
int old_max_allowed_packet= thd->variables.max_allowed_packet;
+ Format_description_log_event *fdev= NULL;
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
@@ -1853,9 +1913,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
bzero((char*) &log,sizeof(log));
bzero(&error_gtid, sizeof(error_gtid));
- my_hash_init(&fake_gtid_hash, &my_charset_bin, 32,
- offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, my_free,
- HASH_UNIQUE);
/*
heartbeat_period from @master_heartbeat_period user variable
*/
@@ -1921,6 +1978,13 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
}
#endif
+ if (!(fdev= new Format_description_log_event(3)))
+ {
+ errmsg= "Out of memory initializing format_description event";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ goto err;
+ }
+
if (!mysql_bin_log.is_open())
{
errmsg = "Binary log is not open";
@@ -1955,8 +2019,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
goto err;
}
if ((error= check_slave_start_position(thd, &gtid_state, &errmsg,
- &error_gtid, until_gtid_state,
- &fake_gtid_hash)))
+ &error_gtid, until_gtid_state)))
{
my_errno= error;
goto err;
@@ -2085,6 +2148,8 @@ impossible position";
(*packet)[EVENT_TYPE_OFFSET+ev_offset]));
if ((*packet)[EVENT_TYPE_OFFSET+ev_offset] == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
current_checksum_alg= get_checksum_alg(packet->ptr() + ev_offset,
packet->length() - ev_offset);
DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF ||
@@ -2102,6 +2167,18 @@ impossible position";
"slaves that cannot process them");
goto err;
}
+
+ if (!(tmp= new Format_description_log_event(packet->ptr()+ev_offset,
+ packet->length()-ev_offset,
+ fdev)))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ errmsg= "Corrupt Format_description event found or out-of-memory";
+ goto err;
+ }
+ delete fdev;
+ fdev= tmp;
+
(*packet)[FLAGS_OFFSET+ev_offset] &= ~LOG_EVENT_BINLOG_IN_USE_F;
/*
mark that this event with "log_pos=0", so the slave
@@ -2219,6 +2296,8 @@ impossible position";
#endif
if (event_type == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
current_checksum_alg= get_checksum_alg(packet->ptr() + ev_offset,
packet->length() - ev_offset);
DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF ||
@@ -2237,6 +2316,17 @@ impossible position";
goto err;
}
+ if (!(tmp= new Format_description_log_event(packet->ptr()+ev_offset,
+ packet->length()-ev_offset,
+ fdev)))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ errmsg= "Corrupt Format_description event found or out-of-memory";
+ goto err;
+ }
+ delete fdev;
+ fdev= tmp;
+
(*packet)[FLAGS_OFFSET+ev_offset] &= ~LOG_EVENT_BINLOG_IN_USE_F;
}
@@ -2261,7 +2351,7 @@ impossible position";
until_gtid_state, &gtid_until_group,
&until_binlog_state,
slave_gtid_strict_mode, &error_gtid,
- &send_fake_gtid_list, &fake_gtid_hash)))
+ &send_fake_gtid_list, fdev)))
{
errmsg= tmp_msg;
goto err;
@@ -2467,8 +2557,7 @@ impossible position";
&gtid_skip_group, until_gtid_state,
&gtid_until_group, &until_binlog_state,
slave_gtid_strict_mode, &error_gtid,
- &send_fake_gtid_list,
- &fake_gtid_hash)))
+ &send_fake_gtid_list, fdev)))
{
errmsg= tmp_msg;
goto err;
@@ -2558,7 +2647,6 @@ impossible position";
end:
end_io_cache(&log);
mysql_file_close(file, MYF(MY_WME));
- my_hash_free(&fake_gtid_hash);
RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags));
my_eof(thd);
@@ -2567,6 +2655,7 @@ end:
thd->current_linfo = 0;
mysql_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
+ delete fdev;
DBUG_VOID_RETURN;
err:
@@ -2595,6 +2684,18 @@ err:
/* Use this error code so slave will know not to try reconnect. */
my_errno = ER_MASTER_FATAL_ERROR_READING_BINLOG;
}
+ else if (my_errno == ER_GTID_POSITION_NOT_FOUND_IN_BINLOG2)
+ {
+ my_snprintf(error_text, sizeof(error_text),
+ "Error: connecting slave requested to start from GTID "
+ "%u-%u-%llu, which is not in the master's binlog. Since the "
+ "master's binlog contains GTIDs with higher sequence numbers, "
+ "it probably means that the slave has diverged due to "
+ "executing extra errorneous transactions",
+ error_gtid.domain_id, error_gtid.server_id, error_gtid.seq_no);
+ /* Use this error code so slave will know not to try reconnect. */
+ my_errno = ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ }
else if (my_errno == ER_GTID_START_FROM_BINLOG_HOLE)
{
my_snprintf(error_text, sizeof(error_text),
@@ -2629,8 +2730,8 @@ err:
mysql_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
mysql_file_close(file, MYF(MY_WME));
- my_hash_free(&fake_gtid_hash);
thd->variables.max_allowed_packet= old_max_allowed_packet;
+ delete fdev;
my_message(my_errno, error_text, MYF(0));
DBUG_VOID_RETURN;
@@ -3434,7 +3535,7 @@ err:
@retval 0 success
@retval 1 error
*/
-int reset_master(THD* thd)
+int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len)
{
if (!mysql_bin_log.is_open())
{
@@ -3443,7 +3544,7 @@ int reset_master(THD* thd)
return 1;
}
- if (mysql_bin_log.reset_logs(thd, 1))
+ if (mysql_bin_log.reset_logs(thd, 1, init_state, init_state_len))
return 1;
RUN_HOOK(binlog_transmit, after_reset_master, (thd, 0 /* flags */));
return 0;
@@ -3893,7 +3994,7 @@ rpl_append_gtid_state(String *dest, bool use_binlog)
/*
- Load the current GITD position into a slave_connection_state, for use when
+ Load the current GTID position into a slave_connection_state, for use when
connecting to a master server with GTID.
If the flag use_binlog is true, then the contents of the binary log (if
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 917da9b598e..da55e3e863f 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -46,7 +46,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report);
bool change_master(THD* thd, Master_info* mi, bool *master_info_added);
bool mysql_show_binlog_events(THD* thd);
int reset_slave(THD *thd, Master_info* mi);
-int reset_master(THD* thd);
+int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len);
bool purge_master_logs(THD* thd, const char* to_log);
bool purge_master_logs_before_date(THD* thd, time_t purge_time);
bool log_in_use(const char* log_name);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 93f47633a95..715ab133376 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1354,6 +1354,15 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S
/* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true
}
+
+ if (impossible_where)
+ {
+ zero_result_cause=
+ "Impossible WHERE noticed after reading const tables";
+ select_lex->mark_const_derived(zero_result_cause);
+ goto setup_subq_exit;
+ }
+
select= make_select(*table, const_table_map,
const_table_map, conds, 1, &error);
if (error)
@@ -1458,6 +1467,12 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S
new store_key_const_item(*tab->ref.key_copy[key_copy_index],
item);
}
+ else if (item->const_item())
+ {
+ tab->ref.key_copy[key_copy_index]=
+ new store_key_item(*tab->ref.key_copy[key_copy_index],
+ item, TRUE);
+ }
else
{
store_key_field *field_copy= ((store_key_field *)key_copy);
@@ -3748,6 +3763,18 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
+ join->impossible_where= false;
+ if (conds && const_count)
+ {
+ conds= remove_eq_conds(join->thd, conds, &join->cond_value);
+ if (join->cond_value == Item::COND_FALSE)
+ {
+ join->impossible_where= true;
+ conds=new Item_int((longlong) 0,1);
+ }
+ join->conds= conds;
+ }
+
/* Calc how many (possible) matched records in each table */
for (s=stat ; s < stat_end ; s++)
@@ -5209,8 +5236,23 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
Optionally (if out_args is supplied) will push the arguments of
AGGFN(DISTINCT) to the list
+ Check for every COUNT(DISTINCT), AVG(DISTINCT) or
+ SUM(DISTINCT). These can be resolved by Loose Index Scan as long
+ as all the aggregate distinct functions refer to the same
+ fields. Thus:
+
+ SELECT AGGFN(DISTINCT a, b), AGGFN(DISTINCT b, a)... => can use LIS
+ SELECT AGGFN(DISTINCT a), AGGFN(DISTINCT a) ... => can use LIS
+ SELECT AGGFN(DISTINCT a, b), AGGFN(DISTINCT a) ... => cannot use LIS
+ SELECT AGGFN(DISTINCT a), AGGFN(DISTINCT b) ... => cannot use LIS
+ etc.
+
@param join the join to check
- @param[out] out_args list of aggregate function arguments
+ @param[out] out_args Collect the arguments of the aggregate functions
+ to a list. We don't worry about duplicates as
+ these will be sorted out later in
+ get_best_group_min_max.
+
@return does the query qualify for indexed AGGFN(DISTINCT)
@retval true it does
@retval false AGGFN(DISTINCT) must apply distinct in it.
@@ -5221,6 +5263,7 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
{
Item_sum **sum_item_ptr;
bool result= false;
+ Field_map first_aggdistinct_fields;
if (join->table_count != 1 || /* reference more than 1 table */
join->select_distinct || /* or a DISTINCT */
@@ -5233,6 +5276,7 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
{
Item_sum *sum_item= *sum_item_ptr;
+ Field_map cur_aggdistinct_fields;
Item *expr;
/* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
switch (sum_item->sum_func())
@@ -5262,15 +5306,23 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
if (expr->real_item()->type() != Item::FIELD_ITEM)
return false;
- /*
- If we came to this point the AGGFN(DISTINCT) loose index scan
- optimization is applicable
- */
+ Item_field* item= static_cast<Item_field*>(expr->real_item());
if (out_args)
- out_args->push_back((Item_field *) expr->real_item());
+ out_args->push_back(item);
+
+ cur_aggdistinct_fields.set_bit(item->field->field_index);
result= true;
}
+ /*
+ If there are multiple aggregate functions, make sure that they all
+ refer to exactly the same set of columns.
+ */
+ if (first_aggdistinct_fields.is_clear_all())
+ first_aggdistinct_fields.merge(cur_aggdistinct_fields);
+ else if (first_aggdistinct_fields != cur_aggdistinct_fields)
+ return false;
}
+
return result;
}
@@ -8703,14 +8755,13 @@ static void add_not_null_conds(JOIN *join)
Item *item= tab->ref.items[keypart];
Item *notnull;
Item *real= item->real_item();
- if (real->basic_const_item())
+ if (real->const_item() && real->type() != Item::FIELD_ITEM &&
+ !real->is_expensive())
{
/*
It could be constant instead of field after constant
propagation.
*/
- DBUG_ASSERT(real->is_expensive() || // prevent early expensive eval
- !real->is_null()); // NULLs are not propagated
continue;
}
DBUG_ASSERT(real->type() == Item::FIELD_ITEM);
@@ -8954,10 +9005,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{ /* there may be a select without a cond. */
if (join->table_count > 1)
cond->update_used_tables(); // Tablenr may have changed
- if (join->const_tables == join->table_count &&
- thd->lex->current_select->master_unit() ==
- &thd->lex->unit) // not upper level SELECT
- join->const_table_map|=RAND_TABLE_BIT;
/*
Extract expressions that depend on constant tables
@@ -9301,19 +9348,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
else
{
sel->needed_reg=tab->needed_reg;
- sel->quick_keys.clear_all();
}
+ sel->quick_keys= tab->table->quick_keys;
if (!sel->quick_keys.is_subset(tab->checked_keys) ||
!sel->needed_reg.is_subset(tab->checked_keys))
{
- tab->keys=sel->quick_keys;
- tab->keys.merge(sel->needed_reg);
tab->use_quick= (!sel->needed_reg.is_clear_all() &&
- (select->quick_keys.is_clear_all() ||
- (select->quick &&
- (select->quick->records >= 100L)))) ?
+ (sel->quick_keys.is_clear_all() ||
+ (sel->quick &&
+ (sel->quick->records >= 100L)))) ?
2 : 1;
sel->read_tables= used_tables & ~current_map;
+ sel->quick_keys.clear_all();
}
if (i != join->const_tables && tab->use_quick != 2 &&
!tab->first_inner)
@@ -10736,6 +10782,11 @@ void JOIN_TAB::cleanup()
{
if (table->pos_in_table_list->jtbm_subselect->is_jtbm_const_tab)
{
+ /*
+ Set this to NULL so that cleanup_empty_jtbm_semi_joins() doesn't
+ attempt to make another free_tmp_table call.
+ */
+ table->pos_in_table_list->table= NULL;
free_tmp_table(join->thd, table);
table= NULL;
}
@@ -11159,6 +11210,7 @@ void JOIN::cleanup(bool full)
}
if (full)
{
+ cleanup_empty_jtbm_semi_joins(this);
/*
Ensure that the following delete_elements() would not be called
twice for the same list.
@@ -13904,22 +13956,230 @@ optimize_cond(JOIN *join, COND *conds,
/**
- Handles the recursive job remove_eq_conds()
+ @brief
+ Propagate multiple equalities to the sub-expressions of a condition
- Remove const and eq items. Return new item, or NULL if no condition
- cond_value is set to according:
- COND_OK query is possible (field = constant)
- COND_TRUE always true ( 1 = 1 )
- COND_FALSE always false ( 1 = 2 )
+ @param thd thread handle
+ @param cond the condition where equalities are to be propagated
+ @param *new_equalities the multiple equalities to be propagated
+ @param inherited path to all inherited multiple equality items
+ @param[out] is_simplifiable_cond 'cond' may be simplified after the
+ propagation of the equalities
+
+ @details
+ The function recursively traverses the tree of the condition 'cond' and
+ for each its AND sub-level of any depth the function merges the multiple
+ equalities from the list 'new_equalities' into the multiple equalities
+ attached to the AND item created for this sub-level.
+ The function also [re]sets references to the equalities formed by the
+ merges of multiple equalities in all field items occurred in 'cond'
+ that are encountered in the equalities.
+ If the result of any merge of multiple equalities is an impossible
+ condition the function returns TRUE in the parameter is_simplifiable_cond.
+*/
- SYNOPSIS
- internal_remove_eq_conds()
- thd THD environment
- cond the condition to handle
- cond_value the resulting value of the condition
+void propagate_new_equalities(THD *thd, Item *cond,
+ List<Item_equal> *new_equalities,
+ COND_EQUAL *inherited,
+ bool *is_simplifiable_cond)
+{
+ if (cond->type() == Item::COND_ITEM)
+ {
+ bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
+ if (and_level)
+ {
+ Item_cond_and *cond_and= (Item_cond_and *) cond;
+ List<Item_equal> *cond_equalities= &cond_and->cond_equal.current_level;
+ cond_and->cond_equal.upper_levels= inherited;
+ if (!cond_equalities->is_empty() && cond_equalities != new_equalities)
+ {
+ Item_equal *equal_item;
+ List_iterator<Item_equal> it(*new_equalities);
+ while ((equal_item= it++))
+ {
+ equal_item->merge_into_list(cond_equalities, true, true);
+ }
+ List_iterator<Item_equal> ei(*cond_equalities);
+ while ((equal_item= ei++))
+ {
+ if (equal_item->const_item() && !equal_item->val_int())
+ {
+ *is_simplifiable_cond= true;
+ return;
+ }
+ }
+ }
+ }
- RETURN
- *COND with the simplified condition
+ Item *item;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ while ((item= li++))
+ {
+ COND_EQUAL *new_inherited= and_level && item->type() == Item::COND_ITEM ?
+ &((Item_cond_and *) cond)->cond_equal :
+ inherited;
+ propagate_new_equalities(thd, item, new_equalities, new_inherited,
+ is_simplifiable_cond);
+ }
+ }
+ else if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ Item_equal *equal_item;
+ List_iterator<Item_equal> it(*new_equalities);
+ Item_equal *equality= (Item_equal *) cond;
+ equality->upper_levels= inherited;
+ while ((equal_item= it++))
+ {
+ equality->merge_with_check(equal_item, true);
+ }
+ if (equality->const_item() && !equality->val_int())
+ *is_simplifiable_cond= true;
+ }
+ else
+ {
+ uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
+ cond= cond->compile(&Item::subst_argument_checker,
+ &is_subst_valid,
+ &Item::equal_fields_propagator,
+ (uchar *) inherited);
+ cond->update_used_tables();
+ }
+}
+
+/*
+ Check if cond_is_datetime_is_null() is true for the condition cond, or
+ for any of its AND/OR-children
+*/
+bool cond_has_datetime_is_null(Item *cond)
+{
+ if (cond_is_datetime_is_null(cond))
+ return true;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ List<Item> *cond_arg_list= ((Item_cond*) cond)->argument_list();
+ List_iterator<Item> li(*cond_arg_list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (cond_has_datetime_is_null(item))
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ Check if passed condtition has for of
+
+ not_null_date_col IS NULL
+
+ where not_null_date_col has a datte or datetime type
+*/
+
+bool cond_is_datetime_is_null(Item *cond)
+{
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
+ {
+ Item **args= ((Item_func_isnull*) cond)->arguments();
+ if (args[0]->type() == Item::FIELD_ITEM)
+ {
+ Field *field=((Item_field*) args[0])->field;
+
+ if (((field->type() == MYSQL_TYPE_DATE) ||
+ (field->type() == MYSQL_TYPE_DATETIME)) &&
+ (field->flags & NOT_NULL_FLAG))
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ @brief
+ Evaluate all constant boolean sub-expressions in a condition
+
+ @param thd thread handle
+ @param cond condition where where to evaluate constant sub-expressions
+ @param[out] cond_value : the returned value of the condition
+ (TRUE/FALSE/UNKNOWN:
+ Item::COND_TRUE/Item::COND_FALSE/Item::COND_OK)
+ @return
+ the item that is the result of the substitution of all inexpensive constant
+ boolean sub-expressions into cond, or,
+ NULL if the condition is constant and is evaluated to FALSE.
+
+ @details
+ This function looks for all inexpensive constant boolean sub-expressions in
+ the given condition 'cond' and substitutes them for their values.
+ For example, the condition 2 > (5 + 1) or a < (10 / 2)
+ will be transformed to the condition a < (10 / 2).
+ Note that a constant sub-expression is evaluated only if it is constant and
+ inexpensive. A sub-expression with an uncorrelated subquery may be evaluated
+ only if the subquery is considered as inexpensive.
+ The function does not evaluate a constant sub-expression if it is not on one
+ of AND/OR levels of the condition 'cond'. For example, the subquery in the
+ condition a > (select max(b) from t1 where b > 5) will never be evaluated
+ by this function.
+ If a constant boolean sub-expression is evaluated to TRUE then:
+ - when the sub-expression is a conjunct of an AND formula it is simply
+ removed from this formula
+ - when the sub-expression is a disjunct of an OR formula the whole OR
+ formula is converted to TRUE
+ If a constant boolean sub-expression is evaluated to FALSE then:
+ - when the sub-expression is a disjunct of an OR formula it is simply
+ removed from this formula
+ - when the sub-expression is a conjuct of an AND formula the whole AND
+ formula is converted to FALSE
+ When a disjunct/conjunct is removed from an OR/AND formula it might happen
+ that there is only one conjunct/disjunct remaining. In this case this
+ remaining disjunct/conjunct must be merged into underlying AND/OR formula,
+ because AND/OR levels must alternate in the same way as they alternate
+ after fix_fields() is called for the original condition.
+ The specifics of merging a formula f into an AND formula A appears
+ when A contains multiple equalities and f contains multiple equalities.
+ In this case the multiple equalities from f and A have to be merged.
+ After this the resulting multiple equalities have to be propagated into
+ the all AND/OR levels of the formula A (see propagate_new_equalities()).
+ The propagation of multiple equalities might result in forming multiple
+ equalities that are always FALSE. This, in its turn, might trigger further
+ simplification of the condition.
+
+ @note
+ EXAMPLE 1:
+ SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
+ First 1 != 1 will be removed from the second conjunct:
+ => SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5);
+ Then (b = 5 AND a = 5) will be merged into the top level condition:
+ => SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5) AND (a = 5);
+ Then (b = 5), (a = 5) will be propagated into the disjuncs of
+ (b = 1 OR a = 1):
+ => SELECT * FROM t1 WHERE ((b = 1) AND (b = 5) AND (a = 5) OR
+ (a = 1) AND (b = 5) AND (a = 5)) AND
+ (b = 5) AND (a = 5)
+ => SELECT * FROM t1 WHERE ((FALSE AND (a = 5)) OR
+ (FALSE AND (b = 5))) AND
+ (b = 5) AND (a = 5)
+ After this an additional call of remove_eq_conds() converts it
+ to FALSE
+
+ EXAMPLE 2:
+ SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
+ => SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5);
+ => SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5) AND (a = 5);
+ => SELECT * FROM t1 WHERE ((b = 1) AND (b = 5) AND (a = 5) OR
+ (a = 5) AND (b = 5) AND (a = 5)) AND
+ (b = 5) AND (a = 5)
+ => SELECT * FROM t1 WHERE ((FALSE AND (a = 5)) OR
+ ((b = 5) AND (a = 5))) AND
+ (b = 5) AND (a = 5)
+ After this an additional call of remove_eq_conds() converts it to
+ => SELECT * FROM t1 WHERE (b = 5) AND (a = 5)
*/
static COND *
@@ -13927,9 +14187,11 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
{
if (cond->type() == Item::COND_ITEM)
{
+ List<Item_equal> new_equalities;
bool and_level= ((Item_cond*) cond)->functype()
== Item_func::COND_AND_FUNC;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ List<Item> *cond_arg_list= ((Item_cond*) cond)->argument_list();
+ List_iterator<Item> li(*cond_arg_list);
Item::cond_result tmp_cond_value;
bool should_fix_fields=0;
@@ -13939,92 +14201,86 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
{
Item *new_item=internal_remove_eq_conds(thd, item, &tmp_cond_value);
if (!new_item)
+ {
+ /* This can happen only when item is converted to TRUE or FALSE */
li.remove();
+ }
else if (item != new_item)
{
- if (and_level)
- {
- /*
- Take a special care of multiple equality predicates
- that may be part of 'cond' and 'new_item'.
- Those multiple equalities that have common members
- must be merged.
- */
- Item_cond_and *cond_and= (Item_cond_and *) cond;
- List<Item_equal> *cond_equal_items=
- &cond_and->cond_equal.current_level;
- List<Item> *cond_and_list= cond_and->argument_list();
-
- if (new_item->type() == Item::COND_ITEM &&
- ((Item_cond*) new_item)->functype() == Item_func::COND_AND_FUNC)
- {
- Item_cond_and *new_item_and= (Item_cond_and *) new_item;
- List<Item_equal> *new_item_equal_items=
- &new_item_and->cond_equal.current_level;
- List<Item> *new_item_and_list= new_item_and->argument_list();
- cond_and_list->disjoin((List<Item>*) cond_equal_items);
- new_item_and_list->disjoin((List<Item>*) new_item_equal_items);
- Item_equal *equal_item;
- List_iterator<Item_equal> it(*new_item_equal_items);
- while ((equal_item= it++))
- {
- equal_item->merge_into_list(cond_equal_items);
- }
- if (new_item_and_list->is_empty())
- li.remove();
- else
+ /*
+ This can happen when:
+ - item was an OR formula converted to one disjunct
+ - item was an AND formula converted to one conjunct
+ In these cases the disjunct/conjunct must be merged into the
+ argument list of cond.
+ */
+ if (new_item->type() == Item::COND_ITEM &&
+ item->type() == Item::COND_ITEM)
+ {
+ DBUG_ASSERT(((Item_cond *) cond)->functype() ==
+ ((Item_cond *) new_item)->functype());
+ List<Item> *new_item_arg_list=
+ ((Item_cond *) new_item)->argument_list();
+ if (and_level)
+ {
+ /*
+ If new_item is an AND formula then multiple equalities
+ of new_item_arg_list must merged into multiple equalities
+ of cond_arg_list.
+ */
+ List<Item_equal> *new_item_equalities=
+ &((Item_cond_and *) new_item)->cond_equal.current_level;
+ if (!new_item_equalities->is_empty())
{
- Item *list_item;
- Item *new_list_item;
- uint cnt= new_item_and_list->elements;
- List_iterator<Item> it(*new_item_and_list);
- while ((list_item= it++))
- {
- uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
- new_list_item=
- list_item->compile(&Item::subst_argument_checker,
- &is_subst_valid,
- &Item::equal_fields_propagator,
- (uchar *) &cond_and->cond_equal);
- if (new_list_item != list_item)
- it.replace(new_list_item);
- new_list_item->update_used_tables();
- }
- li.replace(*new_item_and_list);
- for (cnt--; cnt; cnt--)
- item= li++;
+ /*
+ Cut the multiple equalities from the new_item_arg_list and
+ append them on the list new_equalities. Later the equalities
+ from this list will be merged into the multiple equalities
+ of cond_arg_list all together.
+ */
+ new_item_arg_list->disjoin((List<Item> *) new_item_equalities);
+ new_equalities.concat(new_item_equalities);
}
- cond_and_list->concat((List<Item>*) cond_equal_items);
}
- else if (new_item->type() == Item::FUNC_ITEM &&
- ((Item_cond*) new_item)->functype() ==
- Item_func::MULT_EQUAL_FUNC)
+ if (new_item_arg_list->is_empty())
+ li.remove();
+ else
{
- cond_and_list->disjoin((List<Item>*) cond_equal_items);
- ((Item_equal *) new_item)->merge_into_list(cond_equal_items);
- li.remove();
- cond_and_list->concat((List<Item>*) cond_equal_items);
+ uint cnt= new_item_arg_list->elements;
+ li.replace(*new_item_arg_list);
+ /* Make iterator li ignore new items */
+ for (cnt--; cnt; cnt--)
+ li++;
+ should_fix_fields= 1;
}
- else
- li.replace(new_item);
+ }
+ else if (and_level &&
+ new_item->type() == Item::FUNC_ITEM &&
+ ((Item_cond*) new_item)->functype() ==
+ Item_func::MULT_EQUAL_FUNC)
+ {
+ li.remove();
+ new_equalities.push_back((Item_equal *) new_item);
}
else
- {
+ {
if (new_item->type() == Item::COND_ITEM &&
((Item_cond*) new_item)->functype() ==
((Item_cond*) cond)->functype())
{
- List<Item> *arg_list= ((Item_cond*) new_item)->argument_list();
- uint cnt= arg_list->elements;
- li.replace(*arg_list);
- for ( cnt--; cnt; cnt--)
- item= li++;
+ List<Item> *new_item_arg_list=
+ ((Item_cond *) new_item)->argument_list();
+ uint cnt= new_item_arg_list->elements;
+ li.replace(*new_item_arg_list);
+ /* Make iterator li ignore new items */
+ for (cnt--; cnt; cnt--)
+ li++;
}
- else
+ else
li.replace(new_item);
+ should_fix_fields= 1;
}
- should_fix_fields=1;
- }
+ }
if (*cond_value == Item::COND_UNDEF)
*cond_value=tmp_cond_value;
switch (tmp_cond_value) {
@@ -14050,6 +14306,55 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
break; /* purecov: deadcode */
}
}
+ if (!new_equalities.is_empty())
+ {
+ DBUG_ASSERT(and_level);
+ /*
+ Merge multiple equalities that were cut from the results of
+ simplification of OR formulas converted into AND formulas.
+ These multiple equalities are to be merged into the
+ multiple equalities of cond_arg_list.
+ */
+ COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->cond_equal;
+ List<Item_equal> *cond_equalities= &cond_equal->current_level;
+ cond_arg_list->disjoin((List<Item> *) cond_equalities);
+ Item_equal *equality;
+ List_iterator_fast<Item_equal> it(new_equalities);
+ while ((equality= it++))
+ {
+ equality->upper_levels= cond_equal->upper_levels;
+ equality->merge_into_list(cond_equalities, false, false);
+ List_iterator_fast<Item_equal> ei(*cond_equalities);
+ while ((equality= ei++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ {
+ *cond_value= Item::COND_FALSE;
+ return (COND*) 0;
+ }
+ }
+ }
+ cond_arg_list->concat((List<Item> *) cond_equalities);
+ /*
+ Propagate the newly formed multiple equalities to
+ the all AND/OR levels of cond
+ */
+ bool is_simplifiable_cond= false;
+ propagate_new_equalities(thd, cond, cond_equalities,
+ cond_equal->upper_levels,
+ &is_simplifiable_cond);
+ /*
+ If the above propagation of multiple equalities brings us
+ to multiple equalities that are always FALSE then try to
+ simplify the condition with remove_eq_cond() again.
+ */
+ if (is_simplifiable_cond)
+ {
+ if (!(cond= internal_remove_eq_conds(thd, cond, cond_value)))
+ return cond;
+ }
+ should_fix_fields= 1;
+ }
if (should_fix_fields)
cond->update_used_tables();
@@ -14063,53 +14368,45 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
return item;
}
}
- else if (cond->type() == Item::FUNC_ITEM &&
- ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
+ else if (cond_is_datetime_is_null(cond))
{
- Item_func_isnull *func=(Item_func_isnull*) cond;
- Item **args= func->arguments();
- if (args[0]->type() == Item::FIELD_ITEM)
- {
- Field *field=((Item_field*) args[0])->field;
- /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
- /*
- See BUG#12594011
- Documentation says that
- SELECT datetime_notnull d FROM t1 WHERE d IS NULL
- shall return rows where d=='0000-00-00'
+ /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
+ /*
+ See BUG#12594011
+ Documentation says that
+ SELECT datetime_notnull d FROM t1 WHERE d IS NULL
+ shall return rows where d=='0000-00-00'
- Thus, for DATE and DATETIME columns defined as NOT NULL,
- "date_notnull IS NULL" has to be modified to
- "date_notnull IS NULL OR date_notnull == 0" (if outer join)
- "date_notnull == 0" (otherwise)
+ Thus, for DATE and DATETIME columns defined as NOT NULL,
+ "date_notnull IS NULL" has to be modified to
+ "date_notnull IS NULL OR date_notnull == 0" (if outer join)
+ "date_notnull == 0" (otherwise)
- */
- if (((field->type() == MYSQL_TYPE_DATE) ||
- (field->type() == MYSQL_TYPE_DATETIME)) &&
- (field->flags & NOT_NULL_FLAG))
- {
- Item *item0= new(thd->mem_root) Item_int((longlong)0, 1);
- Item *eq_cond= new(thd->mem_root) Item_func_eq(args[0], item0);
- if (!eq_cond)
- return cond;
+ */
+ Item **args= ((Item_func_isnull*) cond)->arguments();
+ Field *field=((Item_field*) args[0])->field;
- if (field->table->pos_in_table_list->outer_join)
- {
- // outer join: transform "col IS NULL" to "col IS NULL or col=0"
- Item *or_cond= new(thd->mem_root) Item_cond_or(eq_cond, cond);
- if (!or_cond)
- return cond;
- cond= or_cond;
- }
- else
- {
- // not outer join: transform "col IS NULL" to "col=0"
- cond= eq_cond;
- }
+ Item *item0= new(thd->mem_root) Item_int((longlong)0, 1);
+ Item *eq_cond= new(thd->mem_root) Item_func_eq(args[0], item0);
+ if (!eq_cond)
+ return cond;
- cond->fix_fields(thd, &cond);
- }
+ if (field->table->pos_in_table_list->is_inner_table_of_outer_join())
+ {
+ // outer join: transform "col IS NULL" to "col IS NULL or col=0"
+ Item *or_cond= new(thd->mem_root) Item_cond_or(eq_cond, cond);
+ if (!or_cond)
+ return cond;
+ cond= or_cond;
}
+ else
+ {
+ // not outer join: transform "col IS NULL" to "col=0"
+ cond= eq_cond;
+ }
+
+ cond->fix_fields(thd, &cond);
+
if (cond->const_item() && !cond->is_expensive())
{
*cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
@@ -14214,7 +14511,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
}
-/*
+/**
Check if equality can be used in removing components of GROUP BY/DISTINCT
@param l the left comparison argument (a field if any)
@@ -14796,7 +15093,8 @@ TABLE *
create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
- const char *table_alias, bool do_not_open)
+ const char *table_alias, bool do_not_open,
+ bool keep_row_order)
{
MEM_ROOT *mem_root_save, own_root;
TABLE *table;
@@ -15611,6 +15909,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
share->db_record_offset= 1;
table->used_for_duplicate_elimination= (param->sum_func_count == 0 &&
(table->group || table->distinct));
+ table->keep_row_order= keep_row_order;
if (!do_not_open)
{
@@ -15947,7 +16246,8 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
table->no_rows ? NO_RECORD :
(share->reclength < 64 &&
!share->blob_fields ? STATIC_RECORD :
- table->used_for_duplicate_elimination ?
+ table->used_for_duplicate_elimination ||
+ table->keep_row_order ?
DYNAMIC_RECORD : BLOCK_RECORD),
share->keys, &keydef,
(uint) (*recinfo-start_recinfo),
@@ -17171,7 +17471,7 @@ int report_error(TABLE *table, int error)
print them to the .err log
*/
if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT
- && !table->in_use->killed)
+ && error != HA_ERR_TABLE_DEF_CHANGED && !table->in_use->killed)
sql_print_error("Got error %d when reading table '%s'",
error, table->s->path.str);
table->file->print_error(error,MYF(0));
@@ -17545,6 +17845,11 @@ join_read_always_key(JOIN_TAB *tab)
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
+ if ((error= table->file->prepare_index_key_scan_map(tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts))))
+ {
+ report_error(table,error);
+ return -1;
+ }
if ((error= table->file->ha_index_read_map(table->record[0],
tab->ref.key_buff,
make_prev_keypart_map(tab->ref.key_parts),
@@ -17578,6 +17883,11 @@ join_read_last_key(JOIN_TAB *tab)
if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref))
return -1;
+ if ((error= table->file->prepare_index_key_scan_map(tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts))))
+ {
+ report_error(table,error);
+ return -1;
+ }
if ((error= table->file->ha_index_read_map(table->record[0],
tab->ref.key_buff,
make_prev_keypart_map(tab->ref.key_parts),
@@ -21314,22 +21624,20 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
if (field != NULL)
{
/*
- Replace "@:=<expression>" with "@:=<tmp table column>". Otherwise,
- we would re-evaluate <expression>, and if expression were
- a subquery, this would access already-unlocked tables.
- */
+ Replace "@:=<expression>" with "@:=<tmp table column>". Otherwise, we
+ would re-evaluate <expression>, and if expression were a subquery, this
+ would access already-unlocked tables.
+ */
Item_func_set_user_var* suv=
- new Item_func_set_user_var((Item_func_set_user_var*) item);
+ new Item_func_set_user_var(thd, (Item_func_set_user_var*) item);
Item_field *new_field= new Item_field(field);
- if (!suv || !new_field || suv->fix_fields(thd, (Item**)&suv))
+ if (!suv || !new_field)
DBUG_RETURN(true); // Fatal error
- ((Item *)suv)->name= item->name;
/*
- We are replacing the argument of Item_func_set_user_var after its
- value has been read. The argument's null_value should be set by
- now, so we must set it explicitly for the replacement argument
- since the null_value may be read without any preceeding call to
- val_*().
+ We are replacing the argument of Item_func_set_user_var after its value
+ has been read. The argument's null_value should be set by now, so we
+ must set it explicitly for the replacement argument since the null_value
+ may be read without any preceeding call to val_*().
*/
new_field->update_null_value();
List<Item> list;
@@ -21360,15 +21668,15 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
ifield->db_name= iref->db_name;
}
#ifndef DBUG_OFF
- if (!item_field->name)
- {
- char buff[256];
- String str(buff,sizeof(buff),&my_charset_bin);
- str.length(0);
- str.extra_allocation(1024);
- item->print(&str, QT_ORDINARY);
- item_field->name= sql_strmake(str.ptr(),str.length());
- }
+ if (!item_field->name)
+ {
+ char buff[256];
+ String str(buff,sizeof(buff),&my_charset_bin);
+ str.length(0);
+ str.extra_allocation(1024);
+ item->print(&str, QT_ORDINARY);
+ item_field->name= sql_strmake(str.ptr(),str.length());
+ }
#endif
}
else
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 9ff08a3bc03..265b7716a36 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1164,6 +1164,11 @@ public:
bool cleaned;
DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value, having_value;
+ /**
+ Impossible where after reading const tables
+ (set in make_join_statistics())
+ */
+ bool impossible_where;
List<Item> all_fields; ///< to store all fields that used in query
///Above list changed to use temporary table
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
@@ -1816,6 +1821,8 @@ ORDER *simple_remove_const(ORDER *order, COND *where);
bool const_expression_in_where(COND *cond, Item *comp_item,
Field *comp_field= NULL,
Item **const_item= NULL);
+bool cond_is_datetime_is_null(Item *cond);
+bool cond_has_datetime_is_null(Item *cond);
/* Table elimination entry point function */
void eliminate_tables(JOIN *join);
@@ -1837,7 +1844,8 @@ void push_index_cond(JOIN_TAB *tab, uint keyno);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
- const char* alias, bool do_not_open=FALSE);
+ const char* alias, bool do_not_open=FALSE,
+ bool keep_row_order= FALSE);
void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
TMP_ENGINE_COLUMNDEF *start_recinfo,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index f47a58e00d7..e4371250c2e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2628,6 +2628,9 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
table->field[13]->store((longlong) tmp->get_examined_row_count(), TRUE);
table->field[13]->set_notnull();
+ /* QUERY_ID */
+ table->field[14]->store(tmp->query_id, TRUE);
+
if (schema_table_store_record(thd, table))
{
mysql_mutex_unlock(&LOCK_thread_count);
@@ -8686,6 +8689,7 @@ ST_FIELD_INFO processlist_fields_info[]=
SKIP_OPEN_TABLE},
{"MEMORY_USED", 7, MYSQL_TYPE_LONG, 0, 0, "Memory_used", SKIP_OPEN_TABLE},
{"EXAMINED_ROWS", 7, MYSQL_TYPE_LONG, 0, 0, "Examined_rows", SKIP_OPEN_TABLE},
+ {"QUERY_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
diff --git a/sql/sql_show.h b/sql/sql_show.h
index ec4d6a2b7c9..10276e8b65e 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -121,7 +121,7 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
-THD *find_thread_by_id(ulong id);
+THD *find_thread_by_id(longlong id, bool query_id= false);
class select_result_explain_buffer;
/*
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4ab808acb9e..105af72500f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4757,6 +4757,7 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
NO_FRM_RENAME Don't rename the FRM file
but only the table in the storage engine.
NO_HA_TABLE Don't rename table in engine.
+ NO_FK_CHECKS Don't check FK constraints during rename.
@return false OK
@return true Error
@@ -4774,11 +4775,16 @@ mysql_rename_table(handlerton *base, const char *old_db,
char tmp_name[SAFE_NAME_LEN+1];
handler *file;
int error=0;
+ ulonglong save_bits= thd->variables.option_bits;
int length;
DBUG_ENTER("mysql_rename_table");
DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'",
old_db, old_name, new_db, new_name));
+ // Temporarily disable foreign key checks
+ if (flags & NO_FK_CHECKS)
+ thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
+
file= (base == NULL ? 0 :
get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
@@ -4853,6 +4859,9 @@ mysql_rename_table(handlerton *base, const char *old_db,
old_name, strlen(old_name));
}
+ // Restore options bits to the original value
+ thd->variables.option_bits= save_bits;
+
DBUG_RETURN(error != 0);
}
@@ -6518,7 +6527,7 @@ static bool mysql_inplace_alter_table(THD *thd,
*/
(void) mysql_rename_table(db_type,
alter_ctx->new_db, alter_ctx->new_alias,
- alter_ctx->db, alter_ctx->alias, 0);
+ alter_ctx->db, alter_ctx->alias, NO_FK_CHECKS);
DBUG_RETURN(true);
}
rename_table_in_stat_tables(thd, alter_ctx->db,alter_ctx->alias,
@@ -7499,7 +7508,8 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
{
(void) mysql_rename_table(old_db_type,
alter_ctx->new_db, alter_ctx->new_alias,
- alter_ctx->db, alter_ctx->table_name, 0);
+ alter_ctx->db, alter_ctx->table_name,
+ NO_FK_CHECKS);
error= -1;
}
}
@@ -8396,9 +8406,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
// Rename failed, delete the temporary table.
(void) quick_rm_table(thd, new_db_type, alter_ctx.new_db,
alter_ctx.tmp_name, FN_IS_TMP);
+
// Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, alter_ctx.db, backup_name,
- alter_ctx.db, alter_ctx.alias, FN_FROM_IS_TMP);
+ alter_ctx.db, alter_ctx.alias,
+ FN_FROM_IS_TMP | NO_FK_CHECKS);
goto err_with_mdl;
}
@@ -8417,7 +8429,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
alter_ctx.new_db, alter_ctx.new_alias, 0);
// Restore the backup of the original table to the old name.
(void) mysql_rename_table(old_db_type, alter_ctx.db, backup_name,
- alter_ctx.db, alter_ctx.alias, FN_FROM_IS_TMP);
+ alter_ctx.db, alter_ctx.alias,
+ FN_FROM_IS_TMP | NO_FK_CHECKS);
goto err_with_mdl;
}
rename_table_in_stat_tables(thd, alter_ctx.db,alter_ctx.alias,
@@ -8795,6 +8808,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
{
/* Not a duplicate key error. */
to->file->print_error(error, MYF(0));
+ error= 1;
break;
}
else
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 6bd111cae6d..3d8ad3c8875 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates.
+/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
Copyright (c) 2011, 2013, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
@@ -134,6 +134,8 @@ static const uint FRM_ONLY= 1 << 3;
static const uint NO_HA_TABLE= 1 << 4;
/** Don't resolve MySQL's fake "foo.sym" symbolic directory names. */
static const uint SKIP_SYMDIR_ACCESS= 1 << 5;
+/** Don't check foreign key constraints while renaming table */
+static const uint NO_FK_CHECKS= 1 << 6;
uint filename_to_tablename(const char *from, char *to, uint to_length
#ifndef DBUG_OFF
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 9611b947aa3..831a7fa2a20 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -267,7 +267,7 @@ to_ascii(CHARSET_INFO *cs,
/* Character set-aware version of str_to_time() */
bool
str_to_time(CHARSET_INFO *cs, const char *str,uint length,
- MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status)
+ MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status)
{
char cnv[32];
if ((cs->state & MY_CS_NONASCII) != 0)
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index f7168ffb7ab..d7987a62a14 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -129,6 +129,7 @@ bool select_union::flush()
table_alias name of the temporary table
bit_fields_as_long convert bit fields to ulonglong
create_table whether to physically create result table
+ keep_row_order keep rows in order as they were inserted
DESCRIPTION
Create a temporary table that is used to store the result of a UNION,
@@ -143,7 +144,8 @@ bool
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *alias,
- bool bit_fields_as_long, bool create_table)
+ bool bit_fields_as_long, bool create_table,
+ bool keep_row_order)
{
DBUG_ASSERT(table == 0);
tmp_table_param.init();
@@ -153,7 +155,7 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, alias,
- !create_table)))
+ !create_table, keep_row_order)))
return TRUE;
table->keys_in_use_for_query.clear_all();
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 50b30d94f53..674610b4a6a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -23,21 +23,14 @@
*/
%{
-/* thd is passed as an argument to yyparse(), and subsequently to yylex().
-** The type will be void*, so it must be cast to (THD*) when used.
-** Use the YYTHD macro for this.
-*/
-#define YYPARSE_PARAM yythd
-#define YYLEX_PARAM yythd
-#define YYTHD ((THD *)yythd)
-#define YYLIP (& YYTHD->m_parser_state->m_lip)
-#define YYPS (& YYTHD->m_parser_state->m_yacc)
-#define YYCSCL YYTHD->variables.character_set_client
+#define YYLIP (& thd->m_parser_state->m_lip)
+#define YYPS (& thd->m_parser_state->m_yacc)
+#define YYCSCL (thd->variables.character_set_client)
#define MYSQL_YACC
#define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */
-#define Lex (YYTHD->lex)
+#define Lex (thd->lex)
#define Select Lex->current_select
#include "sql_priv.h"
@@ -83,7 +76,7 @@ int yylex(void *yylval, void *yythd);
ulong val= *(F); \
if (my_yyoverflow((B), (D), &val)) \
{ \
- yyerror((char*) (A)); \
+ yyerror(current_thd, (char*) (A)); \
return 2; \
} \
else \
@@ -95,7 +88,7 @@ int yylex(void *yylval, void *yythd);
#define MYSQL_YYABORT \
do \
{ \
- LEX::cleanup_lex_after_parse_error(YYTHD);\
+ LEX::cleanup_lex_after_parse_error(thd); \
YYABORT; \
} while (0)
@@ -181,10 +174,8 @@ void my_parse_error(const char *s)
to abort from the parser.
*/
-void MYSQLerror(const char *s)
+void MYSQLerror(THD *thd, const char *s)
{
- THD *thd= current_thd;
-
/*
Restore the original LEX if it was replaced when parsing
a stored procedure. We must ensure that a parsing error
@@ -961,11 +952,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%}
%pure_parser /* We have threads */
+%parse-param { THD *thd }
+%lex-param { THD *thd }
/*
- Currently there are 185 shift/reduce conflicts.
+ Currently there are 186 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 185
+%expect 186
/*
Comments for TOKENS.
@@ -1208,6 +1201,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM
%token HOUR_SYM /* SQL-2003-R */
+%token ID_SYM /* MYSQL */
%token IDENT
%token IDENTIFIED_SYM
%token IDENT_QUOTED
@@ -1441,6 +1435,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RESTRICT
%token RESUME_SYM
%token RETURNED_SQLSTATE_SYM /* SQL-2003-N */
+%token RETURNING_SYM
%token RETURNS_SYM /* SQL-2003-R */
%token RETURN_SYM /* SQL-2003-R */
%token REVOKE /* SQL-2003-R */
@@ -1920,7 +1915,6 @@ rule: <-- starts at col 1
query:
END_OF_INPUT
{
- THD *thd= YYTHD;
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
{
@@ -1934,7 +1928,7 @@ query:
{
Lex_input_stream *lip = YYLIP;
- if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) &&
+ if ((thd->client_capabilities & CLIENT_MULTI_QUERIES) &&
lip->multi_statements &&
! lip->eof())
{
@@ -2034,7 +2028,6 @@ statement:
deallocate:
deallocate_or_drop PREPARE_SYM ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
lex->prepared_stmt_name= $3;
@@ -2049,7 +2042,6 @@ deallocate_or_drop:
prepare:
PREPARE_SYM ident FROM prepare_src
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
@@ -2059,14 +2051,12 @@ prepare:
prepare_src:
TEXT_STRING_sys
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $1;
lex->prepared_stmt_code_is_varref= FALSE;
}
| '@' ident_or_text
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->prepared_stmt_code= $2;
lex->prepared_stmt_code_is_varref= TRUE;
@@ -2076,7 +2066,6 @@ prepare_src:
execute:
EXECUTE_SYM ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2;
@@ -2215,7 +2204,7 @@ master_def:
}
if (Lex->mi.heartbeat_period > slave_net_timeout)
{
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
}
@@ -2223,7 +2212,7 @@ master_def:
{
if (Lex->mi.heartbeat_period != 0.0)
{
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN,
ER(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MIN));
Lex->mi.heartbeat_period= 0.0;
@@ -2317,7 +2306,6 @@ master_file_def:
optional_connection_name:
/* empty */
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->mi.connection_name= thd->variables.default_master_connection;
}
@@ -2342,7 +2330,6 @@ connection_name:
create:
CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_CREATE_TABLE;
if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
@@ -2367,13 +2354,13 @@ create:
}
create_body
{
- LEX *lex= YYTHD->lex;
+ LEX *lex= thd->lex;
lex->current_select= &lex->select_lex;
if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) &&
!lex->create_info.db_type)
{
- lex->create_info.db_type= ha_default_handlerton(YYTHD);
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ lex->create_info.db_type= ha_default_handlerton(thd);
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
hton_name(lex->create_info.db_type)->str,
@@ -2507,7 +2494,6 @@ server_option:
event_tail:
remember_name EVENT_SYM opt_if_not_exists sp_name
{
- THD *thd= YYTHD;
LEX *lex=Lex;
lex->stmt_definition_begin= $1;
@@ -2574,7 +2560,7 @@ opt_ev_status:
ev_starts:
/* empty */
{
- Item *item= new (YYTHD->mem_root) Item_func_now_local(0);
+ Item *item= new (thd->mem_root) Item_func_now_local(0);
if (item == NULL)
MYSQL_YYABORT;
Lex->event_parse_data->item_starts= item;
@@ -2624,7 +2610,6 @@ opt_ev_comment:
ev_sql_stmt:
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
@@ -2667,7 +2652,6 @@ ev_sql_stmt:
}
ev_sql_stmt_inner
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
/* return back to the original memory root ASAP */
@@ -2726,11 +2710,10 @@ sp_name:
$$= new sp_name($1, $3, true);
if ($$ == NULL)
MYSQL_YYABORT;
- $$->init_qname(YYTHD);
+ $$->init_qname(thd);
}
| ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX_STRING db;
if (check_routine_name(&$1))
@@ -2800,7 +2783,7 @@ call:
lex->sql_command= SQLCOM_CALL;
lex->spname= $2;
lex->value_list.empty();
- sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
+ sp_add_used_routine(lex, thd, $2, TYPE_ENUM_PROCEDURE);
}
opt_sp_cparam_list {}
;
@@ -2871,12 +2854,12 @@ sp_fdparam:
MYSQL_YYABORT;
}
- sp_variable *spvar= spc->add_variable(YYTHD,
+ sp_variable *spvar= spc->add_variable(thd,
$1,
(enum enum_field_types) $3,
sp_variable::MODE_IN);
- if (lex->sphead->fill_field_definition(YYTHD, lex,
+ if (lex->sphead->fill_field_definition(thd, lex,
(enum enum_field_types) $3,
&spvar->field_def))
{
@@ -2909,12 +2892,12 @@ sp_pdparam:
my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
MYSQL_YYABORT;
}
- sp_variable *spvar= spc->add_variable(YYTHD,
+ sp_variable *spvar= spc->add_variable(thd,
$3,
(enum enum_field_types) $4,
(sp_variable::enum_mode) $1);
- if (lex->sphead->fill_field_definition(YYTHD, lex,
+ if (lex->sphead->fill_field_definition(thd, lex,
(enum enum_field_types) $4,
&spvar->field_def))
{
@@ -2977,13 +2960,12 @@ sp_decl:
{
LEX *lex= Lex;
- lex->sphead->reset_lex(YYTHD);
+ lex->sphead->reset_lex(thd);
lex->spcont->declare_var_boundary($2);
}
type_with_opt_collate
sp_opt_default
{
- THD *thd= YYTHD;
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
uint num_vars= pctx->context_var_count();
@@ -3009,7 +2991,7 @@ sp_decl:
spvar->type= var_type;
spvar->default_value= dflt_value_item;
- if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
+ if (lex->sphead->fill_field_definition(thd, lex, var_type,
&spvar->field_def))
{
MYSQL_YYABORT;
@@ -3033,7 +3015,7 @@ sp_decl:
}
pctx->declare_var_boundary(0);
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
$$.vars= $2;
$$.conds= $$.hndlrs= $$.curs= 0;
@@ -3048,14 +3030,13 @@ sp_decl:
my_error(ER_SP_DUP_COND, MYF(0), $2.str);
MYSQL_YYABORT;
}
- if(spc->add_condition(YYTHD, $2, $5))
+ if(spc->add_condition(thd, $2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
}
| DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
{
- THD *thd= YYTHD;
LEX *lex= Lex;
sp_head *sp= lex->sphead;
@@ -3137,7 +3118,7 @@ sp_decl:
sp_cursor_stmt:
{
- Lex->sphead->reset_lex(YYTHD);
+ Lex->sphead->reset_lex(thd);
}
select
{
@@ -3153,7 +3134,7 @@ sp_cursor_stmt:
}
lex->sp_lex_in_use= TRUE;
$$= lex;
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -3201,7 +3182,7 @@ sp_cond:
my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
MYSQL_YYABORT;
}
- $$= new (YYTHD->mem_root) sp_condition_value($1);
+ $$= new (thd->mem_root) sp_condition_value($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3224,7 +3205,7 @@ sqlstate:
my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
MYSQL_YYABORT;
}
- $$= new (YYTHD->mem_root) sp_condition_value($3.str);
+ $$= new (thd->mem_root) sp_condition_value($3.str);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3251,20 +3232,19 @@ sp_hcond:
}
| SQLWARNING_SYM /* SQLSTATEs 01??? */
{
- $$= new (YYTHD->mem_root) sp_condition_value(sp_condition_value::WARNING);
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::WARNING);
if ($$ == NULL)
MYSQL_YYABORT;
}
| not FOUND_SYM /* SQLSTATEs 02??? */
{
- $$= new (YYTHD->mem_root) sp_condition_value(sp_condition_value::NOT_FOUND);
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::NOT_FOUND);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SQLEXCEPTION_SYM /* All other SQLSTATEs */
{
- $$= (sp_condition_value *)YYTHD->alloc(sizeof(sp_condition_value));
- $$= new (YYTHD->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
+ $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3273,7 +3253,6 @@ sp_hcond:
signal_stmt:
SIGNAL_SYM signal_value opt_set_signal_information
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Yacc_state *state= & thd->m_parser_state->m_yacc;
@@ -3323,7 +3302,7 @@ opt_signal_value:
opt_set_signal_information:
/* empty */
{
- YYTHD->m_parser_state->m_yacc.m_set_signal_info.clear();
+ thd->m_parser_state->m_yacc.m_set_signal_info.clear();
}
| SET signal_information_item_list
;
@@ -3332,7 +3311,7 @@ signal_information_item_list:
signal_condition_information_item_name EQ signal_allowed_expr
{
Set_signal_information *info;
- info= & YYTHD->m_parser_state->m_yacc.m_set_signal_info;
+ info= &thd->m_parser_state->m_yacc.m_set_signal_info;
int index= (int) $1;
info->clear();
info->m_item[index]= $3;
@@ -3341,7 +3320,7 @@ signal_information_item_list:
signal_condition_information_item_name EQ signal_allowed_expr
{
Set_signal_information *info;
- info= & YYTHD->m_parser_state->m_yacc.m_set_signal_info;
+ info= &thd->m_parser_state->m_yacc.m_set_signal_info;
int index= (int) $3;
if (info->m_item[index] != NULL)
{
@@ -3412,7 +3391,6 @@ signal_condition_information_item_name:
resignal_stmt:
RESIGNAL_SYM opt_signal_value opt_set_signal_information
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Yacc_state *state= & thd->m_parser_state->m_yacc;
@@ -3433,7 +3411,7 @@ get_diagnostics:
info->set_which_da($2);
Lex->sql_command= SQLCOM_GET_DIAGNOSTICS;
- Lex->m_sql_cmd= new (YYTHD->mem_root) Sql_cmd_get_diagnostics(info);
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_get_diagnostics(info);
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
@@ -3450,13 +3428,13 @@ which_area:
diagnostics_information:
statement_information
{
- $$= new (YYTHD->mem_root) Statement_information($1);
+ $$= new (thd->mem_root) Statement_information($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CONDITION_SYM condition_number condition_information
{
- $$= new (YYTHD->mem_root) Condition_information($2, $3);
+ $$= new (thd->mem_root) Condition_information($2, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3465,7 +3443,7 @@ diagnostics_information:
statement_information:
statement_information_item
{
- $$= new (YYTHD->mem_root) List<Statement_information_item>;
+ $$= new (thd->mem_root) List<Statement_information_item>;
if ($$ == NULL || $$->push_back($1))
MYSQL_YYABORT;
}
@@ -3480,7 +3458,7 @@ statement_information:
statement_information_item:
simple_target_specification EQ statement_information_item_name
{
- $$= new (YYTHD->mem_root) Statement_information_item($3, $1);
+ $$= new (thd->mem_root) Statement_information_item($3, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3488,8 +3466,8 @@ statement_information_item:
simple_target_specification:
ident
{
- Lex_input_stream *lip= &YYTHD->m_parser_state->m_lip;
- $$= create_item_for_sp_var(YYTHD, $1, NULL,
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ $$= create_item_for_sp_var(thd, $1, NULL,
lip->get_tok_start(), lip->get_ptr());
if ($$ == NULL)
@@ -3497,7 +3475,7 @@ simple_target_specification:
}
| '@' ident_or_text
{
- $$= new (YYTHD->mem_root) Item_func_get_user_var($2);
+ $$= new (thd->mem_root) Item_func_get_user_var($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3522,7 +3500,7 @@ condition_number:
condition_information:
condition_information_item
{
- $$= new (YYTHD->mem_root) List<Condition_information_item>;
+ $$= new (thd->mem_root) List<Condition_information_item>;
if ($$ == NULL || $$->push_back($1))
MYSQL_YYABORT;
}
@@ -3537,7 +3515,7 @@ condition_information:
condition_information_item:
simple_target_specification EQ condition_information_item_name
{
- $$= new (YYTHD->mem_root) Condition_information_item($3, $1);
+ $$= new (thd->mem_root) Condition_information_item($3, $1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -3584,7 +3562,7 @@ sp_decl_idents:
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
MYSQL_YYABORT;
}
- spc->add_variable(YYTHD,
+ spc->add_variable(thd,
$1,
MYSQL_TYPE_DECIMAL,
sp_variable::MODE_IN);
@@ -3602,7 +3580,7 @@ sp_decl_idents:
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
MYSQL_YYABORT;
}
- spc->add_variable(YYTHD,
+ spc->add_variable(thd,
$3,
MYSQL_TYPE_DECIMAL,
sp_variable::MODE_IN);
@@ -3640,7 +3618,6 @@ sp_proc_stmt_if:
sp_proc_stmt_statement:
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
@@ -3649,7 +3626,6 @@ sp_proc_stmt_statement:
}
statement
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
sp_head *sp= lex->sphead;
@@ -3696,7 +3672,7 @@ sp_proc_stmt_statement:
sp_proc_stmt_return:
RETURN_SYM
- { Lex->sphead->reset_lex(YYTHD); }
+ { Lex->sphead->reset_lex(thd); }
expr
{
LEX *lex= Lex;
@@ -3718,7 +3694,7 @@ sp_proc_stmt_return:
MYSQL_YYABORT;
sp->m_flags|= sp_head::HAS_RETURN;
}
- if (sp->restore_lex(YYTHD))
+ if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
;
@@ -3727,7 +3703,7 @@ sp_proc_stmt_unlabeled:
{ /* Unlabeled controls get a secret label. */
LEX *lex= Lex;
- lex->spcont->push_label(YYTHD,
+ lex->spcont->push_label(thd,
EMPTY_STR,
lex->sphead->instructions());
}
@@ -3947,7 +3923,7 @@ sp_fetch_list:
;
sp_if:
- { Lex->sphead->reset_lex(YYTHD); }
+ { Lex->sphead->reset_lex(thd); }
expr THEN_SYM
{
LEX *lex= Lex;
@@ -3957,11 +3933,11 @@ sp_if:
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
$2, lex);
if (i == NULL ||
- sp->push_backpatch(i, ctx->push_label(YYTHD, EMPTY_STR, 0)) ||
+ sp->push_backpatch(i, ctx->push_label(thd, EMPTY_STR, 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i))
MYSQL_YYABORT;
- if (sp->restore_lex(YYTHD))
+ if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
sp_proc_stmts1
@@ -3974,7 +3950,7 @@ sp_if:
sp->add_instr(i))
MYSQL_YYABORT;
sp->backpatch(ctx->pop_label());
- sp->push_backpatch(i, ctx->push_label(YYTHD, EMPTY_STR, 0));
+ sp->push_backpatch(i, ctx->push_label(thd, EMPTY_STR, 0));
}
sp_elseifs
{
@@ -4000,7 +3976,7 @@ simple_case_stmt:
{
LEX *lex= Lex;
case_stmt_action_case(lex);
- lex->sphead->reset_lex(YYTHD); /* For expr $3 */
+ lex->sphead->reset_lex(thd); /* For expr $3 */
}
expr
{
@@ -4009,7 +3985,7 @@ simple_case_stmt:
MYSQL_YYABORT;
/* For expr $3 */
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
simple_when_clause_list
@@ -4051,7 +4027,7 @@ searched_when_clause_list:
simple_when_clause:
WHEN_SYM
{
- Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
+ Lex->sphead->reset_lex(thd); /* For expr $3 */
}
expr
{
@@ -4061,7 +4037,7 @@ simple_when_clause:
if (case_stmt_action_when(lex, $3, true))
MYSQL_YYABORT;
/* For expr $3 */
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
THEN_SYM
@@ -4076,7 +4052,7 @@ simple_when_clause:
searched_when_clause:
WHEN_SYM
{
- Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
+ Lex->sphead->reset_lex(thd); /* For expr $3 */
}
expr
{
@@ -4084,7 +4060,7 @@ searched_when_clause:
if (case_stmt_action_when(lex, $3, false))
MYSQL_YYABORT;
/* For expr $3 */
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
THEN_SYM
@@ -4125,7 +4101,7 @@ sp_labeled_control:
}
else
{
- lab= lex->spcont->push_label(YYTHD, $1, lex->sphead->instructions());
+ lab= lex->spcont->push_label(thd, $1, lex->sphead->instructions());
lab->type= sp_label::ITERATION;
}
}
@@ -4164,7 +4140,7 @@ sp_labeled_block:
MYSQL_YYABORT;
}
- lab= lex->spcont->push_label(YYTHD, $1, lex->sphead->instructions());
+ lab= lex->spcont->push_label(thd, $1, lex->sphead->instructions());
lab->type= sp_label::BEGIN;
}
sp_block_content sp_opt_label
@@ -4187,7 +4163,7 @@ sp_unlabeled_block:
{ /* Unlabeled blocks get a secret label. */
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
- sp_label *lab= lex->spcont->push_label(YYTHD, EMPTY_STR, ip);
+ sp_label *lab= lex->spcont->push_label(thd, EMPTY_STR, ip);
lab->type= sp_label::BEGIN;
}
sp_block_content
@@ -4203,7 +4179,7 @@ sp_block_content:
together. No [[NOT] ATOMIC] yet, and we need to figure out how
make it coexist with the existing BEGIN COMMIT/ROLLBACK. */
LEX *lex= Lex;
- lex->spcont= lex->spcont->push_context(YYTHD,
+ lex->spcont= lex->spcont->push_context(thd,
sp_pcontext::REGULAR_SCOPE);
}
sp_decls
@@ -4247,7 +4223,7 @@ sp_unlabeled_control:
MYSQL_YYABORT;
}
| WHILE_SYM
- { Lex->sphead->reset_lex(YYTHD); }
+ { Lex->sphead->reset_lex(thd); }
expr DO_SYM
{
LEX *lex= Lex;
@@ -4261,7 +4237,7 @@ sp_unlabeled_control:
sp->new_cont_backpatch(i) ||
sp->add_instr(i))
MYSQL_YYABORT;
- if (sp->restore_lex(YYTHD))
+ if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
sp_proc_stmts1 END WHILE_SYM
@@ -4276,7 +4252,7 @@ sp_unlabeled_control:
lex->sphead->do_cont_backpatch();
}
| REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
- { Lex->sphead->reset_lex(YYTHD); }
+ { Lex->sphead->reset_lex(thd); }
expr END REPEAT_SYM
{
LEX *lex= Lex;
@@ -4288,7 +4264,7 @@ sp_unlabeled_control:
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
- if (lex->sphead->restore_lex(YYTHD))
+ if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */
i->m_cont_dest= ip+1;
@@ -4653,8 +4629,8 @@ ts_wait:
;
size_number:
- real_ulong_num { $$= $1;}
- | IDENT
+ real_ulonglong_num { $$= $1;}
+ | IDENT_sys
{
ulonglong number;
uint text_shift_number= 0;
@@ -4719,7 +4695,7 @@ create_body:
{
Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
- TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(YYTHD,
+ TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd,
$1, NULL, 0, TL_READ, MDL_SHARED_READ);
if (! src_table)
MYSQL_YYABORT;
@@ -5290,7 +5266,7 @@ part_value_expr_item:
my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
MYSQL_YYABORT;
}
- if (part_info->add_column_list_value(YYTHD, part_expr))
+ if (part_info->add_column_list_value(thd, part_expr))
{
MYSQL_YYABORT;
}
@@ -5734,25 +5710,25 @@ create_table_option:
}
| IDENT_sys equal TEXT_STRING_sys
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->create_info.option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->create_info.option_list,
&Lex->option_list_last);
}
| IDENT_sys equal real_ulonglong_num
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, &Lex->create_info.option_list,
- &Lex->option_list_last, YYTHD->mem_root);
+ &Lex->option_list_last, thd->mem_root);
}
| IDENT_sys equal DEFAULT
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, &Lex->create_info.option_list,
&Lex->option_list_last);
}
@@ -5796,19 +5772,19 @@ default_collation:
storage_engines:
ident_or_text
{
- plugin_ref plugin= ha_resolve_by_name(YYTHD, &$1);
+ plugin_ref plugin= ha_resolve_by_name(thd, &$1);
if (plugin)
$$= plugin_hton(plugin);
else
{
- if (YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
+ if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
{
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
MYSQL_YYABORT;
}
$$= 0;
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
ER(ER_UNKNOWN_STORAGE_ENGINE),
$1.str);
@@ -5820,7 +5796,7 @@ known_storage_engines:
ident_or_text
{
plugin_ref plugin;
- if ((plugin= ha_resolve_by_name(YYTHD, &$1)))
+ if ((plugin= ha_resolve_by_name(thd, &$1)))
$$= plugin_hton(plugin);
else
{
@@ -6154,7 +6130,7 @@ type:
{
char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1];
my_snprintf(buff, sizeof(buff), "YEAR(%lu)", length);
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_NOTE,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_DEPRECATED_SYNTAX,
ER(ER_WARN_DEPRECATED_SYNTAX),
buff, "YEAR(4)");
@@ -6168,7 +6144,7 @@ type:
{ $$=MYSQL_TYPE_TIME; }
| TIMESTAMP opt_field_length
{
- if (YYTHD->variables.sql_mode & MODE_MAXDB)
+ if (thd->variables.sql_mode & MODE_MAXDB)
$$=MYSQL_TYPE_DATETIME;
else
{
@@ -6300,7 +6276,7 @@ int_type:
real_type:
REAL
{
- $$= YYTHD->variables.sql_mode & MODE_REAL_AS_FLOAT ?
+ $$= thd->variables.sql_mode & MODE_REAL_AS_FLOAT ?
MYSQL_TYPE_FLOAT : MYSQL_TYPE_DOUBLE;
}
| DOUBLE_SYM
@@ -6375,7 +6351,7 @@ attribute:
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
- Item *item= new (YYTHD->mem_root) Item_func_now_local($4);
+ Item *item= new (thd->mem_root) Item_func_now_local($4);
if (item == NULL)
MYSQL_YYABORT;
Lex->on_update_value= item;
@@ -6421,25 +6397,25 @@ attribute:
}
| IDENT_sys equal TEXT_STRING_sys
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal real_ulonglong_num
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, &Lex->option_list,
- &Lex->option_list_last, YYTHD->mem_root);
+ &Lex->option_list_last, thd->mem_root);
}
| IDENT_sys equal DEFAULT
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
}
;
@@ -6469,7 +6445,7 @@ type_with_opt_collate:
now_or_signed_literal:
NOW_SYM opt_default_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_now_local($2);
+ $$= new (thd->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -6817,25 +6793,25 @@ all_key_opt:
| COMMENT_SYM TEXT_STRING_sys { Lex->key_create_info.comment= $2; }
| IDENT_sys equal TEXT_STRING_sys
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal real_ulonglong_num
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, $3, &Lex->option_list,
- &Lex->option_list_last, YYTHD->mem_root);
+ &Lex->option_list_last, thd->mem_root);
}
| IDENT_sys equal DEFAULT
{
- new (YYTHD->mem_root)
+ new (thd->mem_root)
engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
}
;
@@ -6944,7 +6920,7 @@ alter:
}
alter_options TABLE_SYM table_ident
{
- if (!Lex->select_lex.add_table_to_list(YYTHD, $5, NULL,
+ if (!Lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
MDL_SHARED_UPGRADABLE))
@@ -6957,7 +6933,7 @@ alter:
if (!Lex->m_sql_cmd)
{
/* Create a generic ALTER TABLE statment. */
- Lex->m_sql_cmd= new (YYTHD->mem_root) Sql_cmd_alter_table();
+ Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_table();
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
}
@@ -7065,7 +7041,7 @@ alter:
Event_parse_data.
*/
- if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
+ if (!(Lex->event_parse_data= Event_parse_data::new_instance(thd)))
MYSQL_YYABORT;
Lex->event_parse_data->identifier= $4;
@@ -7151,7 +7127,7 @@ alter_commands:
/* empty */
| DISCARD TABLESPACE
{
- Lex->m_sql_cmd= new (YYTHD->mem_root)
+ Lex->m_sql_cmd= new (thd->mem_root)
Sql_cmd_discard_import_tablespace(
Sql_cmd_discard_import_tablespace::DISCARD_TABLESPACE);
if (Lex->m_sql_cmd == NULL)
@@ -7159,7 +7135,7 @@ alter_commands:
}
| IMPORT TABLESPACE
{
- Lex->m_sql_cmd= new (YYTHD->mem_root)
+ Lex->m_sql_cmd= new (thd->mem_root)
Sql_cmd_discard_import_tablespace(
Sql_cmd_discard_import_tablespace::IMPORT_TABLESPACE);
if (Lex->m_sql_cmd == NULL)
@@ -7193,7 +7169,6 @@ alter_commands:
| OPTIMIZE PARTITION_SYM opt_no_write_to_binlog
all_or_alt_part_name_list
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -7207,7 +7182,6 @@ alter_commands:
| ANALYZE_SYM PARTITION_SYM opt_no_write_to_binlog
all_or_alt_part_name_list
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -7219,7 +7193,6 @@ alter_commands:
}
| CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->check_opt.init();
DBUG_ASSERT(!lex->m_sql_cmd);
@@ -7232,7 +7205,6 @@ alter_commands:
| REPAIR PARTITION_SYM opt_no_write_to_binlog
all_or_alt_part_name_list
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -7252,7 +7224,6 @@ alter_commands:
}
| TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->check_opt.init();
DBUG_ASSERT(!lex->m_sql_cmd);
@@ -7265,7 +7236,6 @@ alter_commands:
| EXCHANGE_SYM PARTITION_SYM alt_part_name_item
WITH TABLE_SYM table_ident have_partitioning
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
size_t dummy;
lex->select_lex.db=$6->db.str;
@@ -7543,7 +7513,6 @@ alter_list_item:
{
if (!$4)
{
- THD *thd= YYTHD;
$4= thd->variables.collation_database;
}
$5= $5 ? $5 : $4;
@@ -7842,7 +7811,6 @@ repair:
}
table_list opt_mi_repair_type
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
@@ -7880,7 +7848,6 @@ analyze:
}
analyze_table_list
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
@@ -7903,7 +7870,6 @@ opt_persistent_stat_clause:
{}
| PERSISTENT_SYM FOR_SYM persistent_stat_spec
{
- THD *thd= YYTHD;
thd->lex->with_persistent_for_clause= TRUE;
}
;
@@ -7918,7 +7884,6 @@ persistent_column_stat_spec:
ALL {}
| '('
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
lex->column_list= new List<LEX_STRING>;
if (lex->column_list == NULL)
@@ -7932,7 +7897,6 @@ persistent_index_stat_spec:
ALL {}
| '('
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
lex->index_list= new List<LEX_STRING>;
if (lex->index_list == NULL)
@@ -8005,7 +7969,6 @@ check:
}
table_list opt_mi_check_type
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
@@ -8046,7 +8009,6 @@ optimize:
}
table_list
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
@@ -8131,7 +8093,7 @@ keycache_list:
assign_to_keycache:
table_ident cache_keys_spec
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
+ if (!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
MDL_SHARED_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
@@ -8141,7 +8103,7 @@ assign_to_keycache:
assign_to_keycache_parts:
table_ident adm_partition cache_keys_spec
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
+ if (!Select->add_table_to_list(thd, $1, NULL, 0, TL_READ,
MDL_SHARED_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
@@ -8177,7 +8139,7 @@ preload_list:
preload_keys:
table_ident cache_keys_spec opt_ignore_leaves
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL, $3, TL_READ,
+ if (!Select->add_table_to_list(thd, $1, NULL, $3, TL_READ,
MDL_SHARED_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
@@ -8187,7 +8149,7 @@ preload_keys:
preload_keys_parts:
table_ident adm_partition cache_keys_spec opt_ignore_leaves
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL, $4, TL_READ,
+ if (!Select->add_table_to_list(thd, $1, NULL, $4, TL_READ,
MDL_SHARED_READ,
Select->pop_index_hints()))
MYSQL_YYABORT;
@@ -8204,7 +8166,7 @@ adm_partition:
cache_keys_spec:
{
- Lex->select_lex.alloc_index_hints(YYTHD);
+ Lex->select_lex.alloc_index_hints(thd);
Select->set_index_hint_type(INDEX_HINT_USE,
INDEX_HINT_MASK_ALL);
}
@@ -8417,7 +8379,6 @@ select_item_list:
| select_item
| '*'
{
- THD *thd= YYTHD;
Item *item= new (thd->mem_root)
Item_field(&thd->lex->current_select->context,
NULL, NULL, "*");
@@ -8432,14 +8393,11 @@ select_item_list:
select_item:
remember_name table_wild remember_end
{
- THD *thd= YYTHD;
-
if (add_item_to_list(thd, $2))
MYSQL_YYABORT;
}
| remember_name expr remember_end select_alias
{
- THD *thd= YYTHD;
DBUG_ASSERT($1 < $3);
if (add_item_to_list(thd, $2))
@@ -8547,7 +8505,7 @@ expr:
else
{
/* X OR Y */
- $$ = new (YYTHD->mem_root) Item_cond_or($1, $3);
+ $$ = new (thd->mem_root) Item_cond_or($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8555,7 +8513,7 @@ expr:
| expr XOR expr %prec XOR
{
/* XOR is a proprietary extension */
- $$ = new (YYTHD->mem_root) Item_func_xor($1, $3);
+ $$ = new (thd->mem_root) Item_func_xor($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8597,50 +8555,50 @@ expr:
else
{
/* X AND Y */
- $$ = new (YYTHD->mem_root) Item_cond_and($1, $3);
+ $$ = new (thd->mem_root) Item_cond_and($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
}
| NOT_SYM expr %prec NOT_SYM
{
- $$= negate_expression(YYTHD, $2);
+ $$= negate_expression(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS TRUE_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_istrue($1);
+ $$= new (thd->mem_root) Item_func_istrue($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not TRUE_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnottrue($1);
+ $$= new (thd->mem_root) Item_func_isnottrue($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS FALSE_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isfalse($1);
+ $$= new (thd->mem_root) Item_func_isfalse($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not FALSE_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnotfalse($1);
+ $$= new (thd->mem_root) Item_func_isnotfalse($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS UNKNOWN_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnull($1);
+ $$= new (thd->mem_root) Item_func_isnull($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not UNKNOWN_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnotnull($1);
+ $$= new (thd->mem_root) Item_func_isnotnull($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8650,19 +8608,19 @@ expr:
bool_pri:
bool_pri IS NULL_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnull($1);
+ $$= new (thd->mem_root) Item_func_isnull($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri IS not NULL_SYM %prec IS
{
- $$= new (YYTHD->mem_root) Item_func_isnotnull($1);
+ $$= new (thd->mem_root) Item_func_isnotnull($1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
{
- $$= new (YYTHD->mem_root) Item_func_equal($1,$3);
+ $$= new (thd->mem_root) Item_func_equal($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8684,13 +8642,12 @@ bool_pri:
predicate:
bit_expr IN_SYM '(' subselect ')'
{
- $$= new (YYTHD->mem_root) Item_in_subselect($1, $4);
+ $$= new (thd->mem_root) Item_in_subselect($1, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not IN_SYM '(' subselect ')'
{
- THD *thd= YYTHD;
Item *item= new (thd->mem_root) Item_in_subselect($1, $5);
if (item == NULL)
MYSQL_YYABORT;
@@ -8700,7 +8657,7 @@ predicate:
}
| bit_expr IN_SYM '(' expr ')'
{
- $$= handle_sql2003_note184_exception(YYTHD, $1, true, $4);
+ $$= handle_sql2003_note184_exception(thd, $1, true, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8708,13 +8665,13 @@ predicate:
{
$6->push_front($4);
$6->push_front($1);
- $$= new (YYTHD->mem_root) Item_func_in(*$6);
+ $$= new (thd->mem_root) Item_func_in(*$6);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not IN_SYM '(' expr ')'
{
- $$= handle_sql2003_note184_exception(YYTHD, $1, false, $5);
+ $$= handle_sql2003_note184_exception(thd, $1, false, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8722,7 +8679,7 @@ predicate:
{
$7->push_front($5);
$7->push_front($1);
- Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
+ Item_func_in *item = new (thd->mem_root) Item_func_in(*$7);
if (item == NULL)
MYSQL_YYABORT;
item->negate();
@@ -8730,14 +8687,14 @@ predicate:
}
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{
- $$= new (YYTHD->mem_root) Item_func_between($1,$3,$5);
+ $$= new (thd->mem_root) Item_func_between($1,$3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
{
Item_func_between *item;
- item= new (YYTHD->mem_root) Item_func_between($1,$4,$6);
+ item= new (thd->mem_root) Item_func_between($1,$4,$6);
if (item == NULL)
MYSQL_YYABORT;
item->negate();
@@ -8745,42 +8702,42 @@ predicate:
}
| bit_expr SOUNDS_SYM LIKE bit_expr
{
- Item *item1= new (YYTHD->mem_root) Item_func_soundex($1);
- Item *item4= new (YYTHD->mem_root) Item_func_soundex($4);
+ Item *item1= new (thd->mem_root) Item_func_soundex($1);
+ Item *item4= new (thd->mem_root) Item_func_soundex($4);
if ((item1 == NULL) || (item4 == NULL))
MYSQL_YYABORT;
- $$= new (YYTHD->mem_root) Item_func_eq(item1, item4);
+ $$= new (thd->mem_root) Item_func_eq(item1, item4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr LIKE simple_expr opt_escape
{
- $$= new (YYTHD->mem_root) Item_func_like($1,$3,$4,Lex->escape_used);
+ $$= new (thd->mem_root) Item_func_like($1,$3,$4,Lex->escape_used);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not LIKE simple_expr opt_escape
{
- Item *item= new (YYTHD->mem_root) Item_func_like($1,$4,$5,
+ Item *item= new (thd->mem_root) Item_func_like($1,$4,$5,
Lex->escape_used);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (YYTHD->mem_root) Item_func_not(item);
+ $$= new (thd->mem_root) Item_func_not(item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr REGEXP bit_expr
{
- $$= new (YYTHD->mem_root) Item_func_regex($1,$3);
+ $$= new (thd->mem_root) Item_func_regex($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr not REGEXP bit_expr
{
- Item *item= new (YYTHD->mem_root) Item_func_regex($1,$4);
+ Item *item= new (thd->mem_root) Item_func_regex($1,$4);
if (item == NULL)
MYSQL_YYABORT;
- $$= negate_expression(YYTHD, item);
+ $$= negate_expression(thd, item);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8790,85 +8747,85 @@ predicate:
bit_expr:
bit_expr '|' bit_expr %prec '|'
{
- $$= new (YYTHD->mem_root) Item_func_bit_or($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_or($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '&' bit_expr %prec '&'
{
- $$= new (YYTHD->mem_root) Item_func_bit_and($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_and($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
{
- $$= new (YYTHD->mem_root) Item_func_shift_left($1,$3);
+ $$= new (thd->mem_root) Item_func_shift_left($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
{
- $$= new (YYTHD->mem_root) Item_func_shift_right($1,$3);
+ $$= new (thd->mem_root) Item_func_shift_right($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '+' bit_expr %prec '+'
{
- $$= new (YYTHD->mem_root) Item_func_plus($1,$3);
+ $$= new (thd->mem_root) Item_func_plus($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '-' bit_expr %prec '-'
{
- $$= new (YYTHD->mem_root) Item_func_minus($1,$3);
+ $$= new (thd->mem_root) Item_func_minus($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '+' INTERVAL_SYM expr interval %prec '+'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($1,$4,$5,0);
+ $$= new (thd->mem_root) Item_date_add_interval($1,$4,$5,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '-' INTERVAL_SYM expr interval %prec '-'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($1,$4,$5,1);
+ $$= new (thd->mem_root) Item_date_add_interval($1,$4,$5,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '*' bit_expr %prec '*'
{
- $$= new (YYTHD->mem_root) Item_func_mul($1,$3);
+ $$= new (thd->mem_root) Item_func_mul($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '/' bit_expr %prec '/'
{
- $$= new (YYTHD->mem_root) Item_func_div($1,$3);
+ $$= new (thd->mem_root) Item_func_div($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '%' bit_expr %prec '%'
{
- $$= new (YYTHD->mem_root) Item_func_mod($1,$3);
+ $$= new (thd->mem_root) Item_func_mod($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr DIV_SYM bit_expr %prec DIV_SYM
{
- $$= new (YYTHD->mem_root) Item_func_int_div($1,$3);
+ $$= new (thd->mem_root) Item_func_int_div($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr MOD_SYM bit_expr %prec MOD_SYM
{
- $$= new (YYTHD->mem_root) Item_func_mod($1,$3);
+ $$= new (thd->mem_root) Item_func_mod($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| bit_expr '^' bit_expr
{
- $$= new (YYTHD->mem_root) Item_func_bit_xor($1,$3);
+ $$= new (thd->mem_root) Item_func_bit_xor($1,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9004,7 +8961,7 @@ dyncall_create_element:
{
LEX *lex= Lex;
$$= (DYNCALL_CREATE_DEF *)
- alloc_root(YYTHD->mem_root, sizeof(DYNCALL_CREATE_DEF));
+ alloc_root(thd->mem_root, sizeof(DYNCALL_CREATE_DEF));
if ($$ == NULL)
MYSQL_YYABORT;
$$->key= $1;
@@ -9024,7 +8981,7 @@ dyncall_create_element:
dyncall_create_list:
dyncall_create_element
{
- $$= new (YYTHD->mem_root) List<DYNCALL_CREATE_DEF>;
+ $$= new (thd->mem_root) List<DYNCALL_CREATE_DEF>;
if ($$ == NULL)
MYSQL_YYABORT;
$$->push_back($1);
@@ -9044,7 +9001,6 @@ simple_expr:
| function_call_conflict
| simple_expr COLLATE_SYM ident_or_text %prec NEG
{
- THD *thd= YYTHD;
Item *i1= new (thd->mem_root) Item_string($3.str,
$3.length,
thd->charset());
@@ -9060,7 +9016,7 @@ simple_expr:
| sum_expr
| simple_expr OR_OR_SYM simple_expr
{
- $$= new (YYTHD->mem_root) Item_func_concat($1, $3);
+ $$= new (thd->mem_root) Item_func_concat($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9070,25 +9026,25 @@ simple_expr:
}
| '-' simple_expr %prec NEG
{
- $$= new (YYTHD->mem_root) Item_func_neg($2);
+ $$= new (thd->mem_root) Item_func_neg($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '~' simple_expr %prec NEG
{
- $$= new (YYTHD->mem_root) Item_func_bit_neg($2);
+ $$= new (thd->mem_root) Item_func_bit_neg($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| not2 simple_expr %prec NEG
{
- $$= negate_expression(YYTHD, $2);
+ $$= negate_expression(thd, $2);
if ($$ == NULL)
MYSQL_YYABORT;
}
| '(' subselect ')'
{
- $$= new (YYTHD->mem_root) Item_singlerow_subselect($2);
+ $$= new (thd->mem_root) Item_singlerow_subselect($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9097,20 +9053,20 @@ simple_expr:
| '(' expr ',' expr_list ')'
{
$4->push_front($2);
- $$= new (YYTHD->mem_root) Item_row(*$4);
+ $$= new (thd->mem_root) Item_row(*$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ROW_SYM '(' expr ',' expr_list ')'
{
$5->push_front($3);
- $$= new (YYTHD->mem_root) Item_row(*$5);
+ $$= new (thd->mem_root) Item_row(*$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| EXISTS '(' subselect ')'
{
- $$= new (YYTHD->mem_root) Item_exists_subselect($3);
+ $$= new (thd->mem_root) Item_exists_subselect($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9147,7 +9103,7 @@ simple_expr:
}
if (type != MYSQL_TYPE_STRING)
{
- $$= create_temporal_literal(YYTHD,
+ $$= create_temporal_literal(thd,
item->str_value.ptr(),
item->str_value.length(),
item->str_value.charset(),
@@ -9160,7 +9116,7 @@ simple_expr:
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{
$2->push_front($5);
- Item_func_match *i1= new (YYTHD->mem_root) Item_func_match(*$2, $6);
+ Item_func_match *i1= new (thd->mem_root) Item_func_match(*$2, $6);
if (i1 == NULL)
MYSQL_YYABORT;
Select->add_ftfunc_to_list(i1);
@@ -9168,7 +9124,7 @@ simple_expr:
}
| BINARY simple_expr %prec NEG
{
- $$= create_func_cast(YYTHD, $2, ITEM_CAST_CHAR, NULL, NULL,
+ $$= create_func_cast(thd, $2, ITEM_CAST_CHAR, NULL, NULL,
&my_charset_bin);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -9176,27 +9132,27 @@ simple_expr:
| CAST_SYM '(' expr AS cast_type ')'
{
LEX *lex= Lex;
- $$= create_func_cast(YYTHD, $3, $5, lex->length, lex->dec,
+ $$= create_func_cast(thd, $3, $5, lex->length, lex->dec,
lex->charset);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CASE_SYM opt_expr when_list opt_else END
{
- $$= new (YYTHD->mem_root) Item_func_case(* $3, $2, $4 );
+ $$= new (thd->mem_root) Item_func_case(* $3, $2, $4 );
if ($$ == NULL)
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr ',' cast_type ')'
{
- $$= create_func_cast(YYTHD, $3, $5, Lex->length, Lex->dec,
+ $$= create_func_cast(thd, $3, $5, Lex->length, Lex->dec,
Lex->charset);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CONVERT_SYM '(' expr USING charset_name ')'
{
- $$= new (YYTHD->mem_root) Item_func_conv_charset($3,$5);
+ $$= new (thd->mem_root) Item_func_conv_charset($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9209,14 +9165,14 @@ simple_expr:
my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
MYSQL_YYABORT;
}
- $$= new (YYTHD->mem_root) Item_default_value(Lex->current_context(),
+ $$= new (thd->mem_root) Item_default_value(Lex->current_context(),
$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VALUES '(' simple_ident_nospvar ')'
{
- $$= new (YYTHD->mem_root) Item_insert_value(Lex->current_context(),
+ $$= new (thd->mem_root) Item_insert_value(Lex->current_context(),
$3);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -9224,7 +9180,7 @@ simple_expr:
| INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
/* we cannot put interval before - */
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($5,$2,$3,0);
+ $$= new (thd->mem_root) Item_date_add_interval($5,$2,$3,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9239,19 +9195,19 @@ simple_expr:
function_call_keyword:
CHAR_SYM '(' expr_list ')'
{
- $$= new (YYTHD->mem_root) Item_func_char(*$3);
+ $$= new (thd->mem_root) Item_func_char(*$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CHAR_SYM '(' expr_list USING charset_name ')'
{
- $$= new (YYTHD->mem_root) Item_func_char(*$3, $5);
+ $$= new (thd->mem_root) Item_func_char(*$3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CURRENT_USER optional_braces
{
- $$= new (YYTHD->mem_root) Item_func_current_user(Lex->current_context());
+ $$= new (thd->mem_root) Item_func_current_user(Lex->current_context());
if ($$ == NULL)
MYSQL_YYABORT;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
@@ -9259,31 +9215,30 @@ function_call_keyword:
}
| DATE_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_date_typecast($3);
+ $$= new (thd->mem_root) Item_date_typecast($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DAY_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_dayofmonth($3);
+ $$= new (thd->mem_root) Item_func_dayofmonth($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HOUR_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_hour($3);
+ $$= new (thd->mem_root) Item_func_hour($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| INSERT '(' expr ',' expr ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_insert($3,$5,$7,$9);
+ $$= new (thd->mem_root) Item_func_insert($3,$5,$7,$9);
if ($$ == NULL)
MYSQL_YYABORT;
}
| INTERVAL_SYM '(' expr ',' expr ')' %prec INTERVAL_SYM
{
- THD *thd= YYTHD;
List<Item> *list= new (thd->mem_root) List<Item>;
if (list == NULL)
MYSQL_YYABORT;
@@ -9298,7 +9253,6 @@ function_call_keyword:
}
| INTERVAL_SYM '(' expr ',' expr ',' expr_list ')' %prec INTERVAL_SYM
{
- THD *thd= YYTHD;
$7->push_front($5);
$7->push_front($3);
Item_row *item= new (thd->mem_root) Item_row(*$7);
@@ -9310,103 +9264,103 @@ function_call_keyword:
}
| LEFT '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_left($3,$5);
+ $$= new (thd->mem_root) Item_func_left($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MINUTE_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_minute($3);
+ $$= new (thd->mem_root) Item_func_minute($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MONTH_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_month($3);
+ $$= new (thd->mem_root) Item_func_month($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| RIGHT '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_right($3,$5);
+ $$= new (thd->mem_root) Item_func_right($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SECOND_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_second($3);
+ $$= new (thd->mem_root) Item_func_second($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIME_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_time_typecast($3, AUTO_SEC_PART_DIGITS);
+ $$= new (thd->mem_root) Item_time_typecast($3, AUTO_SEC_PART_DIGITS);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_datetime_typecast($3, AUTO_SEC_PART_DIGITS);
+ $$= new (thd->mem_root) Item_datetime_typecast($3, AUTO_SEC_PART_DIGITS);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_add_time($3, $5, 1, 0);
+ $$= new (thd->mem_root) Item_func_add_time($3, $5, 1, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_trim($3);
+ $$= new (thd->mem_root) Item_func_trim($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING expr FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_ltrim($6,$4);
+ $$= new (thd->mem_root) Item_func_ltrim($6,$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING expr FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_rtrim($6,$4);
+ $$= new (thd->mem_root) Item_func_rtrim($6,$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH expr FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_trim($6,$4);
+ $$= new (thd->mem_root) Item_func_trim($6,$4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_ltrim($5);
+ $$= new (thd->mem_root) Item_func_ltrim($5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_rtrim($5);
+ $$= new (thd->mem_root) Item_func_rtrim($5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_trim($5);
+ $$= new (thd->mem_root) Item_func_trim($5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_trim($5,$3);
+ $$= new (thd->mem_root) Item_func_trim($5,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| USER '(' ')'
{
- $$= new (YYTHD->mem_root) Item_func_user();
+ $$= new (thd->mem_root) Item_func_user();
if ($$ == NULL)
MYSQL_YYABORT;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
@@ -9414,7 +9368,7 @@ function_call_keyword:
}
| YEAR_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_year($3);
+ $$= new (thd->mem_root) Item_func_year($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9435,27 +9389,27 @@ function_call_keyword:
function_call_nonkeyword:
ADDDATE_SYM '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3, $5,
+ $$= new (thd->mem_root) Item_date_add_interval($3, $5,
INTERVAL_DAY, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3, $6, $7, 0);
+ $$= new (thd->mem_root) Item_date_add_interval($3, $6, $7, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CURDATE optional_braces
{
- $$= new (YYTHD->mem_root) Item_func_curdate_local();
+ $$= new (thd->mem_root) Item_func_curdate_local();
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| CURTIME opt_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_curtime_local($2);
+ $$= new (thd->mem_root) Item_func_curtime_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
@@ -9463,76 +9417,76 @@ function_call_nonkeyword:
| DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
%prec INTERVAL_SYM
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,0);
+ $$= new (thd->mem_root) Item_date_add_interval($3,$6,$7,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')'
%prec INTERVAL_SYM
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,1);
+ $$= new (thd->mem_root) Item_date_add_interval($3,$6,$7,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| EXTRACT_SYM '(' interval FROM expr ')'
{
- $$=new (YYTHD->mem_root) Item_extract( $3, $5);
+ $$=new (thd->mem_root) Item_extract( $3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| GET_FORMAT '(' date_time_type ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_get_format($3, $5);
+ $$= new (thd->mem_root) Item_func_get_format($3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| NOW_SYM opt_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_now_local($2);
+ $$= new (thd->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| POSITION_SYM '(' bit_expr IN_SYM expr ')'
{
- $$ = new (YYTHD->mem_root) Item_func_locate($5,$3);
+ $$ = new (thd->mem_root) Item_func_locate($5,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBDATE_SYM '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3, $5,
+ $$= new (thd->mem_root) Item_date_add_interval($3, $5,
INTERVAL_DAY, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($3, $6, $7, 1);
+ $$= new (thd->mem_root) Item_date_add_interval($3, $6, $7, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_substr($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_substr($3,$5,$7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_substr($3,$5);
+ $$= new (thd->mem_root) Item_func_substr($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_substr($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_substr($3,$5,$7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_substr($3,$5);
+ $$= new (thd->mem_root) Item_func_substr($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9547,42 +9501,42 @@ function_call_nonkeyword:
*/
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
if (global_system_variables.sysdate_is_now == 0)
- $$= new (YYTHD->mem_root) Item_func_sysdate_local($2);
+ $$= new (thd->mem_root) Item_func_sysdate_local($2);
else
- $$= new (YYTHD->mem_root) Item_func_now_local($2);
+ $$= new (thd->mem_root) Item_func_now_local($2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_date_add_interval($7,$5,$3,0);
+ $$= new (thd->mem_root) Item_date_add_interval($7,$5,$3,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_timestamp_diff($5,$7,$3);
+ $$= new (thd->mem_root) Item_func_timestamp_diff($5,$7,$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| UTC_DATE_SYM optional_braces
{
- $$= new (YYTHD->mem_root) Item_func_curdate_utc();
+ $$= new (thd->mem_root) Item_func_curdate_utc();
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| UTC_TIME_SYM opt_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_curtime_utc($2);
+ $$= new (thd->mem_root) Item_func_curtime_utc($2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| UTC_TIMESTAMP_SYM opt_time_precision
{
- $$= new (YYTHD->mem_root) Item_func_now_utc($2);
+ $$= new (thd->mem_root) Item_func_now_utc($2);
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
@@ -9590,28 +9544,28 @@ function_call_nonkeyword:
|
COLUMN_ADD_SYM '(' expr ',' dyncall_create_list ')'
{
- $$= create_func_dyncol_add(YYTHD, $3, *$5);
+ $$= create_func_dyncol_add(thd, $3, *$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
COLUMN_DELETE_SYM '(' expr ',' expr_list ')'
{
- $$= create_func_dyncol_delete(YYTHD, $3, *$5);
+ $$= create_func_dyncol_delete(thd, $3, *$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
COLUMN_CHECK_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_dyncol_check($3);
+ $$= new (thd->mem_root) Item_func_dyncol_check($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
|
COLUMN_CREATE_SYM '(' dyncall_create_list ')'
{
- $$= create_func_dyncol_create(YYTHD, *$3);
+ $$= create_func_dyncol_create(thd, *$3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9619,7 +9573,7 @@ function_call_nonkeyword:
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{
LEX *lex= Lex;
- $$= create_func_dyncol_get(YYTHD, $3, $5, $7,
+ $$= create_func_dyncol_get(thd, $3, $5, $7,
lex->length, lex->dec,
lex->charset);
if ($$ == NULL)
@@ -9635,69 +9589,68 @@ function_call_nonkeyword:
function_call_conflict:
ASCII_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_ascii($3);
+ $$= new (thd->mem_root) Item_func_ascii($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| CHARSET '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_charset($3);
+ $$= new (thd->mem_root) Item_func_charset($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COALESCE '(' expr_list ')'
{
- $$= new (YYTHD->mem_root) Item_func_coalesce(* $3);
+ $$= new (thd->mem_root) Item_func_coalesce(* $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COLLATION_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_collation($3);
+ $$= new (thd->mem_root) Item_func_collation($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DATABASE '(' ')'
{
- $$= new (YYTHD->mem_root) Item_func_database();
+ $$= new (thd->mem_root) Item_func_database();
if ($$ == NULL)
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
| IF '(' expr ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_if($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_if($3,$5,$7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| LAST_VALUE '(' expr_list ')'
{
- $$= new (YYTHD->mem_root) Item_func_last_value(* $3);
+ $$= new (thd->mem_root) Item_func_last_value(* $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MICROSECOND_SYM '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_microsecond($3);
+ $$= new (thd->mem_root) Item_func_microsecond($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MOD_SYM '(' expr ',' expr ')'
{
- $$ = new (YYTHD->mem_root) Item_func_mod($3, $5);
+ $$ = new (thd->mem_root) Item_func_mod($3, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| OLD_PASSWORD '(' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_old_password($3);
+ $$= new (thd->mem_root) Item_func_old_password($3);
Lex->contains_plaintext_password= true;
if ($$ == NULL)
MYSQL_YYABORT;
}
| PASSWORD '(' expr ')'
{
- THD *thd= YYTHD;
Item* i1;
Lex->contains_plaintext_password= true;
if (thd->variables.old_passwords == 1)
@@ -9710,25 +9663,25 @@ function_call_conflict:
}
| QUARTER_SYM '(' expr ')'
{
- $$ = new (YYTHD->mem_root) Item_func_quarter($3);
+ $$ = new (thd->mem_root) Item_func_quarter($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| REPEAT_SYM '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_repeat($3,$5);
+ $$= new (thd->mem_root) Item_func_repeat($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| REPLACE '(' expr ',' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_replace($3,$5,$7);
+ $$= new (thd->mem_root) Item_func_replace($3,$5,$7);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ROW_COUNT_SYM '(' ')'
{
- $$= new (YYTHD->mem_root) Item_func_row_count();
+ $$= new (thd->mem_root) Item_func_row_count();
if ($$ == NULL)
MYSQL_YYABORT;
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
@@ -9736,13 +9689,12 @@ function_call_conflict:
}
| TRUNCATE_SYM '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_round($3,$5,1);
+ $$= new (thd->mem_root) Item_func_round($3,$5,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| WEEK_SYM '(' expr ')'
{
- THD *thd= YYTHD;
Item *i1= new (thd->mem_root) Item_int((char*) "0",
thd->variables.default_week_format,
1);
@@ -9754,7 +9706,7 @@ function_call_conflict:
}
| WEEK_SYM '(' expr ',' expr ')'
{
- $$= new (YYTHD->mem_root) Item_func_week($3,$5);
+ $$= new (thd->mem_root) Item_func_week($3,$5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -9776,52 +9728,52 @@ function_call_conflict:
geometry_function:
CONTAINS_SYM '(' expr ',' expr ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_rel($3, $5,
Item_func::SP_CONTAINS_FUNC));
}
| GEOMETRYCOLLECTION '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_geometrycollection,
Geometry::wkb_point));
}
| LINESTRING '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_linestring,
Geometry::wkb_point));
}
| MULTILINESTRING '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring));
}
| MULTIPOINT '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_multipoint,
Geometry::wkb_point));
}
| MULTIPOLYGON '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon));
}
| POINT_SYM '(' expr ',' expr ')'
{
- $$= GEOM_NEW(YYTHD, Item_func_point($3,$5));
+ $$= GEOM_NEW(thd, Item_func_point($3,$5));
}
| POLYGON '(' expr_list ')'
{
- $$= GEOM_NEW(YYTHD,
+ $$= GEOM_NEW(thd,
Item_func_spatial_collection(* $3,
Geometry::wkb_polygon,
Geometry::wkb_linestring));
@@ -9859,7 +9811,6 @@ function_call_generic:
}
opt_udf_expr_list ')'
{
- THD *thd= YYTHD;
Create_func *builder;
Item *item= NULL;
@@ -9913,7 +9864,6 @@ function_call_generic:
}
| ident '.' ident '(' opt_expr_list ')'
{
- THD *thd= YYTHD;
Create_qfunc *builder;
Item *item= NULL;
@@ -9977,7 +9927,7 @@ opt_udf_expr_list:
udf_expr_list:
udf_expr
{
- $$= new (YYTHD->mem_root) List<Item>;
+ $$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
$$->push_back($1);
@@ -10010,7 +9960,7 @@ udf_expr:
remember_name we may get quoted or escaped names.
*/
else if ($2->type() != Item::FIELD_ITEM)
- $2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
+ $2->set_name($1, (uint) ($3 - $1), thd->charset());
$$= $2;
}
;
@@ -10018,46 +9968,46 @@ udf_expr:
sum_expr:
AVG_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_avg($3, FALSE);
+ $$= new (thd->mem_root) Item_sum_avg($3, FALSE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| AVG_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_avg($4, TRUE);
+ $$= new (thd->mem_root) Item_sum_avg($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_AND '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_and($3);
+ $$= new (thd->mem_root) Item_sum_and($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_OR '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_or($3);
+ $$= new (thd->mem_root) Item_sum_or($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIT_XOR '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_xor($3);
+ $$= new (thd->mem_root) Item_sum_xor($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COUNT_SYM '(' opt_all '*' ')'
{
- Item *item= new (YYTHD->mem_root) Item_int((int32) 0L,1);
+ Item *item= new (thd->mem_root) Item_int((int32) 0L,1);
if (item == NULL)
MYSQL_YYABORT;
- $$= new (YYTHD->mem_root) Item_sum_count(item);
+ $$= new (thd->mem_root) Item_sum_count(item);
if ($$ == NULL)
MYSQL_YYABORT;
}
| COUNT_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_count($3);
+ $$= new (thd->mem_root) Item_sum_count($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10067,13 +10017,13 @@ sum_expr:
{ Select->in_sum_expr--; }
')'
{
- $$= new (YYTHD->mem_root) Item_sum_count(* $5);
+ $$= new (thd->mem_root) Item_sum_count(* $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MIN_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_min($3);
+ $$= new (thd->mem_root) Item_sum_min($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10084,55 +10034,55 @@ sum_expr:
*/
| MIN_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_min($4);
+ $$= new (thd->mem_root) Item_sum_min($4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MAX_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_max($3);
+ $$= new (thd->mem_root) Item_sum_max($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| MAX_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_max($4);
+ $$= new (thd->mem_root) Item_sum_max($4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| STD_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_std($3, 0);
+ $$= new (thd->mem_root) Item_sum_std($3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VARIANCE_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_variance($3, 0);
+ $$= new (thd->mem_root) Item_sum_variance($3, 0);
if ($$ == NULL)
MYSQL_YYABORT;
}
| STDDEV_SAMP_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_std($3, 1);
+ $$= new (thd->mem_root) Item_sum_std($3, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| VAR_SAMP_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_variance($3, 1);
+ $$= new (thd->mem_root) Item_sum_variance($3, 1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUM_SYM '(' in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_sum($3, FALSE);
+ $$= new (thd->mem_root) Item_sum_sum($3, FALSE);
if ($$ == NULL)
MYSQL_YYABORT;
}
| SUM_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_sum($4, TRUE);
+ $$= new (thd->mem_root) Item_sum_sum($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10144,7 +10094,7 @@ sum_expr:
{
SELECT_LEX *sel= Select;
sel->in_sum_expr--;
- $$= new (YYTHD->mem_root)
+ $$= new (thd->mem_root)
Item_func_group_concat(Lex->current_context(), $3, $5,
sel->gorder_list, $7);
if ($$ == NULL)
@@ -10173,7 +10123,7 @@ variable_aux:
ident_or_text SET_VAR expr
{
Item_func_set_user_var *item;
- $$= item= new (YYTHD->mem_root) Item_func_set_user_var($1, $3);
+ $$= item= new (thd->mem_root) Item_func_set_user_var($1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -10182,7 +10132,7 @@ variable_aux:
}
| ident_or_text
{
- $$= new (YYTHD->mem_root) Item_func_get_user_var($1);
+ $$= new (thd->mem_root) Item_func_get_user_var($1);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
@@ -10196,7 +10146,7 @@ variable_aux:
my_parse_error(ER(ER_SYNTAX_ERROR));
MYSQL_YYABORT;
}
- if (!($$= get_system_var(YYTHD, $2, $3, $4)))
+ if (!($$= get_system_var(thd, $2, $3, $4)))
MYSQL_YYABORT;
if (!((Item_func_get_system_var*) $$)->is_written_to_binlog())
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
@@ -10211,7 +10161,7 @@ opt_distinct:
opt_gconcat_separator:
/* empty */
{
- $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1);
+ $$= new (thd->mem_root) String(",", 1, &my_charset_latin1);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -10238,9 +10188,9 @@ opt_gorder_clause:
gorder_list:
gorder_list ',' order_ident order_dir
- { if (add_gorder_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; }
+ { if (add_gorder_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
| order_ident order_dir
- { if (add_gorder_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; }
+ { if (add_gorder_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
;
in_sum_expr:
@@ -10306,7 +10256,7 @@ opt_expr_list:
expr_list:
expr
{
- $$= new (YYTHD->mem_root) List<Item>;
+ $$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
$$->push_back($1);
@@ -10326,7 +10276,7 @@ ident_list_arg:
ident_list:
simple_ident
{
- $$= new (YYTHD->mem_root) List<Item>;
+ $$= new (thd->mem_root) List<Item>;
if ($$ == NULL)
MYSQL_YYABORT;
$$->push_back($1);
@@ -10427,7 +10377,7 @@ join_table:
{
MYSQL_YYABORT_UNLESS($1 && $3);
/* Change the current name resolution context to a local context. */
- if (push_new_name_resolution_context(YYTHD, $1, $3))
+ if (push_new_name_resolution_context(thd, $1, $3))
MYSQL_YYABORT;
Select->parsing_place= IN_ON;
}
@@ -10462,7 +10412,7 @@ join_table:
{
MYSQL_YYABORT_UNLESS($1 && $5);
/* Change the current name resolution context to a local context. */
- if (push_new_name_resolution_context(YYTHD, $1, $5))
+ if (push_new_name_resolution_context(thd, $1, $5))
MYSQL_YYABORT;
Select->parsing_place= IN_ON;
}
@@ -10498,7 +10448,7 @@ join_table:
{
MYSQL_YYABORT_UNLESS($1 && $5);
/* Change the current name resolution context to a local context. */
- if (push_new_name_resolution_context(YYTHD, $1, $5))
+ if (push_new_name_resolution_context(thd, $1, $5))
MYSQL_YYABORT;
Select->parsing_place= IN_ON;
}
@@ -10575,7 +10525,7 @@ table_factor:
}
table_ident opt_use_partition opt_table_alias opt_key_definition
{
- if (!($$= Select->add_table_to_list(YYTHD, $2, $4,
+ if (!($$= Select->add_table_to_list(thd, $2, $4,
Select->get_table_join_options(),
YYPS->m_lock_type,
YYPS->m_mdl_type,
@@ -10855,7 +10805,7 @@ opt_outer:
index_hint_clause:
/* empty */
{
- $$= YYTHD->variables.old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL;
+ $$= thd->variables.old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL;
}
| FOR_SYM JOIN_SYM { $$= INDEX_HINT_MASK_JOIN; }
| FOR_SYM ORDER_SYM BY { $$= INDEX_HINT_MASK_ORDER; }
@@ -10887,7 +10837,7 @@ index_hints_list:
opt_index_hints_list:
/* empty */
- | { Select->alloc_index_hints(YYTHD); } index_hints_list
+ | { Select->alloc_index_hints(thd); } index_hints_list
;
opt_key_definition:
@@ -10896,15 +10846,15 @@ opt_key_definition:
;
opt_key_usage_list:
- /* empty */ { Select->add_index_hint(YYTHD, NULL, 0); }
+ /* empty */ { Select->add_index_hint(thd, NULL, 0); }
| key_usage_list {}
;
key_usage_element:
ident
- { Select->add_index_hint(YYTHD, $1.str, $1.length); }
+ { Select->add_index_hint(thd, $1.str, $1.length); }
| PRIMARY_SYM
- { Select->add_index_hint(YYTHD, (char *)"PRIMARY", 7); }
+ { Select->add_index_hint(thd, (char *)"PRIMARY", 7); }
;
key_usage_list:
@@ -10917,7 +10867,7 @@ using_list:
{
if (!($$= new List<String>))
MYSQL_YYABORT;
- String *s= new (YYTHD->mem_root) String((const char *) $1.str,
+ String *s= new (thd->mem_root) String((const char *) $1.str,
$1.length,
system_charset_info);
if (s == NULL)
@@ -10926,7 +10876,7 @@ using_list:
}
| using_list ',' ident
{
- String *s= new (YYTHD->mem_root) String((const char *) $3.str,
+ String *s= new (thd->mem_root) String((const char *) $3.str,
$3.length,
system_charset_info);
if (s == NULL)
@@ -11031,7 +10981,6 @@ opt_escape:
}
| /* empty */
{
- THD *thd= YYTHD;
Lex->escape_used= FALSE;
$$= ((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
new (thd->mem_root) Item_string("", 0, &my_charset_latin1) :
@@ -11052,9 +11001,9 @@ group_clause:
group_list:
group_list ',' order_ident order_dir
- { if (add_group_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; }
+ { if (add_group_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
| order_ident order_dir
- { if (add_group_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; }
+ { if (add_group_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
;
olap_opt:
@@ -11115,7 +11064,6 @@ alter_order_list:
alter_order_item:
simple_ident_nospvar order_dir
{
- THD *thd= YYTHD;
bool ascending= ($2 == 1) ? true : false;
if (add_order_to_list(thd, $1, ascending))
MYSQL_YYABORT;
@@ -11168,9 +11116,9 @@ order_clause:
order_list:
order_list ',' order_ident order_dir
- { if (add_order_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; }
+ { if (add_order_to_list(thd, $3,(bool) $4)) MYSQL_YYABORT; }
| order_ident order_dir
- { if (add_order_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; }
+ { if (add_order_to_list(thd, $1,(bool) $2)) MYSQL_YYABORT; }
;
order_dir:
@@ -11239,7 +11187,6 @@ limit_option:
ident
{
Item_splocal *splocal;
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
sp_variable *spv;
@@ -11276,19 +11223,19 @@ limit_option:
}
| ULONGLONG_NUM
{
- $$= new (YYTHD->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| LONG_NUM
{
- $$= new (YYTHD->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| NUM
{
- $$= new (YYTHD->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -11392,7 +11339,7 @@ procedure_clause:
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
- Item_field *item= new (YYTHD->mem_root)
+ Item_field *item= new (thd->mem_root)
Item_field(&lex->current_select->context,
NULL, NULL, $2.str);
if (item == NULL)
@@ -11417,8 +11364,6 @@ procedure_list2:
procedure_item:
remember_name expr remember_end
{
- THD *thd= YYTHD;
-
if (add_proc_to_list(thd, $2))
MYSQL_YYABORT;
if (!$2->name)
@@ -11592,7 +11537,6 @@ drop:
}
| DROP FUNCTION_SYM opt_if_exists ident '.' ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
sp_name *spname;
if ($4.str && check_db_name(&$4))
@@ -11615,7 +11559,6 @@ drop:
}
| DROP FUNCTION_SYM opt_if_exists ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX_STRING db= {0, 0};
sp_name *spname;
@@ -11700,7 +11643,7 @@ table_list:
table_name:
table_ident
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL,
+ if (!Select->add_table_to_list(thd, $1, NULL,
TL_OPTION_UPDATING,
YYPS->m_lock_type,
YYPS->m_mdl_type))
@@ -11711,7 +11654,7 @@ table_name:
table_name_with_opt_use_partition:
table_ident opt_use_partition
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL,
+ if (!Select->add_table_to_list(thd, $1, NULL,
TL_OPTION_UPDATING,
YYPS->m_lock_type,
YYPS->m_mdl_type,
@@ -11729,7 +11672,7 @@ table_alias_ref_list:
table_alias_ref:
table_ident_opt_wild
{
- if (!Select->add_table_to_list(YYTHD, $1, NULL,
+ if (!Select->add_table_to_list(thd, $1, NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
YYPS->m_lock_type,
YYPS->m_mdl_type))
@@ -11807,7 +11750,7 @@ insert_lock_option:
| DELAYED_SYM
{
Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
- YYTHD->query());
+ thd->query());
Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
YYLIP->yyLength() + 1;
$$= TL_WRITE_DELAYED;
@@ -11820,7 +11763,7 @@ replace_lock_option:
| DELAYED_SYM
{
Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
- YYTHD->query());
+ thd->query());
Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
YYLIP->yyLength() + 1;
$$= TL_WRITE_DELAYED;
@@ -11937,7 +11880,7 @@ expr_or_default:
expr { $$= $1;}
| DEFAULT
{
- $$= new (YYTHD->mem_root) Item_default_value(Lex->current_context());
+ $$= new (thd->mem_root) Item_default_value(Lex->current_context());
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -11990,7 +11933,7 @@ update_list:
update_elem:
simple_ident_nospvar equal expr_or_default
{
- if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3))
+ if (add_item_to_list(thd, $1) || add_value_to_list(thd, $3))
MYSQL_YYABORT;
}
;
@@ -12035,7 +11978,7 @@ delete:
single_multi:
FROM table_ident opt_use_partition
{
- if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
+ if (!Select->add_table_to_list(thd, $2, NULL, TL_OPTION_UPDATING,
YYPS->m_lock_type,
YYPS->m_mdl_type,
NULL,
@@ -12046,6 +11989,7 @@ single_multi:
}
where_clause opt_order_clause
delete_limit_clause {}
+ opt_select_expressions {}
| table_wild_list
{
mysql_init_multi_delete(Lex);
@@ -12070,6 +12014,11 @@ single_multi:
}
;
+opt_select_expressions:
+ /* empty */
+ | RETURNING_SYM select_item_list
+ ;
+
table_wild_list:
table_wild_one
| table_wild_list ',' table_wild_one
@@ -12081,7 +12030,7 @@ table_wild_one:
Table_ident *ti= new Table_ident($1);
if (ti == NULL)
MYSQL_YYABORT;
- if (!Select->add_table_to_list(YYTHD,
+ if (!Select->add_table_to_list(thd,
ti,
NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
@@ -12091,10 +12040,10 @@ table_wild_one:
}
| ident '.' ident opt_wild
{
- Table_ident *ti= new Table_ident(YYTHD, $1, $3, 0);
+ Table_ident *ti= new Table_ident(thd, $1, $3, 0);
if (ti == NULL)
MYSQL_YYABORT;
- if (!Select->add_table_to_list(YYTHD,
+ if (!Select->add_table_to_list(thd,
ti,
NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
@@ -12134,7 +12083,6 @@ truncate:
}
table_name
{
- THD *thd= YYTHD;
LEX* lex= thd->lex;
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
@@ -12229,7 +12177,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_DATABASES;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
+ if (prepare_schema_table(thd, lex, 0, SCH_SCHEMATA))
MYSQL_YYABORT;
}
| opt_full TABLES opt_db wild_and_where
@@ -12237,7 +12185,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLES;
lex->select_lex.db= $3;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))
MYSQL_YYABORT;
}
| opt_full TRIGGERS_SYM opt_db wild_and_where
@@ -12245,7 +12193,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TRIGGERS;
lex->select_lex.db= $3;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
+ if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))
MYSQL_YYABORT;
}
| EVENTS_SYM opt_db wild_and_where
@@ -12253,7 +12201,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_EVENTS;
lex->select_lex.db= $2;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
+ if (prepare_schema_table(thd, lex, 0, SCH_EVENTS))
MYSQL_YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
@@ -12261,7 +12209,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATUS;
lex->select_lex.db= $3;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLES))
MYSQL_YYABORT;
}
| OPEN_SYM TABLES opt_db wild_and_where
@@ -12269,27 +12217,27 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_OPEN_TABLES;
lex->select_lex.db= $3;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
+ if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))
MYSQL_YYABORT;
}
| PLUGINS_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
+ if (prepare_schema_table(thd, lex, 0, SCH_PLUGINS))
MYSQL_YYABORT;
}
| PLUGINS_SYM SONAME_SYM TEXT_STRING_sys
{
Lex->ident= $3;
Lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (prepare_schema_table(YYTHD, Lex, 0, SCH_ALL_PLUGINS))
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
MYSQL_YYABORT;
}
| PLUGINS_SYM SONAME_SYM wild_and_where
{
Lex->sql_command= SQLCOM_SHOW_PLUGINS;
- if (prepare_schema_table(YYTHD, Lex, 0, SCH_ALL_PLUGINS))
+ if (prepare_schema_table(thd, Lex, 0, SCH_ALL_PLUGINS))
MYSQL_YYABORT;
}
| ENGINE_SYM known_storage_engines show_engine_param
@@ -12302,7 +12250,7 @@ show_param:
lex->sql_command= SQLCOM_SHOW_FIELDS;
if ($5)
$4->change_db($5);
- if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
+ if (prepare_schema_table(thd, lex, $4, SCH_COLUMNS))
MYSQL_YYABORT;
}
| master_or_binary LOGS_SYM
@@ -12329,21 +12277,21 @@ show_param:
lex->sql_command= SQLCOM_SHOW_KEYS;
if ($4)
$3->change_db($4);
- if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
+ if (prepare_schema_table(thd, lex, $3, SCH_STATISTICS))
MYSQL_YYABORT;
}
| opt_storage ENGINES_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES))
+ if (prepare_schema_table(thd, lex, 0, SCH_ENGINES))
MYSQL_YYABORT;
}
| AUTHORS_SYM
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_AUTHORS;
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
"SHOW AUTHORS");
@@ -12352,7 +12300,7 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_CONTRIBUTORS;
- push_warning_printf(YYTHD, Sql_condition::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
ER(ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
"SHOW CONTRIBUTORS");
@@ -12376,7 +12324,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_PROFILE;
- if (prepare_schema_table(YYTHD, lex, NULL, SCH_PROFILES) != 0)
+ if (prepare_schema_table(thd, lex, NULL, SCH_PROFILES) != 0)
YYABORT;
}
| opt_var_type STATUS_SYM wild_and_where
@@ -12384,7 +12332,7 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS;
lex->option_type= $1;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS))
+ if (prepare_schema_table(thd, lex, 0, SCH_STATUS))
MYSQL_YYABORT;
}
| opt_full PROCESSLIST_SYM
@@ -12394,21 +12342,21 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_VARIABLES;
lex->option_type= $1;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES))
+ if (prepare_schema_table(thd, lex, 0, SCH_VARIABLES))
MYSQL_YYABORT;
}
| charset wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_CHARSETS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
+ if (prepare_schema_table(thd, lex, 0, SCH_CHARSETS))
MYSQL_YYABORT;
}
| COLLATION_SYM wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_COLLATIONS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
+ if (prepare_schema_table(thd, lex, 0, SCH_COLLATIONS))
MYSQL_YYABORT;
}
| GRANTS
@@ -12438,7 +12386,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL,0))
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL,0))
MYSQL_YYABORT;
lex->only_view= 0;
lex->create_info.storage_media= HA_SM_DEFAULT;
@@ -12447,7 +12395,7 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_SHOW_CREATE;
- if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0))
+ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))
MYSQL_YYABORT;
lex->only_view= 1;
}
@@ -12462,7 +12410,6 @@ show_param:
}
| SLAVE STATUS_SYM
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->mi.connection_name= thd->variables.default_master_connection;
lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
@@ -12477,28 +12424,28 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_CLIENT_STATS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_CLIENT_STATS))
+ if (prepare_schema_table(thd, lex, 0, SCH_CLIENT_STATS))
MYSQL_YYABORT;
}
| USER_STATS_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_USER_STATS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_USER_STATS))
+ if (prepare_schema_table(thd, lex, 0, SCH_USER_STATS))
MYSQL_YYABORT;
}
| TABLE_STATS_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_TABLE_STATS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_STATS))
+ if (prepare_schema_table(thd, lex, 0, SCH_TABLE_STATS))
MYSQL_YYABORT;
}
| INDEX_STATS_SYM
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_INDEX_STATS;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_INDEX_STATS))
+ if (prepare_schema_table(thd, lex, 0, SCH_INDEX_STATS))
MYSQL_YYABORT;
}
| CREATE PROCEDURE_SYM sp_name
@@ -12525,14 +12472,14 @@ show_param:
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS_PROC;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ if (prepare_schema_table(thd, lex, 0, SCH_PROCEDURES))
MYSQL_YYABORT;
}
| FUNCTION_SYM STATUS_SYM wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_STATUS_FUNC;
- if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ if (prepare_schema_table(thd, lex, 0, SCH_PROCEDURES))
MYSQL_YYABORT;
}
| PROCEDURE_SYM CODE_SYM sp_name
@@ -12552,7 +12499,6 @@ show_param:
}
| describe_command FOR_SYM expr
{
- THD *thd= YYTHD;
Lex->sql_command= SQLCOM_SHOW_EXPLAIN;
if (prepare_schema_table(thd, Lex, 0, SCH_EXPLAIN))
MYSQL_YYABORT;
@@ -12608,7 +12554,7 @@ wild_and_where:
/* empty */
| LIKE TEXT_STRING_sys
{
- Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length,
+ Lex->wild= new (thd->mem_root) String($2.str, $2.length,
system_charset_info);
if (Lex->wild == NULL)
MYSQL_YYABORT;
@@ -12631,7 +12577,7 @@ describe:
lex->sql_command= SQLCOM_SHOW_FIELDS;
lex->select_lex.db= 0;
lex->verbose= 0;
- if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
+ if (prepare_schema_table(thd, lex, $2, SCH_COLUMNS))
MYSQL_YYABORT;
}
opt_describe_column
@@ -12663,7 +12609,7 @@ opt_describe_column:
| text_string { Lex->wild= $1; }
| ident
{
- Lex->wild= new (YYTHD->mem_root) String((const char*) $1.str,
+ Lex->wild= new (thd->mem_root) String((const char*) $1.str,
$1.length,
system_charset_info);
if (Lex->wild == NULL)
@@ -12861,6 +12807,7 @@ kill:
lex->value_list.empty();
lex->users_list.empty();
lex->sql_command= SQLCOM_KILL;
+ lex->kill_type= KILL_TYPE_ID;
}
kill_type kill_option kill_expr
{
@@ -12877,13 +12824,17 @@ kill_option:
/* empty */ { $$= (int) KILL_CONNECTION; }
| CONNECTION_SYM { $$= (int) KILL_CONNECTION; }
| QUERY_SYM { $$= (int) KILL_QUERY; }
+ | QUERY_SYM ID_SYM
+ {
+ $$= (int) KILL_QUERY;
+ Lex->kill_type= KILL_TYPE_QUERY;
+ }
;
kill_expr:
expr
{
Lex->value_list.push_front($$);
- Lex->kill_type= KILL_TYPE_ID;
}
| USER user
{
@@ -12913,7 +12864,6 @@ use:
load:
LOAD data_or_xml
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
if (lex->sphead)
@@ -12936,7 +12886,7 @@ load:
opt_duplicate INTO TABLE_SYM table_ident opt_use_partition
{
LEX *lex=Lex;
- if (!Select->add_table_to_list(YYTHD, $12, NULL, TL_OPTION_UPDATING,
+ if (!Select->add_table_to_list(thd, $12, NULL, TL_OPTION_UPDATING,
$4, MDL_SHARED_WRITE, NULL, $13))
MYSQL_YYABORT;
lex->field_list.empty();
@@ -13075,7 +13025,7 @@ field_or_var:
simple_ident_nospvar {$$= $1;}
| '@' ident_or_text
{
- $$= new (YYTHD->mem_root) Item_user_var_as_out_param($2);
+ $$= new (thd->mem_root) Item_user_var_as_out_param($2);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13098,7 +13048,7 @@ load_data_set_elem:
if (lex->update_list.push_back($1) ||
lex->value_list.push_back($4))
MYSQL_YYABORT;
- $4->set_name_no_truncate($3, (uint) ($5 - $3), YYTHD->charset());
+ $4->set_name_no_truncate($3, (uint) ($5 - $3), thd->charset());
}
;
@@ -13108,7 +13058,6 @@ text_literal:
TEXT_STRING
{
LEX_STRING tmp;
- THD *thd= YYTHD;
CHARSET_INFO *cs_con= thd->variables.collation_connection;
CHARSET_INFO *cs_cli= thd->variables.character_set_client;
uint repertoire= thd->lex->text_string_is_7bit &&
@@ -13134,7 +13083,7 @@ text_literal:
uint repertoire= Lex->text_string_is_7bit ?
MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
- $$= new (YYTHD->mem_root) Item_string($1.str, $1.length,
+ $$= new (thd->mem_root) Item_string($1.str, $1.length,
national_charset_info,
DERIVATION_COERCIBLE,
repertoire);
@@ -13143,7 +13092,7 @@ text_literal:
}
| UNDERSCORE_CHARSET TEXT_STRING
{
- Item_string *str= new (YYTHD->mem_root) Item_string($2.str,
+ Item_string *str= new (thd->mem_root) Item_string($2.str,
$2.length, $1);
if (str == NULL)
MYSQL_YYABORT;
@@ -13162,7 +13111,7 @@ text_literal:
If the string has been pure ASCII so far,
check the new part.
*/
- CHARSET_INFO *cs= YYTHD->variables.collation_connection;
+ CHARSET_INFO *cs= thd->variables.collation_connection;
item->collation.repertoire|= my_string_repertoire(cs,
$2.str,
$2.length);
@@ -13173,15 +13122,15 @@ text_literal:
text_string:
TEXT_STRING_literal
{
- $$= new (YYTHD->mem_root) String($1.str,
+ $$= new (thd->mem_root) String($1.str,
$1.length,
- YYTHD->variables.collation_connection);
+ thd->variables.collation_connection);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HEX_NUM
{
- Item *tmp= new (YYTHD->mem_root) Item_hex_hybrid($1.str, $1.length);
+ Item *tmp= new (thd->mem_root) Item_hex_hybrid($1.str, $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -13193,7 +13142,7 @@ text_string:
}
| HEX_STRING
{
- Item *tmp= new (YYTHD->mem_root) Item_hex_string($1.str, $1.length);
+ Item *tmp= new (thd->mem_root) Item_hex_string($1.str, $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
tmp->quick_fix_field();
@@ -13201,7 +13150,7 @@ text_string:
}
| BIN_NUM
{
- Item *tmp= new (YYTHD->mem_root) Item_bin_string($1.str, $1.length);
+ Item *tmp= new (thd->mem_root) Item_bin_string($1.str, $1.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -13216,7 +13165,6 @@ text_string:
param_marker:
PARAM_MARKER
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
Item_param *item;
@@ -13250,44 +13198,44 @@ literal:
| temporal_literal { $$= $1; }
| NULL_SYM
{
- $$ = new (YYTHD->mem_root) Item_null();
+ $$ = new (thd->mem_root) Item_null();
if ($$ == NULL)
MYSQL_YYABORT;
YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT;
}
| FALSE_SYM
{
- $$= new (YYTHD->mem_root) Item_int((char*) "FALSE",0,1);
+ $$= new (thd->mem_root) Item_int((char*) "FALSE",0,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRUE_SYM
{
- $$= new (YYTHD->mem_root) Item_int((char*) "TRUE",1,1);
+ $$= new (thd->mem_root) Item_int((char*) "TRUE",1,1);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HEX_NUM
{
- $$ = new (YYTHD->mem_root) Item_hex_hybrid($1.str, $1.length);
+ $$ = new (thd->mem_root) Item_hex_hybrid($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| HEX_STRING
{
- $$ = new (YYTHD->mem_root) Item_hex_string($1.str, $1.length);
+ $$ = new (thd->mem_root) Item_hex_string($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BIN_NUM
{
- $$= new (YYTHD->mem_root) Item_bin_string($1.str, $1.length);
+ $$= new (thd->mem_root) Item_bin_string($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| UNDERSCORE_CHARSET hex_num_or_string
{
- Item *tmp= new (YYTHD->mem_root) Item_hex_string($2.str, $2.length);
+ Item *tmp= new (thd->mem_root) Item_hex_string($2.str, $2.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -13298,7 +13246,7 @@ literal:
String *str= tmp->val_str((String*) 0);
Item_string *item_str;
- item_str= new (YYTHD->mem_root)
+ item_str= new (thd->mem_root)
Item_string(NULL, /* name will be set in select_item */
str ? str->ptr() : "",
str ? str->length() : 0,
@@ -13316,7 +13264,7 @@ literal:
}
| UNDERSCORE_CHARSET BIN_NUM
{
- Item *tmp= new (YYTHD->mem_root) Item_bin_string($2.str, $2.length);
+ Item *tmp= new (thd->mem_root) Item_bin_string($2.str, $2.length);
if (tmp == NULL)
MYSQL_YYABORT;
/*
@@ -13327,7 +13275,7 @@ literal:
String *str= tmp->val_str((String*) 0);
Item_string *item_str;
- item_str= new (YYTHD->mem_root)
+ item_str= new (thd->mem_root)
Item_string(NULL, /* name will be set in select_item */
str ? str->ptr() : "",
str ? str->length() : 0,
@@ -13348,7 +13296,7 @@ NUM_literal:
NUM
{
int error;
- $$= new (YYTHD->mem_root)
+ $$= new (thd->mem_root)
Item_int($1.str,
(longlong) my_strtoll10($1.str, NULL, &error),
$1.length);
@@ -13358,7 +13306,7 @@ NUM_literal:
| LONG_NUM
{
int error;
- $$= new (YYTHD->mem_root)
+ $$= new (thd->mem_root)
Item_int($1.str,
(longlong) my_strtoll10($1.str, NULL, &error),
$1.length);
@@ -13367,23 +13315,23 @@ NUM_literal:
}
| ULONGLONG_NUM
{
- $$= new (YYTHD->mem_root) Item_uint($1.str, $1.length);
+ $$= new (thd->mem_root) Item_uint($1.str, $1.length);
if ($$ == NULL)
MYSQL_YYABORT;
}
| DECIMAL_NUM
{
- $$= new (YYTHD->mem_root) Item_decimal($1.str, $1.length,
- YYTHD->charset());
- if (($$ == NULL) || (YYTHD->is_error()))
+ $$= new (thd->mem_root) Item_decimal($1.str, $1.length,
+ thd->charset());
+ if (($$ == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
}
| FLOAT_NUM
{
- $$= new (YYTHD->mem_root) Item_float($1.str, $1.length);
- if (($$ == NULL) || (YYTHD->is_error()))
+ $$= new (thd->mem_root) Item_float($1.str, $1.length);
+ if (($$ == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
@@ -13394,19 +13342,19 @@ NUM_literal:
temporal_literal:
DATE_SYM TEXT_STRING
{
- if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL,
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
MYSQL_TYPE_DATE, true)))
MYSQL_YYABORT;
}
| TIME_SYM TEXT_STRING
{
- if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL,
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
MYSQL_TYPE_TIME, true)))
MYSQL_YYABORT;
}
| TIMESTAMP TEXT_STRING
{
- if (!($$= create_temporal_literal(YYTHD, $2.str, $2.length, YYCSCL,
+ if (!($$= create_temporal_literal(thd, $2.str, $2.length, YYCSCL,
MYSQL_TYPE_DATETIME, true)))
MYSQL_YYABORT;
}
@@ -13428,7 +13376,7 @@ table_wild:
ident '.' '*'
{
SELECT_LEX *sel= Select;
- $$= new (YYTHD->mem_root) Item_field(Lex->current_context(),
+ $$= new (thd->mem_root) Item_field(Lex->current_context(),
NullS, $1.str, "*");
if ($$ == NULL)
MYSQL_YYABORT;
@@ -13436,7 +13384,6 @@ table_wild:
}
| ident '.' ident '.' '*'
{
- THD *thd= YYTHD;
SELECT_LEX *sel= Select;
const char* schema= thd->client_capabilities & CLIENT_NO_SCHEMA ?
NullS : $1.str;
@@ -13456,7 +13403,6 @@ order_ident:
simple_ident:
ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
sp_variable *spv;
@@ -13507,7 +13453,6 @@ simple_ident:
simple_ident_nospvar:
ident
{
- THD *thd= YYTHD;
SELECT_LEX *sel=Select;
if ((sel->parsing_place != IN_HAVING) ||
(sel->get_in_sum_expr() > 0))
@@ -13529,7 +13474,6 @@ simple_ident_nospvar:
simple_ident_q:
ident '.' ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
/*
@@ -13608,7 +13552,6 @@ simple_ident_q:
}
| '.' ident '.' ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
@@ -13633,7 +13576,6 @@ simple_ident_q:
}
| ident '.' ident '.' ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
SELECT_LEX *sel= lex->current_select;
const char* schema= (thd->client_capabilities & CLIENT_NO_SCHEMA ?
@@ -13701,7 +13643,7 @@ table_ident:
}
| ident '.' ident
{
- $$= new Table_ident(YYTHD, $1,$3,0);
+ $$= new Table_ident(thd, $1,$3,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13723,7 +13665,7 @@ table_ident_opt_wild:
}
| ident '.' ident opt_wild
{
- $$= new Table_ident(YYTHD, $1,$3,0);
+ $$= new Table_ident(thd, $1,$3,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13733,7 +13675,7 @@ table_ident_nodb:
ident
{
LEX_STRING db={(char*) any_db,3};
- $$= new Table_ident(YYTHD, db,$1,0);
+ $$= new Table_ident(thd, db,$1,0);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -13743,8 +13685,6 @@ IDENT_sys:
IDENT { $$= $1; }
| IDENT_QUOTED
{
- THD *thd= YYTHD;
-
if (thd->charset_is_system_charset)
{
CHARSET_INFO *cs= system_charset_info;
@@ -13773,8 +13713,6 @@ IDENT_sys:
TEXT_STRING_sys:
TEXT_STRING
{
- THD *thd= YYTHD;
-
if (thd->charset_is_system_charset)
$$= $1;
else
@@ -13789,8 +13727,6 @@ TEXT_STRING_sys:
TEXT_STRING_literal:
TEXT_STRING
{
- THD *thd= YYTHD;
-
if (thd->charset_is_collation_connection)
$$= $1;
else
@@ -13805,8 +13741,6 @@ TEXT_STRING_literal:
TEXT_STRING_filesystem:
TEXT_STRING
{
- THD *thd= YYTHD;
-
if (thd->charset_is_character_set_filesystem)
$$= $1;
else
@@ -13823,7 +13757,6 @@ ident:
IDENT_sys { $$=$1; }
| keyword
{
- THD *thd= YYTHD;
$$.str= thd->strmake($1.str, $1.length);
if ($$.str == NULL)
MYSQL_YYABORT;
@@ -13835,7 +13768,6 @@ label_ident:
IDENT_sys { $$=$1; }
| keyword_sp
{
- THD *thd= YYTHD;
$$.str= thd->strmake($1.str, $1.length);
if ($$.str == NULL)
MYSQL_YYABORT;
@@ -13852,7 +13784,6 @@ ident_or_text:
user:
ident_or_text
{
- THD *thd= YYTHD;
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
@@ -13869,7 +13800,6 @@ user:
}
| ident_or_text '@' ident_or_text
{
- THD *thd= YYTHD;
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1; $$->host=$3;
@@ -13891,7 +13821,7 @@ user:
}
| CURRENT_USER optional_braces
{
- if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
/*
empty LEX_USER means current_user and
@@ -14075,6 +14005,7 @@ keyword_sp:
| HARD_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
+ | ID_SYM {}
| IDENTIFIED_SYM {}
| IGNORE_SERVER_IDS_SYM {}
| INDEX_STATS_SYM {}
@@ -14299,7 +14230,7 @@ set:
lex->var_list.empty();
lex->one_shot_set= 0;
lex->autocommit= 0;
- sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
{}
@@ -14310,7 +14241,7 @@ set:
start_option_value_list:
option_value_no_option_type
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
option_value_list_continued
@@ -14320,7 +14251,7 @@ start_option_value_list:
}
transaction_characteristics
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
| option_type
@@ -14335,13 +14266,13 @@ start_option_value_list:
start_option_value_list_following_option_type:
option_value_following_option_type
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
option_value_list_continued
| TRANSACTION_SYM transaction_characteristics
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
;
@@ -14355,20 +14286,20 @@ option_value_list_continued:
// Repeating list of option values after first option value.
option_value_list:
{
- sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
| option_value_list ','
{
- sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
option_value
{
- if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ if (sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
;
@@ -14407,7 +14338,6 @@ opt_var_ident_type:
option_value_following_option_type:
internal_variable_name equal set_expr_or_default
{
- THD *thd= YYTHD;
LEX *lex= Lex;
if ($1.var && $1.var != trg_new_row_fake_var)
@@ -14432,13 +14362,12 @@ option_value_following_option_type:
option_value_no_option_type:
internal_variable_name equal set_expr_or_default
{
- THD *thd= YYTHD;
LEX *lex= Lex;
if ($1.var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
- if (set_trigger_new_row(YYTHD, &$1.base_name, $3))
+ if (set_trigger_new_row(thd, &$1.base_name, $3))
MYSQL_YYABORT;
}
else if ($1.var)
@@ -14460,7 +14389,7 @@ option_value_no_option_type:
| '@' ident_or_text equal expr
{
Item_func_set_user_var *item;
- item= new (YYTHD->mem_root) Item_func_set_user_var($2, $4);
+ item= new (thd->mem_root) Item_func_set_user_var($2, $4);
if (item == NULL)
MYSQL_YYABORT;
set_var_user *var= new set_var_user(item);
@@ -14470,7 +14399,6 @@ option_value_no_option_type:
}
| '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
{
- THD *thd= YYTHD;
struct sys_var_with_base tmp= $4;
/* Lookup if necessary: must be a system variable. */
if (tmp.var == NULL)
@@ -14483,7 +14411,6 @@ option_value_no_option_type:
}
| charset old_or_new_charset_name_or_default
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
CHARSET_INFO *cs2;
cs2= $2 ? $2: global_system_variables.character_set_client;
@@ -14531,7 +14458,6 @@ option_value_no_option_type:
}
| PASSWORD equal text_or_password
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX_USER *user;
sp_pcontext *spc= lex->spcont;
@@ -14572,7 +14498,6 @@ option_value_no_option_type:
internal_variable_name:
ident
{
- THD *thd= YYTHD;
sp_pcontext *spc= thd->lex->spcont;
sp_variable *spv;
@@ -14631,7 +14556,7 @@ internal_variable_name:
}
else
{
- sys_var *tmp=find_sys_var(YYTHD, $3.str, $3.length);
+ sys_var *tmp=find_sys_var(thd, $3.str, $3.length);
if (!tmp)
MYSQL_YYABORT;
if (!tmp->is_struct())
@@ -14642,7 +14567,7 @@ internal_variable_name:
}
| DEFAULT '.' ident
{
- sys_var *tmp=find_sys_var(YYTHD, $3.str, $3.length);
+ sys_var *tmp=find_sys_var(thd, $3.str, $3.length);
if (!tmp)
MYSQL_YYABORT;
if (!tmp->is_struct())
@@ -14663,7 +14588,6 @@ transaction_characteristics:
transaction_access_mode:
transaction_access_mode_types
{
- THD *thd= YYTHD;
LEX *lex=Lex;
Item *item= new (thd->mem_root) Item_int((int32) $1);
if (item == NULL)
@@ -14681,7 +14605,6 @@ transaction_access_mode:
isolation_level:
ISOLATION LEVEL_SYM isolation_types
{
- THD *thd= YYTHD;
LEX *lex=Lex;
Item *item= new (thd->mem_root) Item_int((int32) $3);
if (item == NULL)
@@ -14715,13 +14638,13 @@ text_or_password:
if ($3.length == 0)
$$= $3.str;
else
- switch (YYTHD->variables.old_passwords) {
+ switch (thd->variables.old_passwords) {
case 1: $$= Item_func_old_password::
- alloc(YYTHD, $3.str, $3.length);
+ alloc(thd, $3.str, $3.length);
break;
case 0:
case 2: $$= Item_func_password::
- create_password_hash_buffer(YYTHD, $3.str, $3.length);
+ create_password_hash_buffer(thd, $3.str, $3.length);
break;
}
if ($$ == NULL)
@@ -14731,7 +14654,7 @@ text_or_password:
| OLD_PASSWORD '(' TEXT_STRING ')'
{
$$= $3.length ? Item_func_old_password::
- alloc(YYTHD, $3.str, $3.length) :
+ alloc(thd, $3.str, $3.length) :
$3.str;
if ($$ == NULL)
MYSQL_YYABORT;
@@ -14744,19 +14667,19 @@ set_expr_or_default:
| DEFAULT { $$=0; }
| ON
{
- $$=new (YYTHD->mem_root) Item_string("ON", 2, system_charset_info);
+ $$=new (thd->mem_root) Item_string("ON", 2, system_charset_info);
if ($$ == NULL)
MYSQL_YYABORT;
}
| ALL
{
- $$=new (YYTHD->mem_root) Item_string("ALL", 3, system_charset_info);
+ $$=new (thd->mem_root) Item_string("ALL", 3, system_charset_info);
if ($$ == NULL)
MYSQL_YYABORT;
}
| BINARY
{
- $$=new (YYTHD->mem_root) Item_string("binary", 6, system_charset_info);
+ $$=new (thd->mem_root) Item_string("binary", 6, system_charset_info);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -14795,7 +14718,7 @@ table_lock:
{
thr_lock_type lock_type= (thr_lock_type) $3;
bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
- if (!Select->add_table_to_list(YYTHD, $1, $2, 0, lock_type,
+ if (!Select->add_table_to_list(thd, $1, $2, 0, lock_type,
(lock_for_write ?
lock_type == TL_WRITE_CONCURRENT_INSERT ?
MDL_SHARED_WRITE :
@@ -14873,7 +14796,7 @@ handler:
lex->expr_allows_subselect= FALSE;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- Item *one= new (YYTHD->mem_root) Item_int((int32) 1);
+ Item *one= new (thd->mem_root) Item_int((int32) 1);
if (one == NULL)
MYSQL_YYABORT;
lex->current_select->select_limit= one;
@@ -15223,10 +15146,10 @@ grant_user:
MYSQL_YYABORT;
if ($4.length)
{
- if (YYTHD->variables.old_passwords == 1)
+ if (thd->variables.old_passwords == 1)
{
char *buff=
- (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
+ (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
if (buff == NULL)
MYSQL_YYABORT;
my_make_scrambled_password_323(buff, $4.str, $4.length);
@@ -15236,7 +15159,7 @@ grant_user:
else
{
char *buff=
- (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
+ (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff == NULL)
MYSQL_YYABORT;
my_make_scrambled_password_sha1(buff, $4.str, $4.length);
@@ -15283,7 +15206,7 @@ column_list:
column_list_id:
ident
{
- String *new_str = new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
+ String *new_str = new (thd->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
if (new_str == NULL)
MYSQL_YYABORT;
List_iterator <LEX_COLUMN> iter(Lex->columns);
@@ -15493,7 +15416,6 @@ opt_union_order_or_limit:
union_order_or_limit:
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
SELECT_LEX *sel= lex->current_select;
@@ -15509,7 +15431,6 @@ union_order_or_limit:
}
order_or_limit
{
- THD *thd= YYTHD;
thd->lex->current_select->no_table_names_allowed= 0;
thd->where= "";
}
@@ -15691,14 +15612,14 @@ no_definer:
from older master servers (i.e. to create non-suid trigger in this
case).
*/
- YYTHD->lex->definer= 0;
+ thd->lex->definer= 0;
}
;
definer:
DEFINER_SYM EQ user
{
- YYTHD->lex->definer= get_current_user(YYTHD, $3);
+ thd->lex->definer= get_current_user(thd, $3);
}
;
@@ -15743,7 +15664,6 @@ view_suid:
view_tail:
view_suid VIEW_SYM table_ident
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_CREATE_VIEW;
/* first table in list is target VIEW name */
@@ -15787,7 +15707,6 @@ view_select:
}
view_select_aux view_check_option
{
- THD *thd= YYTHD;
LEX *lex= Lex;
uint len= YYLIP->get_cpp_ptr() - lex->create_view_select.str;
void *create_view_select= thd->memdup(lex->create_view_select.str, len);
@@ -15843,7 +15762,6 @@ trigger_tail:
EACH_SYM
ROW_SYM
{ /* $15 */
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
sp_head *sp;
@@ -15877,8 +15795,8 @@ trigger_tail:
sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
- sp->set_stmt_end(YYTHD);
- sp->restore_thd_mem_root(YYTHD);
+ sp->set_stmt_end(thd);
+ sp->restore_thd_mem_root(thd);
if (sp->is_not_allowed_in_function("trigger"))
MYSQL_YYABORT;
@@ -15888,7 +15806,7 @@ trigger_tail:
sp_proc_stmt alternatives are not saving/restoring LEX, so
lex->query_tables can be wiped out.
*/
- if (!lex->select_lex.add_table_to_list(YYTHD, $9,
+ if (!lex->select_lex.add_table_to_list(thd, $9,
(LEX_STRING*) 0,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
@@ -15907,7 +15825,6 @@ udf_tail:
AGGREGATE_SYM remember_name FUNCTION_SYM ident
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
if (is_native_function(thd, & $4))
{
@@ -15925,7 +15842,6 @@ udf_tail:
| remember_name FUNCTION_SYM ident
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
if (is_native_function(thd, & $3))
{
@@ -15948,7 +15864,6 @@ sf_tail:
sp_name /* $3 */
'(' /* $4 */
{ /* $5 */
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
sp_head *sp;
@@ -16007,7 +15922,7 @@ sf_tail:
MYSQL_YYABORT;
}
- if (sp->fill_field_definition(YYTHD, lex,
+ if (sp->fill_field_definition(thd, lex,
(enum enum_field_types) $11,
&sp->m_return_field_def))
MYSQL_YYABORT;
@@ -16016,7 +15931,6 @@ sf_tail:
}
sp_c_chistics /* $13 */
{ /* $14 */
- THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP;
@@ -16025,7 +15939,6 @@ sf_tail:
}
sp_proc_stmt /* $15 */
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
@@ -16096,10 +16009,10 @@ sp_tail:
sp= new sp_head();
if (sp == NULL)
MYSQL_YYABORT;
- sp->reset_thd_mem_root(YYTHD);
+ sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE;
- sp->init_sp_name(YYTHD, $3);
+ sp->init_sp_name(thd, $3);
lex->sphead= sp;
}
@@ -16114,7 +16027,6 @@ sp_tail:
sp_pdparam_list
')'
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sphead->m_param_end= YYLIP->get_cpp_tok_start();
@@ -16122,7 +16034,6 @@ sp_tail:
}
sp_c_chistics
{
- THD *thd= YYTHD;
LEX *lex= thd->lex;
lex->sphead->m_chistics= &lex->sp_chistics;
@@ -16133,9 +16044,9 @@ sp_tail:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
- sp->set_stmt_end(YYTHD);
+ sp->set_stmt_end(thd);
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
- sp->restore_thd_mem_root(YYTHD);
+ sp->restore_thd_mem_root(thd);
}
;
@@ -16172,21 +16083,21 @@ xid:
text_string
{
MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE);
- if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
MYSQL_YYABORT;
Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
}
| text_string ',' text_string
{
MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
- if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
MYSQL_YYABORT;
Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
}
| text_string ',' text_string ',' ulong_num
{
MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
- if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
+ if (!(Lex->xid=(XID *)thd->alloc(sizeof(XID))))
MYSQL_YYABORT;
Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index f3c90cdb643..05ee72c0c6b 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1439,9 +1439,6 @@ Sys_var_gtid_binlog_pos::global_value_ptr(THD *thd, LEX_STRING *base)
String str(buf, sizeof(buf), system_charset_info);
char *p;
- if (!rpl_global_gtid_slave_state.loaded)
- return NULL;
-
str.length(0);
if ((opt_bin_log && mysql_bin_log.append_state_pos(&str)) ||
!(p= thd->strmake(str.ptr(), str.length())))
@@ -1489,7 +1486,7 @@ Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var)
DBUG_ASSERT(var->type == OPT_GLOBAL);
- if (!rpl_global_gtid_slave_state.loaded)
+ if (rpl_load_gtid_slave_state(thd))
{
my_error(ER_CANNOT_LOAD_SLAVE_GTID_STATE, MYF(0), "mysql",
rpl_gtid_slave_state_table_name.str);
@@ -1554,11 +1551,17 @@ Sys_var_gtid_slave_pos::global_value_ptr(THD *thd, LEX_STRING *base)
String str;
char *p;
- if (!rpl_global_gtid_slave_state.loaded)
- return NULL;
-
str.length(0);
- if (rpl_append_gtid_state(&str, false) ||
+ /*
+ If the mysql.rpl_slave_pos table could not be loaded, then we cannot
+ easily automatically try to reload it here - we may be inside a statement
+ that already has tables locked and so opening more tables is problematic.
+
+ But if the table is not loaded (eg. missing mysql_upgrade_db or some such),
+ then the slave state must be empty anyway.
+ */
+ if ((rpl_global_gtid_slave_state.loaded &&
+ rpl_append_gtid_state(&str, false)) ||
!(p= thd->strmake(str.ptr(), str.length())))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -1584,6 +1587,107 @@ static Sys_var_mybool Sys_gtid_strict_mode(
"generate an out-of-order binlog if executed.",
GLOBAL_VAR(opt_gtid_strict_mode),
CMD_LINE(OPT_ARG), DEFAULT(FALSE));
+
+
+struct gtid_binlog_state_data { rpl_gtid *list; uint32 list_len; };
+
+bool
+Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var)
+{
+ String str, *res;
+ struct gtid_binlog_state_data *data;
+ rpl_gtid *list;
+ uint32 list_len;
+
+ DBUG_ASSERT(var->type == OPT_GLOBAL);
+
+ if (!(res= var->value->val_str(&str)))
+ return true;
+ if (thd->in_active_multi_stmt_transaction())
+ {
+ my_error(ER_CANT_DO_THIS_DURING_AN_TRANSACTION, MYF(0));
+ return true;
+ }
+ if (!mysql_bin_log.is_open())
+ {
+ my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(0));
+ return true;
+ }
+ if (!mysql_bin_log.is_empty_state())
+ {
+ my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
+ return true;
+ }
+ if (res->length() == 0)
+ list= NULL;
+ else if (!(list= gtid_parse_string_to_list(res->ptr(), res->length(),
+ &list_len)))
+ {
+ my_error(ER_INCORRECT_GTID_STATE, MYF(0));
+ return true;
+ }
+ if (!(data= (gtid_binlog_state_data *)my_malloc(sizeof(*data), MYF(0))))
+ {
+ my_free(list);
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+ data->list= list;
+ data->list_len= list_len;
+ var->save_result.ptr= data;
+ return false;
+}
+
+
+bool
+Sys_var_gtid_binlog_state::global_update(THD *thd, set_var *var)
+{
+ bool res;
+
+ DBUG_ASSERT(var->type == OPT_GLOBAL);
+
+ if (!var->value)
+ {
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
+ return true;
+ }
+
+ struct gtid_binlog_state_data *data=
+ (struct gtid_binlog_state_data *)var->save_result.ptr;
+ mysql_mutex_unlock(&LOCK_global_system_variables);
+ res= (0 != reset_master(thd, data->list, data->list_len));
+ mysql_mutex_lock(&LOCK_global_system_variables);
+ my_free(data->list);
+ my_free(data);
+ return res;
+}
+
+
+uchar *
+Sys_var_gtid_binlog_state::global_value_ptr(THD *thd, LEX_STRING *base)
+{
+ char buf[512];
+ String str(buf, sizeof(buf), system_charset_info);
+ char *p;
+
+ str.length(0);
+ if ((opt_bin_log && mysql_bin_log.append_state(&str)) ||
+ !(p= thd->strmake(str.ptr(), str.length())))
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return NULL;
+ }
+
+ return (uchar *)p;
+}
+
+
+static unsigned char opt_gtid_binlog_state_dummy;
+static Sys_var_gtid_binlog_state Sys_gtid_binlog_state(
+ "gtid_binlog_state",
+ "The internal GTID state of the binlog, used to keep track of all "
+ "GTIDs ever logged to the binlog.",
+ GLOBAL_VAR(opt_gtid_binlog_state_dummy), NO_CMD_LINE);
#endif
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index cd16dc8d80a..bef5fbdd126 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2002, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2013, Monty Program Ab.
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
@@ -140,6 +141,7 @@ public:
option.u_max_value= (uchar**)max_var_ptr();
if (max_var_ptr())
*max_var_ptr()= max_val;
+
global_var(T)= def_val;
SYSVAR_ASSERT(size == sizeof(T));
SYSVAR_ASSERT(min_val < max_val);
@@ -431,7 +433,10 @@ public:
void cleanup()
{
if (flags & ALLOCATED)
+ {
my_free(global_var(char*));
+ global_var(char *)= NULL;
+ }
flags&= ~ALLOCATED;
}
static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset)
@@ -993,13 +998,14 @@ public:
on_update_function on_update_func=0,
const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
- getopt.arg_type, SHOW_DOUBLE, (longlong) double2ulonglong(def_val),
+ getopt.arg_type, SHOW_DOUBLE,
+ (longlong) getopt_double2ulonglong(def_val),
lock, binlog_status_arg, on_check_func, on_update_func,
substitute)
{
option.var_type= GET_DOUBLE;
- option.min_value= (longlong) double2ulonglong(min_val);
- option.max_value= (longlong) double2ulonglong(max_val);
+ option.min_value= (longlong) getopt_double2ulonglong(min_val);
+ option.max_value= (longlong) getopt_double2ulonglong(max_val);
global_var(double)= (double)option.def_value;
SYSVAR_ASSERT(min_val < max_val);
SYSVAR_ASSERT(min_val <= def_val);
@@ -1031,7 +1037,7 @@ public:
void session_save_default(THD *thd, set_var *var)
{ var->save_result.double_value= global_var(double); }
void global_save_default(THD *thd, set_var *var)
- { var->save_result.double_value= (double)option.def_value; }
+ { var->save_result.double_value= getopt_ulonglong2double(option.def_value); }
};
/**
@@ -2191,3 +2197,44 @@ public:
}
uchar *global_value_ptr(THD *thd, LEX_STRING *base);
};
+
+
+/**
+ Class for @@global.gtid_binlog_state.
+*/
+class Sys_var_gtid_binlog_state: public sys_var
+{
+public:
+ Sys_var_gtid_binlog_state(const char *name_arg,
+ const char *comment, int flag_args, ptrdiff_t off, size_t size,
+ CMD_LINE getopt)
+ : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
+ getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
+ NULL, NULL, NULL)
+ {
+ option.var_type= GET_STR;
+ }
+ bool do_check(THD *thd, set_var *var);
+ bool session_update(THD *thd, set_var *var)
+ {
+ DBUG_ASSERT(false);
+ return true;
+ }
+ bool global_update(THD *thd, set_var *var);
+ bool check_update_type(Item_result type) { return type != STRING_RESULT; }
+ void session_save_default(THD *thd, set_var *var)
+ {
+ DBUG_ASSERT(false);
+ }
+ void global_save_default(THD *thd, set_var *var)
+ {
+ /* Record the attempt to use default so we can error. */
+ var->value= 0;
+ }
+ uchar *session_value_ptr(THD *thd, LEX_STRING *base)
+ {
+ DBUG_ASSERT(false);
+ return NULL;
+ }
+ uchar *global_value_ptr(THD *thd, LEX_STRING *base);
+};
diff --git a/sql/table.cc b/sql/table.cc
index 912dd0dfa54..eed1de9bb35 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -653,6 +653,184 @@ err_not_open:
DBUG_RETURN(share->error);
}
+static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
+ uint keys, KEY *keyinfo,
+ uint new_frm_ver, uint &ext_key_parts,
+ TABLE_SHARE *share, uint len,
+ KEY *first_keyinfo, char* &keynames)
+{
+ uint i, j, n_length;
+ KEY_PART_INFO *key_part= NULL;
+ ulong *rec_per_key= NULL;
+ KEY_PART_INFO *first_key_part= NULL;
+ uint first_key_parts= 0;
+
+ if (!keys)
+ {
+ if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, len)))
+ return 1;
+ bzero((char*) keyinfo, len);
+ key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo);
+ }
+
+ /*
+ If share->use_ext_keys is set to TRUE we assume that any key
+ can be extended by the components of the primary key whose
+ definition is read first from the frm file.
+ For each key only those fields of the assumed primary key are
+ added that are not included in the proper key definition.
+ If after all it turns out that there is no primary key the
+ added components are removed from each key.
+
+ When in the future we support others schemes of extending of
+ secondary keys with components of the primary key we'll have
+ to change the type of this flag for an enumeration type.
+ */
+
+ for (i=0 ; i < keys ; i++, keyinfo++)
+ {
+ if (new_frm_ver >= 3)
+ {
+ if (strpos + 8 >= frm_image_end)
+ return 1;
+ keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
+ keyinfo->key_length= (uint) uint2korr(strpos+2);
+ keyinfo->user_defined_key_parts= (uint) strpos[4];
+ keyinfo->algorithm= (enum ha_key_alg) strpos[5];
+ keyinfo->block_size= uint2korr(strpos+6);
+ strpos+=8;
+ }
+ else
+ {
+ if (strpos + 4 >= frm_image_end)
+ return 1;
+ keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
+ keyinfo->key_length= (uint) uint2korr(strpos+1);
+ keyinfo->user_defined_key_parts= (uint) strpos[3];
+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+ strpos+=4;
+ }
+
+ if (i == 0)
+ {
+ ext_key_parts+= (share->use_ext_keys ? first_keyinfo->user_defined_key_parts*(keys-1) : 0);
+ n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO);
+ if (!(keyinfo= (KEY*) alloc_root(&share->mem_root,
+ n_length + len)))
+ return 1;
+ bzero((char*) keyinfo,n_length);
+ share->key_info= keyinfo;
+ key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo + keys);
+
+ if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
+ sizeof(ulong) * ext_key_parts)))
+ return 1;
+ first_key_part= key_part;
+ first_key_parts= first_keyinfo->user_defined_key_parts;
+ keyinfo->flags= first_keyinfo->flags;
+ keyinfo->key_length= first_keyinfo->key_length;
+ keyinfo->user_defined_key_parts= first_keyinfo->user_defined_key_parts;
+ keyinfo->algorithm= first_keyinfo->algorithm;
+ if (new_frm_ver >= 3)
+ keyinfo->block_size= first_keyinfo->block_size;
+ }
+
+ keyinfo->key_part= key_part;
+ keyinfo->rec_per_key= rec_per_key;
+ for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++)
+ {
+ if (strpos + (new_frm_ver >= 1 ? 9 : 7) >= frm_image_end)
+ return 1;
+ *rec_per_key++=0;
+ key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
+ key_part->offset= (uint) uint2korr(strpos+2)-1;
+ key_part->key_type= (uint) uint2korr(strpos+5);
+ // key_part->field= (Field*) 0; // Will be fixed later
+ if (new_frm_ver >= 1)
+ {
+ key_part->key_part_flag= *(strpos+4);
+ key_part->length= (uint) uint2korr(strpos+7);
+ strpos+=9;
+ }
+ else
+ {
+ key_part->length= *(strpos+4);
+ key_part->key_part_flag=0;
+ if (key_part->length > 128)
+ {
+ key_part->length&=127; /* purecov: inspected */
+ key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
+ }
+ strpos+=7;
+ }
+ key_part->store_length=key_part->length;
+ }
+
+ /*
+ Add primary key to end of extended keys for non unique keys for
+ storage engines that supports it.
+ */
+ keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
+ keyinfo->ext_key_flags= keyinfo->flags;
+ keyinfo->ext_key_part_map= 0;
+ if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME))
+ {
+ keyinfo->ext_key_part_map= 0;
+ for (j= 0;
+ j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
+ j++)
+ {
+ uint key_parts= keyinfo->user_defined_key_parts;
+ KEY_PART_INFO* curr_key_part= keyinfo->key_part;
+ KEY_PART_INFO* curr_key_part_end= curr_key_part+key_parts;
+ for ( ; curr_key_part < curr_key_part_end; curr_key_part++)
+ {
+ if (curr_key_part->fieldnr == first_key_part[j].fieldnr)
+ break;
+ }
+ if (curr_key_part == curr_key_part_end)
+ {
+ *key_part++= first_key_part[j];
+ *rec_per_key++= 0;
+ keyinfo->ext_key_parts++;
+ keyinfo->ext_key_part_map|= 1 << j;
+ }
+ }
+ if (j == first_key_parts)
+ keyinfo->ext_key_flags= keyinfo->flags | HA_EXT_NOSAME;
+ }
+ share->ext_key_parts+= keyinfo->ext_key_parts;
+ }
+ keynames=(char*) key_part;
+ strpos+= strnmov(keynames, (char *) strpos, frm_image_end - strpos) - keynames;
+ if (*strpos++) // key names are \0-terminated
+ return 1;
+
+ //reading index comments
+ for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
+ {
+ if (keyinfo->flags & HA_USES_COMMENT)
+ {
+ if (strpos + 2 >= frm_image_end)
+ return 1;
+ keyinfo->comment.length= uint2korr(strpos);
+ strpos+= 2;
+
+ if (strpos + keyinfo->comment.length >= frm_image_end)
+ return 1;
+ keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos,
+ keyinfo->comment.length);
+ strpos+= keyinfo->comment.length;
+ }
+ DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
+ (keyinfo->comment.length > 0));
+ }
+
+ share->keys= keys; // do it *after* all key_info's are initialized
+
+ return 0;
+}
+
/**
Read data from a binary .frm file image into a TABLE_SHARE
@@ -680,7 +858,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
uint db_create_options, keys, key_parts, n_length;
uint com_length, null_bit_pos;
uint extra_rec_buf_length;
- uint i,j;
+ uint i;
bool use_hash;
char *keynames, *names, *comment_pos;
const uchar *forminfo, *extra2;
@@ -688,7 +866,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
uchar *record, *null_flags, *null_pos;
const uchar *disk_buff, *strpos;
ulong pos, record_offset;
- ulong *rec_per_key= NULL;
ulong rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -703,9 +880,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
const uchar *options= 0;
KEY first_keyinfo;
uint len;
- KEY_PART_INFO *first_key_part= NULL;
uint ext_key_parts= 0;
- uint first_key_parts= 0;
plugin_ref se_plugin= 0;
keyinfo= &first_keyinfo;
share->ext_key_parts= 0;
@@ -869,191 +1044,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (disk_buff[0] & 0x80)
{
- share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
+ keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
share->key_parts= key_parts= uint2korr(disk_buff+2);
}
else
{
- share->keys= keys= disk_buff[0];
+ keys= disk_buff[0];
share->key_parts= key_parts= disk_buff[1];
}
share->keys_for_keyread.init(0);
share->keys_in_use.init(keys);
-
- /*
- At this point we don't have enough information read from the frm file
- to get a proper handlerton for the interesting engine in order to get
- properties of this engine.
- */
- /* Currently only InnoDB can use extended keys */
- share->set_use_ext_keys_flag(legacy_db_type == DB_TYPE_INNODB);
+ ext_key_parts= key_parts;
len= (uint) uint2korr(disk_buff+4);
- if (!keys)
- {
- if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, len)))
- goto err;
- bzero((char*) keyinfo, len);
- key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
- }
- strpos= disk_buff+6;
-
- /*
- If share->use_ext_keys is set to TRUE we assume that any key
- can be extended by the components of the primary key whose
- definition is read first from the frm file.
- For each key only those fields of the assumed primary key are
- added that are not included in the proper key definition.
- If after all it turns out that there is no primary key the
- added components are removed from each key.
-
- When in the future we support others schemes of extending of
- secondary keys with components of the primary key we'll have
- to change the type of this flag for an enumeration type.
- */
-
- for (i=0 ; i < keys ; i++, keyinfo++)
- {
- if (new_frm_ver >= 3)
- {
- if (strpos + 8 >= frm_image_end)
- goto err;
- keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+2);
- keyinfo->user_defined_key_parts= (uint) strpos[4];
- keyinfo->algorithm= (enum ha_key_alg) strpos[5];
- keyinfo->block_size= uint2korr(strpos+6);
- strpos+=8;
- }
- else
- {
- if (strpos + 4 >= frm_image_end)
- goto err;
- keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+1);
- keyinfo->user_defined_key_parts= (uint) strpos[3];
- keyinfo->algorithm= HA_KEY_ALG_UNDEF;
- strpos+=4;
- }
-
- if (i == 0)
- {
- ext_key_parts= key_parts +
- (share->use_ext_keys ? first_keyinfo.user_defined_key_parts*(keys-1) : 0);
-
- n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO);
- if (!(keyinfo= (KEY*) alloc_root(&share->mem_root,
- n_length + len)))
- goto err; /* purecov: inspected */
- bzero((char*) keyinfo,n_length);
- share->key_info= keyinfo;
- key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo + keys);
-
- if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
- sizeof(ulong) * ext_key_parts)))
- goto err;
- first_key_part= key_part;
- first_key_parts= first_keyinfo.user_defined_key_parts;
- keyinfo->flags= first_keyinfo.flags;
- keyinfo->key_length= first_keyinfo.key_length;
- keyinfo->user_defined_key_parts= first_keyinfo.user_defined_key_parts;
- keyinfo->algorithm= first_keyinfo.algorithm;
- if (new_frm_ver >= 3)
- keyinfo->block_size= first_keyinfo.block_size;
- }
-
- keyinfo->key_part= key_part;
- keyinfo->rec_per_key= rec_per_key;
- for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++)
- {
- if (strpos + (new_frm_ver >= 1 ? 9 : 7) >= frm_image_end)
- goto err;
- *rec_per_key++=0;
- key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
- key_part->offset= (uint) uint2korr(strpos+2)-1;
- key_part->key_type= (uint) uint2korr(strpos+5);
- // key_part->field= (Field*) 0; // Will be fixed later
- if (new_frm_ver >= 1)
- {
- key_part->key_part_flag= *(strpos+4);
- key_part->length= (uint) uint2korr(strpos+7);
- strpos+=9;
- }
- else
- {
- key_part->length= *(strpos+4);
- key_part->key_part_flag=0;
- if (key_part->length > 128)
- {
- key_part->length&=127; /* purecov: inspected */
- key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
- }
- strpos+=7;
- }
- key_part->store_length=key_part->length;
- }
- /*
- Add primary key to end of extended keys for non unique keys for
- storage engines that supports it.
- */
- keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
- keyinfo->ext_key_flags= keyinfo->flags;
- keyinfo->ext_key_part_map= 0;
- if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME))
- {
- keyinfo->ext_key_part_map= 0;
- for (j= 0;
- j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
- j++)
- {
- uint key_parts= keyinfo->user_defined_key_parts;
- KEY_PART_INFO* curr_key_part= keyinfo->key_part;
- KEY_PART_INFO* curr_key_part_end= curr_key_part+key_parts;
- for ( ; curr_key_part < curr_key_part_end; curr_key_part++)
- {
- if (curr_key_part->fieldnr == first_key_part[j].fieldnr)
- break;
- }
- if (curr_key_part == curr_key_part_end)
- {
- *key_part++= first_key_part[j];
- *rec_per_key++= 0;
- keyinfo->ext_key_parts++;
- keyinfo->ext_key_part_map|= 1 << j;
- }
- }
- if (j == first_key_parts)
- keyinfo->ext_key_flags= keyinfo->flags | HA_EXT_NOSAME;
- }
- share->ext_key_parts+= keyinfo->ext_key_parts;
- }
- keynames=(char*) key_part;
- strpos+= strnmov(keynames, (char *) strpos, frm_image_end - strpos) - keynames;
- if (*strpos++) // key names are \0-terminated
- goto err;
-
- //reading index comments
- for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
- {
- if (keyinfo->flags & HA_USES_COMMENT)
- {
- if (strpos + 2 >= frm_image_end)
- goto err;
- keyinfo->comment.length= uint2korr(strpos);
- strpos+= 2;
-
- if (strpos + keyinfo->comment.length >= frm_image_end)
- goto err;
- keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos,
- keyinfo->comment.length);
- strpos+= keyinfo->comment.length;
- }
- DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
- (keyinfo->comment.length > 0));
- }
-
- share->reclength = uint2korr((frm_image+16));
+ share->reclength = uint2korr(frm_image+16);
share->stored_rec_length= share->reclength;
if (frm_image[26] == 1)
share->system= 1; /* one-record-database */
@@ -1098,7 +1103,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (se_plugin)
{
/* bad file, legacy_db_type did not match the name */
- goto err;
+ sql_print_warning("%s.frm is inconsistent: engine typecode %d, engine name %s (%d)",
+ share->normalized_path.str, legacy_db_type,
+ plugin_name(tmp_plugin)->str,
+ ha_legacy_type(plugin_data(tmp_plugin, handlerton *)));
}
/*
tmp_plugin is locked with a local lock.
@@ -1139,6 +1147,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
next_chunk+= str_db_type_length + 2;
}
+
+ share->set_use_ext_keys_flag(plugin_hton(se_plugin)->flags & HTON_EXTENDED_KEYS);
+
+ if (create_key_infos(disk_buff + 6, frm_image_end, keys, keyinfo,
+ new_frm_ver, ext_key_parts,
+ share, len, &first_keyinfo, keynames))
+ goto err;
+
if (next_chunk + 5 < buff_end)
{
uint32 partition_info_str_len = uint4korr(next_chunk);
@@ -1225,6 +1241,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
DBUG_ASSERT(next_chunk <= buff_end);
}
+ else
+ {
+ if (create_key_infos(disk_buff + 6, frm_image_end, keys, keyinfo,
+ new_frm_ver, ext_key_parts,
+ share, len, &first_keyinfo, keynames))
+ goto err;
+ }
+
share->key_block_size= uint2korr(frm_image+62);
if (share->db_plugin && !plugin_equals(share->db_plugin, se_plugin))
@@ -1260,7 +1284,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->comment.length);
}
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length));
if (!(field_ptr = (Field **)
@@ -1614,12 +1638,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
else
{
- add_first_key_parts= first_key_parts;
+ add_first_key_parts= first_keyinfo.user_defined_key_parts;
/*
Do not add components of the primary key starting from
the major component defined over the beginning of a field.
*/
- for (i= 0; i < first_key_parts; i++)
+ for (i= 0; i < first_keyinfo.user_defined_key_parts; i++)
{
uint fieldnr= keyinfo[0].key_part[i].fieldnr;
if (share->field[fieldnr-1]->key_length() !=
@@ -1632,7 +1656,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
- for (uint key=0 ; key < share->keys ; key++,keyinfo++)
+ for (uint key=0 ; key < keys ; key++,keyinfo++)
{
uint usable_parts= 0;
keyinfo->name=(char*) share->keynames.type_names[key];
@@ -1902,7 +1926,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
reg_field= *share->found_next_number_field;
if ((int) (share->next_number_index= (uint)
- find_ref_key(share->key_info, share->keys,
+ find_ref_key(share->key_info, keys,
share->default_values, reg_field,
&share->next_number_key_offset,
&share->next_number_keypart)) < 0)
@@ -2191,7 +2215,7 @@ bool fix_vcol_expr(THD *thd,
Item* func_expr= vcol_info->expr_item;
bool result= TRUE;
TABLE_LIST tables;
- int error;
+ int error= 0;
const char *save_where;
Field **ptr, *field;
enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
@@ -2204,7 +2228,11 @@ bool fix_vcol_expr(THD *thd,
thd->where= "virtual column function";
/* Fix fields referenced to by the virtual column function */
- error= func_expr->fix_fields(thd, (Item**)0);
+ if (!func_expr->fixed)
+ error= func_expr->fix_fields(thd, &vcol_info->expr_item);
+ /* fix_fields could change the expression */
+ func_expr= vcol_info->expr_item;
+ /* Number of columns will be checked later */
if (unlikely(error))
{
diff --git a/sql/table.h b/sql/table.h
index dc0c0b7fc20..8e5f8794a51 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -987,6 +987,9 @@ struct st_cond_statistic;
#define CHECK_ROW_FOR_NULLS_TO_REJECT (1 << 0)
#define REJECT_ROW_DUE_TO_NULL_FIELDS (1 << 1)
+/* Bitmap of table's fields */
+typedef Bitmap<MAX_FIELDS> Field_map;
+
struct TABLE
{
TABLE() {} /* Remove gcc warning */
@@ -1186,6 +1189,10 @@ public:
*/
bool distinct;
bool const_table,no_rows, used_for_duplicate_elimination;
+ /**
+ Forces DYNAMIC Aria row format for internal temporary tables.
+ */
+ bool keep_row_order;
/**
If set, the optimizer has found that row retrieval should access index
@@ -2180,6 +2187,16 @@ struct TABLE_LIST
bool single_table_updatable();
+ bool is_inner_table_of_outer_join()
+ {
+ for (TABLE_LIST *tbl= this; tbl; tbl= tbl->embedding)
+ {
+ if (tbl->outer_join)
+ return true;
+ }
+ return false;
+ }
+
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
bool prep_where(THD *thd, Item **conds, bool no_where_clause);