summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-05-18 17:30:02 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-05-18 17:30:02 +0300
commit23047d3ed42eacb5eaa5475a8fa4161550d01c52 (patch)
treee723067fea7cfb663ef7e4777e29ffd7dcd2905d /sql
parentf86d97c3fee0127d83c009e448f419ac857c72c7 (diff)
parentfaf6d0ef3f9323c6d24f8cdb6533ed23d1a6bb40 (diff)
downloadmariadb-git-23047d3ed42eacb5eaa5475a8fa4161550d01c52.tar.gz
Merge 10.4 into 10.5
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc11
-rw-r--r--sql/field.h16
-rw-r--r--sql/item.h26
-rw-r--r--sql/item_func.cc11
-rw-r--r--sql/item_subselect.cc9
-rw-r--r--sql/item_sum.cc8
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_base.cc26
-rw-r--r--sql/sql_repl.cc5
-rw-r--r--sql/sql_statistics.cc1
-rw-r--r--sql/sql_tvc.cc9
-rw-r--r--sql/table.cc6
13 files changed, 104 insertions, 28 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 6234de43ec8..0f5caed57f6 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1455,7 +1455,7 @@ void Field::error_generated_column_function_is_not_allowed(THD *thd,
QT_ITEM_IDENT_SKIP_TABLE_NAMES));
my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED,
MYF(error ? 0 : ME_WARNING),
- tmp.c_ptr(), vcol_info->get_vcol_type_name(),
+ tmp.c_ptr_safe(), vcol_info->get_vcol_type_name(),
const_cast<const char*>(field_name.str));
}
@@ -7680,6 +7680,15 @@ my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value)
}
+#ifdef HAVE_valgrind_or_MSAN
+void Field_varstring::mark_unused_memory_as_defined()
+{
+ uint used_length= get_length();
+ MEM_MAKE_DEFINED(get_data() + used_length, field_length - used_length);
+}
+#endif
+
+
int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
uint max_len) const
{
diff --git a/sql/field.h b/sql/field.h
index d709a84e0fe..bef73705f60 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -977,6 +977,19 @@ public:
DBUG_ASSERT(ls.length < UINT_MAX32);
return store(ls.str, (uint) ls.length, cs);
}
+
+#ifdef HAVE_valgrind_or_MSAN
+ /**
+ Mark unused memory in the field as defined. Mainly used to ensure
+ that if we write full field to disk (for example in
+ Count_distinct_field::add(), we don't write unitalized data to
+ disk which would confuse valgrind or MSAN.
+ */
+ virtual void mark_unused_memory_as_defined() {}
+#else
+ void mark_unused_memory_as_defined() {}
+#endif
+
virtual double val_real()=0;
virtual longlong val_int()=0;
/*
@@ -4096,6 +4109,9 @@ public:
}
int store(const char *to,size_t length,CHARSET_INFO *charset) override;
using Field_str::store;
+#ifdef HAVE_valgrind_or_MSAN
+ void mark_unused_memory_as_defined() override;
+#endif
double val_real() override;
longlong val_int() override;
String *val_str(String *, String *) override;
diff --git a/sql/item.h b/sql/item.h
index c5fd5d074f6..cb11b5d8773 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1592,7 +1592,14 @@ public:
a constant expression. Used in the optimizer to propagate basic constants.
*/
virtual bool basic_const_item() const { return 0; }
- /*
+ /**
+ Determines if the expression is allowed as
+ a virtual column assignment source:
+ INSERT INTO t1 (vcol) VALUES (10) -> error
+ INSERT INTO t1 (vcol) VALUES (NULL) -> ok
+ */
+ virtual bool vcol_assignment_allowed_value() const { return false; }
+ /**
Test if "this" is an ORDER position (rather than an expression).
Notes:
- can be called before fix_fields().
@@ -3616,6 +3623,7 @@ public:
collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
enum Type type() const { return NULL_ITEM; }
+ bool vcol_assignment_allowed_value() const { return true; }
double val_real();
longlong val_int();
String *val_str(String *str);
@@ -3861,6 +3869,21 @@ public:
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
+ bool vcol_assignment_allowed_value() const
+ {
+ switch (state) {
+ case NULL_VALUE:
+ case DEFAULT_VALUE:
+ case IGNORE_VALUE:
+ return true;
+ case NO_VALUE:
+ case SHORT_DATA_VALUE:
+ case LONG_DATA_VALUE:
+ break;
+ }
+ return false;
+ }
+
Item_param(THD *thd, const LEX_CSTRING *name_arg,
uint pos_in_query_arg, uint len_in_query_arg);
@@ -6255,6 +6278,7 @@ public:
Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a)
:Item_field(thd, context_arg) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
+ bool vcol_assignment_allowed_value() const { return arg == NULL; }
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
void cleanup();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 52eeaf10cd5..da185f9878b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2184,6 +2184,12 @@ longlong Item_func_bit_neg::val_int()
void Item_func_int_val::fix_length_and_dec_int_or_decimal()
{
+ /*
+ The INT branch of this code should be revised.
+ It creates too large data types, e.g.
+ CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(9999999.999) AS fa;
+ results in a BININT(10) column, while INT(7) should probably be enough.
+ */
ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
max_length= tmp_max_length > (ulonglong) UINT_MAX32 ?
@@ -2198,6 +2204,9 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal()
*/
if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2)
{
+ fix_char_length(
+ my_decimal_precision_to_length_no_truncation(
+ args[0]->decimal_int_part(), 0, false));
set_handler(&type_handler_newdecimal);
}
else
@@ -2314,6 +2323,8 @@ void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set)
set_handler(&type_handler_newdecimal);
unsigned_flag= args[0]->unsigned_flag;
decimals= decimals_to_set;
+ if (!precision)
+ precision= 1; // DECIMAL(0,0) -> DECIMAL(1,0)
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4bbb33d4eb7..be78f333951 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2192,10 +2192,13 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
}
else
{
+ /*
+ No need to use real_item for the item, as the ref items that are possible
+ in the subquery either belong to views or to the parent select.
+ For such case we need to refer to the reference and not to the original
+ item.
+ */
Item *item= (Item*) select_lex->item_list.head();
- if (item->type() != REF_ITEM ||
- ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF)
- item= item->real_item();
if (select_lex->table_list.elements)
{
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 052ac173747..b676186f571 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1387,10 +1387,12 @@ Item_sum_sp::execute()
bool res;
uint old_server_status= thd->server_status;
- /* We set server status so we can send a signal to exit from the
- function with the return value. */
+ /*
+ We set server status so we can send a signal to exit from the
+ function with the return value.
+ */
- thd->server_status= SERVER_STATUS_LAST_ROW_SENT;
+ thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
res= Item_sp::execute(thd, &null_value, args, arg_count);
thd->server_status= old_server_status;
return res;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 1b273b19c33..d5ec2060c02 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3134,6 +3134,8 @@ const char *sql_ex_info::init(const char *buf, const char *buf_end,
}
else
{
+ if (buf_end - buf < 7)
+ return 0; // Wrong data
field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
field_term = buf++; // Use first byte in string
enclosed= buf++;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index f840904def3..e61164e8e40 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -4648,7 +4648,7 @@ sp_instr_agg_cfetch::execute(THD *thd, uint *nextp)
else
{
thd->spcont->pause_state= FALSE;
- if (thd->server_status == SERVER_STATUS_LAST_ROW_SENT)
+ if (thd->server_status & SERVER_STATUS_LAST_ROW_SENT)
{
my_message(ER_SP_FETCH_NO_DATA,
ER_THD(thd, ER_SP_FETCH_NO_DATA), MYF(0));
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b5064fe9fd9..3413b3787bd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8375,11 +8375,9 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
if (table->next_number_field &&
rfield->field_index == table->next_number_field->field_index)
table->auto_increment_field_not_null= TRUE;
- Item::Type type= value->type();
const bool skip_sys_field= rfield->vers_sys_field(); // TODO: && !thd->vers_modify_history() [MDEV-16546]
if ((rfield->vcol_info || skip_sys_field) &&
- type != Item::DEFAULT_VALUE_ITEM &&
- type != Item::NULL_ITEM &&
+ !value->vcol_assignment_allowed_value() &&
table->s->table_category != TABLE_CATEGORY_TEMPORARY)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -8660,20 +8658,16 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
if (field->field_index == autoinc_index)
table->auto_increment_field_not_null= TRUE;
- if (unlikely(field->vcol_info) || (vers_sys_field && !ignore_errors))
+ if ((unlikely(field->vcol_info) || (vers_sys_field && !ignore_errors)) &&
+ !value->vcol_assignment_allowed_value() &&
+ table->s->table_category != TABLE_CATEGORY_TEMPORARY)
{
- Item::Type type= value->type();
- if (type != Item::DEFAULT_VALUE_ITEM &&
- type != Item::NULL_ITEM &&
- table->s->table_category != TABLE_CATEGORY_TEMPORARY)
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN,
- ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN),
- field->field_name.str, table->s->table_name.str);
- if (vers_sys_field)
- continue;
- }
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN,
+ ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN),
+ field->field_name.str, table->s->table_name.str);
+ if (vers_sys_field)
+ continue;
}
if (use_value)
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 55e5e940b19..83ae25c962d 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2006,7 +2006,7 @@ send_event_to_slave(binlog_send_info *info, Log_event_type event_type,
pos= my_b_tell(log);
if (repl_semisync_master.update_sync_header(info->thd,
- (uchar*) packet->ptr(),
+ (uchar*) packet->c_ptr_safe(),
info->log_file_name + info->dirlen,
pos, &need_sync))
{
@@ -2030,7 +2030,8 @@ send_event_to_slave(binlog_send_info *info, Log_event_type event_type,
}
}
- if (need_sync && repl_semisync_master.flush_net(info->thd, packet->c_ptr()))
+ if (need_sync && repl_semisync_master.flush_net(info->thd,
+ packet->c_ptr_safe()))
{
info->error= ER_UNKNOWN_ERROR;
return "Failed to run hook 'after_send_event'";
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 55e8e52c052..a6c489f02be 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1671,6 +1671,7 @@ public:
*/
virtual bool add()
{
+ table_field->mark_unused_memory_as_defined();
return tree->unique_add(table_field->ptr);
}
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index 678dd81709e..e228b3ca211 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -52,7 +52,14 @@ bool fix_fields_for_tvc(THD *thd, List_iterator_fast<List_item> &li)
while ((item= it++))
{
- if (item->fix_fields(thd, 0))
+ /*
+ Some items have already been fixed.
+ For example Item_splocal items get fixed in
+ Item_splocal::append_for_log(), which is called from subst_spvars()
+ while replacing their values to NAME_CONST()s.
+ So fix only those that have not been.
+ */
+ if (item->fix_fields_if_needed(thd, 0))
DBUG_RETURN(true);
}
}
diff --git a/sql/table.cc b/sql/table.cc
index 92e3d2e4800..98d299afb37 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -7219,6 +7219,12 @@ void TABLE::mark_columns_needed_for_update()
}
need_signal= true;
}
+ else
+ {
+ if (found_next_number_field)
+ mark_auto_increment_column();
+ }
+
if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE)
{
/*