summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/event_data_objects.cc34
-rw-r--r--sql/events.cc27
-rw-r--r--sql/field.cc59
-rw-r--r--sql/field.h62
-rw-r--r--sql/ha_partition.cc6
-rw-r--r--sql/ha_sequence.cc6
-rw-r--r--sql/handler.cc19
-rw-r--r--sql/item.cc74
-rw-r--r--sql/item.h94
-rw-r--r--sql/item_cmpfunc.cc164
-rw-r--r--sql/item_cmpfunc.h20
-rw-r--r--sql/item_create.cc50
-rw-r--r--sql/item_geofunc.cc12
-rw-r--r--sql/item_jsonfunc.cc22
-rw-r--r--sql/item_row.cc1
-rw-r--r--sql/item_row.h11
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_strfunc.h19
-rw-r--r--sql/item_subselect.cc8
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/item_timefunc.cc15
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/item_xmlfunc.cc26
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log_event.cc40
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/opt_range.cc84
-rw-r--r--sql/opt_range_mrr.cc12
-rw-r--r--sql/opt_subselect.cc56
-rw-r--r--sql/opt_sum.cc4
-rw-r--r--sql/opt_table_elimination.cc8
-rw-r--r--sql/parse_file.cc2
-rw-r--r--sql/partition_info.cc4
-rw-r--r--sql/rpl_record.cc6
-rw-r--r--sql/rpl_record_old.cc6
-rw-r--r--sql/share/errmsg-utf8.txt38
-rw-r--r--sql/slave.cc1
-rw-r--r--sql/sp.cc5
-rw-r--r--sql/sp_head.cc32
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sp_pcontext.h2
-rw-r--r--sql/sp_rcontext.cc35
-rw-r--r--sql/sp_rcontext.h7
-rw-r--r--sql/spatial.cc2
-rw-r--r--sql/sql_acl.cc51
-rw-r--r--sql/sql_acl.h8
-rw-r--r--sql/sql_admin.cc1
-rw-r--r--sql/sql_base.cc82
-rw-r--r--sql/sql_base.h5
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_class.cc57
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_const.h13
-rw-r--r--sql/sql_cte.cc10
-rw-r--r--sql/sql_db.cc4
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_insert.cc17
-rw-r--r--sql/sql_join_cache.cc6
-rw-r--r--sql/sql_lex.cc318
-rw-r--r--sql/sql_lex.h35
-rw-r--r--sql/sql_load.cc12
-rw-r--r--sql/sql_parse.cc35
-rw-r--r--sql/sql_partition.cc41
-rw-r--r--sql/sql_partition.h3
-rw-r--r--sql/sql_plugin.cc84
-rw-r--r--sql/sql_prepare.cc47
-rw-r--r--sql/sql_repl.cc6
-rw-r--r--sql/sql_select.cc83
-rw-r--r--sql/sql_sequence.cc30
-rw-r--r--sql/sql_sequence.h4
-rw-r--r--sql/sql_show.cc56
-rw-r--r--sql/sql_statistics.cc20
-rw-r--r--sql/sql_table.cc46
-rw-r--r--sql/sql_test.cc10
-rw-r--r--sql/sql_time.cc2
-rw-r--r--sql/sql_trigger.cc5
-rw-r--r--sql/sql_type.cc39
-rw-r--r--sql/sql_type.h17
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_view.cc6
-rw-r--r--sql/sql_yacc.yy58
-rw-r--r--sql/sql_yacc_ora.yy40
-rw-r--r--sql/strfunc.cc2
-rw-r--r--sql/sys_vars.cc4
-rw-r--r--sql/table.cc9
-rw-r--r--sql/table.h3
-rw-r--r--sql/unireg.cc8
88 files changed, 1559 insertions, 833 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 69d17725bea..c85192ee258 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -431,7 +431,7 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
definer_host.str= strmake_root(&mem_root, ptr + 1, len);
definer_host.length= len;
- sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
+ sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int();
DBUG_RETURN(FALSE);
}
@@ -637,7 +637,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
else
comment.length= 0;
- sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
+ sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int();
DBUG_RETURN(FALSE);
}
@@ -1478,19 +1478,33 @@ end:
bool save_tx_read_only= thd->tx_read_only;
thd->tx_read_only= false;
- if (WSREP(thd))
- {
+ /*
+ This code is processing event execution and does not have client
+ connection. Here, event execution will now execute a prepared
+ DROP EVENT statement, but thd->lex->sql_command is set to
+ SQLCOM_CREATE_PROCEDURE
+ DROP EVENT will be logged in binlog, and we have to
+ replicate it to make all nodes have consistent event definitions
+ Wsrep DDL replication is triggered inside Events::drop_event(),
+ and here we need to prepare the THD so that DDL replication is
+ possible, essentially it requires setting sql_command to
+ SQLCOMM_DROP_EVENT, we will switch sql_command for the duration
+ of DDL replication only.
+ */
+ const enum_sql_command sql_command_save= thd->lex->sql_command;
+ const bool sql_command_set= WSREP(thd);
+
+ if (sql_command_set)
thd->lex->sql_command = SQLCOM_DROP_EVENT;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
- }
ret= Events::drop_event(thd, &dbname, &name, FALSE);
- WSREP_TO_ISOLATION_END;
+ if (sql_command_set)
+ {
+ WSREP_TO_ISOLATION_END;
+ thd->lex->sql_command = sql_command_save;
+ }
-#ifdef WITH_WSREP
- error:
-#endif
thd->tx_read_only= save_tx_read_only;
thd->security_ctx->master_access= saved_master_access;
}
diff --git a/sql/events.cc b/sql/events.cc
index 069fa97aa36..3ad546217a7 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -189,8 +189,8 @@ common_1_lev_code:
expr= tmp_expr - (tmp_expr/60)*60;
/* the code after the switch will finish */
- }
break;
+ }
case INTERVAL_HOUR_SECOND:
{
ulonglong tmp_expr= expr;
@@ -206,8 +206,8 @@ common_1_lev_code:
expr= tmp_expr - (tmp_expr/60)*60;
/* the code after the switch will finish */
- }
break;
+ }
case INTERVAL_DAY_SECOND:
{
ulonglong tmp_expr= expr;
@@ -229,8 +229,8 @@ common_1_lev_code:
expr= tmp_expr - (tmp_expr/60)*60;
/* the code after the switch will finish */
- }
break;
+ }
case INTERVAL_DAY_MICROSECOND:
case INTERVAL_HOUR_MICROSECOND:
case INTERVAL_MINUTE_MICROSECOND:
@@ -244,7 +244,8 @@ common_1_lev_code:
break;
case INTERVAL_WEEK:
expr/= 7;
- /* fall through */
+ close_quote= FALSE;
+ break;
default:
close_quote= FALSE;
break;
@@ -335,6 +336,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
@@ -417,6 +419,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+#ifdef WITH_WSREP
+ error:
+ DBUG_RETURN(TRUE);
+#endif /* WITH_WSREP */
}
@@ -457,6 +463,9 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
DBUG_RETURN(TRUE);
@@ -541,6 +550,10 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+#ifdef WITH_WSREP
+error:
+ DBUG_RETURN(TRUE);
+#endif /* WITH_WSREP */
}
@@ -582,6 +595,8 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
if (check_access(thd, EVENT_ACL, dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
/*
Turn off row binlogging of this statement and use statement-based so
that all supporting tables are updated for DROP EVENT command.
@@ -603,6 +618,10 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
+#ifdef WITH_WSREP
+error:
+ DBUG_RETURN(TRUE);
+#endif
}
diff --git a/sql/field.cc b/sql/field.cc
index e10c82347d5..51562dd4198 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2008, 2013, Monty Program Ab.
+ Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2017, MariaDB
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
@@ -240,7 +240,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_FLOAT, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
- MYSQL_TYPE_FLOAT, MYSQL_TYPE_FLOAT,
+ MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
@@ -2240,15 +2240,15 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff)
return tmp;
}
-void Field::set_default()
+int Field::set_default()
{
if (default_value)
{
Query_arena backup_arena;
table->in_use->set_n_backup_active_arena(table->expr_arena, &backup_arena);
- (void) default_value->expr->save_in_field(this, 0);
+ int rc= default_value->expr->save_in_field(this, 0);
table->in_use->restore_active_arena(table->expr_arena, &backup_arena);
- return;
+ return rc;
}
/* Copy constant value stored in s->default_values */
my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values -
@@ -2257,6 +2257,7 @@ void Field::set_default()
if (maybe_null_in_table())
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
(null_ptr[l_offset] & null_bit));
+ return 0;
}
@@ -2271,6 +2272,16 @@ void Field_null::sql_type(String &res) const
/****************************************************************************
+ Field_row, e.g. for ROW-type SP variables
+****************************************************************************/
+
+Field_row::~Field_row()
+{
+ delete m_table;
+}
+
+
+/****************************************************************************
Functions for the Field_decimal class
This is an number stored as a pre-space (or pre-zero) string
****************************************************************************/
@@ -9005,13 +9016,13 @@ String *Field_set::val_str(String *val_buffer,
ulonglong tmp=(ulonglong) Field_enum::val_int();
uint bitnr=0;
+ /*
+ Some callers expect *val_buffer to contain the result,
+ so we assign to it, rather than doing 'return &empty_set_string.
+ */
+ *val_buffer= empty_set_string;
if (tmp == 0)
{
- /*
- Some callers expect *val_buffer to contain the result,
- so we assign to it, rather than doing 'return &empty_set_string.
- */
- *val_buffer= empty_set_string;
return val_buffer;
}
@@ -9764,7 +9775,7 @@ Field_bit::unpack(uchar *to, const uchar *from, const uchar *from_end,
}
-void Field_bit::set_default()
+int Field_bit::set_default()
{
if (bit_len > 0)
{
@@ -9772,7 +9783,7 @@ void Field_bit::set_default()
uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len);
set_rec_bits(bits, bit_ptr, bit_ofs, bit_len);
}
- Field::set_default();
+ return Field::set_default();
}
/*
@@ -10301,6 +10312,21 @@ Field *make_field(TABLE_SHARE *share,
uchar *UNINIT_VAR(bit_ptr);
uchar UNINIT_VAR(bit_offset);
+ DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
+ handler->name().ptr(), field_length, interval,
+ FLAGSTR(pack_flag, FIELDFLAG_BINARY),
+ FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
+ FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
+ FLAGSTR(pack_flag, FIELDFLAG_PACK),
+ FLAGSTR(pack_flag, FIELDFLAG_BLOB)));
+
+ if (handler == &type_handler_row)
+ {
+ DBUG_ASSERT(field_length == 0);
+ DBUG_ASSERT(f_maybe_null(pack_flag));
+ return new (mem_root) Field_row(ptr, field_name);
+ }
+
if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
{
bit_ptr= null_pos;
@@ -10322,13 +10348,6 @@ Field *make_field(TABLE_SHARE *share,
null_bit= ((uchar) 1) << null_bit;
}
- DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
- handler->name().ptr(), field_length, interval,
- FLAGSTR(pack_flag, FIELDFLAG_BINARY),
- FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
- FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
- FLAGSTR(pack_flag, FIELDFLAG_PACK),
- FLAGSTR(pack_flag, FIELDFLAG_BLOB)));
if (f_is_alpha(pack_flag))
{
diff --git a/sql/field.h b/sql/field.h
index bf115b38816..eb6510bc9a4 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -45,6 +45,7 @@ class Column_statistics_collected;
class Item_func;
class Item_bool_func;
class Item_equal;
+class Virtual_tmp_table;
enum enum_check_fields
{
@@ -973,7 +974,7 @@ public:
my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]);
return ptr + l_offset;
}
- virtual void set_default();
+ virtual int set_default();
bool has_update_default_function() const
{
@@ -1527,6 +1528,11 @@ public:
virtual Compression_method *compression_method() const { return 0; }
+ virtual Virtual_tmp_table **virtual_tmp_table_addr()
+ {
+ return NULL;
+ }
+
friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value);
friend class Copy_field;
@@ -3902,7 +3908,7 @@ public:
virtual uchar *pack(uchar *to, const uchar *from, uint max_length);
virtual const uchar *unpack(uchar *to, const uchar *from,
const uchar *from_end, uint param_data);
- virtual void set_default();
+ virtual int set_default();
Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uint32 length,
@@ -3954,6 +3960,19 @@ public:
};
+class Field_row: public Field_null
+{
+ class Virtual_tmp_table *m_table;
+public:
+ Field_row(uchar *ptr_arg, const LEX_CSTRING *field_name_arg)
+ :Field_null(ptr_arg, 0, Field::NONE, field_name_arg, &my_charset_bin),
+ m_table(NULL)
+ {}
+ ~Field_row();
+ Virtual_tmp_table **virtual_tmp_table_addr() { return &m_table; }
+};
+
+
extern const LEX_CSTRING null_clex_str;
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
@@ -4205,6 +4224,23 @@ public:
|| unireg_check == Field::TIMESTAMP_DNUN_FIELD;
}
+ void set_type(const Column_definition &other)
+ {
+ set_handler(other.type_handler());
+ length= other.length;
+ char_length= other.char_length;
+ decimals= other.decimals;
+ flags= other.flags;
+ pack_length= other.pack_length;
+ key_length= other.key_length;
+ unireg_check= other.unireg_check;
+ interval= other.interval;
+ charset= other.charset;
+ srid= other.srid;
+ geom_type= other.geom_type;
+ pack_flag= other.pack_flag;
+ }
+
// Replace the entire value by another definition
void set_column_definition(const Column_definition *def)
{
@@ -4276,12 +4312,14 @@ class Spvar_definition: public Column_definition
class Qualified_column_ident *m_column_type_ref; // for %TYPE
class Table_ident *m_table_rowtype_ref; // for table%ROWTYPE
bool m_cursor_rowtype_ref; // for cursor%ROWTYPE
+ uint m_cursor_rowtype_offset; // for cursor%ROWTYPE
Row_definition_list *m_row_field_definitions; // for ROW
public:
Spvar_definition()
:m_column_type_ref(NULL),
m_table_rowtype_ref(NULL),
m_cursor_rowtype_ref(false),
+ m_cursor_rowtype_offset(0),
m_row_field_definitions(NULL)
{ }
Spvar_definition(THD *thd, Field *field)
@@ -4289,13 +4327,12 @@ public:
m_column_type_ref(NULL),
m_table_rowtype_ref(NULL),
m_cursor_rowtype_ref(false),
+ m_cursor_rowtype_offset(0),
m_row_field_definitions(NULL)
{ }
const Type_handler *type_handler() const
{
- return is_row() || is_table_rowtype_ref() || is_cursor_rowtype_ref() ?
- &type_handler_row :
- Type_handler_hybrid_field_type::type_handler();
+ return Type_handler_hybrid_field_type::type_handler();
}
bool is_column_type_ref() const { return m_column_type_ref != 0; }
bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; }
@@ -4315,11 +4352,20 @@ public:
}
void set_table_rowtype_ref(class Table_ident *ref)
{
+ DBUG_ASSERT(ref);
+ set_handler(&type_handler_row);
m_table_rowtype_ref= ref;
}
- void set_cursor_rowtype_ref(bool ref)
+
+ uint cursor_rowtype_offset() const
+ {
+ return m_cursor_rowtype_offset;
+ }
+ void set_cursor_rowtype_ref(uint offset)
{
- m_cursor_rowtype_ref= ref;
+ set_handler(&type_handler_row);
+ m_cursor_rowtype_ref= true;
+ m_cursor_rowtype_offset= offset;
}
/*
@@ -4347,6 +4393,8 @@ public:
}
void set_row_field_definitions(Row_definition_list *list)
{
+ DBUG_ASSERT(list);
+ set_handler(&type_handler_row);
m_row_field_definitions= list;
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index effabc3a3c0..67132e5ee4f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2005, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab & SkySQL Ab
+ Copyright (c) 2005, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, MariaDB
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
@@ -1931,7 +1931,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
cleanup_new_partition(part_count);
DBUG_RETURN(error);
}
-
+
DBUG_PRINT("info", ("Add partition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
new_file_array[i],
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index e5db6781464..93f6f32d473 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -112,6 +112,12 @@ int ha_sequence::open(const char *name, int mode, uint flags)
}
else
table->m_needs_reopen= true;
+
+ /*
+ The following is needed to fix comparison of rows in
+ ha_update_first_row() for InnoDB
+ */
+ memcpy(table->record[1], table->s->default_values, table->s->reclength);
}
DBUG_RETURN(error);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 7609ed047a0..ca4f8634091 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -405,7 +405,7 @@ static int ha_finish_errors(void)
}
static volatile int32 need_full_discover_for_existence= 0;
-static volatile int32 engines_with_discover_table_names= 0;
+static volatile int32 engines_with_discover_file_names= 0;
static volatile int32 engines_with_discover= 0;
static int full_discover_for_existence(handlerton *, const char *, const char *)
@@ -430,8 +430,8 @@ static void update_discovery_counters(handlerton *hton, int val)
if (hton->discover_table_existence == full_discover_for_existence)
my_atomic_add32(&need_full_discover_for_existence, val);
- if (hton->discover_table_names)
- my_atomic_add32(&engines_with_discover_table_names, val);
+ if (hton->discover_table_names && hton->tablefile_extensions[0])
+ my_atomic_add32(&engines_with_discover_file_names, val);
if (hton->discover_table)
my_atomic_add32(&engines_with_discover, val);
@@ -5229,6 +5229,7 @@ void Discovered_table_list::remove_duplicates()
{
LEX_CSTRING **src= tables->front();
LEX_CSTRING **dst= src;
+ sort();
while (++dst <= tables->back())
{
LEX_CSTRING *s= *src, *d= *dst;
@@ -5296,10 +5297,12 @@ int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp,
int error;
DBUG_ENTER("ha_discover_table_names");
- if (engines_with_discover_table_names == 0 && !reusable)
+ if (engines_with_discover_file_names == 0 && !reusable)
{
- error= ext_table_discovery_simple(dirp, result);
- result->sort();
+ st_discover_names_args args= {db, NULL, result, 0};
+ error= ext_table_discovery_simple(dirp, result) ||
+ plugin_foreach(thd, discover_names,
+ MYSQL_STORAGE_ENGINE_PLUGIN, &args);
}
else
{
@@ -5312,8 +5315,6 @@ int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp,
error= extension_based_table_discovery(dirp, reg_ext, result) ||
plugin_foreach(thd, discover_names,
MYSQL_STORAGE_ENGINE_PLUGIN, &args);
- result->sort();
-
if (args.possible_duplicates > 0)
result->remove_duplicates();
}
@@ -6078,7 +6079,7 @@ int handler::update_first_row(uchar *new_data)
/*
We have to do the memcmp as otherwise we may get error 169 from InnoDB
*/
- if (memcmp(table->record[0], table->record[1], table->s->reclength))
+ if (memcmp(new_data, table->record[1], table->s->reclength))
error= update_row(table->record[1], new_data);
}
end_error= ha_rnd_end();
diff --git a/sql/item.cc b/sql/item.cc
index ad17cd5811c..024fbd87d79 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -109,6 +109,19 @@ void Item::push_note_converted_to_positive_complement(THD *thd)
}
+longlong Item::val_datetime_packed_result()
+{
+ MYSQL_TIME ltime, tmp;
+ if (get_date_result(&ltime, TIME_FUZZY_DATES | TIME_INVALID_DATES))
+ return 0;
+ if (ltime.time_type != MYSQL_TIMESTAMP_TIME)
+ return pack_time(&ltime);
+ if ((null_value= time_to_datetime_with_warn(current_thd, &ltime, &tmp, 0)))
+ return 0;
+ return pack_time(&tmp);
+}
+
+
/**
Get date/time/datetime.
Optionally extend TIME result to DATETIME.
@@ -1752,17 +1765,15 @@ void Item_sp_variable::make_field(THD *thd, Send_field *field)
Item_splocal::Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name,
uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q, uint len_in_q):
Item_sp_variable(thd, sp_var_name),
Rewritable_query_parameter(pos_in_q, len_in_q),
+ Type_handler_hybrid_field_type(handler),
m_var_idx(sp_var_idx)
{
maybe_null= TRUE;
-
- sp_var_type= real_type_to_type(sp_var_type);
- m_type= sp_map_item_type(sp_var_type);
- set_handler_by_field_type(sp_var_type);
+ m_type= sp_map_item_type(handler);
}
@@ -1777,7 +1788,7 @@ bool Item_splocal::fix_fields(THD *thd, Item **ref)
Item *
Item_splocal::this_item()
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1785,7 +1796,7 @@ Item_splocal::this_item()
const Item *
Item_splocal::this_item() const
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1794,7 +1805,7 @@ Item_splocal::this_item() const
Item **
Item_splocal::this_item_addr(THD *thd, Item **)
{
- DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(m_sp == thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return thd->spcont->get_item_addr(m_var_idx);
}
@@ -1901,7 +1912,7 @@ bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref)
Item *
Item_splocal_row_field::this_item()
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
}
@@ -1910,7 +1921,7 @@ Item_splocal_row_field::this_item()
const Item *
Item_splocal_row_field::this_item() const
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
}
@@ -1919,7 +1930,7 @@ Item_splocal_row_field::this_item() const
Item **
Item_splocal_row_field::this_item_addr(THD *thd, Item **)
{
- DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(m_sp == thd->spcont->m_sp);
DBUG_ASSERT(fixed);
return thd->spcont->get_item(m_var_idx)->addr(m_field_idx);
}
@@ -2007,7 +2018,7 @@ bool Item_case_expr::fix_fields(THD *thd, Item **ref)
Item *
Item_case_expr::this_item()
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
@@ -2017,7 +2028,7 @@ Item_case_expr::this_item()
const Item *
Item_case_expr::this_item() const
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
@@ -2026,7 +2037,7 @@ Item_case_expr::this_item() const
Item **
Item_case_expr::this_item_addr(THD *thd, Item **)
{
- DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(m_sp == thd->spcont->m_sp);
return thd->spcont->get_case_expr_addr(m_case_expr_id);
}
@@ -2595,6 +2606,9 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
Item **args, uint nargs,
uint flags, int item_sep)
{
+ THD *thd= current_thd;
+ if (thd->lex->is_ps_or_view_context_analysis())
+ return false;
Item **arg, *safe_args[2]= {NULL, NULL};
/*
@@ -2610,7 +2624,6 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
safe_args[1]= args[item_sep];
}
- THD *thd= current_thd;
bool res= FALSE;
uint i;
@@ -7070,6 +7083,7 @@ bool Item::cache_const_expr_analyzer(uchar **arg)
*/
if (const_item() &&
!(basic_const_item() || item->basic_const_item() ||
+ item->type() == Item::NULL_ITEM || /* Item_name_const hack */
item->type() == Item::FIELD_ITEM ||
item->type() == SUBSELECT_ITEM ||
item->type() == CACHE_ITEM ||
@@ -7445,7 +7459,11 @@ public:
// Find which select the field is in. This is achieved by walking up
// the select tree and looking for the table of interest.
st_select_lex *sel;
- for (sel= current_select; sel; sel= sel->outer_select())
+ for (sel= current_select;
+ sel ;
+ sel= (sel->context.outer_context ?
+ sel->context.outer_context->select_lex:
+ NULL))
{
List_iterator<TABLE_LIST> li(sel->leaf_tables);
TABLE_LIST *tbl;
@@ -8619,7 +8637,6 @@ bool Item_direct_view_ref::send(Protocol *protocol, st_value *buffer)
bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
{
- DBUG_ASSERT(1);
/* view fild reference must be defined */
DBUG_ASSERT(*ref);
/* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */
@@ -9677,14 +9694,19 @@ bool Item_cache_temporal::cache_value()
{
if (!example)
return false;
+ value_cached= true;
+ value= example->val_datetime_packed_result();
+ null_value= example->null_value;
+ return true;
+}
+
+bool Item_cache_time::cache_value()
+{
+ if (!example)
+ return false;
value_cached= true;
-
- MYSQL_TIME ltime;
- if (example->get_date_result(&ltime, 0))
- value=0;
- else
- value= pack_time(&ltime);
+ value= example->val_time_packed_result();
null_value= example->null_value;
return true;
}
@@ -9735,8 +9757,8 @@ void Item_cache_temporal::store_packed(longlong val_arg, Item *example_arg)
Item *Item_cache_temporal::clone_item(THD *thd)
{
- Item_cache_temporal *item= new (thd->mem_root)
- Item_cache_temporal(thd, Item_cache_temporal::type_handler());
+ Item_cache *tmp= type_handler()->Item_get_cache(thd, this);
+ Item_cache_temporal *item= static_cast<Item_cache_temporal*>(tmp);
item->store_packed(value, example);
return item;
}
@@ -10184,7 +10206,7 @@ void Item_direct_view_ref::update_used_tables()
table_map Item_direct_view_ref::used_tables() const
{
- DBUG_ASSERT(null_ref_table);
+ DBUG_ASSERT(fixed);
if (get_depended_from())
return OUTER_REF_TABLE_BIT;
diff --git a/sql/item.h b/sql/item.h
index 0e7db0d6575..1f743913d78 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1,8 +1,8 @@
#ifndef SQL_ITEM_INCLUDED
#define SQL_ITEM_INCLUDED
-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2017, MariaDB Corporation.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, MariaDB
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
@@ -1397,6 +1397,14 @@ public:
ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES | TIME_TIME_ONLY;
return get_date(&ltime, fuzzydate) ? 0 : pack_time(&ltime);
}
+ longlong val_datetime_packed_result();
+ longlong val_time_packed_result()
+ {
+ MYSQL_TIME ltime;
+ ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES | TIME_TIME_ONLY;
+ return get_date_result(&ltime, fuzzydate) ? 0 : pack_time(&ltime);
+ }
+
// Get a temporal value in packed DATE/DATETIME or TIME format
longlong val_temporal_packed(enum_field_types f_type)
{
@@ -2093,17 +2101,6 @@ public:
};
-class Item_spvar_args: public Item_args
-{
- Virtual_tmp_table *m_table;
-public:
- Item_spvar_args():Item_args(), m_table(NULL) { }
- ~Item_spvar_args();
- bool row_create_items(THD *thd, List<Spvar_definition> *list);
- Field *get_row_field(uint i) const;
-};
-
-
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -2271,7 +2268,7 @@ public:
Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling.
*/
- sp_head *m_sp;
+ const sp_head *m_sp;
#endif
public:
@@ -2337,7 +2334,7 @@ protected:
bool append_value_for_log(THD *thd, String *str);
public:
Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0);
bool fix_fields(THD *, Item **);
@@ -2390,20 +2387,6 @@ public:
};
-class Item_splocal_row: public Item_splocal
-{
-public:
- Item_splocal_row(THD *thd, const LEX_CSTRING *sp_var_name,
- uint sp_var_idx, uint pos_in_q, uint len_in_q)
- :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
- pos_in_q, len_in_q)
- {
- set_handler(&type_handler_row);
- }
- enum Type type() const { return ROW_ITEM; }
-};
-
-
/**
An Item_splocal variant whose data type becomes known only at
sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE".
@@ -2415,7 +2398,7 @@ public:
const LEX_CSTRING *sp_var_name,
uint sp_var_idx,
uint pos_in_q, uint len_in_q)
- :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ :Item_splocal(thd, sp_var_name, sp_var_idx, &type_handler_null,
pos_in_q, len_in_q)
{ }
};
@@ -2437,9 +2420,9 @@ public:
const LEX_CSTRING *sp_var_name,
const LEX_CSTRING *sp_field_name,
uint sp_var_idx, uint sp_field_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0)
- :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type,
+ :Item_splocal(thd, sp_var_name, sp_var_idx, handler,
pos_in_q, len_in_q),
m_field_name(*sp_field_name),
m_field_idx(sp_field_idx)
@@ -2461,11 +2444,11 @@ public:
const LEX_CSTRING *sp_var_name,
const LEX_CSTRING *sp_field_name,
uint sp_var_idx,
- enum_field_types sp_var_type,
+ const Type_handler *handler,
uint pos_in_q= 0, uint len_in_q= 0)
:Item_splocal_row_field(thd, sp_var_name, sp_field_name,
sp_var_idx, 0 /* field index will be set later */,
- sp_var_type, pos_in_q, len_in_q)
+ handler, pos_in_q, len_in_q)
{ }
bool fix_fields(THD *thd, Item **it);
void print(String *str, enum_query_type query_type);
@@ -2930,14 +2913,13 @@ public:
Item_field for the ROW data type
*/
class Item_field_row: public Item_field,
- public Item_spvar_args
+ public Item_args
{
public:
Item_field_row(THD *thd, Field *field)
:Item_field(thd, field),
- Item_spvar_args()
+ Item_args()
{ }
-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_field_row>(thd, mem_root, this); }
@@ -2955,6 +2937,8 @@ public:
}
return false;
}
+ bool row_create_items(THD *thd, List<Spvar_definition> *list);
+ Field *get_row_field(uint i) const;
};
@@ -4680,6 +4664,8 @@ public:
bool fix_fields(THD *thd, Item **it);
void cleanup();
+ Item *get_orig_item() const { return orig_item; }
+
/* Methods of getting value which should be cached in the cache */
void save_val(Field *to);
double val_real();
@@ -5782,8 +5768,9 @@ public:
class Item_cache_temporal: public Item_cache_int
{
-public:
+protected:
Item_cache_temporal(THD *thd, const Type_handler *handler);
+public:
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
longlong val_int();
@@ -5801,8 +5788,37 @@ public:
*/
Item *clone_item(THD *thd);
Item *convert_to_basic_const_item(THD *thd);
+};
+
+
+class Item_cache_time: public Item_cache_temporal
+{
+public:
+ Item_cache_time(THD *thd)
+ :Item_cache_temporal(thd, &type_handler_time2) { }
+ bool cache_value();
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_cache_time>(thd, mem_root, this); }
+};
+
+
+class Item_cache_datetime: public Item_cache_temporal
+{
+public:
+ Item_cache_datetime(THD *thd)
+ :Item_cache_temporal(thd, &type_handler_datetime2) { }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_cache_datetime>(thd, mem_root, this); }
+};
+
+
+class Item_cache_date: public Item_cache_temporal
+{
+public:
+ Item_cache_date(THD *thd)
+ :Item_cache_temporal(thd, &type_handler_newdate) { }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_cache_temporal>(thd, mem_root, this); }
+ { return get_item_copy<Item_cache_date>(thd, mem_root, this); }
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 0d57066c2d2..f35017629aa 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -569,18 +569,24 @@ bool Arg_comparator::set_cmp_func_string()
bool Arg_comparator::set_cmp_func_time()
{
+ THD *thd= current_thd;
m_compare_collation= &my_charset_numeric;
func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
&Arg_comparator::compare_time;
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
bool Arg_comparator::set_cmp_func_datetime()
{
+ THD *thd= current_thd;
m_compare_collation= &my_charset_numeric;
func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
&Arg_comparator::compare_datetime;
+ a= cache_converted_constant(thd, a, &a_cache, compare_type_handler());
+ b= cache_converted_constant(thd, b, &b_cache, compare_type_handler());
return false;
}
@@ -683,17 +689,12 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
const Type_handler *handler)
{
/*
- get_datetime_value creates Item_cache internally when comparing
- values for the first row.
- Arg_comparator::cache_converted_constant() is never called for TIME_RESULT.
- */
- DBUG_ASSERT(handler->cmp_type() != TIME_RESULT);
- /*
Don't need cache if doing context analysis only.
*/
if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
(*value)->const_item() &&
- handler->cmp_type() != (*value)->cmp_type())
+ handler->type_handler_for_comparison() !=
+ (*value)->type_handler_for_comparison())
{
Item_cache *cache= handler->Item_get_cache(thd_arg, *value);
cache->setup(thd_arg, *value);
@@ -750,7 +751,8 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
if (!thd)
thd= current_thd;
const Type_handler *h= Type_handler::get_handler_by_field_type(f_type);
- Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, h);
+ Item_cache *tmp_cache= h->Item_get_cache(thd, item);
+ Item_cache_temporal *cache= static_cast<Item_cache_temporal*>(tmp_cache);
cache->store_packed(value, item);
*cache_arg= cache;
*item_arg= cache_arg;
@@ -759,63 +761,57 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
}
-/*
- Compare items values as dates.
-
- SYNOPSIS
- Arg_comparator::compare_datetime()
-
- DESCRIPTION
- Compare items values as DATE/DATETIME for both EQUAL_FUNC and from other
- comparison functions. The correct DATETIME values are obtained
- with help of the get_datetime_value() function.
-
- RETURN
- -1 a < b or at least one item is null
- 0 a == b
- 1 a > b
-*/
-
-int Arg_comparator::compare_temporal(enum_field_types type)
+int Arg_comparator::compare_time()
{
- bool a_is_null, b_is_null;
- longlong a_value, b_value;
-
+ longlong val1= (*a)->val_time_packed();
+ if (!(*a)->null_value)
+ {
+ longlong val2= (*b)->val_time_packed();
+ if (!(*b)->null_value)
+ return compare_not_null_values(val1, val2);
+ }
if (set_null)
- owner->null_value= 1;
+ owner->null_value= true;
+ return -1;
+}
- /* Get DATE/DATETIME/TIME value of the 'a' item. */
- a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null);
- if (a_is_null)
- return -1;
- /* Get DATE/DATETIME/TIME value of the 'b' item. */
- b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null);
- if (b_is_null)
- return -1;
+int Arg_comparator::compare_e_time()
+{
+ longlong val1= (*a)->val_time_packed();
+ longlong val2= (*b)->val_time_packed();
+ if ((*a)->null_value || (*b)->null_value)
+ return MY_TEST((*a)->null_value && (*b)->null_value);
+ return MY_TEST(val1 == val2);
+}
- /* Here we have two not-NULL values. */
- if (set_null)
- owner->null_value= 0;
- /* Compare values. */
- return a_value < b_value ? -1 : a_value > b_value ? 1 : 0;
-}
-int Arg_comparator::compare_e_temporal(enum_field_types type)
+int Arg_comparator::compare_datetime()
{
- bool a_is_null, b_is_null;
- longlong a_value, b_value;
+ longlong val1= (*a)->val_datetime_packed();
+ if (!(*a)->null_value)
+ {
+ longlong val2= (*b)->val_datetime_packed();
+ if (!(*b)->null_value)
+ return compare_not_null_values(val1, val2);
+ }
+ if (set_null)
+ owner->null_value= true;
+ return -1;
+}
- /* Get DATE/DATETIME/TIME value of the 'a' item. */
- a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null);
- /* Get DATE/DATETIME/TIME value of the 'b' item. */
- b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null);
- return a_is_null || b_is_null ? a_is_null == b_is_null
- : a_value == b_value;
+int Arg_comparator::compare_e_datetime()
+{
+ longlong val1= (*a)->val_datetime_packed();
+ longlong val2= (*b)->val_datetime_packed();
+ if ((*a)->null_value || (*b)->null_value)
+ return MY_TEST((*a)->null_value && (*b)->null_value);
+ return MY_TEST(val1 == val2);
}
+
int Arg_comparator::compare_string()
{
String *res1,*res2;
@@ -962,13 +958,7 @@ int Arg_comparator::compare_int_signed()
{
longlong val2= (*b)->val_int();
if (!(*b)->null_value)
- {
- if (set_null)
- owner->null_value= 0;
- if (val1 < val2) return -1;
- if (val1 == val2) return 0;
- return 1;
- }
+ return compare_not_null_values(val1, val2);
}
if (set_null)
owner->null_value= 1;
@@ -2112,38 +2102,40 @@ bool Item_func_between::fix_length_and_dec_numeric(THD *thd)
}
-longlong Item_func_between::val_int_cmp_temporal()
+bool Item_func_between::fix_length_and_dec_temporal(THD *thd)
{
- THD *thd= current_thd;
- longlong value, a, b;
- Item *cache, **ptr;
- bool value_is_null, a_is_null, b_is_null;
+ if (!thd->lex->is_ps_or_view_context_analysis())
+ {
+ for (uint i= 0; i < 3; i ++)
+ {
+ if (args[i]->const_item() &&
+ args[i]->type_handler_for_comparison() != m_comparator.type_handler())
+ {
+ Item_cache *cache= m_comparator.type_handler()->Item_get_cache(thd, args[i]);
+ if (!cache || cache->setup(thd, args[i]))
+ return true;
+ thd->change_item_tree(&args[i], cache);
+ }
+ }
+ }
+ return false;
+}
- ptr= &args[0];
- enum_field_types f_type= m_comparator.type_handler()->field_type();
- value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
- if (ptr != &args[0])
- thd->change_item_tree(&args[0], *ptr);
- if ((null_value= value_is_null))
+longlong Item_func_between::val_int_cmp_temporal()
+{
+ enum_field_types f_type= m_comparator.type_handler()->field_type();
+ longlong value= args[0]->val_temporal_packed(f_type), a, b;
+ if ((null_value= args[0]->null_value))
return 0;
-
- ptr= &args[1];
- a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
- if (ptr != &args[1])
- thd->change_item_tree(&args[1], *ptr);
-
- ptr= &args[2];
- b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
- if (ptr != &args[2])
- thd->change_item_tree(&args[2], *ptr);
-
- if (!a_is_null && !b_is_null)
+ a= args[1]->val_temporal_packed(f_type);
+ b= args[2]->val_temporal_packed(f_type);
+ if (!args[1]->null_value && !args[2]->null_value)
return (longlong) ((value >= a && value <= b) != negated);
- if (a_is_null && b_is_null)
+ if (args[1]->null_value && args[2]->null_value)
null_value= true;
- else if (a_is_null)
- null_value= value <= b; // not null if false range.
+ else if (args[1]->null_value)
+ null_value= value <= b; // not null if false range.
else
null_value= value >= a;
return (longlong) (!null_value && negated);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index f0862608463..62066ef61e5 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -60,9 +60,14 @@ class Arg_comparator: public Sql_alloc
int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2);
- int compare_temporal(enum_field_types type);
- int compare_e_temporal(enum_field_types type);
-
+ int compare_not_null_values(longlong val1, longlong val2)
+ {
+ if (set_null)
+ owner->null_value= false;
+ if (val1 < val2) return -1;
+ if (val1 == val2) return 0;
+ return 1;
+ }
public:
/* Allow owner function to use string buffers. */
String value1, value2;
@@ -112,10 +117,10 @@ public:
int compare_e_row(); // compare args[0] & args[1]
int compare_real_fixed();
int compare_e_real_fixed();
- int compare_datetime() { return compare_temporal(MYSQL_TYPE_DATETIME); }
- int compare_e_datetime() { return compare_e_temporal(MYSQL_TYPE_DATETIME); }
- int compare_time() { return compare_temporal(MYSQL_TYPE_TIME); }
- int compare_e_time() { return compare_e_temporal(MYSQL_TYPE_TIME); }
+ int compare_datetime();
+ int compare_e_datetime();
+ int compare_time();
+ int compare_e_time();
int compare_json_str_basic(Item *j, Item *s);
int compare_json_str();
int compare_str_json();
@@ -899,6 +904,7 @@ public:
{
return agg_arg_charsets_for_comparison(cmp_collation, args, 3);
}
+ bool fix_length_and_dec_temporal(THD *);
bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 6edeade0244..5d6d9742c7a 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -2876,6 +2876,20 @@ protected:
};
+class Create_func_substr_oracle : public Create_native_func
+{
+public:
+ virtual Item *create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list);
+
+ static Create_func_substr_oracle s_singleton;
+
+protected:
+ Create_func_substr_oracle() {}
+ virtual ~Create_func_substr_oracle() {}
+};
+
+
class Create_func_subtime : public Create_func_arg2
{
public:
@@ -6466,6 +6480,40 @@ Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *a
}
+Create_func_substr_oracle Create_func_substr_oracle::s_singleton;
+
+Item*
+Create_func_substr_oracle::create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list)
+{
+ Item *func= NULL;
+ int arg_count= item_list ? item_list->elements : 0;
+
+ switch (arg_count) {
+ case 2:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_substr_oracle(thd, param_1, param_2);
+ break;
+ }
+ case 3:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ Item *param_3= item_list->pop();
+ func= new (thd->mem_root) Item_func_substr_oracle(thd, param_1, param_2, param_3);
+ break;
+ }
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ break;
+ }
+
+ return func;
+}
+
+
Create_func_subtime Create_func_subtime::s_singleton;
Item*
@@ -7119,6 +7167,8 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
{ { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
{ { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
+ { { C_STRING_WITH_LEN("SUBSTR_ORACLE") },
+ BUILDER(Create_func_substr_oracle)},
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
{ { C_STRING_WITH_LEN("SUBTIME") }, BUILDER(Create_func_subtime)},
{ { C_STRING_WITH_LEN("TAN") }, BUILDER(Create_func_tan)},
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 3047595b58c..fe089e6283d 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -66,9 +66,9 @@ String *Item_func_geometry_from_text::val_str(String *str)
srid= (uint32)args[1]->val_int();
str->set_charset(&my_charset_bin);
+ str->length(0);
if (str->reserve(SRID_SIZE, 512))
return 0;
- str->length(0);
str->q_append(srid);
if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0)))
return 0;
@@ -1323,6 +1323,8 @@ static int setup_relate_func(Geometry *g1, Geometry *g2,
}
else
func->repeat_expression(shape_a);
+ if (func->reserve_op_buffer(1))
+ return 1;
func->add_operation(op_matrix(nc%3), 1);
if (do_store_shapes)
{
@@ -1493,11 +1495,13 @@ longlong Item_func_spatial_precise_rel::val_int()
Gcalc_function::op_intersection, 2);
func.add_operation(Gcalc_function::op_internals, 1);
shape_a= func.get_next_expression_pos();
- if ((null_value= g1.store_shapes(&trn)))
+ if ((null_value= g1.store_shapes(&trn)) ||
+ func.reserve_op_buffer(1))
break;
func.add_operation(Gcalc_function::op_internals, 1);
shape_b= func.get_next_expression_pos();
- if ((null_value= g2.store_shapes(&trn)))
+ if ((null_value= g2.store_shapes(&trn)) ||
+ func.reserve_op_buffer(1))
break;
func.add_operation(Gcalc_function::v_find_t |
Gcalc_function::op_intersection, 2);
@@ -1732,6 +1736,8 @@ int Item_func_buffer::Transporter::single_point(double x, double y)
{
if (buffer_op == Gcalc_function::op_difference)
{
+ if (m_fn->reserve_op_buffer(1))
+ return 1;
m_fn->add_operation(Gcalc_function::op_false, 0);
return 0;
}
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index f804f83f122..7edafa3dc33 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -581,7 +581,8 @@ String *Item_func_json_quote::val_str(String *str)
void Item_func_json_unquote::fix_length_and_dec()
{
- collation.set(&my_charset_utf8_general_ci);
+ collation.set(&my_charset_utf8_general_ci,
+ DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length= args[0]->max_length;
maybe_null= 1;
}
@@ -1011,6 +1012,8 @@ static int check_contains(json_engine_t *js, json_engine_t *value)
case JSON_VALUE_ARRAY:
if (value->value_type != JSON_VALUE_ARRAY)
{
+ loc_js= *value;
+ set_js= FALSE;
while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END)
{
int c_level, v_scalar;
@@ -1021,6 +1024,11 @@ static int check_contains(json_engine_t *js, json_engine_t *value)
if (!(v_scalar= json_value_scalar(js)))
c_level= json_get_level(js);
+ if (set_js)
+ *value= loc_js;
+ else
+ set_js= TRUE;
+
if (check_contains(js, value))
{
if (json_skip_level(js))
@@ -1452,7 +1460,8 @@ void Item_func_json_array::fix_length_and_dec()
if (arg_count == 0)
{
- collation.set(&my_charset_utf8_general_ci);
+ collation.set(&my_charset_utf8_general_ci,
+ DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
tmp_val.set_charset(&my_charset_utf8_general_ci);
max_length= 2;
return;
@@ -2126,6 +2135,7 @@ longlong Item_func_json_length::val_int()
json_engine_t je;
uint length= 0;
uint array_counters[JSON_DEPTH_LIMIT];
+ int err;
if ((null_value= args[0]->null_value))
return 0;
@@ -2167,7 +2177,7 @@ longlong Item_func_json_length::val_int()
if (json_value_scalar(&je))
return 1;
- while (json_scan_next(&je) == 0 &&
+ while (!(err= json_scan_next(&je)) &&
je.state != JST_OBJ_END && je.state != JST_ARRAY_END)
{
switch (je.state)
@@ -2186,6 +2196,12 @@ longlong Item_func_json_length::val_int()
};
}
+ if (!err)
+ {
+ /* Parse to the end of the JSON just to check it's valid. */
+ while (json_scan_next(&je) == 0) {}
+ }
+
if (!je.s.error)
return length;
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 8b7cc814694..3b8bd8d3e59 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -24,7 +24,6 @@
#include "sql_class.h" // THD, set_var.h: THD
#include "set_var.h"
-
void Item_row::illegal_method_call(const char *method)
{
DBUG_ENTER("Item_row::illegal_method_call");
diff --git a/sql/item_row.h b/sql/item_row.h
index 9c92e19caab..83e9743fede 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -47,13 +47,10 @@ public:
Item_row(THD *thd, List<Item> &list):
Item(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0)
{ }
- Item_row(THD *thd, Item_row *item):
- Item(thd),
- Item_args(item),
- Used_tables_and_const_cache(item),
- not_null_tables_cache(0),
- with_null(0)
- {}
+ Item_row(THD *thd, Item_row *row):
+ Item(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(),
+ not_null_tables_cache(0), with_null(0)
+ { }
enum Type type() const { return ROW_ITEM; };
const Type_handler *type_handler() const { return &type_handler_row; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d9b375e7be1..90bfb11e822 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1777,7 +1777,7 @@ String *Item_func_substr::val_str(String *str)
DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
/* must be longlong to avoid truncation */
- longlong start= args[1]->val_int();
+ longlong start= get_position();
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Limit so that code sees out-of-bound value properly. */
longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32;
@@ -1827,7 +1827,7 @@ void Item_func_substr::fix_length_and_dec()
DBUG_ASSERT(collation.collation != NULL);
if (args[1]->const_item())
{
- int32 start= (int32) args[1]->val_int();
+ int32 start= (int32) get_position();
if (args[1]->null_value)
max_length= 0;
else if (start < 0)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1c35588f884..c322136bef2 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -505,9 +505,12 @@ public:
class Item_func_substr :public Item_str_func
{
String tmp_value;
+protected:
+ virtual longlong get_position() { return args[1]->val_int(); }
public:
Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
- Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {}
+ Item_func_substr(THD *thd, Item *a, Item *b, Item *c):
+ Item_str_func(thd, a, b, c) {}
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "substr"; }
@@ -515,6 +518,20 @@ public:
{ return get_item_copy<Item_func_substr>(thd, mem_root, this); }
};
+class Item_func_substr_oracle :public Item_func_substr
+{
+protected:
+ longlong get_position()
+ { longlong pos= args[1]->val_int(); return pos == 0 ? 1 : pos; }
+public:
+ Item_func_substr_oracle(THD *thd, Item *a, Item *b):
+ Item_func_substr(thd, a, b) {}
+ Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c):
+ Item_func_substr(thd, a, b, c) {}
+ const char *func_name() const { return "substr_oracle"; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_substr_oracle>(thd, mem_root, this); }
+};
class Item_func_substr_index :public Item_str_func
{
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 84e1aae1ad5..1f2949903b4 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1433,6 +1433,10 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy));
left_expr_orig= left_expr= left_exp;
+ /* prepare to possible disassembling the item in convert_subq_to_sj() */
+ if (left_exp->type() == Item::ROW_ITEM)
+ left_expr_orig= new (thd->mem_root)
+ Item_row(thd, static_cast<Item_row*>(left_exp));
func= &eq_creator;
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
max_columns= UINT_MAX;
@@ -1456,6 +1460,10 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
{
DBUG_ENTER("Item_allany_subselect::Item_allany_subselect");
left_expr_orig= left_expr= left_exp;
+ /* prepare to possible disassembling the item in convert_subq_to_sj() */
+ if (left_exp->type() == Item::ROW_ITEM)
+ left_expr_orig= new (thd->mem_root)
+ Item_row(thd, static_cast<Item_row*>(left_exp));
func= func_creator(all_arg);
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
max_columns= 1;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index d6e42efd11c..b047dc4ea4d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3593,7 +3593,7 @@ bool Item_func_group_concat::setup(THD *thd)
syntax of this function). If there is no ORDER BY clause, we don't
create this tree.
*/
- init_tree(tree, (uint) MY_MIN(thd->variables.max_heap_table_size,
+ init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0,
tree_key_length,
group_concat_key_cmp_with_order, NULL, (void*) this,
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index d00120018b8..3a7684fe7b4 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1825,9 +1825,18 @@ overflow:
ltime->hour= TIME_MAX_HOUR+1;
check_time_range(ltime, decimals, &unused);
- make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
- err->ptr(), err->length(),
- MYSQL_TIMESTAMP_TIME, NullS);
+ if (!err)
+ {
+ ErrConvInteger err2(sec, unsigned_flag);
+ make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ &err2, MYSQL_TIMESTAMP_TIME, NullS);
+ }
+ else
+ {
+ ErrConvString err2(err);
+ make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
+ &err2, MYSQL_TIMESTAMP_TIME, NullS);
+ }
return 0;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 94794c6789d..9c102e8a666 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -574,8 +574,6 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; }
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
- int save_in_field(Field *field, bool no_conversions)
- { return save_date_in_field(field, no_conversions); }
};
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index ba24ebe76c5..ee307ba2194 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -176,7 +176,7 @@ public:
{
nodebeg= (MY_XML_NODE*) pxml->ptr();
nodeend= (MY_XML_NODE*) (pxml->ptr() + pxml->length());
- numnodes= nodeend - nodebeg;
+ numnodes= (uint)(nodeend - nodebeg);
}
void prepare(String *nodeset)
{
@@ -615,7 +615,7 @@ public:
if ((node->parent == flt->num) &&
(node->type == MY_XML_NODE_TEXT))
{
- fake->set_value(node->beg, node->end - node->beg,
+ fake->set_value(node->beg, (uint)(node->end - node->beg),
collation.collation);
if (args[1]->val_int())
return 1;
@@ -817,7 +817,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str)
Item_func *comp_func= (Item_func*)args[1];
uint pos= 0, size;
prepare(str);
- size= fltend - fltbeg;
+ size= (uint)(fltend - fltbeg);
for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++)
{
nodeset_func->context_cache.length(0);
@@ -836,7 +836,7 @@ String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset)
Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0];
prepare(nodeset);
MY_XPATH_FLT *flt;
- uint pos, size= fltend - fltbeg;
+ uint pos, size= (uint)(fltend - fltbeg);
for (pos= 0, flt= fltbeg; flt < fltend; flt++)
{
nodeset_func->context_cache.length(0);
@@ -995,7 +995,7 @@ static Item *create_comparator(MY_XPATH *xpath,
else if (a->type() == Item::XPATH_NODESET &&
b->type() == Item::XPATH_NODESET)
{
- uint len= xpath->query.end - context->beg;
+ uint len= (uint)(xpath->query.end - context->beg);
set_if_smaller(len, 32);
my_printf_error(ER_UNKNOWN_ERROR,
"XPATH error: "
@@ -1399,7 +1399,7 @@ MY_XPATH_FUNC *
my_xpath_function(const char *beg, const char *end)
{
MY_XPATH_FUNC *k, *function_names;
- uint length= end-beg;
+ uint length= (uint)(end-beg);
switch (length)
{
case 1: return 0;
@@ -1961,7 +1961,7 @@ static int my_xpath_parse_PrimaryExpr_literal(MY_XPATH *xpath)
return 0;
xpath->item= new (xpath->thd->mem_root)
Item_string(xpath->thd, xpath->prevtok.beg + 1,
- xpath->prevtok.end - xpath->prevtok.beg - 2,
+ (uint)(xpath->prevtok.end - xpath->prevtok.beg - 2),
xpath->cs);
return 1;
}
@@ -2499,13 +2499,13 @@ static int my_xpath_parse_Number(MY_XPATH *xpath)
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOT))
{
xpath->item= new (thd->mem_root) Item_int(thd, xpath->prevtok.beg,
- xpath->prevtok.end - xpath->prevtok.beg);
+ (uint)(xpath->prevtok.end - xpath->prevtok.beg));
return 1;
}
my_xpath_parse_term(xpath, MY_XPATH_LEX_DIGITS);
xpath->item= new (thd->mem_root) Item_float(thd, beg,
- xpath->prevtok.end - beg);
+ (uint)(xpath->prevtok.end - beg));
return 1;
}
@@ -2621,7 +2621,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
(spv= spc->find_variable(&name, false)))
{
Item_splocal *splocal= new (thd->mem_root)
- Item_splocal(thd, &name, spv->offset, spv->sql_type(), 0);
+ Item_splocal(thd, &name, spv->offset, spv->type_handler(), 0);
#ifdef DBUG_ASSERT_EXISTS
if (splocal)
splocal->m_sp= lex->sphead;
@@ -2632,7 +2632,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
{
xpath->item= NULL;
DBUG_ASSERT(xpath->query.end > dollar_pos);
- uint len= xpath->query.end - dollar_pos;
+ uint len= (uint)(xpath->query.end - dollar_pos);
set_if_smaller(len, 32);
my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'",
MYF(0), len, dollar_pos);
@@ -2660,7 +2660,7 @@ my_xpath_parse_NodeTest_QName(MY_XPATH *xpath)
if (!my_xpath_parse_QName(xpath))
return 0;
DBUG_ASSERT(xpath->context);
- uint len= xpath->prevtok.end - xpath->prevtok.beg;
+ uint len= (uint)(xpath->prevtok.end - xpath->prevtok.beg);
xpath->context= nametestfunc(xpath, xpath->axis, xpath->context,
xpath->prevtok.beg, len);
return 1;
@@ -2759,7 +2759,7 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref)
if (!rc)
{
- uint clen= xpath.query.end - xpath.lasttok.beg;
+ uint clen= (uint)(xpath.query.end - xpath.lasttok.beg);
set_if_smaller(clen, 32);
my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'",
MYF(0), clen, xpath.lasttok.beg);
diff --git a/sql/log.cc b/sql/log.cc
index 450f677d363..008cc0b59aa 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3044,7 +3044,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
if (thd->spcont)
if (my_b_printf(&log_file, "# Stored_routine: %s\n",
- ErrConvDQName(thd->spcont->sp).ptr()) == (uint) -1)
+ ErrConvDQName(thd->spcont->m_sp).ptr()) == (uint) -1)
tmp_errno= errno;
if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) &&
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 841478b511b..f1ceaec6456 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1131,7 +1131,7 @@ int append_query_string(CHARSET_INFO *csinfo, String *to,
*ptr++= '\'';
}
- to->length(orig_len + ptr - beg);
+ to->length((uint32)(orig_len + ptr - beg));
return 0;
}
#endif
@@ -8681,21 +8681,6 @@ User_var_log_event(const char* buf, uint event_len,
we keep the flags set to UNDEF_F.
*/
size_t bytes_read= ((val + val_len) - buf_start);
-#ifdef DBUG_ASSERT_EXISTS
- bool old_pre_checksum_fd= description_event->is_version_before_checksum(
- &description_event->server_version_split);
-#endif
- DBUG_ASSERT((bytes_read == data_written -
- (old_pre_checksum_fd ||
- (description_event->checksum_alg ==
- BINLOG_CHECKSUM_ALG_OFF)) ?
- 0 : BINLOG_CHECKSUM_LEN)
- ||
- (bytes_read == data_written -1 -
- (old_pre_checksum_fd ||
- (description_event->checksum_alg ==
- BINLOG_CHECKSUM_ALG_OFF)) ?
- 0 : BINLOG_CHECKSUM_LEN));
if ((data_written - bytes_read) > 0)
{
flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
@@ -10041,7 +10026,7 @@ Execute_load_query_log_event::do_apply_event(rpl_group_info *rgi)
p= strmake(p, STRING_WITH_LEN(" INTO "));
p= strmake(p, query+fn_pos_end, q_len-fn_pos_end);
- error= Query_log_event::do_apply_event(rgi, buf, p-buf);
+ error= Query_log_event::do_apply_event(rgi, buf, (uint32)(p-buf));
/* Forging file name for deletion in same buffer */
*fname_end= 0;
@@ -10493,7 +10478,7 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length)
{
size_t const block_size= 1024;
- ulong cur_size= m_rows_cur - m_rows_buf;
+ size_t cur_size= m_rows_cur - m_rows_buf;
DBUG_EXECUTE_IF("simulate_too_big_row_case1",
cur_size= UINT_MAX32 - (block_size * 10);
length= UINT_MAX32 - (block_size * 10););
@@ -10506,21 +10491,21 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
DBUG_EXECUTE_IF("simulate_too_big_row_case4",
cur_size= UINT_MAX32 - (block_size * 10);
length= (block_size * 10) - block_size + 1;);
- ulong remaining_space= UINT_MAX32 - cur_size;
+ size_t remaining_space= UINT_MAX32 - cur_size;
/* Check that the new data fits within remaining space and we can add
block_size without wrapping.
*/
- if (length > remaining_space ||
+ if (cur_size > UINT_MAX32 || length > remaining_space ||
((length + block_size) > remaining_space))
{
sql_print_error("The row data is greater than 4GB, which is too big to "
"write to the binary log.");
DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED);
}
- ulong const new_alloc=
+ size_t const new_alloc=
block_size * ((cur_size + length + block_size - 1) / block_size);
- uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc,
+ uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, new_alloc,
MYF(MY_ALLOW_ZERO_PTR|MY_WME));
if (unlikely(!new_buf))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -11253,11 +11238,11 @@ bool Rows_log_event::write_compressed()
uchar *m_rows_cur_tmp = m_rows_cur;
bool ret = true;
uint32 comlen, alloc_size;
- comlen= alloc_size= binlog_get_compress_len(m_rows_cur_tmp - m_rows_buf_tmp);
+ comlen= alloc_size= binlog_get_compress_len((uint32)(m_rows_cur_tmp - m_rows_buf_tmp));
m_rows_buf = (uchar *)my_safe_alloca(alloc_size);
if(m_rows_buf &&
!binlog_buf_compress((const char *)m_rows_buf_tmp, (char *)m_rows_buf,
- m_rows_cur_tmp - m_rows_buf_tmp, &comlen))
+ (uint32)(m_rows_cur_tmp - m_rows_buf_tmp), &comlen))
{
m_rows_cur= comlen + m_rows_buf;
ret= Log_event::write();
@@ -12493,7 +12478,7 @@ Rows_log_event::write_row(rpl_group_info *rgi,
the size of the first row and use that value to initialize
storage engine for bulk insertion */
DBUG_ASSERT(!(m_curr_row > m_curr_row_end));
- ulong estimated_rows= 0;
+ ha_rows estimated_rows= 0;
if (m_curr_row < m_curr_row_end)
estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
else if (m_curr_row == m_curr_row_end)
@@ -12712,7 +12697,7 @@ int Rows_log_event::update_sequence()
longlong round= table->field[ROUND_FIELD_NO]->val_int();
dbug_tmp_restore_column_map(table->read_set, old_map);
- return table->s->sequence->set_value(table, nextval, round, 0);
+ return table->s->sequence->set_value(table, nextval, round, 0) > 0;
}
/*
@@ -12731,6 +12716,7 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi)
DBUG_ASSERT(m_table != NULL);
const char *tmp= thd->get_proc_info();
const char *message= "Write_rows_log_event::write_row()";
+ int error;
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
@@ -12740,7 +12726,7 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi)
#endif /* WSREP_PROC_INFO */
thd_proc_info(thd, message);
- int error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
+ error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
thd_proc_info(thd, tmp);
if (error && !thd->is_error())
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 4fcdc37c912..ad27c58f67f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -8867,8 +8867,8 @@ static int mysql_init_variables(void)
/* Set directory paths */
mysql_real_data_home_len=
- strmake_buf(mysql_real_data_home,
- get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home;
+ (uint)(strmake_buf(mysql_real_data_home,
+ get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home);
/* Replication parameters */
master_info_file= (char*) "master.info",
relay_log_info_file= (char*) "relay-log.info";
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 404c5a1f6d3..3180c509737 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -499,9 +499,9 @@ int SEL_IMERGE::or_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree)
if (trees_next == trees_end)
{
const int realloc_ratio= 2; /* Double size for next round */
- uint old_elements= (trees_end - trees);
- uint old_size= sizeof(SEL_TREE**) * old_elements;
- uint new_size= old_size * realloc_ratio;
+ size_t old_elements= (trees_end - trees);
+ size_t old_size= sizeof(SEL_TREE**) * old_elements;
+ size_t new_size= old_size * realloc_ratio;
SEL_TREE **new_trees;
if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size)))
return -1;
@@ -846,10 +846,10 @@ SEL_TREE::SEL_TREE(SEL_TREE *arg, bool without_merges,
SEL_IMERGE::SEL_IMERGE(SEL_IMERGE *arg, uint cnt,
RANGE_OPT_PARAM *param) : Sql_alloc()
{
- uint elements= (arg->trees_end - arg->trees);
+ size_t elements= (arg->trees_end - arg->trees);
if (elements > PREALLOCED_TREES)
{
- uint size= elements * sizeof (SEL_TREE **);
+ size_t size= elements * sizeof (SEL_TREE **);
if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size)))
goto mem_err;
}
@@ -951,7 +951,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param,
uint rc;
bool is_last_check_pass= FALSE;
SEL_IMERGE *imerge= im1->head();
- uint elems= imerge->trees_next-imerge->trees;
+ uint elems= (uint)(imerge->trees_next-imerge->trees);
MEM_ROOT *mem_root= current_thd->mem_root;
im1->empty();
@@ -1051,7 +1051,7 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param,
SEL_TREE *or_tree= new (mem_root) SEL_TREE (tree, FALSE, param);
if (or_tree)
{
- uint elems= imerge->trees_next-imerge->trees;
+ uint elems= (uint)(imerge->trees_next-imerge->trees);
rc= imerge->or_sel_tree_with_checks(param, elems, or_tree,
TRUE, &is_last_check_pass);
if (!is_last_check_pass)
@@ -2897,7 +2897,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
uint keynr;
uint max_quick_key_parts= 0;
MY_BITMAP *used_fields= &table->cond_set;
- double table_records= table->stat_records();
+ double table_records= (double)table->stat_records();
DBUG_ENTER("calculate_cond_selectivity_for_table");
table->cond_selectivity= 1.0;
@@ -3994,8 +3994,8 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
store_length_array,
range_par->min_key,
range_par->max_key,
- tmp_min_key - range_par->min_key,
- tmp_max_key - range_par->max_key,
+ (uint)(tmp_min_key - range_par->min_key),
+ (uint)(tmp_max_key - range_par->max_key),
flag,
&ppar->part_iter);
if (!res)
@@ -4643,6 +4643,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
double roru_index_costs;
ha_rows roru_total_records;
double roru_intersect_part= 1.0;
+ size_t n_child_scans;
DBUG_ENTER("get_best_disjunct_quick");
DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
@@ -4659,7 +4660,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
}
}
- uint n_child_scans= imerge->trees_next - imerge->trees;
+ n_child_scans= imerge->trees_next - imerge->trees;
if (!n_child_scans)
DBUG_RETURN(NULL);
@@ -4877,8 +4878,8 @@ skip_to_ror_scan:
(TIME_FOR_COMPARE_ROWID * M_LN2) +
get_sweep_read_cost(param, roru_total_records);
- DBUG_PRINT("info", ("ROR-union: cost %g, %d members", roru_total_cost,
- n_child_scans));
+ DBUG_PRINT("info", ("ROR-union: cost %g, %zu members",
+ roru_total_cost, n_child_scans));
TRP_ROR_UNION* roru;
if (roru_total_cost < read_time)
{
@@ -5203,7 +5204,7 @@ bool prepare_search_best_index_intersect(PARAM *param,
INDEX_SCAN_INFO **scan_ptr;
INDEX_SCAN_INFO *cpk_scan= NULL;
TABLE *table= param->table;
- uint n_index_scans= tree->index_scans_end - tree->index_scans;
+ uint n_index_scans= (uint)(tree->index_scans_end - tree->index_scans);
if (!n_index_scans)
return 1;
@@ -5846,7 +5847,7 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree,
}
}
- count= tree->index_scans_end - tree->index_scans;
+ count= (uint)(tree->index_scans_end - tree->index_scans);
for (i= 0; i < count; i++)
{
index_scan= tree->index_scans[i];
@@ -6506,7 +6507,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
intersect_scans_best););
*are_all_covering= intersect->is_covering;
- uint best_num= intersect_scans_best - intersect_scans;
+ uint best_num= (uint)(intersect_scans_best - intersect_scans);
ror_intersect_cpy(intersect, intersect_best);
/*
@@ -6688,7 +6689,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
TRP_ROR_INTERSECT *trp;
if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT))
DBUG_RETURN(trp);
- uint best_num= (ror_scan_mark - tree->ror_scans);
+ uint best_num= (uint)(ror_scan_mark - tree->ror_scans);
if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
sizeof(ROR_SCAN_INFO*)*
best_num)))
@@ -8557,6 +8558,34 @@ bool sel_trees_can_be_ored(RANGE_OPT_PARAM* param,
}
/*
+ Check whether the key parts inf_init..inf_end-1 of one index can compose
+ an infix for the key parts key_init..key_end-1 of another index
+*/
+
+static
+bool is_key_infix(KEY_PART *key_init, KEY_PART *key_end,
+ KEY_PART *inf_init, KEY_PART *inf_end)
+{
+ KEY_PART *key_part, *inf_part;
+ for (key_part= key_init; key_part < key_end; key_part++)
+ {
+ if (key_part->field->eq(inf_init->field))
+ break;
+ }
+ if (key_part == key_end)
+ return false;
+ for (key_part++, inf_part= inf_init + 1;
+ key_part < key_end && inf_part < inf_end;
+ key_part++, inf_part++)
+ {
+ if (!key_part->field->eq(inf_part->field))
+ return false;
+ }
+ return inf_part == inf_end;
+}
+
+
+/*
Check whether range parts of two trees must be ored for some indexes
SYNOPSIS
@@ -8612,14 +8641,9 @@ bool sel_trees_must_be_ored(RANGE_OPT_PARAM* param,
KEY_PART *key2_init= param->key[idx2]+tree2->keys[idx2]->part;
KEY_PART *key2_end= param->key[idx2]+tree2->keys[idx2]->max_part_no;
- KEY_PART *part1, *part2;
- for (part1= key1_init, part2= key2_init;
- part1 < key1_end && part2 < key2_end;
- part1++, part2++)
- {
- if (!part1->field->eq(part2->field))
- DBUG_RETURN(FALSE);
- }
+ if (!is_key_infix(key1_init, key1_end, key2_init, key2_end) &&
+ !is_key_infix(key2_init, key2_end, key1_init, key1_end))
+ DBUG_RETURN(FALSE);
}
}
@@ -11476,7 +11500,7 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
DBUG_RETURN(0);
}
- uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
+ uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer);
if (count == 0)
{
/* Ranges have already been used up before. None is left for read. */
@@ -11521,7 +11545,7 @@ int QUICK_RANGE_SELECT_GEOM::get_next()
DBUG_RETURN(result);
}
- uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer);
+ uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer);
if (count == 0)
{
/* Ranges have already been used up before. None is left for read. */
@@ -11975,7 +11999,7 @@ void QUICK_SELECT_I::add_key_and_length(String *key_names,
bool *first)
{
char buf[64];
- uint length;
+ size_t length;
KEY *key_info= head->key_info + index;
if (*first)
@@ -12529,7 +12553,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
cur_group_prefix_len+= cur_part->store_length;
++cur_group_key_parts;
- max_key_part= cur_part - cur_index_info->key_part + 1;
+ max_key_part= (uint)(cur_part - cur_index_info->key_part) + 1;
used_key_parts_map.set_bit(max_key_part);
}
else
@@ -13252,7 +13276,7 @@ get_field_keypart(KEY *index, Field *field)
part < end; part++)
{
if (field->eq(part->field))
- return part - index->key_part + 1;
+ return (uint)(part - index->key_part + 1);
}
return 0;
}
diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc
index b3350191d13..ace6208fd77 100644
--- a/sql/opt_range_mrr.cc
+++ b/sql/opt_range_mrr.cc
@@ -199,9 +199,9 @@ walk_right_n_up:
{
{
RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
- uint min_key_length= cur->min_key - seq->param->min_key;
- uint max_key_length= cur->max_key - seq->param->max_key;
- uint len= cur->min_key - cur[-1].min_key;
+ size_t min_key_length= cur->min_key - seq->param->min_key;
+ size_t max_key_length= cur->max_key - seq->param->max_key;
+ size_t len= cur->min_key - cur[-1].min_key;
if (!(min_key_length == max_key_length &&
!memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
!key_tree->min_flag && !key_tree->max_flag))
@@ -238,7 +238,7 @@ walk_up_n_right:
/* Ok got a tuple */
RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
- uint min_key_length= cur->min_key - seq->param->min_key;
+ uint min_key_length= (uint)(cur->min_key - seq->param->min_key);
range->ptr= (char*)(intptr)(key_tree->part);
if (cur->min_key_flag & GEOM_FLAG)
@@ -256,13 +256,13 @@ walk_up_n_right:
range->range_flag= cur->min_key_flag | cur->max_key_flag;
range->start_key.key= seq->param->min_key;
- range->start_key.length= cur->min_key - seq->param->min_key;
+ range->start_key.length= (uint)(cur->min_key - seq->param->min_key);
range->start_key.keypart_map= make_prev_keypart_map(cur->min_key_parts);
range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
HA_READ_KEY_EXACT);
range->end_key.key= seq->param->max_key;
- range->end_key.length= cur->max_key - seq->param->max_key;
+ range->end_key.length= (uint)(cur->max_key - seq->param->max_key);
range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
HA_READ_AFTER_KEY);
range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 5335001683c..6dc5e08152c 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -1589,6 +1589,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
sj-nest.
*/
st_select_lex *subq_lex= subq_pred->unit->first_select();
+ DBUG_ASSERT(subq_lex->next_select() == NULL);
nested_join->join_list.empty();
List_iterator_fast<TABLE_LIST> li(subq_lex->top_join_list);
TABLE_LIST *tl;
@@ -1692,7 +1693,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
if (subq_pred->left_expr->cols() == 1)
{
- nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr,
+ /* add left = select_list_element */
+ nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr,
thd->mem_root);
/*
Create Item_func_eq. Note that
@@ -1706,26 +1708,62 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Item_func_eq *item_eq=
new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig,
subq_lex->ref_pointer_array[0]);
+ if (!item_eq)
+ DBUG_RETURN(TRUE);
if (subq_pred->left_expr_orig != subq_pred->left_expr)
thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr);
item_eq->in_equality_no= 0;
sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq);
}
- else
+ else if (subq_pred->left_expr->type() == Item::ROW_ITEM)
{
+ /*
+ disassemple left expression and add
+ left1 = select_list_element1 and left2 = select_list_element2 ...
+ */
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
{
- nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->
- element_index(i),
+ nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->addr(i),
thd->mem_root);
- Item_func_eq *item_eq=
+ Item_func_eq *item_eq=
new (thd->mem_root)
- Item_func_eq(thd, subq_pred->left_expr->element_index(i),
+ Item_func_eq(thd, subq_pred->left_expr_orig->element_index(i),
subq_lex->ref_pointer_array[i]);
+ if (!item_eq)
+ DBUG_RETURN(TRUE);
+ DBUG_ASSERT(subq_pred->left_expr->element_index(i)->fixed);
+ if (subq_pred->left_expr_orig->element_index(i) !=
+ subq_pred->left_expr->element_index(i))
+ thd->change_item_tree(item_eq->arguments(),
+ subq_pred->left_expr->element_index(i));
item_eq->in_equality_no= i;
sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq);
}
}
+ else
+ {
+ /*
+ add row operation
+ left = (select_list_element1, select_list_element2, ...)
+ */
+ Item_row *row= new (thd->mem_root) Item_row(thd, subq_lex->pre_fix);
+ /* fix fields on subquery was call so they should be the same */
+ DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols());
+ if (!row)
+ DBUG_RETURN(TRUE);
+ nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr);
+ Item_func_eq *item_eq=
+ new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, row);
+ if (!item_eq)
+ DBUG_RETURN(TRUE);
+ for (uint i= 0; i < row->cols(); i++)
+ {
+ if (row->element_index(i) != subq_lex->ref_pointer_array[i])
+ thd->change_item_tree(row->addr(i), subq_lex->ref_pointer_array[i]);
+ }
+ item_eq->in_equality_no= 0;
+ sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq);
+ }
/*
Fix the created equality and AND
@@ -3274,8 +3312,8 @@ void restore_prev_sj_state(const table_map remaining_tables,
ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest,
table_map remaining_tables)
{
- List_iterator<Item> li(sj_nest->nested_join->sj_outer_expr_list);
- Item *item;
+ List_iterator<Item_ptr> li(sj_nest->nested_join->sj_outer_expr_list);
+ Item **item;
uint i= 0;
ulonglong res= 0;
while ((item= li++))
@@ -3286,7 +3324,7 @@ ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest,
class and see if there is an element that is bound?
(this is an optional feature)
*/
- if (!(item->used_tables() & remaining_tables))
+ if (!(item[0]->used_tables() & remaining_tables))
{
res |= 1ULL << i;
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 6cdf0e0f26a..72b28473e15 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -768,12 +768,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
key_part_map org_key_part_used= *key_part_used;
if (eq_type || between || max_fl == less_fl)
{
- uint length= (key_ptr-ref->key_buff)+part->store_length;
+ uint length= (uint)(key_ptr-ref->key_buff)+part->store_length;
if (ref->key_length < length)
{
/* Ultimately ref->key_length will contain the length of the search key */
ref->key_length= length;
- ref->key_parts= (part - keyinfo->key_part) + 1;
+ ref->key_parts= (uint)(part - keyinfo->key_part) + 1;
}
if (!*prefix_len && part+1 == field_part)
*prefix_len= length;
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 1d6fb4dabfe..390afc575ca 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -849,7 +849,7 @@ bool check_func_dependency(JOIN *join,
*/
uint and_level=0;
build_eq_mods_for_cond(join->thd, &dac, &last_eq_mod, &and_level, cond);
- if (!(dac.n_equality_mods= last_eq_mod - dac.equality_mods))
+ if (!(dac.n_equality_mods= (uint)(last_eq_mod - dac.equality_mods)))
return FALSE; /* No useful conditions */
List<Dep_module> bound_modules;
@@ -1062,7 +1062,7 @@ bool Dep_analysis_context::setup_equality_modules_deps(List<Dep_module>
eq_mod < equality_mods + n_equality_mods;
eq_mod++)
{
- deps_recorder.expr_offset= eq_mod - equality_mods;
+ deps_recorder.expr_offset= (uint)(eq_mod - equality_mods);
deps_recorder.visited_other_tables= FALSE;
eq_mod->unbound_args= 0;
@@ -1080,7 +1080,7 @@ bool Dep_analysis_context::setup_equality_modules_deps(List<Dep_module>
Dep_value_field* field_val;
while ((field_val= it++))
{
- uint offs= field_val->bitmap_offset + eq_mod - equality_mods;
+ uint offs= (uint)(field_val->bitmap_offset + eq_mod - equality_mods);
bitmap_set_bit(&expr_deps, offs);
}
}
@@ -1159,7 +1159,7 @@ void build_eq_mods_for_cond(THD *thd, Dep_analysis_context *ctx,
if (cond->type() == Item_func::COND_ITEM)
{
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
- uint orig_offset= *eq_mod - ctx->equality_mods;
+ size_t orig_offset= *eq_mod - ctx->equality_mods;
/* AND/OR */
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index ebb08a23009..aedb7a4f0af 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -255,7 +255,7 @@ sql_create_definition_file(const LEX_CSTRING *dir,
File handler;
IO_CACHE file;
char path[FN_REFLEN+1]; // +1 to put temporary file name for sure
- int path_end;
+ size_t path_end;
File_option *param;
DBUG_ENTER("sql_create_definition_file");
DBUG_PRINT("enter", ("Dir: %s, file: %s, base %p",
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index a52c7873817..6fdbdfce893 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -1674,7 +1674,7 @@ void partition_info::print_no_partition_found(TABLE *table_arg, myf errflag)
bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr,
char *end_token, bool is_subpart)
{
- uint expr_len= end_token - start_token;
+ size_t expr_len= end_token - start_token;
char *func_string= (char*) thd->memdup(start_token, expr_len);
if (!func_string)
@@ -2347,7 +2347,7 @@ bool partition_info::fix_column_value_functions(THD *thd,
{
uchar *val_ptr;
uint len= field->pack_length();
- ulonglong save_sql_mode;
+ sql_mode_t save_sql_mode;
bool save_got_warning;
if (!(column_item= get_column_item(column_item,
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index 9ff5004414c..6da3f15cfb9 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -80,7 +80,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols,
unsigned int null_mask= 1U;
for ( ; (field= *p_field) ; p_field++)
{
- if (bitmap_is_set(cols, p_field - table->field))
+ if (bitmap_is_set(cols, (uint)(p_field - table->field)))
{
my_ptrdiff_t offset;
if (field->is_null(rec_offset))
@@ -262,7 +262,7 @@ unpack_row(rpl_group_info *rgi,
No need to bother about columns that does not exist: they have
gotten default values when being emptied above.
*/
- if (bitmap_is_set(cols, field_ptr - begin_ptr))
+ if (bitmap_is_set(cols, (uint)(field_ptr - begin_ptr)))
{
if ((null_mask & 0xFF) == 0)
{
@@ -434,7 +434,7 @@ unpack_row(rpl_group_info *rgi,
if (master_reclength)
{
if (*field_ptr)
- *master_reclength = (*field_ptr)->ptr - table->record[0];
+ *master_reclength = (ulong)((*field_ptr)->ptr - table->record[0]);
else
*master_reclength = table->s->reclength;
}
diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc
index 4180557f018..523049cf959 100644
--- a/sql/rpl_record_old.cc
+++ b/sql/rpl_record_old.cc
@@ -134,7 +134,7 @@ unpack_row_old(rpl_group_info *rgi,
{
Field *const f= *field_ptr;
- if (bitmap_is_set(cols, field_ptr - begin_ptr))
+ if (bitmap_is_set(cols, (uint)(field_ptr - begin_ptr)))
{
f->move_field_offset(offset);
ptr= f->unpack(f->ptr, ptr, row_buffer_end, 0);
@@ -149,14 +149,14 @@ unpack_row_old(rpl_group_info *rgi,
}
}
else
- bitmap_clear_bit(rw_set, field_ptr - begin_ptr);
+ bitmap_clear_bit(rw_set, (uint)(field_ptr - begin_ptr));
}
*row_end = ptr;
if (master_reclength)
{
if (*field_ptr)
- *master_reclength = (*field_ptr)->ptr - table->record[0];
+ *master_reclength = (ulong)((*field_ptr)->ptr - table->record[0]);
else
*master_reclength = table->s->reclength;
}
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 0204121c553..e414a674af6 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7675,8 +7675,11 @@ ER_SLAVE_SAME_ID
ER_FLASHBACK_NOT_SUPPORTED
eng "Flashback does not support %s %s"
-# MARIAROCKS-TODO: Should we add RocksDB error messages here or use some other
-# solution?
+
+
+#
+# MyRocks error messages
+#
ER_KEYS_OUT_OF_ORDER
eng "Keys are out order during bulk load"
@@ -7710,39 +7713,40 @@ ER_UNSUPPORTED_COLLATION
ER_METADATA_INCONSISTENCY
eng "Table '%s' does not exist, but metadata information exists inside MyRocks. This is a sign of data inconsistency. Please check if '%s.frm' exists, and try to restore it if it does not exist."
-ER_KEY_CREATE_DURING_ALTER
- eng "MyRocks failed creating new key definitions during alter."
-
-ER_SK_POPULATE_DURING_ALTER
- eng "MyRocks failed populating secondary key during alter."
-
ER_CF_DIFFERENT
eng "Column family ('%s') flag (%d) is different from an existing flag (%d). Assign a new CF flag, or do not change existing CF flag."
+ER_RDB_TTL_DURATION_FORMAT
+ eng "TTL duration (%s) in MyRocks must be an unsigned non-null 64-bit integer."
+
ER_RDB_STATUS_GENERAL
- eng "Status error %d received from RocksDB: %s"
+ eng "Status error %d received from RocksDB: %s"
ER_RDB_STATUS_MSG
- eng "%s, Status error %d received from RocksDB: %s"
-
-ER_NET_OK_PACKET_TOO_LARGE
- eng "OK packet too large"
+ eng "%s, Status error %d received from RocksDB: %s"
ER_RDB_TTL_UNSUPPORTED
- eng "TTL support is currently disabled when table has secondary indexes or hidden PK."
+ eng "TTL support is currently disabled when table has a hidden PK."
ER_RDB_TTL_COL_FORMAT
eng "TTL column (%s) in MyRocks must be an unsigned non-null 64-bit integer, exist inside the table, and have an accompanying ttl duration."
-ER_RDB_TTL_DURATION_FORMAT
- eng "TTL duration (%s) in MyRocks must be an unsigned non-null 64-bit integer."
-
ER_PER_INDEX_CF_DEPRECATED
eng "The per-index column family option has been deprecated"
+ER_KEY_CREATE_DURING_ALTER
+ eng "MyRocks failed creating new key definitions during alter."
+
+ER_SK_POPULATE_DURING_ALTER
+ eng "MyRocks failed populating secondary key during alter."
+
+# MyRocks messages end
ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG
eng "Window functions can not be used as arguments to group functions."
+ER_NET_OK_PACKET_TOO_LARGE
+ eng "OK packet too large"
+
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
eng "Illegal parameter data types %s and %s for operation '%s'"
ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
diff --git a/sql/slave.cc b/sql/slave.cc
index 46932e36e95..94e35bec4f8 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3433,7 +3433,6 @@ static int init_slave_thread(THD* thd, Master_info *mi,
thd->connection_name= mi->connection_name;
thd->variables.sql_log_slow= !MY_TEST(thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_SLAVE);
set_slave_thread_options(thd);
- thd->client_capabilities = CLIENT_LOCAL_FILES;
if (thd_type == SLAVE_THD_SQL)
THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log);
diff --git a/sql/sp.cc b/sql/sp.cc
index e2884f49d99..e02283d1f17 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -173,7 +173,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
"'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
"'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
"'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
- "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") },
+ "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH',"
+ "'EMPTY_STRING_IS_NULL')") },
{ NULL, 0 }
},
{
@@ -688,7 +689,7 @@ Sp_handler::db_find_routine(THD *thd,
// Get additional information
modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
- sql_mode= (ulong) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
+ sql_mode= (sql_mode_t) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 0bc269c414c..df9471880d9 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -70,8 +70,12 @@ static void reset_start_time_for_sp(THD *thd)
Item::Type
-sp_map_item_type(enum enum_field_types type)
+sp_map_item_type(const Type_handler *handler)
{
+ if (handler == &type_handler_row)
+ return Item::ROW_ITEM;
+ enum_field_types type= real_type_to_type(handler->real_field_type());
+
switch (type) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_TINY:
@@ -994,7 +998,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
sp_rcontext *ctx= thd->spcont;
bool err_status= FALSE;
uint ip= 0;
- ulonglong save_sql_mode;
+ sql_mode_t save_sql_mode;
bool save_abort_on_warning;
Query_arena *old_arena;
/* per-instruction arena */
@@ -1444,7 +1448,7 @@ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value,
bool switch_security_ctx)
{
if (!(m_flags & HAS_COLUMN_TYPE_REFS))
- return sp_rcontext::create(thd, m_pcont, ret_value, *defs);
+ return sp_rcontext::create(thd, this, m_pcont, ret_value, *defs);
sp_rcontext *res= NULL;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context *save_security_ctx;
@@ -1453,7 +1457,7 @@ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value,
return NULL;
#endif
if (!defs->resolve_type_refs(thd))
- res= sp_rcontext::create(thd, m_pcont, ret_value, *defs);
+ res= sp_rcontext::create(thd, this, m_pcont, ret_value, *defs);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (switch_security_ctx)
m_security_ctx.restore_security_context(thd, save_security_ctx);
@@ -1590,9 +1594,6 @@ sp_head::execute_trigger(THD *thd,
goto err_with_cleanup;
}
- /* Needed by slow log */
- nctx->sp= this;
-
thd->spcont= nctx;
err_status= execute(thd, FALSE);
@@ -1713,9 +1714,6 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
*/
thd->restore_active_arena(&call_arena, &backup_arena);
- /* Needed by slow log */
- nctx->sp= this;
-
/* Pass arguments. */
for (arg_no= 0; arg_no < argcount; arg_no++)
{
@@ -1918,7 +1916,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
DBUG_RETURN(TRUE);
}
- octx->sp= 0;
thd->spcont= octx;
/* set callers_arena to thd, for upper-level function to work */
@@ -1931,7 +1928,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= save_spcont;
DBUG_RETURN(TRUE);
}
- nctx->sp= this;
if (params > 0)
{
@@ -2566,10 +2562,18 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
*full_access= ((!check_table_access(thd, SELECT_ACL, &tables, FALSE,
1, TRUE) &&
(tables.grant.privilege & SELECT_ACL) != 0) ||
+ /* Check if user owns the routine. */
(!strcmp(sp->m_definer.user.str,
thd->security_ctx->priv_user) &&
!strcmp(sp->m_definer.host.str,
- thd->security_ctx->priv_host)));
+ thd->security_ctx->priv_host)) ||
+ /* Check if current role or any of the sub-granted roles
+ own the routine. */
+ (sp->m_definer.host.length == 0 &&
+ (!strcmp(sp->m_definer.user.str,
+ thd->security_ctx->priv_role) ||
+ check_role_is_granted(thd->security_ctx->priv_role, NULL,
+ sp->m_definer.user.str))));
if (!*full_access)
return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str,
sp->m_handler);
@@ -4812,11 +4816,11 @@ bool sp_head::spvar_fill_row(THD *thd,
sp_variable *spvar,
Row_definition_list *defs)
{
+ spvar->field_def.set_row_field_definitions(defs);
spvar->field_def.field_name= spvar->name;
if (fill_spvar_definition(thd, &spvar->field_def))
return true;
row_fill_field_definitions(thd, defs);
- spvar->field_def.set_row_field_definitions(defs);
return false;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index c3ace46a789..734c0dea3e3 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -40,7 +40,7 @@
*/
Item::Type
-sp_map_item_type(enum enum_field_types type);
+sp_map_item_type(const Type_handler *handler);
uint
sp_get_flags_for_command(LEX *lex);
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 9c879099410..990ad35cb57 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -60,8 +60,6 @@ public:
Spvar_definition field_def;
/// Field-type of the SP-variable.
- enum_field_types sql_type() const { return field_def.real_field_type(); }
-
const Type_handler *type_handler() const { return field_def.type_handler(); }
public:
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 70ab5a576b3..6716aa54170 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -35,10 +35,12 @@
///////////////////////////////////////////////////////////////////////////
-sp_rcontext::sp_rcontext(const sp_pcontext *root_parsing_ctx,
+sp_rcontext::sp_rcontext(const sp_head *owner,
+ const sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
bool in_sub_stmt)
:end_partial_result_set(false),
+ m_sp(owner),
m_root_parsing_ctx(root_parsing_ctx),
m_var_table(NULL),
m_return_value_fld(return_value_fld),
@@ -59,11 +61,13 @@ sp_rcontext::~sp_rcontext()
sp_rcontext *sp_rcontext::create(THD *thd,
+ const sp_head *owner,
const sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
Row_definition_list &field_def_lst)
{
- sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx,
+ sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(owner,
+ root_parsing_ctx,
return_value_fld,
thd->in_sub_stmt);
if (!ctx)
@@ -352,10 +356,13 @@ bool sp_rcontext::init_var_items(THD *thd,
}
-bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
+bool Item_field_row::row_create_items(THD *thd, List<Spvar_definition> *list)
{
DBUG_ASSERT(list);
- if (!(m_table= create_virtual_tmp_table(thd, *list)))
+ DBUG_ASSERT(field);
+ Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
+ DBUG_ASSERT(ptable);
+ if (!(ptable[0]= create_virtual_tmp_table(thd, *list)))
return true;
if (alloc_arguments(thd, list->elements))
@@ -366,23 +373,19 @@ bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
for (arg_count= 0; (def= it++); arg_count++)
{
if (!(args[arg_count]= new (thd->mem_root)
- Item_field(thd, m_table->field[arg_count])))
+ Item_field(thd, ptable[0]->field[arg_count])))
return true;
}
return false;
}
-Field *Item_spvar_args::get_row_field(uint i) const
+Field *Item_field_row::get_row_field(uint i) const
{
- DBUG_ASSERT(m_table);
- return m_table->field[i];
-}
-
-
-Item_spvar_args::~Item_spvar_args()
-{
- delete m_table;
+ DBUG_ASSERT(field);
+ Virtual_tmp_table **ptable= field->virtual_tmp_table_addr();
+ DBUG_ASSERT(ptable);
+ return ptable[0]->field[i];
}
@@ -685,13 +688,13 @@ int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items)
{
DBUG_ENTER("sp_rcontext::set_variable_row");
- DBUG_ASSERT(thd->spcont->get_item(var_idx)->cols() == items.elements);
+ DBUG_ASSERT(get_item(var_idx)->cols() == items.elements);
List_iterator<Item> it(items);
Item *item;
for (uint i= 0 ; (item= it++) ; i++)
{
int rc;
- if ((rc= thd->spcont->set_variable_row_field(thd, var_idx, i, &item)))
+ if ((rc= set_variable_row_field(thd, var_idx, i, &item)))
DBUG_RETURN(rc);
}
DBUG_RETURN(0);
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 66df0359d28..658972ece40 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -70,6 +70,7 @@ public:
///
/// @return valid sp_rcontext object or NULL in case of OOM-error.
static sp_rcontext *create(THD *thd,
+ const sp_head *owner,
const sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
Row_definition_list &defs);
@@ -77,7 +78,8 @@ public:
~sp_rcontext();
private:
- sp_rcontext(const sp_pcontext *root_parsing_ctx,
+ sp_rcontext(const sp_head *owner,
+ const sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
bool in_sub_stmt);
@@ -179,7 +181,8 @@ public:
/// The stored program for which this runtime context is created. Used for
/// checking if correct runtime context is used for variable handling.
- sp_head *sp;
+ /// Also used by slow log.
+ const sp_head *m_sp;
/////////////////////////////////////////////////////////////////////////
// SP-variables.
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 8d595541eef..19035a4e882 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -2565,7 +2565,7 @@ uint Gis_multi_polygon::init_from_opresult(String *bin,
n_poly++;
}
bin->write_at_position(np_pos, n_poly);
- return opres - opres_orig;
+ return (uint)(opres - opres_orig);
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ae7dc336720..7e31d448bdf 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -9238,6 +9238,16 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
mysql_mutex_unlock(&acl_cache->lock);
}
+static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
+{
+ LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data);
+ if (rolename->length == grantee->user.length &&
+ !strcmp(rolename->str, grantee->user.str))
+ return -1; // End search, we've found our role.
+
+ /* Keep looking, we haven't found our role yet. */
+ return 0;
+}
/*
Modify a privilege table.
@@ -11258,7 +11268,6 @@ bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool)
}
#endif /*NO_EMBEDDED_ACCESS_CHECKS */
-
SHOW_VAR acl_statistics[] = {
#ifndef NO_EMBEDDED_ACCESS_CHECKS
{"column_grants", (char*)show_column_grants, SHOW_SIMPLE_FUNC},
@@ -11274,6 +11283,43 @@ SHOW_VAR acl_statistics[] = {
{NullS, NullS, SHOW_LONG},
};
+/* Check if a role is granted to a user/role. We traverse the role graph
+ and return true if we find a match.
+
+ hostname == NULL means we are looking for a role as a starting point,
+ otherwise a user.
+*/
+bool check_role_is_granted(const char *username,
+ const char *hostname,
+ const char *rolename)
+{
+ DBUG_ENTER("check_role_is_granted");
+ bool result= false;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ ACL_USER_BASE *root;
+ mysql_mutex_lock(&acl_cache->lock);
+ if (hostname)
+ root= find_user_exact(username, hostname);
+ else
+ root= find_acl_role(username);
+
+ LEX_CSTRING role_lex;
+ role_lex.str= rolename;
+ role_lex.length= strlen(rolename);
+
+ if (root && /* No grantee, nothing to search. */
+ traverse_role_graph_down(root, &role_lex, check_role_is_granted_callback,
+ NULL) == -1)
+ {
+ /* We have found the role during our search. */
+ result= true;
+ }
+
+ /* We haven't found the role or we had no initial grantee to start from. */
+ mysql_mutex_unlock(&acl_cache->lock);
+#endif
+ DBUG_RETURN(result);
+}
int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond)
{
@@ -12402,7 +12448,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
char *end= user + packet_length;
/* Safe because there is always a trailing \0 at the end of the packet */
char *passwd= strend(user) + 1;
- uint user_len= passwd - user - 1;
+ uint user_len= (uint)(passwd - user - 1);
char *db= passwd;
char db_buff[SAFE_NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
@@ -13662,4 +13708,3 @@ maria_declare_plugin(mysql_password)
MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */
}
maria_declare_plugin_end;
-
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index dacddd603dd..e3dba20422d 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -408,6 +408,14 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
extern SHOW_VAR acl_statistics[];
+/* Check if a role is granted to a user/role.
+
+ If hostname == NULL, search for a role as the starting grantee.
+*/
+bool check_role_is_granted(const char *username,
+ const char *hostname,
+ const char *rolename);
+
#ifndef DBUG_OFF
extern ulong role_global_merges, role_db_merges, role_table_merges,
role_column_merges, role_routine_merges;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index c81ca438bcc..4ed8234aa64 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -67,7 +67,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
if (thd->get_stmt_da()->is_ok())
thd->get_stmt_da()->reset_diagnostics_area();
table_list->table= NULL;
- result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
DBUG_RETURN(result_code);
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e59007d3e5a..7fd6599df51 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3046,6 +3046,46 @@ thr_lock_type read_lock_type_for_table(THD *thd,
/*
+ Extend the prelocking set with tables and routines used by a routine.
+
+ @param[in] thd Thread context.
+ @param[in] rt Element of prelocking set to be processed.
+ @param[in] ot_ctx Context of open_table used to recover from
+ locking failures.
+ @retval false Success.
+ @retval true Failure (Conflicting metadata lock, OOM, other errors).
+*/
+static bool
+sp_acquire_mdl(THD *thd, Sroutine_hash_entry *rt, Open_table_context *ot_ctx)
+{
+ DBUG_ENTER("sp_acquire_mdl");
+ /*
+ Since we acquire only shared lock on routines we don't
+ need to care about global intention exclusive locks.
+ */
+ DBUG_ASSERT(rt->mdl_request.type == MDL_SHARED);
+
+ /*
+ Waiting for a conflicting metadata lock to go away may
+ lead to a deadlock, detected by MDL subsystem.
+ If possible, we try to resolve such deadlocks by releasing all
+ metadata locks and restarting the pre-locking process.
+ To prevent the error from polluting the diagnostics area
+ in case of successful resolution, install a special error
+ handler for ER_LOCK_DEADLOCK error.
+ */
+ MDL_deadlock_handler mdl_deadlock_handler(ot_ctx);
+
+ thd->push_internal_handler(&mdl_deadlock_handler);
+ bool result= thd->mdl_context.acquire_lock(&rt->mdl_request,
+ ot_ctx->get_timeout());
+ thd->pop_internal_handler();
+
+ DBUG_RETURN(result);
+}
+
+
+/*
Handle element of prelocking set other than table. E.g. cache routine
and, if prelocking strategy prescribes so, extend the prelocking set
with tables and routines used by it.
@@ -3099,29 +3139,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
if (rt != (Sroutine_hash_entry*)prelocking_ctx->sroutines_list.first ||
mdl_type != MDL_key::PROCEDURE)
{
- /*
- Since we acquire only shared lock on routines we don't
- need to care about global intention exclusive locks.
- */
- DBUG_ASSERT(rt->mdl_request.type == MDL_SHARED);
-
- /*
- Waiting for a conflicting metadata lock to go away may
- lead to a deadlock, detected by MDL subsystem.
- If possible, we try to resolve such deadlocks by releasing all
- metadata locks and restarting the pre-locking process.
- To prevent the error from polluting the diagnostics area
- in case of successful resolution, install a special error
- handler for ER_LOCK_DEADLOCK error.
- */
- MDL_deadlock_handler mdl_deadlock_handler(ot_ctx);
-
- thd->push_internal_handler(&mdl_deadlock_handler);
- bool result= thd->mdl_context.acquire_lock(&rt->mdl_request,
- ot_ctx->get_timeout());
- thd->pop_internal_handler();
-
- if (result)
+ if (sp_acquire_mdl(thd, rt, ot_ctx))
DBUG_RETURN(TRUE);
DEBUG_SYNC(thd, "after_shared_lock_pname");
@@ -3320,9 +3338,14 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
/*
If this TABLE_LIST object has an associated open TABLE object
(TABLE_LIST::table is not NULL), that TABLE object must be a pre-opened
- temporary table.
+ temporary table or SEQUENCE (see sequence_insert()).
*/
- DBUG_ASSERT(is_temporary_table(tables));
+ DBUG_ASSERT(is_temporary_table(tables) || tables->table->s->sequence);
+ if (tables->sequence && tables->table->s->table_type != TABLE_TYPE_SEQUENCE)
+ {
+ my_error(ER_NOT_SEQUENCE, MYF(0), tables->db, tables->alias);
+ DBUG_RETURN(true);
+ }
}
else if (tables->open_type == OT_TEMPORARY_ONLY)
{
@@ -5479,7 +5502,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
if (field_ptr && *field_ptr)
{
- *cached_field_index_ptr= field_ptr - table->field;
+ *cached_field_index_ptr= (uint)(field_ptr - table->field);
field= *field_ptr;
}
else
@@ -7038,13 +7061,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, enum_mark_columns mark_used_columns,
- List<Item> *sum_func_list, bool allow_sum_func)
+ List<Item> *sum_func_list, List<Item> *pre_fix,
+ bool allow_sum_func)
{
reg2 Item *item;
enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
List_iterator<Item> it(fields);
bool save_is_item_list_lookup;
+ bool make_pre_fix= (pre_fix && (pre_fix->elements == 0));
DBUG_ENTER("setup_fields");
DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array.array()));
@@ -7094,6 +7119,9 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
thd->lex->current_select->cur_pos_in_select_list= 0;
while ((item= it++))
{
+ if (make_pre_fix)
+ pre_fix->push_back(item, thd->stmt_arena->mem_root);
+
if ((!item->fixed && item->fix_fields(thd, it.ref())) ||
(item= *(it.ref()))->check_cols(1))
{
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 7a8d27c9147..bb33af66590 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -159,7 +159,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &item, enum_mark_columns mark_used_columns,
- List<Item> *sum_func_list, bool allow_sum_func);
+ List<Item> *sum_func_list, List<Item> *pre_fix,
+ bool allow_sum_func);
void unfix_fields(List<Item> &items);
bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields,
List<Item> &values, bool ignore_errors, bool update);
@@ -366,7 +367,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
bool res;
thd->lex->select_lex.no_wrap_view_item= TRUE;
res= setup_fields(thd, ref_pointer_array, item, mark_used_columns,
- sum_func_list, allow_sum_func);
+ sum_func_list, NULL, allow_sum_func);
thd->lex->select_lex.no_wrap_view_item= FALSE;
return res;
}
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index e09b1788441..2dc977c9b5d 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -4280,7 +4280,7 @@ my_bool Query_cache::move_by_type(uchar **border,
*pprev = block->pprev,
*pnext = block->pnext,
*new_block =(Query_cache_block *) *border;
- uint tablename_offset = block->table()->table() - block->table()->db();
+ size_t tablename_offset = block->table()->table() - block->table()->db();
char *data = (char*) block->data();
uchar *key;
size_t key_length;
@@ -4589,7 +4589,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path,
filename= tablename + dirname_length(tablename + 2) + 2;
/* Find start of databasename */
for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
- *db_length= (filename - dbname) - 1;
+ *db_length= (uint32)(filename - dbname) - 1;
DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename));
DBUG_RETURN((uint) (strmake(strmake(key, dbname,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5c8a378eacd..889acc57b76 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2406,9 +2406,11 @@ bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
}
-Item_string *THD::make_string_literal(const char *str, size_t length,
- uint repertoire)
+Item *THD::make_string_literal(const char *str, size_t length,
+ uint repertoire)
{
+ if (!length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL))
+ return new (mem_root) Item_null(this, 0, variables.collation_connection);
if (!charset_is_collation_connection &&
(repertoire != MY_REPERTOIRE_ASCII ||
!my_charset_is_ascii_based(variables.collation_connection)))
@@ -2426,6 +2428,57 @@ Item_string *THD::make_string_literal(const char *str, size_t length,
}
+Item *THD::make_string_literal_nchar(const Lex_string_with_metadata_st &str)
+{
+ DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
+ if (!str.length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL))
+ return new (mem_root) Item_null(this, 0, national_charset_info);
+
+ return new (mem_root) Item_string(this, str.str, str.length,
+ national_charset_info,
+ DERIVATION_COERCIBLE,
+ str.repertoire());
+}
+
+
+Item *THD::make_string_literal_charset(const Lex_string_with_metadata_st &str,
+ CHARSET_INFO *cs)
+{
+ if (!str.length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL))
+ return new (mem_root) Item_null(this, 0, cs);
+ return new (mem_root) Item_string_with_introducer(this,
+ str.str, str.length, cs);
+}
+
+
+Item *THD::make_string_literal_concat(Item *item, const LEX_CSTRING &str)
+{
+ if (item->type() == Item::NULL_ITEM)
+ {
+ DBUG_ASSERT(variables.sql_mode & MODE_EMPTY_STRING_IS_NULL);
+ if (str.length)
+ {
+ CHARSET_INFO *cs= variables.collation_connection;
+ uint repertoire= my_string_repertoire(cs, str.str, str.length);
+ return new (mem_root) Item_string(this, str.str, str.length, cs,
+ DERIVATION_COERCIBLE, repertoire);
+ }
+ return item;
+ }
+
+ DBUG_ASSERT(item->type() == Item::STRING_ITEM);
+ DBUG_ASSERT(item->basic_const_item());
+ static_cast<Item_string*>(item)->append(str.str, str.length);
+ if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
+ {
+ // If the string has been pure ASCII so far, check the new part.
+ CHARSET_INFO *cs= variables.collation_connection;
+ item->collation.repertoire|= my_string_repertoire(cs, str.str, str.length);
+ }
+ return item;
+}
+
+
/*
Update some cache variables when character set changes
*/
diff --git a/sql/sql_class.h b/sql/sql_class.h
index bc72fc25a18..fda56c8cc3a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -139,6 +139,7 @@ enum enum_binlog_row_image {
#define MODE_HIGH_NOT_PRECEDENCE (1ULL << 29)
#define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30)
#define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31)
+#define MODE_EMPTY_STRING_IS_NULL (1ULL << 32)
/* Bits for different old style modes */
#define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0)
@@ -3548,14 +3549,17 @@ public:
@param length - length of the string
@param repertoire - the repertoire of the string
*/
- Item_string *make_string_literal(const char *str, size_t length,
- uint repertoire);
- Item_string *make_string_literal(const Lex_string_with_metadata_st &str)
+ Item *make_string_literal(const char *str, size_t length,
+ uint repertoire);
+ Item *make_string_literal(const Lex_string_with_metadata_st &str)
{
uint repertoire= str.repertoire(variables.character_set_client);
return make_string_literal(str.str, str.length, repertoire);
}
-
+ Item *make_string_literal_nchar(const Lex_string_with_metadata_st &str);
+ Item *make_string_literal_charset(const Lex_string_with_metadata_st &str,
+ CHARSET_INFO *cs);
+ Item *make_string_literal_concat(Item *item1, const LEX_CSTRING &str);
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, long key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
diff --git a/sql/sql_const.h b/sql/sql_const.h
index 8d5f56de6b0..a5756aa1f39 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -45,7 +45,18 @@
#define MAX_MBWIDTH 3 /* Max multibyte sequence */
#define MAX_FILENAME_MBWIDTH 5
#define MAX_FIELD_CHARLENGTH 255
-#define MAX_FIELD_VARCHARLENGTH 65535
+/*
+ In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead:
+ - 2 bytes for the length
+ - 1 byte for NULL bits
+ to avoid the "Row size too large" error for these three corner definitions:
+ CREATE TABLE t1 (c VARBINARY(65533));
+ CREATE TABLE t1 (c VARBINARY(65534));
+ CREATE TABLE t1 (c VARBINARY(65535));
+ Like VARCHAR(65536), they will be converted to BLOB automatically
+ in non-sctict mode.
+*/
+#define MAX_FIELD_VARCHARLENGTH (65535-2-1)
#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */
#define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 2047c7c8762..ad37ef36e2c 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -1007,7 +1007,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
been done yet.
*/
if (with_elem && sl->master_unit() == with_elem->spec)
- break;
+ break;
With_clause *with_clause=sl->get_with_clause();
if (with_clause)
{
@@ -1055,13 +1055,21 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
}
with= with_elem;
if (!with_elem->is_referenced() || with_elem->is_recursive)
+ {
derived= with_elem->spec;
+ if (derived->get_master() != select_lex &&
+ !is_with_table_recursive_reference())
+ {
+ derived->move_as_slave(select_lex);
+ }
+ }
else
{
if(!(derived= with_elem->clone_parsed_spec(thd, this)))
return true;
derived->with_element= with_elem;
}
+ derived->first_select()->linkage= DERIVED_TABLE_TYPE;
with_elem->inc_references();
return false;
}
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 4db216a3a41..d41e9acfdc8 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1006,7 +1006,7 @@ update_binlog:
These DDL methods and logging are protected with the exclusive
metadata lock on the schema.
*/
- if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len))
+ if (write_to_binlog(thd, query, (uint)(query_pos -1 - query), db, db_len))
{
error= true;
goto exit;
@@ -1024,7 +1024,7 @@ update_binlog:
These DDL methods and logging are protected with the exclusive
metadata lock on the schema.
*/
- if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len))
+ if (write_to_binlog(thd, query, (uint)(query_pos -1 - query), db, db_len))
{
error= true;
goto exit;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 32ff44d9343..c880374f9ab 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -821,7 +821,7 @@ l
DBUG_RETURN(TRUE);
if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) ||
setup_fields(thd, Ref_ptr_array(),
- field_list, MARK_COLUMNS_READ, NULL, 0) ||
+ field_list, MARK_COLUMNS_READ, NULL, NULL, 0) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index a25bdef3d9d..f556dc282ed 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -29,7 +29,7 @@ bool mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
- if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, NULL, 0))
DBUG_RETURN(TRUE);
while ((value = li++))
(void) value->is_null();
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index e592a873ef0..b12b470209c 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -268,7 +268,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (table_list->is_view())
unfix_fields(fields);
- res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0);
+ res= setup_fields(thd, Ref_ptr_array(),
+ fields, MARK_COLUMNS_WRITE, 0, NULL, 0);
/* Restore the current context. */
ctx_state.restore_state(context, table_list);
@@ -380,7 +381,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
/* Check the fields we are going to modify */
if (setup_fields(thd, Ref_ptr_array(),
- update_fields, MARK_COLUMNS_WRITE, 0, 0))
+ update_fields, MARK_COLUMNS_WRITE, 0, NULL, 0))
return -1;
if (insert_table_list->is_view() &&
@@ -806,7 +807,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto abort;
}
- if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ *values, MARK_COLUMNS_READ, 0, NULL, 0))
goto abort;
switch_to_nullable_trigger_fields(*values, table);
}
@@ -1531,13 +1533,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
context->resolve_in_table_list_only(table_list);
res= (setup_fields(thd, Ref_ptr_array(),
- *values, MARK_COLUMNS_READ, 0, 0) ||
+ *values, MARK_COLUMNS_READ, 0, NULL, 0) ||
check_insert_fields(thd, context->table_list, fields, *values,
!insert_into_view, 0, &map));
if (!res)
res= setup_fields(thd, Ref_ptr_array(),
- update_values, MARK_COLUMNS_READ, 0, 0);
+ update_values, MARK_COLUMNS_READ, 0, NULL, 0);
if (!res && duplic == DUP_UPDATE)
{
@@ -3527,7 +3529,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/
lex->current_select= &lex->select_lex;
- res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) ||
+ res= (setup_fields(thd, Ref_ptr_array(),
+ values, MARK_COLUMNS_READ, 0, NULL, 0) ||
check_insert_fields(thd, table_list, *fields, values,
!insert_into_view, 1, &map));
@@ -3580,7 +3583,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
ctx_state.get_first_name_resolution_table();
res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values,
- MARK_COLUMNS_READ, 0, 0);
+ MARK_COLUMNS_READ, 0, NULL, 0);
if (!res)
{
/*
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 9a7b8f2af21..2f1a81cc2ec 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -407,7 +407,7 @@ void JOIN_CACHE::create_flag_fields()
}
/* Theoretically the new value of flag_fields can be less than the old one */
- flag_fields= copy-field_descr;
+ flag_fields= (uint)(copy-field_descr);
}
@@ -1375,7 +1375,7 @@ uint JOIN_CACHE::write_record_data(uchar * link, bool *is_full)
}
/* Save the offset of the field to put it later at the end of the record */
if (copy->referenced_field_no)
- copy->offset= cp-curr_rec_pos;
+ copy->offset= (uint)(cp-curr_rec_pos);
switch (copy->type) {
case CACHE_BLOB:
@@ -1779,7 +1779,7 @@ uint JOIN_CACHE::read_flag_fields()
memcpy(copy->str, pos, copy->length);
pos+= copy->length;
}
- return (pos-init_pos);
+ return (uint)(pos-init_pos);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b8d51a5783f..ce43a45b872 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2386,6 +2386,30 @@ st_select_lex_node *st_select_lex_node:: insert_chain_before(
return this;
}
+
+/*
+ Detach the node from its master and attach it to a new master
+*/
+
+void st_select_lex_node::move_as_slave(st_select_lex_node *new_master)
+{
+ exclude_from_tree();
+ if (new_master->slave)
+ {
+ st_select_lex_node *curr= new_master->slave;
+ for ( ; curr->next ; curr= curr->next) ;
+ prev= &curr->next;
+ }
+ else
+ {
+ prev= &new_master->slave;
+ new_master->slave= this;
+ }
+ next= 0;
+ master= new_master;
+}
+
+
/*
Exclude a node from the tree lex structure, but leave it in the global
list of nodes.
@@ -4495,7 +4519,8 @@ void st_select_lex::set_explain_type(bool on_the_fly)
pos_in_table_list=NULL for e.g. post-join aggregation JOIN_TABs.
*/
if (tab->table && tab->table->pos_in_table_list &&
- tab->table->pos_in_table_list->with)
+ tab->table->pos_in_table_list->with &&
+ tab->table->pos_in_table_list->with->is_recursive)
{
uses_cte= true;
break;
@@ -5208,15 +5233,73 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars)
thd->variables.collation_database);
}
+
+bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
+ Item *dflt_value_item)
+{
+ if (!dflt_value_item &&
+ !(dflt_value_item= new (thd->mem_root) Item_null(thd)))
+ return true;
+
+ for (uint i= 0 ; i < (uint) nvars ; i++)
+ {
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ bool last= i + 1 == (uint) nvars;
+ spvar->default_value= dflt_value_item;
+ /* The last instruction is responsible for freeing LEX. */
+ sp_instr_set *is= new (this->thd->mem_root)
+ sp_instr_set(sphead->instructions(),
+ spcont, spvar->offset, dflt_value_item,
+ this, last);
+ if (is == NULL || sphead->add_instr(is))
+ return true;
+ }
+ return false;
+}
+
+
+bool
+LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
+ const Column_definition &ref,
+ Row_definition_list *fields,
+ Item *default_value)
+{
+ for (uint i= 0 ; i < (uint) nvars; i++)
+ {
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ spvar->field_def.set_type(ref);
+ if (fields)
+ {
+ DBUG_ASSERT(ref.type_handler() == &type_handler_row);
+ spvar->field_def.set_row_field_definitions(fields);
+ }
+ spvar->field_def.field_name= spvar->name;
+ }
+ if (sp_variable_declarations_set_default(thd, nvars, default_value))
+ return true;
+ spcont->declare_var_boundary(0);
+ return sphead->restore_lex(thd);
+}
+
+
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
- Row_definition_list *row,
Item *dflt_value_item)
{
- if (!dflt_value_item &&
- !(dflt_value_item= new (thd->mem_root) Item_null(thd)))
+ DBUG_ASSERT(cdef);
+ Column_definition tmp(*cdef);
+ if (sphead->fill_spvar_definition(thd, &tmp))
return true;
+ return sp_variable_declarations_copy_type_finalize(thd, nvars, tmp, NULL,
+ dflt_value_item);
+}
+
+bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars,
+ Row_definition_list *row,
+ Item *dflt_value_item)
+{
+ DBUG_ASSERT(row);
/*
Prepare all row fields.
Note, we do it only one time outside of the below loop.
@@ -5229,37 +5312,19 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
...
END;
*/
- if (row && sphead->row_fill_field_definitions(thd, row))
+ if (sphead->row_fill_field_definitions(thd, row))
return true;
for (uint i= 0 ; i < (uint) nvars ; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
- bool last= i + 1 == (uint) nvars;
-
- if (!spvar)
- return true;
-
- spvar->default_value= dflt_value_item;
-
- if (cdef)
- {
- if (!last)
- spvar->field_def.set_column_definition(cdef);
- }
- if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
- return true;
spvar->field_def.set_row_field_definitions(row);
-
- /* The last instruction is responsible for freeing LEX. */
- sp_instr_set *is= new (this->thd->mem_root)
- sp_instr_set(sphead->instructions(),
- spcont, spvar->offset, dflt_value_item,
- this, last);
- if (is == NULL || sphead->add_instr(is))
+ if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name))
return true;
}
+ if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item))
+ return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
}
@@ -5283,57 +5348,76 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL :
spcont->find_cursor(&ref->m_column, &coffp,
false);
+ if (pcursor)
+ return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
+ coffp, def);
+ /*
+ When parsing a qualified identifier chain, the parser does not know yet
+ if it's going to be a qualified column name (for %TYPE),
+ or a qualified table name (for %ROWTYPE). So it collects the chain
+ into Qualified_column_ident.
+ Now we know that it was actually a qualified table name (%ROWTYPE).
+ Create a new Table_ident from Qualified_column_ident,
+ shifting fields as follows:
+ - ref->m_column becomes table_ref->table
+ - ref->table becomes table_ref->db
+ */
+ return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
+ ref->table,
+ ref->m_column,
+ def);
+}
+
- if (!def && !(def= new (thd->mem_root) Item_null(thd)))
+bool
+LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
+ const LEX_CSTRING &db,
+ const LEX_CSTRING &table,
+ Item *def)
+{
+ Table_ident *table_ref;
+ if (!(table_ref= new (thd->mem_root) Table_ident(thd, &db, &table, false)))
+ return true;
+ // Loop through all variables in the same declaration
+ for (uint i= 0 ; i < (uint) nvars; i++)
+ {
+ sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
+ spvar->field_def.set_table_rowtype_ref(table_ref);
+ sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
+ }
+ if (sp_variable_declarations_set_default(thd, nvars, def))
return true;
+ // Make sure sp_rcontext is created using the invoker security context:
+ sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
+ spcont->declare_var_boundary(0);
+ return sphead->restore_lex(thd);
+}
+
+
+bool
+LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
+ uint offset,
+ Item *def)
+{
+ const sp_pcursor *pcursor= spcont->find_cursor(offset);
// Loop through all variables in the same declaration
for (uint i= 0 ; i < (uint) nvars; i++)
{
- bool last= i + 1 == (uint) nvars;
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
- if (pcursor)
- {
- spvar->field_def.set_cursor_rowtype_ref(true);
- sp_instr_cursor_copy_struct *instr=
- new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
- spcont, pcursor->lex(),
- spvar->offset);
- if (instr == NULL || sphead->add_instr(instr))
- return true;
- }
- else
- {
- /*
- When parsing a qualified identifier chain, the parser does not know yet
- if it's going to be a qualified column name (for %TYPE),
- or a qualified table name (for %ROWTYPE). So it collects the chain
- into Qualified_column_ident.
- Now we know that it was actually a qualified table name (%ROWTYPE).
- Create a new Table_ident from Qualified_column_ident,
- shifting fields as follows:
- - ref->m_column becomes table_ref->table
- - ref->table becomes table_ref->db
- */
- Table_ident *table_ref;
- if (!(table_ref= new (thd->mem_root) Table_ident(thd,
- &ref->table,
- &ref->m_column,
- false)))
- return true;
- spvar->field_def.set_table_rowtype_ref(table_ref);
- }
+ spvar->field_def.set_cursor_rowtype_ref(offset);
+ sp_instr_cursor_copy_struct *instr=
+ new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
+ spcont, pcursor->lex(),
+ spvar->offset);
+ if (instr == NULL || sphead->add_instr(instr))
+ return true;
+
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
- spvar->default_value= def;
- /* The last instruction is responsible for freeing LEX. */
- sp_instr_set *is= new (this->thd->mem_root)
- sp_instr_set(sphead->instructions(),
- spcont, spvar->offset, def,
- this, last);
- if (is == NULL || sphead->add_instr(is))
- return true;
}
+ if (sp_variable_declarations_set_default(thd, nvars, def))
+ return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
spcont->declare_var_boundary(0);
@@ -5341,11 +5425,28 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
}
+/*
+ Add declarations for table column and SP variable anchor types:
+ - DECLARE spvar1 TYPE OF db1.table1.column1;
+ - DECLARE spvar1 TYPE OF table1.column1;
+ - DECLARE spvar1 TYPE OF spvar0;
+*/
bool
LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *ref,
Item *def)
{
+ return ref->db.length == 0 && ref->table.length == 0 ?
+ sp_variable_declarations_vartype_finalize(thd, nvars, ref->m_column, def) :
+ sp_variable_declarations_column_type_finalize(thd, nvars, ref, def);
+}
+
+
+bool
+LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
+ Qualified_column_ident *ref,
+ Item *def)
+{
for (uint i= 0 ; i < (uint) nvars; i++)
{
sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i);
@@ -5353,7 +5454,55 @@ LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
spvar->field_def.field_name= spvar->name;
}
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
- return sp_variable_declarations_finalize(thd, nvars, NULL, NULL, def);
+ if (sp_variable_declarations_set_default(thd, nvars, def))
+ return true;
+ spcont->declare_var_boundary(0);
+ return sphead->restore_lex(thd);
+}
+
+
+bool
+LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
+ const LEX_CSTRING &ref,
+ Item *default_value)
+{
+ sp_variable *t;
+ if (!spcont || !(t= spcont->find_variable(&ref, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), ref.str);
+ return true;
+ }
+
+ if (t->field_def.is_cursor_rowtype_ref())
+ {
+ uint offset= t->field_def.cursor_rowtype_offset();
+ return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars,
+ offset,
+ default_value);
+ }
+
+ if (t->field_def.is_column_type_ref())
+ {
+ Qualified_column_ident *tmp= t->field_def.column_type_ref();
+ return sp_variable_declarations_column_type_finalize(thd, nvars, tmp,
+ default_value);
+ }
+
+ if (t->field_def.is_table_rowtype_ref())
+ {
+ const Table_ident *tmp= t->field_def.table_rowtype_ref();
+ return sp_variable_declarations_table_rowtype_finalize(thd, nvars,
+ tmp->db,
+ tmp->table,
+ default_value);
+ }
+
+ // A reference to a scalar or a row variable with an explicit data type
+ return sp_variable_declarations_copy_type_finalize(thd, nvars,
+ t->field_def,
+ t->field_def.
+ row_field_definitions(),
+ default_value);
}
@@ -5421,7 +5570,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd,
if (!(spvar->default_value= new (thd->mem_root) Item_null(thd)))
return NULL;
- spvar->field_def.set_cursor_rowtype_ref(true);
+ spvar->field_def.set_cursor_rowtype_ref(coffset);
if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset,
param_lex, parameters))
@@ -5445,7 +5594,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
{
sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound;
args[i]= new (thd->mem_root)
- Item_splocal(thd, &src->name, src->offset, src->sql_type());
+ Item_splocal(thd, &src->name, src->offset, src->type_handler());
if (args[i] == NULL)
return true;
#ifdef DBUG_ASSERT_EXISTS
@@ -5579,7 +5728,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
{
Item_splocal *splocal= new (thd->mem_root)
Item_splocal(thd, &loop.m_index->name, loop.m_index->offset,
- loop.m_index->sql_type());
+ loop.m_index->type_handler());
if (splocal == NULL)
return true;
#ifdef DBUG_ASSERT_EXISTS
@@ -6350,7 +6499,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
{
if (!(item= new (thd->mem_root)
Item_splocal_row_field_by_name(thd, a, b, spv->offset,
- MYSQL_TYPE_NULL,
+ &type_handler_null,
pos.pos(), pos.length())))
return NULL;
}
@@ -6364,7 +6513,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
if (!(item= new (thd->mem_root)
Item_splocal_row_field(thd, a, b,
spv->offset, row_field_offset,
- def->real_field_type(),
+ def->type_handler(),
pos.pos(), pos.length())))
return NULL;
}
@@ -6533,7 +6682,7 @@ Item *LEX::create_item_limit(THD *thd,
Query_fragment pos(thd, sphead, start, end);
Item_splocal *item;
if (!(item= new (thd->mem_root) Item_splocal(thd, a,
- spv->offset, spv->sql_type(),
+ spv->offset, spv->type_handler(),
pos.pos(), pos.length())))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
@@ -6652,11 +6801,8 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
spv->offset,
pos.pos(),
pos.length()) :
- spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ?
- new (thd->mem_root) Item_splocal_row(thd, name, spv->offset,
- pos.pos(), pos.length()) :
new (thd->mem_root) Item_splocal(thd, name,
- spv->offset, spv->sql_type(),
+ spv->offset, spv->type_handler(),
pos.pos(), pos.length());
if (splocal == NULL)
return NULL;
@@ -7186,6 +7332,22 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
}
+Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b, Item *c)
+{
+ return (thd->variables.sql_mode & MODE_ORACLE) ?
+ new (thd->mem_root) Item_func_substr_oracle(thd, a, b, c) :
+ new (thd->mem_root) Item_func_substr(thd, a, b, c);
+}
+
+
+Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b)
+{
+ return (thd->variables.sql_mode & MODE_ORACLE) ?
+ new (thd->mem_root) Item_func_substr_oracle(thd, a, b) :
+ new (thd->mem_root) Item_func_substr(thd, a, b);
+}
+
+
Item *LEX::make_item_func_replace(THD *thd,
Item *org,
Item *find,
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 5f1f4a397d4..7619353d922 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -612,6 +612,7 @@ public:
}
st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert,
st_select_lex_node *end_chain_node);
+ void move_as_slave(st_select_lex_node *new_master);
friend class st_select_lex_unit;
friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel);
friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
@@ -848,6 +849,7 @@ public:
Group_list_ptrs *group_list_ptrs;
List<Item> item_list; /* list of fields & expressions */
+ List<Item> pre_fix; /* above list before fix_fields */
bool is_item_list_lookup;
/*
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
@@ -3175,26 +3177,34 @@ public:
void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
- Row_definition_list *row,
Item *def);
- bool sp_variable_declarations_finalize(THD *thd, int nvars,
- const Column_definition *cdef,
- Item *def)
- {
- return sp_variable_declarations_finalize(thd, nvars, cdef, NULL, def);
- }
+ bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def);
bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
Row_definition_list *row,
- Item *def)
- {
- return sp_variable_declarations_finalize(thd, nvars, NULL, row, def);
- }
+ Item *def);
bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *col,
Item *def);
bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars,
Qualified_column_ident *,
Item *def);
+ bool sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
+ uint offset,
+ Item *def);
+ bool sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
+ const LEX_CSTRING &db,
+ const LEX_CSTRING &table,
+ Item *def);
+ bool sp_variable_declarations_column_type_finalize(THD *thd, int nvars,
+ Qualified_column_ident *ref,
+ Item *def);
+ bool sp_variable_declarations_vartype_finalize(THD *thd, int nvars,
+ const LEX_CSTRING &name,
+ Item *def);
+ bool sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
+ const Column_definition &ref,
+ Row_definition_list *fields,
+ Item *def);
bool sp_handler_declaration_init(THD *thd, int type);
bool sp_handler_declaration_finalize(THD *thd, int type);
@@ -3336,7 +3346,8 @@ public:
const char *end);
Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace);
-
+ Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c);
+ Item *make_item_func_substr(THD *thd, Item *a, Item *b);
/*
Create a my_var instance for a ROW field variable that was used
as an OUT SP parameter: CALL p1(var.field);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 6cd0b76c66d..cf676d5f706 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -387,21 +387,23 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
in this case.
*/
if (setup_fields(thd, Ref_ptr_array(),
- set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
- setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
+ set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
+ setup_fields(thd, Ref_ptr_array(),
+ set_values, MARK_COLUMNS_READ, 0, NULL, 0))
DBUG_RETURN(TRUE);
}
else
{ // Part field list
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
if (setup_fields(thd, Ref_ptr_array(),
- fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
+ fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
setup_fields(thd, Ref_ptr_array(),
- set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
+ set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) ||
check_that_all_fields_are_given_values(thd, table, table_list))
DBUG_RETURN(TRUE);
/* Fix the expressions in SET clause */
- if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ set_values, MARK_COLUMNS_READ, 0, NULL, 0))
DBUG_RETURN(TRUE);
}
switch_to_nullable_trigger_fields(fields_vars, table);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0c68615f911..2f886d91780 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1424,8 +1424,7 @@ out:
@retval FALSE The statement isn't updating any relevant tables.
*/
-static my_bool deny_updates_if_read_only_option(THD *thd,
- TABLE_LIST *all_tables)
+static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables)
{
DBUG_ENTER("deny_updates_if_read_only_option");
@@ -1447,10 +1446,20 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
- /* a table-to-create is not in the temp table list, needs a special check */
+ /*
+ a table-to-be-created is not in the temp table list yet,
+ so CREATE TABLE needs a special treatment
+ */
if (lex->sql_command == SQLCOM_CREATE_TABLE)
DBUG_RETURN(!lex->tmp_table());
+ /*
+ a table-to-be-dropped might not exist (DROP TEMPORARY TABLE IF EXISTS),
+ cannot use the temp table list either.
+ */
+ if (lex->sql_command == SQLCOM_DROP_TABLE && lex->tmp_table())
+ DBUG_RETURN(FALSE);
+
/* Check if we created or dropped databases */
if ((sql_command_flags[lex->sql_command] & CF_DB_CHANGE))
DBUG_RETURN(TRUE);
@@ -4065,7 +4074,7 @@ mysql_execute_command(THD *thd)
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
partition_info *part_info= thd->lex->part_info;
- if (part_info && !(part_info= thd->lex->part_info->get_clone(thd)))
+ if (part_info && !(part_info= part_info->get_clone(thd)))
{
res= -1;
goto end_with_restore_list;
@@ -4541,7 +4550,7 @@ end_with_restore_list:
if (up_result != 2)
break;
}
- /* Fall through */
+ /* fall through */
case SQLCOM_UPDATE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -4653,7 +4662,7 @@ end_with_restore_list:
DBUG_PRINT("debug", ("Just after generate_incident()"));
}
#endif
- /* fall through */
+ /* fall through */
case SQLCOM_INSERT:
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
@@ -5275,7 +5284,6 @@ end_with_restore_list:
if (res)
break;
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
{
@@ -5309,7 +5317,6 @@ end_with_restore_list:
&lex->spname->m_name);
break;
case SQLCOM_DROP_EVENT:
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (!(res= Events::drop_event(thd,
&lex->spname->m_db, &lex->spname->m_name,
lex->if_exists())))
@@ -5437,11 +5444,10 @@ end_with_restore_list:
}
if (first_table)
{
- if (lex->type == TYPE_ENUM_PROCEDURE ||
- lex->type == TYPE_ENUM_FUNCTION)
+ const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
+ lex->type);
+ if (sph)
{
- const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
- lex->type);
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
@@ -6049,7 +6055,6 @@ end_with_restore_list:
Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
as specified through the thd->lex->create_view->mode flag.
*/
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_create_view(thd, first_table, thd->lex->create_view->mode);
break;
}
@@ -6065,7 +6070,6 @@ end_with_restore_list:
case SQLCOM_CREATE_TRIGGER:
{
/* Conditionally writes to binlog. */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_create_or_drop_trigger(thd, all_tables, 1);
break;
@@ -6073,7 +6077,6 @@ end_with_restore_list:
case SQLCOM_DROP_TRIGGER:
{
/* Conditionally writes to binlog. */
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_create_or_drop_trigger(thd, all_tables, 0);
break;
}
@@ -6138,13 +6141,11 @@ end_with_restore_list:
my_ok(thd);
break;
case SQLCOM_INSTALL_PLUGIN:
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (! (res= mysql_install_plugin(thd, &thd->lex->comment,
&thd->lex->ident)))
my_ok(thd);
break;
case SQLCOM_UNINSTALL_PLUGIN:
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment,
&thd->lex->ident)))
my_ok(thd);
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 3fc49dc42ca..fadd7009822 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2005, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+/* Copyright (c) 2005, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2017, SkySQL 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
@@ -6561,7 +6561,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->alter_info= alter_info;
lpt->create_info= create_info;
lpt->db_options= create_info->table_options;
- if (create_info->row_type == ROW_TYPE_DYNAMIC)
+ if (create_info->row_type != ROW_TYPE_FIXED &&
+ create_info->row_type != ROW_TYPE_DEFAULT)
lpt->db_options|= HA_OPTION_PACK_RECORD;
lpt->table= table;
lpt->key_info_buffer= 0;
@@ -8073,6 +8074,7 @@ int create_partition_name(char *out, size_t outlen, const char *in1,
}
else
transl_part= in2;
+
if (name_variant == NORMAL_PART_NAME)
end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS);
else if (name_variant == TEMP_PART_NAME)
@@ -8087,25 +8089,19 @@ int create_partition_name(char *out, size_t outlen, const char *in1,
return 0;
}
-
-/*
- Create subpartition name
-
- SYNOPSIS
- create_subpartition_name()
- out:out The buffer for the created partition name string
- must be *at least* of FN_REFLEN+1 bytes
- in1 First part
- in2 Second part
- in3 Third part
- name_variant Normal, temporary or renamed partition name
-
- RETURN VALUE
- 0 if ok, error if name too long
-
- DESCRIPTION
- This method is used to calculate the subpartition name, service routine to
- the del_ren_cre_table method.
+/**
+ Create subpartition name. This method is used to calculate the
+ subpartition name, service routine to the del_ren_cre_table method.
+ The output buffer size should be FN_REFLEN + 1(terminating '\0').
+
+ @param [out] out Created partition name string
+ @param in1 First part
+ @param in2 Second part
+ @param in3 Third part
+ @param name_variant Normal, temporary or renamed partition name
+
+ @retval true Error.
+ @retval false Success.
*/
int create_subpartition_name(char *out, size_t outlen,
@@ -8117,6 +8113,7 @@ int create_subpartition_name(char *out, size_t outlen,
tablename_to_filename(in2, transl_part_name, FN_REFLEN);
tablename_to_filename(in3, transl_subpart_name, FN_REFLEN);
+
if (name_variant == NORMAL_PART_NAME)
end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name,
"#SP#", transl_subpart_name, NullS);
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index b0dede7487e..992229afb05 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -1,7 +1,8 @@
#ifndef SQL_PARTITION_INCLUDED
#define SQL_PARTITION_INCLUDED
-/* Copyright (c) 2006, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2006, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2017, MariaDB
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_plugin.cc b/sql/sql_plugin.cc
index a4e6546e38a..9478db8e6d5 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -228,7 +228,6 @@ static DYNAMIC_ARRAY plugin_array;
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
static MEM_ROOT plugin_mem_root;
static bool reap_needed= false;
-static int plugin_array_version=0;
static bool initialized= 0;
ulong dlopen_count;
@@ -323,7 +322,6 @@ static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(struct system_variables *vars);
static void plugin_vars_free_values(sys_var *vars);
static void restore_ptr_backup(uint n, st_ptr_backup *backup);
-static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
static void reap_plugins(void);
@@ -951,15 +949,17 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type)
If LEX is passed non-NULL, an automatic unlock of the plugin will happen
in the LEX destructor.
*/
-static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc)
+static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc,
+ uint state_mask= PLUGIN_IS_READY |
+ PLUGIN_IS_UNINITIALIZED |
+ PLUGIN_IS_DELETED)
{
st_plugin_int *pi= plugin_ref_to_int(rc);
DBUG_ENTER("intern_plugin_lock");
mysql_mutex_assert_owner(&LOCK_plugin);
- if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED |
- PLUGIN_IS_DELETED))
+ if (pi->state & state_mask)
{
plugin_ref plugin;
#ifdef DBUG_OFF
@@ -1174,7 +1174,6 @@ static bool plugin_add(MEM_ROOT *tmp_root,
if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
goto err;
- plugin_array_version++;
if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr))
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096, MYF(0));
@@ -1274,7 +1273,6 @@ static void plugin_del(struct st_plugin_int *plugin)
my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin);
plugin_dl_del(plugin->plugin_dl);
plugin->state= PLUGIN_IS_FREED;
- plugin_array_version++;
free_root(&plugin->mem_root, MYF(0));
}
else
@@ -1893,11 +1891,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
switch ((*(p++)= *(list++))) {
case '\0':
list= NULL; /* terminate the loop */
-#ifndef __WIN__
/* fall through */
+ case ';':
+#ifndef __WIN__
case ':': /* can't use this as delimiter as it may be drive letter */
#endif
- case ';':
str->str[str->length]= '\0';
if (str == &name) // load all plugins in named module
{
@@ -2158,12 +2156,16 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
bool error;
int argc=orig_argc;
char **argv=orig_argv;
+ unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
+ { MYSQL_AUDIT_GENERAL_CLASSMASK };
DBUG_ENTER("mysql_install_plugin");
tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE);
if (!opt_noacl && check_table_access(thd, INSERT_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
/* need to open before acquiring LOCK_plugin or it will deadlock */
if (! (table = open_ltable(thd, &tables, TL_WRITE,
MYSQL_LOCK_IGNORE_TIMEOUT)))
@@ -2196,8 +2198,6 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
See also mysql_uninstall_plugin() and initialize_audit_plugin()
*/
- unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
- { MYSQL_AUDIT_GENERAL_CLASSMASK };
if (mysql_audit_general_enabled())
mysql_audit_acquire_plugins(thd, event_class_mask);
@@ -2229,6 +2229,10 @@ err:
if (argv)
free_defaults(argv);
DBUG_RETURN(error);
+#ifdef WITH_WSREP
+error:
+ DBUG_RETURN(TRUE);
+#endif /* WITH_WSREP */
}
@@ -2295,6 +2299,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
TABLE_LIST tables;
LEX_CSTRING dl= *dl_arg;
bool error= false;
+ unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
+ { MYSQL_AUDIT_GENERAL_CLASSMASK };
DBUG_ENTER("mysql_uninstall_plugin");
tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE);
@@ -2302,6 +2308,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
/* need to open before acquiring LOCK_plugin or it will deadlock */
if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT)))
DBUG_RETURN(TRUE);
@@ -2327,8 +2335,6 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
See also mysql_install_plugin() and initialize_audit_plugin()
*/
- unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] =
- { MYSQL_AUDIT_GENERAL_CLASSMASK };
if (mysql_audit_general_enabled())
mysql_audit_acquire_plugins(thd, event_class_mask);
@@ -2359,70 +2365,65 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name,
mysql_mutex_unlock(&LOCK_plugin);
DBUG_RETURN(error);
+#ifdef WITH_WSREP
+error:
+ DBUG_RETURN(TRUE);
+#endif /* WITH_WSREP */
}
bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
int type, uint state_mask, void *arg)
{
- uint idx, total;
- struct st_plugin_int *plugin, **plugins;
- int version=plugin_array_version;
+ uint idx, total= 0;
+ struct st_plugin_int *plugin;
+ plugin_ref *plugins;
+ my_bool res= FALSE;
DBUG_ENTER("plugin_foreach_with_mask");
if (!initialized)
DBUG_RETURN(FALSE);
- state_mask= ~state_mask; // do it only once
-
mysql_mutex_lock(&LOCK_plugin);
- total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements
- : plugin_hash[type].records;
/*
Do the alloca out here in case we do have a working alloca:
- leaving the nested stack frame invalidates alloca allocation.
+ leaving the nested stack frame invalidates alloca allocation.
*/
- plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin));
if (type == MYSQL_ANY_PLUGIN)
{
- for (idx= 0; idx < total; idx++)
+ plugins= (plugin_ref*) my_alloca(plugin_array.elements * sizeof(plugin_ref));
+ for (idx= 0; idx < plugin_array.elements; idx++)
{
plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **);
- plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
+ if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin),
+ state_mask)))
+ total++;
}
}
else
{
HASH *hash= plugin_hash + type;
- for (idx= 0; idx < total; idx++)
+ plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref));
+ for (idx= 0; idx < hash->records; idx++)
{
plugin= (struct st_plugin_int *) my_hash_element(hash, idx);
- plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL;
+ if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin),
+ state_mask)))
+ total++;
}
}
mysql_mutex_unlock(&LOCK_plugin);
for (idx= 0; idx < total; idx++)
{
- if (unlikely(version != plugin_array_version))
- {
- mysql_mutex_lock(&LOCK_plugin);
- for (uint i=idx; i < total; i++)
- if (plugins[i] && plugins[i]->state & state_mask)
- plugins[i]=0;
- mysql_mutex_unlock(&LOCK_plugin);
- }
- plugin= plugins[idx];
/* It will stop iterating on first engine error when "func" returns TRUE */
- if (plugin && func(thd, plugin_int_to_ref(plugin), arg))
- goto err;
+ if ((res= func(thd, plugins[idx], arg)))
+ break;
}
+ plugin_unlock_list(0, plugins, total);
my_afree(plugins);
- DBUG_RETURN(FALSE);
-err:
- my_afree(plugins);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(res);
}
@@ -3550,7 +3551,6 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)
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)
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 7fc6141bcea..775717fe62b 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -725,13 +725,36 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
#endif /*!EMBEDDED_LIBRARY*/
-static void set_param_str(Item_param *param, uchar **pos, ulong len)
+static void set_param_str_or_null(Item_param *param, uchar **pos, ulong len,
+ bool empty_string_is_null)
{
ulong length= get_param_length(pos, len);
- if (length > len)
- length= len;
- param->set_str((const char *)*pos, length);
- *pos+= length;
+ if (length == 0 && empty_string_is_null)
+ param->set_null();
+ else
+ {
+ if (length > len)
+ length= len;
+ param->set_str((const char *) *pos, length);
+ *pos+= length;
+ }
+}
+
+
+static void set_param_str(Item_param *param, uchar **pos, ulong len)
+{
+ set_param_str_or_null(param, pos, len, false);
+}
+
+
+/*
+ set_param_str_empty_is_null : bind empty string as null value
+ when sql_mode=MODE_EMPTY_STRING_IS_NULL
+*/
+static void set_param_str_empty_is_null(Item_param *param, uchar **pos,
+ ulong len)
+{
+ set_param_str_or_null(param, pos, len, true);
}
@@ -806,7 +829,10 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
param->value.cs_info.final_character_set_of_str_value=
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
tocs : fromcs;
- param->set_param_func= set_param_str;
+
+ param->set_param_func=
+ (thd->variables.sql_mode & MODE_EMPTY_STRING_IS_NULL) ?
+ set_param_str_empty_is_null : set_param_str;
/*
Exact value of max_length is not known unless data is converted to
charset of connection, so we have to set it later.
@@ -1365,7 +1391,8 @@ static bool mysql_test_insert(Prepared_statement *stmt,
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto error;
}
- if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(),
+ *values, MARK_COLUMNS_NONE, 0, NULL, 0))
goto error;
}
}
@@ -1459,7 +1486,7 @@ static int mysql_test_update(Prepared_statement *stmt,
#endif
thd->lex->select_lex.no_wrap_view_item= TRUE;
res= setup_fields(thd, Ref_ptr_array(),
- select->item_list, MARK_COLUMNS_READ, 0, 0);
+ select->item_list, MARK_COLUMNS_READ, 0, NULL, 0);
thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res)
goto error;
@@ -1471,7 +1498,7 @@ static int mysql_test_update(Prepared_statement *stmt,
table_list->register_want_access(SELECT_ACL);
#endif
if (setup_fields(thd, Ref_ptr_array(),
- stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) ||
+ stmt->lex->value_list, MARK_COLUMNS_NONE, 0, NULL, 0) ||
check_unique_table(thd, table_list))
goto error;
/* TODO: here we should send types of placeholders to the client. */
@@ -1646,7 +1673,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
DT_PREPARE | DT_CREATE))
DBUG_RETURN(TRUE);
DBUG_RETURN(setup_fields(thd, Ref_ptr_array(),
- *values, MARK_COLUMNS_NONE, 0, 0));
+ *values, MARK_COLUMNS_NONE, 0, NULL, 0));
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 49e3d60795d..839b98dc785 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2680,7 +2680,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
Gtid_list_log_event glev(&info->until_binlog_state, 0);
if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg) ||
- fake_gtid_list_event(info, &glev, &info->errmsg, my_b_tell(log)))
+ fake_gtid_list_event(info, &glev, &info->errmsg, (uint32)my_b_tell(log)))
{
info->error= ER_UNKNOWN_ERROR;
return 1;
@@ -2690,7 +2690,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
if (info->until_gtid_state &&
is_until_reached(info, &ev_offset, event_type, &info->errmsg,
- my_b_tell(log)))
+ (uint32)my_b_tell(log)))
{
if (info->errmsg)
{
@@ -2745,7 +2745,7 @@ static int send_one_binlog_file(binlog_send_info *info,
if (end_pos <= 1)
{
/** end of file or error */
- return end_pos;
+ return (int)end_pos;
}
/**
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 394492f6a1d..53d445177f7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -809,7 +809,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
thd->lex->current_select->context_analysis_place;
thd->lex->current_select->context_analysis_place= SELECT_LIST;
if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
- &all_fields, 1))
+ &all_fields, &select_lex->pre_fix, 1))
DBUG_RETURN(-1);
thd->lex->current_select->context_analysis_place= save_place;
@@ -6144,7 +6144,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint,
{
TABLE *table= s->table;
double sel= table->cond_selectivity;
- double table_records= table->stat_records();
+ double table_records= (double)table->stat_records();
dbl_records= table_records * sel;
return dbl_records;
}
@@ -6170,7 +6170,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint,
if (s->table->quick_condition_rows != s->found_records)
records= s->table->quick_condition_rows;
- dbl_records= records;
+ dbl_records= (double)records;
return dbl_records;
}
@@ -6861,7 +6861,7 @@ static void choose_initial_table_order(JOIN *join)
if ((emb_subq= get_emb_subq(*tab)))
break;
}
- uint n_subquery_tabs= tabs_end - tab;
+ uint n_subquery_tabs= (uint)(tabs_end - tab);
if (!n_subquery_tabs)
DBUG_VOID_RETURN;
@@ -6889,7 +6889,7 @@ static void choose_initial_table_order(JOIN *join)
last_tab_for_subq < subq_tabs_end &&
get_emb_subq(*last_tab_for_subq) == cur_subq_nest;
last_tab_for_subq++) {}
- uint n_subquery_tables= last_tab_for_subq - subq_tab;
+ uint n_subquery_tables= (uint)(last_tab_for_subq - subq_tab);
/*
Walk the original array and find where this subquery would have been
@@ -6907,7 +6907,7 @@ static void choose_initial_table_order(JOIN *join)
if (!need_tables)
{
/* Move away the top-level tables that are after top_level_tab */
- uint top_tail_len= last_top_level_tab - top_level_tab - 1;
+ size_t top_tail_len= last_top_level_tab - top_level_tab - 1;
memmove(top_level_tab + 1 + n_subquery_tables, top_level_tab + 1,
sizeof(JOIN_TAB*)*top_tail_len);
last_top_level_tab += n_subquery_tables;
@@ -7653,7 +7653,7 @@ double JOIN::get_examined_rows()
JOIN_TAB *tab= first_breadth_first_tab();
JOIN_TAB *prev_tab= tab;
- examined_rows= tab->get_examined_rows();
+ examined_rows= (double)tab->get_examined_rows();
while ((tab= next_breadth_first_tab(first_breadth_first_tab(),
top_join_tab_count, tab)))
@@ -7951,7 +7951,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
}
if (keyparts > 1)
{
- ref_keyuse_steps[keyparts-2]= keyuse - prev_ref_keyuse;
+ ref_keyuse_steps[keyparts-2]= (uint16)(keyuse - prev_ref_keyuse);
prev_ref_keyuse= keyuse;
}
}
@@ -8192,9 +8192,11 @@ best_extension_by_limited_search(JOIN *join,
best_access_path(join, s, remaining_tables, idx, disable_jbuf,
record_count, join->positions + idx, &loose_scan_pos);
- /* Compute the cost of extending the plan with 's' */
-
- current_record_count= record_count * position->records_read;
+ /* Compute the cost of extending the plan with 's', avoid overflow */
+ if (position->records_read < DBL_MAX / record_count)
+ current_record_count= record_count * position->records_read;
+ else
+ current_record_count= DBL_MAX;
current_read_time=read_time + position->read_time +
current_record_count / (double) TIME_FOR_COMPARE;
@@ -9313,8 +9315,8 @@ bool JOIN::get_best_combination()
j= j->bush_root_tab;
}
- top_join_tab_count= join_tab_ranges.head()->end -
- join_tab_ranges.head()->start;
+ top_join_tab_count= (uint)(join_tab_ranges.head()->end -
+ join_tab_ranges.head()->start);
update_depend_map(this);
DBUG_RETURN(0);
@@ -10891,7 +10893,7 @@ static uint make_join_orderinfo(JOIN *join)
if (join->need_tmp)
return join->table_count;
tab= join->get_sort_by_join_tab();
- return tab ? tab-join->join_tab : join->table_count;
+ return tab ? (uint)(tab-join->join_tab) : join->table_count;
}
/*
@@ -11908,8 +11910,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
str.append(" final_pushdown_cond");
print_where(tab->select_cond, str.c_ptr_safe(), QT_ORDINARY););
}
- uint n_top_tables= join->join_tab_ranges.head()->end -
- join->join_tab_ranges.head()->start;
+ uint n_top_tables= (uint)(join->join_tab_ranges.head()->end -
+ join->join_tab_ranges.head()->start);
join->join_tab[n_top_tables - 1].next_select=0; /* Set by do_select */
@@ -12133,7 +12135,7 @@ ha_rows JOIN_TAB::get_examined_rows()
SQL_SELECT *sel= filesort? filesort->select : this->select;
if (sel && sel->quick && use_quick != 2)
- examined_rows= sel->quick->records;
+ examined_rows= (double)sel->quick->records;
else if (type == JT_NEXT || type == JT_ALL ||
type == JT_HASH || type ==JT_HASH_NEXT)
{
@@ -12143,19 +12145,19 @@ ha_rows JOIN_TAB::get_examined_rows()
@todo This estimate is wrong, a LIMIT query may examine much more rows
than the LIMIT itself.
*/
- examined_rows= limit;
+ examined_rows= (double)limit;
}
else
{
if (table->is_filled_at_execution())
- examined_rows= records;
+ examined_rows= (double)records;
else
{
/*
handler->info(HA_STATUS_VARIABLE) has been called in
make_join_statistics()
*/
- examined_rows= table->stat_records();
+ examined_rows= (double)table->stat_records();
}
}
}
@@ -13984,7 +13986,7 @@ static int compare_fields_by_table_order(Item *field1,
tab2= tab2->bush_root_tab;
}
- cmp= tab1 - tab2;
+ cmp= (int)(tab1 - tab2);
if (!cmp)
{
@@ -15008,10 +15010,23 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
nested_join= table->nested_join;
if (table->sj_on_expr && !in_sj)
{
- /*
- If this is a semi-join that is not contained within another semi-join,
- leave it intact (otherwise it is flattened)
- */
+ /*
+ If this is a semi-join that is not contained within another semi-join
+ leave it intact (otherwise it is flattened)
+ */
+ /*
+ Make sure that any semi-join appear in
+ the join->select_lex->sj_nests list only once
+ */
+ List_iterator_fast<TABLE_LIST> sj_it(join->select_lex->sj_nests);
+ TABLE_LIST *sj_nest;
+ while ((sj_nest= sj_it++))
+ {
+ if (table == sj_nest)
+ break;
+ }
+ if (sj_nest)
+ continue;
join->select_lex->sj_nests.push_back(table, join->thd->mem_root);
/*
@@ -17146,7 +17161,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
share->default_values= table->record[1]+alloc_length;
}
copy_func[0]=0; // End marker
- param->func_count= copy_func - param->items_to_copy;
+ param->func_count= (uint)(copy_func - param->items_to_copy);
setup_tmp_table_column_bitmaps(table, bitmaps);
@@ -17830,7 +17845,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
Emulate behaviour by making column not-nullable when creating the
table.
*/
- uint cols= (*recinfo-start_recinfo);
+ uint cols= (uint)(*recinfo-start_recinfo);
start_recinfo[cols-1].null_bit= 0;
}
}
@@ -21055,7 +21070,7 @@ static int test_if_order_by_key(JOIN *join,
(1) this is an extended key
(2) we've reached its end
*/
- key_parts= (key_part - table->key_info[idx].key_part);
+ key_parts= (uint)(key_part - table->key_info[idx].key_part);
if (have_pk_suffix &&
reverse == 0 && // all were =const so far
key_parts == table->key_info[idx].ext_key_parts &&
@@ -24696,7 +24711,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta,
}
else
{
- double examined_rows= get_examined_rows();
+ double examined_rows= (double)get_examined_rows();
eta->rows_set= true;
eta->rows= (ha_rows) examined_rows;
@@ -26081,8 +26096,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
Start from quick select's rows and cost. These are always cheaper than
full index scan/cost.
*/
- double best_rows= table->quick_rows[keynr];
- double best_cost= table->quick_costs[keynr];
+ double best_rows= (double)table->quick_rows[keynr];
+ double best_cost= (double)table->quick_costs[keynr];
/*
Check if ref(const) access was possible on this index.
@@ -26116,7 +26131,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
if (ref_rows > 0)
{
- double tmp= ref_rows;
+ double tmp= (double)ref_rows;
/* Reuse the cost formula from best_access_path: */
set_if_smaller(tmp, (double) tab->join->thd->variables.max_seeks_for_key);
if (table->covering_keys.is_set(keynr))
@@ -26127,7 +26142,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab,
if (tmp < best_cost)
{
best_cost= tmp;
- best_rows= ref_rows;
+ best_rows= (double)ref_rows;
}
}
}
@@ -26240,7 +26255,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
if (join)
{
- uint tablenr= tab - join->join_tab;
+ uint tablenr= (uint)(tab - join->join_tab);
read_time= join->best_positions[tablenr].read_time;
for (uint i= tablenr+1; i < join->table_count; i++)
fanout*= join->best_positions[i].records_read; // fanout is always >= 1
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 53c9c160593..1af37fe1fad 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -335,7 +335,6 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list)
trans_commit_implicit(thd);
if (!temporary_table)
close_thread_tables(thd);
- thd->mdl_context.release_transactional_locks();
DBUG_RETURN(error);
}
@@ -596,12 +595,6 @@ int sequence_definition::write(TABLE *table, bool all_fields)
else
table->rpl_write_set= &table->s->all_set;
- /*
- The following is needed to fix comparison of rows in
- ha_update_first_row() for InnoDB
- */
- memcpy(table->record[1],table->s->default_values, table->s->reclength);
-
/* Update table */
save_write_set= table->write_set;
save_read_set= table->read_set;
@@ -759,12 +752,12 @@ void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
@param in table Sequence table
@param in next_val Next free value
- @param in next_round Round for 'next_value' (in cace of cycles)
+ @param in next_round Round for 'next_value' (in case of cycles)
@param in is_used 1 if next_val is already used
@retval 0 ok, value adjusted
- 1 value was less than current value or
- error when storing value
+ -1 value was less than current value
+ 1 error when storing value
@comment
A new value is set only if "nextval,next_round" is less than
@@ -774,10 +767,10 @@ void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
contain the highest used value when the slave is promoted to a master.
*/
-bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
+int SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
bool is_used)
{
- bool error= 1;
+ int error= -1;
bool needs_to_be_stored= 0;
longlong org_reserved_until= reserved_until;
longlong org_next_free_value= next_free_value;
@@ -789,13 +782,13 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
next_val= increment_value(next_val);
if (round > next_round)
- goto end;
+ goto end; // error = -1
if (round == next_round)
{
if (real_increment > 0 ?
next_val < next_free_value :
next_val > next_free_value)
- goto end;
+ goto end; // error = -1
if (next_val == next_free_value)
{
error= 0;
@@ -803,7 +796,13 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
}
}
else if (cycle == 0)
- goto end; // round < next_round && no cycles
+ {
+ // round < next_round && no cycles, which is impossible
+ my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
+ table->s->table_name.str);
+ error= 1;
+ goto end;
+ }
else
needs_to_be_stored= 1;
@@ -820,6 +819,7 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
reserved_until= org_reserved_until;
next_free_value= org_next_free_value;
round= org_round;
+ error= 1;
goto end;
}
}
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
index b61e4ffe40d..2d609d8591b 100644
--- a/sql/sql_sequence.h
+++ b/sql/sql_sequence.h
@@ -105,8 +105,8 @@ public:
all_values_used= 0;
}
longlong next_value(TABLE *table, bool second_round, int *error);
- bool set_value(TABLE *table, longlong next_value, ulonglong round_arg,
- bool is_used);
+ int set_value(TABLE *table, longlong next_value, ulonglong round_arg,
+ bool is_used);
longlong increment_value(longlong value)
{
if (real_increment > 0)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index de928fe9e85..cd08959cc26 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -142,6 +142,12 @@ bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *)
** List all table types supported
***************************************************************************/
+
+static bool is_show_command(THD *thd)
+{
+ return sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND;
+}
+
static int make_version_string(char *buf, int buf_length, uint version)
{
return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
@@ -281,7 +287,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE *table= tables->table;
if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
- ~PLUGIN_IS_FREED, table))
+ ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), table))
DBUG_RETURN(1);
DBUG_RETURN(0);
@@ -989,13 +995,20 @@ find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db,
if (tl.add_file(file->name))
goto err;
}
- tl.sort();
}
else
{
if (ha_discover_table_names(thd, db, dirp, &tl, false))
goto err;
}
+#if 1 // TODO: MDEV-13049: #if MYSQL_VERSION_ID < 100300
+ /* incomplete optimization, but a less drastic change in GA version */
+ if (!thd->lex->select_lex.order_list.elements &&
+ !thd->lex->select_lex.group_list.elements)
+#else
+ if (is_show_command(thd))
+#endif
+ tl.sort();
DBUG_PRINT("info",("found: %zu files", files->elements()));
my_dirend(dirp);
@@ -3460,7 +3473,7 @@ static bool show_status_array(THD *thd, const char *wild,
prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
if (*prefix)
*prefix_end++= '_';
- len=name_buffer + sizeof(name_buffer) - prefix_end;
+ len=(int)(name_buffer + sizeof(name_buffer) - prefix_end);
#ifdef WITH_WSREP
bool is_wsrep_var= FALSE;
@@ -3803,6 +3816,15 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
return 0;
}
}
+ else if (item->type() == Item::ROW_ITEM)
+ {
+ Item_row *item_row= static_cast<Item_row*>(item);
+ for (uint i= 0; i < item_row->cols(); i++)
+ {
+ if (!uses_only_table_name_fields(item_row->element_index(i), table))
+ return 0;
+ }
+ }
else if (item->type() == Item::FIELD_ITEM)
{
Item_field *item_field= (Item_field*)item;
@@ -3822,6 +3844,11 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
item_field->field_name.length)))
return 0;
}
+ else if (item->type() == Item::EXPR_CACHE_ITEM)
+ {
+ Item_cache_wrapper *tmp= static_cast<Item_cache_wrapper*>(item);
+ return uses_only_table_name_fields(tmp->get_orig_item(), table);
+ }
else if (item->type() == Item::REF_ITEM)
return uses_only_table_name_fields(item->real_item(), table);
@@ -4216,7 +4243,7 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names,
*/
if (res == FIND_FILES_DIR)
{
- if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)
+ if (is_show_command(thd))
return 1;
thd->clear_error();
return 2;
@@ -5435,7 +5462,7 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
*/
tmp_buff= strchr(column_type.c_ptr_safe(), ' ');
table->field[offset]->store(column_type.ptr(),
- (tmp_buff ? tmp_buff - column_type.ptr() :
+ (tmp_buff ? (uint)(tmp_buff - column_type.ptr()) :
column_type.length()), cs);
is_blob= (field->type() == MYSQL_TYPE_BLOB);
@@ -5757,7 +5784,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_ENTER("fill_schema_engines");
if (plugin_foreach_with_mask(thd, iter_schema_engines,
MYSQL_STORAGE_ENGINE_PLUGIN,
- ~PLUGIN_IS_FREED, tables->table))
+ ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING),
+ tables->table))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
@@ -6017,11 +6045,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
check_some_routine_access(thd, db.str, name.str, sph))
return 0;
- if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
- sph->type() == TYPE_ENUM_PROCEDURE) ||
- (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
- sph->type() == TYPE_ENUM_FUNCTION) ||
- (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
+ if (!is_show_command(thd) ||
+ sph == Sp_handler::handler(lex->sql_command))
{
restore_record(table, s->default_values);
if (!wild || !wild[0] || !wild_case_compare(system_charset_info,
@@ -6147,6 +6172,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(1);
}
+ /* Disable padding temporarily so it doesn't break the query */
+ ulonglong sql_mode_was = thd->variables.sql_mode;
+ thd->variables.sql_mode &= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+
if (proc_table->file->ha_index_init(0, 1))
{
res= 1;
@@ -6182,6 +6211,7 @@ err:
(void) proc_table->file->ha_index_end();
close_system_tables(thd, &open_tables_state_backup);
+ thd->variables.sql_mode = sql_mode_was;
DBUG_RETURN(res);
}
@@ -6405,7 +6435,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
table->field[5]->store(STRING_WITH_LEN("NO"), cs);
}
- definer_len= (strxmov(definer, tables->definer.user.str, "@",
+ definer_len= (uint)(strxmov(definer, tables->definer.user.str, "@",
tables->definer.host.str, NullS) - definer);
table->field[6]->store(definer, definer_len, cs);
if (tables->view_suid)
@@ -7769,7 +7799,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
tmp_table_param->field_count= field_count;
tmp_table_param->schema_table= 1;
SELECT_LEX *select_lex= thd->lex->current_select;
- bool keep_row_order= sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND;
+ bool keep_row_order= is_show_command(thd);
if (!(table= create_tmp_table(thd, tmp_table_param,
field_list, (ORDER*) 0, 0, 0,
(select_lex->options | thd->variables.option_bits |
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 0048e525cad..2cb47634fe4 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -849,7 +849,7 @@ public:
else
{
stat_field->set_notnull();
- stat_field->store(table->collected_stats->cardinality);
+ stat_field->store(table->collected_stats->cardinality,true);
}
}
@@ -1060,7 +1060,7 @@ public:
switch (i) {
case COLUMN_STAT_MIN_VALUE:
if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->min_value->val_int());
+ stat_field->store(table_field->collected_stats->min_value->val_int(),true);
else
{
table_field->collected_stats->min_value->val_str(&val);
@@ -1069,7 +1069,7 @@ public:
break;
case COLUMN_STAT_MAX_VALUE:
if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->max_value->val_int());
+ stat_field->store(table_field->collected_stats->max_value->val_int(),true);
else
{
table_field->collected_stats->max_value->val_str(&val);
@@ -1636,7 +1636,7 @@ public:
of the parameters to be passed to the constructor of the Unique object.
*/
- Count_distinct_field(Field *field, uint max_heap_table_size)
+ Count_distinct_field(Field *field, size_t max_heap_table_size)
{
table_field= field;
tree_key_length= field->pack_length();
@@ -1734,7 +1734,7 @@ class Count_distinct_field_bit: public Count_distinct_field
{
public:
- Count_distinct_field_bit(Field *field, uint max_heap_table_size)
+ Count_distinct_field_bit(Field *field, size_t max_heap_table_size)
{
table_field= field;
tree_key_length= sizeof(ulonglong);
@@ -1830,7 +1830,7 @@ public:
if ((calc_state=
(Prefix_calc_state *) thd->alloc(sizeof(Prefix_calc_state)*key_parts)))
{
- uint keyno= key_info-table->key_info;
+ uint keyno= (uint)(key_info-table->key_info);
for (i= 0, state= calc_state; i < key_parts; i++, state++)
{
/*
@@ -2444,7 +2444,7 @@ int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share,
inline
void Column_statistics_collected::init(THD *thd, Field *table_field)
{
- uint max_heap_table_size= thd->variables.max_heap_table_size;
+ size_t max_heap_table_size= (size_t)thd->variables.max_heap_table_size;
TABLE *table= table_field->table;
uint pk= table->s->primary_key;
@@ -3725,14 +3725,14 @@ double get_column_avg_frequency(Field * field)
*/
if (!table->s->field)
{
- res= table->stat_records();
+ res= (double)table->stat_records();
return res;
}
Column_statistics *col_stats= field->read_stats;
if (!col_stats)
- res= table->stat_records();
+ res= (double)table->stat_records();
else
res= col_stats->get_avg_frequency();
return res;
@@ -3771,7 +3771,7 @@ double get_column_range_cardinality(Field *field,
double res;
TABLE *table= field->table;
Column_statistics *col_stats= field->read_stats;
- double tab_records= table->stat_records();
+ double tab_records= (double)table->stat_records();
if (!col_stats)
return tab_records;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 724389592e3..7371889cc7f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -230,7 +230,7 @@ uint explain_filename(THD* thd,
{
db_name= table_name;
/* calculate the length */
- db_name_len= tmp_p - db_name;
+ db_name_len= (int)(tmp_p - db_name);
tmp_p++;
table_name= tmp_p;
}
@@ -252,7 +252,7 @@ uint explain_filename(THD* thd,
case 's':
if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#')
{
- part_name_len= tmp_p - part_name - 1;
+ part_name_len= (int)(tmp_p - part_name - 1);
subpart_name= tmp_p + 3;
tmp_p+= 3;
}
@@ -284,7 +284,7 @@ uint explain_filename(THD* thd,
}
if (part_name)
{
- table_name_len= part_name - table_name - 3;
+ table_name_len= (int)(part_name - table_name - 3);
if (subpart_name)
subpart_name_len= strlen(subpart_name);
else
@@ -357,7 +357,7 @@ uint explain_filename(THD* thd,
to_p= strnmov(to_p, " */", end_p - to_p);
}
DBUG_PRINT("exit", ("to '%s'", to));
- DBUG_RETURN(to_p - to);
+ DBUG_RETURN((uint)(to_p - to));
}
@@ -553,7 +553,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db,
pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
DBUG_PRINT("exit", ("buff: '%s'", buff));
- DBUG_RETURN(pos - buff);
+ DBUG_RETURN((uint)(pos - buff));
}
@@ -1990,7 +1990,7 @@ int write_bin_log(THD *thd, bool clear_error,
tables List of tables to delete
if_exists If 1, don't give error if one table doesn't exists
drop_temporary 1 if DROP TEMPORARY
- drop_seqeunce 1 if DROP SEQUENCE
+ drop_sequence 1 if DROP SEQUENCE
NOTES
Will delete all tables that can be deleted and give a compact error
@@ -2038,6 +2038,25 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
if (!thd->locked_tables_mode)
{
+ if (drop_sequence)
+ {
+ /* We are trying to drop a sequence.
+ Change all temporary tables that are not sequences to
+ normal tables so that we can try to drop them instead.
+ If we don't do this, we will get an error 'not a sequence'
+ when trying to drop a sequence that is hidden by a temporary
+ table.
+ */
+ for (table= tables; table; table= table->next_global)
+ {
+ if (table->open_type == OT_TEMPORARY_OR_BASE &&
+ is_temporary_table(table) && !table->table->s->sequence)
+ {
+ thd->mark_tmp_table_as_free_for_reuse(table->table);
+ table->table= NULL;
+ }
+ }
+ }
if (lock_table_names(thd, tables, NULL,
thd->variables.lock_wait_timeout, 0))
DBUG_RETURN(true);
@@ -2134,7 +2153,7 @@ static uint32 comment_length(THD *thd, uint32 comment_pos,
for (query+= 3; query < query_end; query++)
{
if (query[-1] == '*' && query[0] == '/')
- return (char*) query - *comment_start + 1;
+ return (uint32)((char*) query - *comment_start + 1);
}
return 0;
}
@@ -2724,7 +2743,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const char *db,
bool error= 0;
DBUG_ENTER("quick_rm_table");
- uint path_length= table_path ?
+ size_t path_length= table_path ?
(strxnmov(path, sizeof(path) - 1, table_path, reg_ext, NullS) - path) :
build_table_filename(path, sizeof(path)-1, db, table_name, reg_ext, flags);
if (mysql_file_delete(key_file_frm, path, MYF(0)))
@@ -3306,7 +3325,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->ha_table_flags() & HA_CAN_TABLES_WITHOUT_ROLLBACK))
{
- my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->engine_name()->str,
+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->table_type(),
"SEQUENCE");
DBUG_RETURN(TRUE);
}
@@ -4022,7 +4041,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (!sql_field->default_value &&
!sql_field->has_default_function() &&
(sql_field->flags & NOT_NULL_FLAG) &&
- !sql_field->is_timestamp_type())
+ (!sql_field->is_timestamp_type() ||
+ opt_explicit_defaults_for_timestamp))
{
sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
@@ -4031,6 +4051,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
!sql_field->default_value && !sql_field->vcol_info &&
sql_field->is_timestamp_type() &&
+ !opt_explicit_defaults_for_timestamp &&
(sql_field->flags & NOT_NULL_FLAG) &&
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
{
@@ -6558,7 +6579,7 @@ static bool fill_alter_inplace_info(THD *thd,
table_key;
ha_alter_info->index_add_buffer
[ha_alter_info->index_add_count++]=
- new_key - ha_alter_info->key_info_buffer;
+ (uint)(new_key - ha_alter_info->key_info_buffer);
/* Mark all old fields which are used in newly created index. */
DBUG_PRINT("info", ("index changed: '%s'", table_key->name.str));
}
@@ -6583,7 +6604,7 @@ static bool fill_alter_inplace_info(THD *thd,
/* Key not found. Add the offset of the key to the add buffer. */
ha_alter_info->index_add_buffer
[ha_alter_info->index_add_count++]=
- new_key - ha_alter_info->key_info_buffer;
+ (uint)(new_key - ha_alter_info->key_info_buffer);
DBUG_PRINT("info", ("index added: '%s'", new_key->name.str));
}
else
@@ -6923,7 +6944,6 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
case Alter_info::LEAVE_AS_IS:
if (!indexes_were_disabled)
break;
- /* disabled indexes */
/* fall through */
case Alter_info::DISABLE:
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index ab12278ef8c..3d43c35177d 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -85,8 +85,9 @@ static my_bool print_cached_tables_callback(TDC_element *element,
while ((entry= it++))
{
THD *in_use= entry->in_use;
- printf("%-14.14s %-32s%6ld%8ld%6d %s\n",
- entry->s->db.str, entry->s->table_name.str, element->version,
+ printf("%-14.14s %-32s%6lu%8ld%6d %s\n",
+ entry->s->db.str, entry->s->table_name.str,
+ (ulong) element->version,
in_use ? (long) in_use->thread_id : (long) 0,
entry->db_stat ? 1 : 0,
in_use ? lock_descriptions[(int)entry->reginfo.lock_type] :
@@ -106,7 +107,8 @@ static void print_cached_tables(void)
tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true);
- printf("\nCurrent refresh version: %ld\n", tdc_refresh_version());
+ printf("\nCurrent refresh version: %ld\n",
+ (long) tdc_refresh_version());
fflush(stdout);
/* purecov: end */
return;
@@ -172,7 +174,7 @@ TEST_join(JOIN *join)
in order not to garble the tabular output below.
*/
String ref_key_parts[MAX_TABLES];
- int tables_in_range= jt_range->end - jt_range->start;
+ int tables_in_range= (int)(jt_range->end - jt_range->start);
for (i= 0; i < tables_in_range; i++)
{
JOIN_TAB *tab= jt_range->start + i;
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index a8a0ffa3cf2..309ede45ecc 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -274,7 +274,7 @@ to_ascii(CHARSET_INFO *cs,
*dst++= static_cast<char>(wc);
}
*dst= '\0';
- return dst - dst0;
+ return (uint)(dst - dst0);
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index dcce8ae3724..d6c722246e7 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -453,6 +453,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
}
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!create)
{
@@ -616,6 +617,10 @@ end:
my_ok(thd);
DBUG_RETURN(result);
+#ifdef WITH_WSREP
+ error:
+ DBUG_RETURN(true);
+#endif /* WITH_WSREP */
}
/**
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 3ea364f2fba..62dcff33f1d 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -1625,6 +1625,17 @@ bool Type_handler_null::
return false;
}
+bool Type_handler_row::
+ Column_definition_prepare_stage1(THD *thd,
+ MEM_ROOT *mem_root,
+ Column_definition *def,
+ handler *file,
+ ulonglong table_flags) const
+{
+ def->create_length_to_internal_length_null();
+ return false;
+}
+
bool Type_handler_newdecimal::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
@@ -2687,9 +2698,27 @@ Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const
}
Item_cache *
-Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const
+Type_handler_timestamp_common::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_datetime(thd);
+}
+
+Item_cache *
+Type_handler_datetime_common::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_datetime(thd);
+}
+
+Item_cache *
+Type_handler_time_common::Item_get_cache(THD *thd, const Item *item) const
+{
+ return new (thd->mem_root) Item_cache_time(thd);
+}
+
+Item_cache *
+Type_handler_date_common::Item_get_cache(THD *thd, const Item *item) const
{
- return new (thd->mem_root) Item_cache_temporal(thd, item->type_handler());
+ return new (thd->mem_root) Item_cache_date(thd);
}
/*************************************************************************/
@@ -3531,7 +3560,7 @@ bool Type_handler_numeric::
bool Type_handler_temporal_result::
Item_func_between_fix_length_and_dec(Item_func_between *func) const
{
- return func->fix_length_and_dec_numeric(current_thd);
+ return func->fix_length_and_dec_temporal(current_thd);
}
bool Type_handler_string_result::
@@ -5259,7 +5288,7 @@ Item *Type_handler_time_common::
longlong value= item->val_time_packed();
if (item->null_value)
return new (thd->mem_root) Item_null(thd, item->name.str);
- cache= new (thd->mem_root) Item_cache_temporal(thd, this);
+ cache= new (thd->mem_root) Item_cache_time(thd);
if (cache)
cache->store_packed(value, item);
return cache;
@@ -5273,7 +5302,7 @@ Item *Type_handler_temporal_with_date::
longlong value= item->val_datetime_packed();
if (item->null_value)
return new (thd->mem_root) Item_null(thd, item->name.str);
- cache= new (thd->mem_root) Item_cache_temporal(thd, this);
+ cache= new (thd->mem_root) Item_cache_datetime(thd);
if (cache)
cache->store_packed(value, item);
return cache;
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 0354adfde1e..d94c5a87811 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -1046,18 +1046,13 @@ public:
}
bool Column_definition_fix_attributes(Column_definition *c) const
{
- DBUG_ASSERT(0);
- return true;
+ return false;
}
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
- ulonglong table_flags) const
- {
- DBUG_ASSERT(0);
- return true;
- }
+ ulonglong table_flags) const;
bool Column_definition_redefine_stage1(Column_definition *def,
const Column_definition *dup,
const handler *file,
@@ -1071,8 +1066,7 @@ public:
handler *file,
ulonglong table_flags) const
{
- DBUG_ASSERT(0);
- return true;
+ return false;
}
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
@@ -1584,7 +1578,6 @@ public:
Item *source_expr, Item *source_const) const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
- Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
@@ -2066,6 +2059,7 @@ public:
}
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
@@ -2152,6 +2146,7 @@ public:
bool Column_definition_fix_attributes(Column_definition *c) const;
uint Item_decimal_precision(const Item *item) const;
String *print_item_value(THD *thd, Item *item, String *str) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
@@ -2225,6 +2220,7 @@ public:
return Item_send_datetime(item, protocol, buf);
}
String *print_item_value(THD *thd, Item *item, String *str) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
@@ -2304,6 +2300,7 @@ public:
return Item_send_datetime(item, protocol, buf);
}
String *print_item_value(THD *thd, Item *item, String *str) const;
+ Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index d188be8bc97..96f48be5ff2 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -80,7 +80,7 @@ bool compare_record(const TABLE *table)
{
if (field->real_maybe_null())
{
- uchar null_byte_index= field->null_ptr - table->record[0];
+ uchar null_byte_index= (uchar)(field->null_ptr - table->record[0]);
if (((table->record[0][null_byte_index]) & field->null_bit) !=
((table->record[1][null_byte_index]) & field->null_bit))
@@ -362,7 +362,7 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~table->grant.privilege);
#endif
- if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0))
+ if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0))
{
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(1); /* purecov: inspected */
@@ -1683,7 +1683,7 @@ int multi_update::prepare(List<Item> &not_used_values,
*/
int error= setup_fields(thd, Ref_ptr_array(),
- *values, MARK_COLUMNS_READ, 0, 0);
+ *values, MARK_COLUMNS_READ, 0, NULL, 0);
ti.rewind();
while ((table_ref= ti++))
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index fd6ecbbdec9..2d8129fd223 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -430,6 +430,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY;
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
{
res= TRUE;
@@ -707,6 +709,10 @@ err:
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
DBUG_RETURN(res || thd->is_error());
+#ifdef WITH_WSREP
+ error:
+ DBUG_RETURN(true);
+#endif /* WITH_WSREP */
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 277d67ca014..67b73dea506 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -392,11 +392,11 @@ LEX::create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar,
DBUG_ASSERT(spcont && spvar);
/* Position and length of the SP variable name in the query. */
- pos_in_q= start_in_q - sphead->m_tmp_query;
- len_in_q= end_in_q - start_in_q;
+ pos_in_q= (uint)(start_in_q - sphead->m_tmp_query);
+ len_in_q= (uint)(end_in_q - start_in_q);
item= new (thd->mem_root)
- Item_splocal(thd, name, spvar->offset, spvar->sql_type(),
+ Item_splocal(thd, name, spvar->offset, spvar->type_handler(),
pos_in_q, len_in_q);
#ifdef DBUG_ASSERT_EXISTS
@@ -4762,17 +4762,11 @@ size_number:
switch (end_ptr[0])
{
case 'g':
- case 'G':
- text_shift_number+=10;
- /* fall through */
+ case 'G': text_shift_number+=30; break;
case 'm':
- case 'M':
- text_shift_number+=10;
- /* fall through */
+ case 'M': text_shift_number+=20; break;
case 'k':
- case 'K':
- text_shift_number+=10;
- break;
+ case 'K': text_shift_number+=10; break;
default:
my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
}
@@ -5906,7 +5900,7 @@ create_table_option:
| SEQUENCE_SYM opt_equal choice
{
Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
- Lex->create_info.sequence= $3;
+ Lex->create_info.sequence= ($3 == HA_CHOICE_YES);
}
;
@@ -9877,26 +9871,22 @@ function_call_nonkeyword:
}
| SUBSTRING '(' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5)))
MYSQL_YYABORT;
}
| SYSDATE opt_time_precision
@@ -13872,36 +13862,18 @@ text_literal:
}
| NCHAR_STRING
{
- DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
- $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
- national_charset_info,
- DERIVATION_COERCIBLE,
- $1.repertoire());
- if ($$ == NULL)
+ if (!($$= thd->make_string_literal_nchar($1)))
MYSQL_YYABORT;
}
| UNDERSCORE_CHARSET TEXT_STRING
{
- $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str,
- $2.length, $1);
- if ($$ == NULL)
+ if (!($$= thd->make_string_literal_charset($2, $1)))
MYSQL_YYABORT;
}
| text_literal TEXT_STRING_literal
{
- Item_string* item= (Item_string*) $1;
- item->append($2.str, $2.length);
- if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
- {
- /*
- If the string has been pure ASCII so far,
- check the new part.
- */
- CHARSET_INFO *cs= thd->variables.collation_connection;
- item->collation.repertoire|= my_string_repertoire(cs,
- $2.str,
- $2.length);
- }
+ if (!($$= thd->make_string_literal_concat($1, $2)))
+ MYSQL_YYABORT;
}
;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index ad8b6697ce7..db45414fd28 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -5777,7 +5777,7 @@ create_table_option:
| SEQUENCE_SYM opt_equal choice
{
Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE;
- Lex->create_info.sequence= $3;
+ Lex->create_info.sequence= ($3 == HA_CHOICE_YES);
}
;
@@ -9896,26 +9896,22 @@ function_call_nonkeyword:
}
| SUBSTRING '(' expr ',' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr ',' expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| SUBSTRING '(' expr FROM expr ')'
{
- $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
- if ($$ == NULL)
+ if (!($$= Lex->make_item_func_substr(thd, $3, $5)))
MYSQL_YYABORT;
}
| SYSDATE opt_time_precision
@@ -13924,36 +13920,18 @@ text_literal:
}
| NCHAR_STRING
{
- DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
- $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
- national_charset_info,
- DERIVATION_COERCIBLE,
- $1.repertoire());
- if ($$ == NULL)
+ if (!($$= thd->make_string_literal_nchar($1)))
MYSQL_YYABORT;
}
| UNDERSCORE_CHARSET TEXT_STRING
{
- $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str,
- $2.length, $1);
- if ($$ == NULL)
+ if (!($$= thd->make_string_literal_charset($2, $1)))
MYSQL_YYABORT;
}
| text_literal TEXT_STRING_literal
{
- Item_string* item= (Item_string*) $1;
- item->append($2.str, $2.length);
- if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
- {
- /*
- If the string has been pure ASCII so far,
- check the new part.
- */
- CHARSET_INFO *cs= thd->variables.collation_connection;
- item->collation.repertoire|= my_string_repertoire(cs,
- $2.str,
- $2.length);
- }
+ if (!($$= thd->make_string_literal_concat($1, $2)))
+ MYSQL_YYABORT;
}
;
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index f4c8fcd517f..45a0f8f6558 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -339,7 +339,7 @@ int find_string_in_array(LEX_CSTRING * const haystack, LEX_CSTRING * const needl
if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length,
(uchar *) needle->str, needle->length))
{
- return (pos - haystack);
+ return (int)(pos - haystack);
}
return -1;
}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index fd704ca6dae..e5f9be5c769 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1523,7 +1523,7 @@ static Sys_var_ulonglong Sys_max_heap_table_size(
"max_heap_table_size",
"Don't allow creation of heap tables bigger than this",
SESSION_VAR(max_heap_table_size), CMD_LINE(REQUIRED_ARG),
- VALID_RANGE(16384, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024),
+ VALID_RANGE(16384, SIZE_T_MAX), DEFAULT(16*1024*1024),
BLOCK_SIZE(1024));
static ulong mdl_locks_cache_size;
@@ -3138,7 +3138,7 @@ static const char *sql_mode_names[]=
"STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE",
"ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL",
"NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION",
- "PAD_CHAR_TO_FULL_LENGTH",
+ "PAD_CHAR_TO_FULL_LENGTH", "EMPTY_STRING_IS_NULL",
0
};
diff --git a/sql/table.cc b/sql/table.cc
index 70adb869e0a..6d32440bb11 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2516,7 +2516,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
the correct null_bytes can now be set, since bitfields have been taken
into account
*/
- share->null_bytes= (null_pos - (uchar*) null_flags +
+ share->null_bytes= (uint)(null_pos - (uchar*) null_flags +
(null_bit_pos + 7) / 8);
share->last_null_bit_pos= null_bit_pos;
share->null_bytes_for_compare= null_bits_are_used ? share->null_bytes : 0;
@@ -5721,7 +5721,8 @@ Item *Field_iterator_table::create_item(THD *thd)
Item_field *item= new (thd->mem_root) Item_field(thd, &select->context, *ptr);
DBUG_ASSERT(strlen(item->name.str) == item->name.length);
if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
- !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS)
+ !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS &&
+ select->join)
{
select->join->non_agg_fields.push_back(item);
item->marker= select->cur_pos_in_select_list;
@@ -6002,8 +6003,8 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_
/* The field belongs to a merge view or information schema table. */
Field_translator *translated_field= view_field_it.field_translator();
nj_col= new Natural_join_column(translated_field, table_ref);
- field_count= table_ref->field_translation_end -
- table_ref->field_translation;
+ field_count= (uint)(table_ref->field_translation_end -
+ table_ref->field_translation);
}
else
{
diff --git a/sql/table.h b/sql/table.h
index 5a9f3c18ab9..94a161eefba 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -35,6 +35,7 @@
/* Structs that defines the TABLE */
class Item; /* Needed by ORDER */
+typedef Item (*Item_ptr);
class Item_subselect;
class Item_field;
class GRANT_TABLE;
@@ -2556,7 +2557,7 @@ typedef struct st_nested_join
table_map sj_depends_on;
/* Outer non-trivially correlated tables */
table_map sj_corr_tables;
- List<Item> sj_outer_expr_list;
+ List<Item_ptr> sj_outer_expr_list;
/**
True if this join nest node is completely covered by the query execution
plan. This means two things.
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 49724a3f47e..1ca0233552e 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -981,13 +981,18 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
null_count+= field->length & 7;
if (field->default_value && !field->default_value->flags &&
- !(field->flags & BLOB_FLAG))
+ (!(field->flags & BLOB_FLAG) ||
+ field->real_field_type() == MYSQL_TYPE_GEOMETRY))
{
Item *expr= field->default_value->expr;
+
int res= !expr->fixed && // may be already fixed if ALTER TABLE
expr->fix_fields(thd, &expr);
if (!res)
res= expr->save_in_field(regfield, 1);
+ if (!res && (field->flags & BLOB_FLAG))
+ regfield->reset();
+
/* If not ok or warning of level 'note' */
if (res != 0 && res != 3)
{
@@ -996,6 +1001,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
delete regfield; //To avoid memory leak
goto err;
}
+ delete regfield; //To avoid memory leak
}
else if (regfield->real_type() == MYSQL_TYPE_ENUM &&
(field->flags & NOT_NULL_FLAG))