summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2022-08-09 09:52:15 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2022-08-09 09:52:15 +0200
commit75d631f333544de4487a6dd251d6f361e1d55d6b (patch)
tree4e234afa19a458b9b0727859c53c290c683a502d /sql
parent9cbf8ccf2990f9db8d9debee42bc9213cbb04457 (diff)
parent1d480419822b53c840de54542c1d1a0851dbe2c8 (diff)
downloadmariadb-git-75d631f333544de4487a6dd251d6f361e1d55d6b.tar.gz
Merge branch '10.7' into 10.8
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc29
-rw-r--r--sql/field.h10
-rw-r--r--sql/handler.cc37
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item.h10
-rw-r--r--sql/item_cmpfunc.cc15
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_func.h3
-rw-r--r--sql/item_jsonfunc.cc42
-rw-r--r--sql/log_event.cc23
-rw-r--r--sql/log_event.h38
-rw-r--r--sql/log_event_client.cc11
-rw-r--r--sql/log_event_server.cc4
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/opt_range.cc40
-rw-r--r--sql/opt_range.h1
-rw-r--r--sql/share/errmsg-utf8.txt5
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc39
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_insert.cc21
-rw-r--r--sql/sql_insert.h1
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_plugin.cc2
-rw-r--r--sql/sql_prepare.cc14
-rw-r--r--sql/sql_priv.h6
-rw-r--r--sql/sql_select.cc23
-rw-r--r--sql/sql_select.h1
-rw-r--r--sql/sql_table.cc18
-rw-r--r--sql/sql_type.cc13
-rw-r--r--sql/sql_type.h6
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_yacc.yy7
-rw-r--r--sql/sys_vars.cc8
-rw-r--r--sql/table.cc10
-rw-r--r--sql/table.h13
38 files changed, 286 insertions, 195 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 433a65b51c7..9a084724838 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -964,7 +964,8 @@ Type_handler::aggregate_for_result_traditional(const Type_handler *a,
}
-bool Field::check_assignability_from(const Type_handler *from) const
+bool Field::check_assignability_from(const Type_handler *from,
+ bool ignore) const
{
/*
Using type_handler_for_item_field() here to get the data type handler
@@ -982,9 +983,26 @@ bool Field::check_assignability_from(const Type_handler *from) const
type_handler_for_item_field());
if (th.aggregate_for_result(from->type_handler_for_item_field()))
{
- my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
- type_handler()->name().ptr(), from->name().ptr(), "SET");
- return true;
+ bool error= !ignore && get_thd()->is_strict_mode();
+ /*
+ Display fully qualified column name for table columns.
+ Display non-qualified names for other things,
+ e.g. SP variables, SP return values, SP and CURSOR parameters.
+ */
+ if (table->s->db.str && table->s->table_name.str)
+ my_printf_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION,
+ "Cannot cast '%s' as '%s' in assignment of %`s.%`s.%`s",
+ MYF(error ? 0 : ME_WARNING),
+ from->name().ptr(), type_handler()->name().ptr(),
+ table->s->db.str, table->s->table_name.str,
+ field_name.str);
+ else
+ my_printf_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION,
+ "Cannot cast '%s' as '%s' in assignment of %`s",
+ MYF(error ? 0 : ME_WARNING),
+ from->name().ptr(), type_handler()->name().ptr(),
+ field_name.str);
+ return error;
}
return false;
}
@@ -10725,7 +10743,7 @@ bool Column_definition::check(THD *thd)
TIMESTAMP columns get implicit DEFAULT value when
explicit_defaults_for_timestamp is not set.
*/
- if ((opt_explicit_defaults_for_timestamp ||
+ if (((thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP) ||
!is_timestamp_type()) && !vers_sys_field())
{
flags|= NO_DEFAULT_VALUE_FLAG;
@@ -10860,6 +10878,7 @@ Column_definition::Column_definition(THD *thd, Field *old_field,
comment= old_field->comment;
vcol_info= old_field->vcol_info;
option_list= old_field->option_list;
+ explicitly_nullable= !(old_field->flags & NOT_NULL_FLAG);
compression_method_ptr= 0;
versioning= VERSIONING_NOT_SET;
invisible= old_field->invisible;
diff --git a/sql/field.h b/sql/field.h
index 9856e42ac14..dce87df550c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -905,10 +905,10 @@ public:
bool is_unsigned() const { return flags & UNSIGNED_FLAG; }
- bool check_assignability_from(const Type_handler *from) const;
- bool check_assignability_from(const Field *from) const
+ bool check_assignability_from(const Type_handler *from, bool ignore) const;
+ bool check_assignability_from(const Field *from, bool ignore) const
{
- return check_assignability_from(from->type_handler());
+ return check_assignability_from(from->type_handler(), ignore);
}
/**
@@ -5281,7 +5281,7 @@ public:
uint flags, pack_length;
List<String> interval_list;
engine_option_value *option_list;
-
+ bool explicitly_nullable;
/*
This is additinal data provided for any computed(virtual) field.
@@ -5303,7 +5303,7 @@ public:
comment(null_clex_str),
on_update(NULL), invisible(VISIBLE), char_length(0),
flags(0), pack_length(0),
- option_list(NULL),
+ option_list(NULL), explicitly_nullable(false),
vcol_info(0), default_value(0), check_constraint(0),
versioning(VERSIONING_NOT_SET), period(NULL)
{
diff --git a/sql/handler.cc b/sql/handler.cc
index 9ba96244557..4405f2583cd 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4933,17 +4933,32 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type != F_UNLCK);
- if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
+ const ulong v= table->s->mysql_version;
+
+ if ((v >= MYSQL_VERSION_ID) &&
(check_opt->sql_flags & TT_FOR_UPGRADE))
return 0;
- if (table->s->mysql_version < MYSQL_VERSION_ID)
+ if (v < MYSQL_VERSION_ID)
{
if (unlikely((error= check_old_types())))
return error;
error= ha_check_for_upgrade(check_opt);
if (unlikely(error && (error != HA_ADMIN_NEEDS_CHECK)))
return error;
+ if (table->s->table_category == TABLE_CATEGORY_USER &&
+ (v < 100142 ||
+ (v >= 100200 && v < 100228) ||
+ (v >= 100300 && v < 100319) ||
+ (v >= 100400 && v < 100409)))
+ {
+ for (const KEY *key= table->key_info,
+ *end= table->key_info + table->s->keys; key < end; key++)
+ {
+ if (key->flags & HA_BINARY_PACK_KEY && key->flags & HA_VAR_LENGTH_KEY)
+ return HA_ADMIN_NEEDS_UPGRADE;
+ }
+ }
if (unlikely(!error && (check_opt->sql_flags & TT_FOR_UPGRADE)))
return 0;
}
@@ -7535,6 +7550,17 @@ int handler::ha_write_row(const uchar *buf)
if ((error= ha_check_overlaps(NULL, buf)))
DBUG_RETURN(error);
+ /*
+ NOTE: this != table->file is true in 3 cases:
+
+ 1. under copy_partitions() (REORGANIZE PARTITION): that does not
+ require long unique check as it does not introduce new rows or new index.
+ 2. under partition's ha_write_row() (INSERT): check_duplicate_long_entries()
+ was already done by ha_partition::ha_write_row(), no need to check it
+ again for each single partition.
+ 3. under ha_mroonga::wrapper_write_row()
+ */
+
if (table->s->long_unique_table && this == table->file)
{
DBUG_ASSERT(inited == NONE || lookup_handler != this);
@@ -7588,6 +7614,13 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data)
uint saved_status= table->status;
error= ha_check_overlaps(old_data, new_data);
+ /*
+ NOTE: this != table->file is true under partition's ha_update_row():
+ check_duplicate_long_entries_update() was already done by
+ ha_partition::ha_update_row(), no need to check it again for each single
+ partition. Same applies to ha_mroonga wrapper.
+ */
+
if (!error && table->s->long_unique_table && this == table->file)
error= check_duplicate_long_entries_update(new_data);
table->status= saved_status;
diff --git a/sql/item.cc b/sql/item.cc
index 0d6f6cda544..991825663c2 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4509,13 +4509,13 @@ bool Item_param::is_evaluable_expression() const
}
-bool Item_param::check_assignability_to(const Field *to) const
+bool Item_param::check_assignability_to(const Field *to, bool ignore) const
{
switch (state) {
case SHORT_DATA_VALUE:
case LONG_DATA_VALUE:
case NULL_VALUE:
- return to->check_assignability_from(type_handler());
+ return to->check_assignability_from(type_handler(), ignore);
case NO_VALUE:
case IGNORE_VALUE:
case DEFAULT_VALUE:
diff --git a/sql/item.h b/sql/item.h
index 117a252c025..c720ab47a92 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1838,14 +1838,14 @@ public:
*/
virtual bool is_evaluable_expression() const { return true; }
- virtual bool check_assignability_to(const Field *to) const
+ virtual bool check_assignability_to(const Field *to, bool ignore) const
{
/*
"this" must be neither DEFAULT/IGNORE,
nor Item_param bound to DEFAULT/IGNORE.
*/
DBUG_ASSERT(is_evaluable_expression());
- return to->check_assignability_from(type_handler());
+ return to->check_assignability_from(type_handler(), ignore);
}
/**
@@ -4101,7 +4101,7 @@ class Item_param :public Item_basic_value,
const String *value_query_val_str(THD *thd, String* str) const;
Item *value_clone_item(THD *thd);
bool is_evaluable_expression() const override;
- bool check_assignability_to(const Field *field) const override;
+ bool check_assignability_to(const Field *field, bool ignore) const override;
bool can_return_value() const;
public:
@@ -6782,7 +6782,7 @@ public:
{
str->append(STRING_WITH_LEN("default"));
}
- bool check_assignability_to(const Field *to) const override
+ bool check_assignability_to(const Field *to, bool ignore) const override
{
return false;
}
@@ -6819,7 +6819,7 @@ public:
{
str->append(STRING_WITH_LEN("ignore"));
}
- bool check_assignability_to(const Field *to) const override
+ bool check_assignability_to(const Field *to, bool ignore) const override
{
return false;
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 9123bd96d5e..c202a32c3be 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -318,7 +318,18 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item,
field_item->field_type() != MYSQL_TYPE_YEAR)
return 1;
- if ((*item)->can_eval_in_optimize())
+ /*
+ Replace (*item) with its value if the item can be computed.
+
+ Do not replace items that contain aggregate functions:
+ There can be such items that are constants, e.g. COLLATION(AVG(123)),
+ but this function is called at Name Resolution phase.
+ Removing aggregate functions may confuse query plan generation code, e.g.
+ the optimizer might conclude that the query doesn't need to do grouping
+ at all.
+ */
+ if ((*item)->can_eval_in_optimize() &&
+ !(*item)->with_sum_func())
{
TABLE *table= field->table;
MY_BITMAP *old_maps[2] = { NULL, NULL };
@@ -780,7 +791,9 @@ int Arg_comparator::compare_e_string()
{
String *res1,*res2;
res1= (*a)->val_str(&value1);
+ DBUG_ASSERT((res1 == NULL) == (*a)->null_value);
res2= (*b)->val_str(&value2);
+ DBUG_ASSERT((res2 == NULL) == (*b)->null_value);
if (!res1 || !res2)
return MY_TEST(res1 == res2);
return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index dae2be5aa4e..0174569b554 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6197,6 +6197,8 @@ bool Item_func_match::init_search(THD *thd, bool no_order)
ft_handler= table->file->ft_init_ext(match_flags, key, ft_tmp);
+ if (!ft_handler)
+ DBUG_RETURN(1);
if (join_key)
table->file->ft_handler=ft_handler;
diff --git a/sql/item_func.h b/sql/item_func.h
index d323dc27fcc..86a8e7d5099 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -2117,8 +2117,7 @@ public:
void cleanup() override { first_eval= TRUE; Item_real_func::cleanup(); }
bool check_vcol_func_processor(void *arg) override
{
- return mark_unsupported_function(func_name(), "()", arg,
- VCOL_NON_DETERMINISTIC);
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
}
Item *get_copy(THD *thd) override
{ return get_item_copy<Item_func_rand>(thd, this); }
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 725fe4ab33e..b36f9d1ccb4 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -150,10 +150,12 @@ int json_path_parts_compare(
{
int res, res2;
- long arbitrary_var;
- long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
DBUG_EXECUTE_IF("json_check_min_stack_requirement",
- {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);});
+ {
+ long arbitrary_var;
+ long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
+ ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);
+ });
if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL))
return 1;
@@ -1166,13 +1168,15 @@ my_decimal *Item_func_json_extract::val_decimal(my_decimal *to)
case JSON_VALUE_OBJECT:
case JSON_VALUE_ARRAY:
case JSON_VALUE_FALSE:
- case JSON_VALUE_NULL:
case JSON_VALUE_UNINITIALIZED:
- break;
+ // TODO: fix: NULL should be NULL
+ case JSON_VALUE_NULL:
+ int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to);
+ return to;
};
}
- int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to);
- return to;
+ DBUG_ASSERT(null_value);
+ return 0;
}
@@ -1210,10 +1214,12 @@ static int check_contains(json_engine_t *js, json_engine_t *value)
{
json_engine_t loc_js;
bool set_js;
- long arbitrary_var;
- long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
DBUG_EXECUTE_IF("json_check_min_stack_requirement",
- {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);});
+ {
+ long arbitrary_var;
+ long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
+ ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);
+ });
if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL))
return 1;
@@ -2180,10 +2186,12 @@ err_return:
static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2)
{
- long arbitrary_var;
- long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
DBUG_EXECUTE_IF("json_check_min_stack_requirement",
- {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);});
+ {
+ long arbitrary_var;
+ long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
+ ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);
+ });
if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL))
return 1;
@@ -2521,10 +2529,12 @@ static int copy_value_patch(String *str, json_engine_t *je)
static int do_merge_patch(String *str, json_engine_t *je1, json_engine_t *je2,
bool *empty_result)
{
- long arbitrary_var;
- long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
DBUG_EXECUTE_IF("json_check_min_stack_requirement",
- {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);});
+ {
+ long arbitrary_var;
+ long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var));
+ ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);
+ });
if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL))
return 1;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b3943760720..e8e854fba31 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2201,6 +2201,7 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
break;
}
calc_server_version_split();
+ deduct_options_written_to_bin_log();
checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
reset_crypto();
}
@@ -2259,6 +2260,7 @@ Format_description_log_event(const uchar *buf, uint event_len,
{
checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
}
+ deduct_options_written_to_bin_log();
reset_crypto();
DBUG_VOID_RETURN;
@@ -2335,6 +2337,27 @@ void Format_description_log_event::calc_server_version_split()
}
+void Format_description_log_event::deduct_options_written_to_bin_log()
+{
+ options_written_to_bin_log= OPTION_AUTO_IS_NULL | OPTION_NOT_AUTOCOMMIT |
+ OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS;
+ if (!server_version_split.version_is_valid() ||
+ server_version_split.kind == master_version_split::KIND_MYSQL ||
+ server_version_split < Version(10,5,2))
+ return;
+ options_written_to_bin_log|= OPTION_IF_EXISTS;
+ if (server_version_split[0] == 10)
+ {
+ const static char v[10]={99,99,99,99,99,17,9,5,4,2};
+ if (server_version_split[1] < 10 &&
+ server_version_split[2] < v[server_version_split[1]])
+ return;
+ }
+ options_written_to_bin_log|= OPTION_EXPLICIT_DEF_TIMESTAMP;
+
+ DBUG_ASSERT(options_written_to_bin_log == OPTIONS_WRITTEN_TO_BIN_LOG);
+}
+
/**
@return TRUE is the event's version is earlier than one that introduced
the replication event checksum. FALSE otherwise.
diff --git a/sql/log_event.h b/sql/log_event.h
index 405b9a15003..06f51d263e1 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -521,33 +521,16 @@ class String;
be written to the binlog. OPTIONS_WRITTEN_TO_BIN_LOG could be
written into the Format_description_log_event, so that if later we
don't want to replicate a variable we did replicate, or the
- contrary, it's doable. But it should not be too hard to decide once
- for all of what we replicate and what we don't, among the fixed 32
- bits of thd->options.
-
- I (Guilhem) have read through every option's usage, and it looks
- like OPTION_AUTO_IS_NULL and OPTION_NO_FOREIGN_KEYS are the only
- ones which alter how the query modifies the table. It's good to
- replicate OPTION_RELAXED_UNIQUE_CHECKS too because otherwise, the
- slave may insert data slower than the master, in InnoDB.
- OPTION_BIG_SELECTS is not needed (the slave thread runs with
- max_join_size=HA_POS_ERROR) and OPTION_BIG_TABLES is not needed
- either, as the manual says (because a too big in-memory temp table
- is automatically written to disk).
+ contrary, it's doable. But it should not be too hard to deduct
+ the value of OPTIONS_WRITTEN_TO_BIN_LOG from the master's version.
+
+ This is done in deduct_options_written_to_bin_log().
+ You *must* update it, when changing the definition below.
*/
-#define OPTIONS_WRITTEN_TO_BIN_LOG \
- (OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \
+#define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_EXPLICIT_DEF_TIMESTAMP |\
+ OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \
OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT | OPTION_IF_EXISTS)
-/* Shouldn't be defined before */
-#define EXPECTED_OPTIONS \
- ((1ULL << 14) | (1ULL << 26) | (1ULL << 27) | (1ULL << 19) | (1ULL << 28))
-
-#if OPTIONS_WRITTEN_TO_BIN_LOG != EXPECTED_OPTIONS
-#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
-#endif
-#undef EXPECTED_OPTIONS /* You shouldn't use this one */
-
#define CHECKSUM_CRC32_SIGNATURE_LEN 4
/**
defined statically while there is just one alg implemented
@@ -1893,10 +1876,7 @@ protected:
<td>The flags in @c thd->options, binary AND-ed with @c
OPTIONS_WRITTEN_TO_BIN_LOG. The @c thd->options bitfield contains
options for "SELECT". @c OPTIONS_WRITTEN identifies those options
- that need to be written to the binlog (not all do). Specifically,
- @c OPTIONS_WRITTEN_TO_BIN_LOG equals (@c OPTION_AUTO_IS_NULL | @c
- OPTION_NO_FOREIGN_KEY_CHECKS | @c OPTION_RELAXED_UNIQUE_CHECKS |
- @c OPTION_NOT_AUTOCOMMIT), or 0x0c084000 in hex.
+ that need to be written to the binlog (not all do).
These flags correspond to the SQL variables SQL_AUTO_IS_NULL,
FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, and AUTOCOMMIT, documented in
@@ -2903,6 +2883,7 @@ public:
};
master_version_split server_version_split;
const uint8 *event_type_permutation;
+ uint32 options_written_to_bin_log;
Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
Format_description_log_event(const uchar *buf, uint event_len,
@@ -2950,6 +2931,7 @@ public:
}
void calc_server_version_split();
+ void deduct_options_written_to_bin_log();
static bool is_version_before_checksum(const master_version_split *version_split);
protected:
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc
index e460fc17848..6d308ac6cd6 100644
--- a/sql/log_event_client.cc
+++ b/sql/log_event_client.cc
@@ -1887,6 +1887,7 @@ bool Query_log_event::print_query_header(IO_CACHE* file,
if (unlikely(tmp)) /* some bits have changed */
{
bool need_comma= 0;
+ ulonglong mask= glob_description_event->options_written_to_bin_log;
if (my_b_write_string(file, "SET ") ||
print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
"@@session.foreign_key_checks", &need_comma)||
@@ -1896,11 +1897,13 @@ bool Query_log_event::print_query_header(IO_CACHE* file,
"@@session.unique_checks", &need_comma) ||
print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
"@@session.autocommit", &need_comma) ||
- print_set_option(file, tmp, OPTION_NO_CHECK_CONSTRAINT_CHECKS,
- ~flags2,
+ print_set_option(file, tmp, OPTION_NO_CHECK_CONSTRAINT_CHECKS, ~flags2,
"@@session.check_constraint_checks", &need_comma) ||
- print_set_option(file, tmp, OPTION_IF_EXISTS, flags2,
- "@@session.sql_if_exists", &need_comma)||
+ print_set_option(file, tmp, mask & OPTION_IF_EXISTS, flags2,
+ "@@session.sql_if_exists", &need_comma) ||
+ print_set_option(file, tmp, mask & OPTION_EXPLICIT_DEF_TIMESTAMP, flags2,
+ "@@session.explicit_defaults_for_timestamp",
+ &need_comma) ||
my_b_printf(file,"%s\n", print_event_info->delimiter))
goto err;
print_event_info->flags2= flags2;
diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc
index 6969c409ef4..e57c19ba1b9 100644
--- a/sql/log_event_server.cc
+++ b/sql/log_event_server.cc
@@ -1970,7 +1970,9 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
OPTIONS_WRITTEN_TO_BIN_LOG must take their value from
flags2.
*/
- thd->variables.option_bits= flags2|(thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
+ ulonglong mask= rli->relay_log.description_event_for_exec->options_written_to_bin_log;
+ thd->variables.option_bits= (flags2 & mask) |
+ (thd->variables.option_bits & ~mask);
}
/*
else, we are in a 3.23/4.0 binlog; we previously received a
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c4c2f88176d..25b77a09db2 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -390,7 +390,6 @@ my_bool opt_show_slave_auth_info;
my_bool opt_log_slave_updates= 0;
my_bool opt_replicate_annotate_row_events= 0;
my_bool opt_mysql56_temporal_format=0, strict_password_validation= 1;
-my_bool opt_explicit_defaults_for_timestamp= 0;
char *opt_slave_skip_errors;
char *opt_slave_transaction_retry_errors;
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 9c09e993470..3aab2ba0da6 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -965,7 +965,6 @@ extern my_bool opt_stack_trace, disable_log_notes;
extern my_bool opt_expect_abort;
extern my_bool opt_slave_sql_verify_checksum;
extern my_bool opt_mysql56_temporal_format, strict_password_validation;
-extern my_bool opt_explicit_defaults_for_timestamp;
extern ulong binlog_checksum_options;
extern bool max_user_connections_checking;
extern ulong opt_binlog_dbug_fsync_sleep;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 391a04c2a1a..6825918cb89 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1901,7 +1901,9 @@ inline void SEL_ARG::make_root()
left=right= &null_element;
color=BLACK;
next=prev=0;
- use_count=0; elements=1;
+ use_count=0;
+ elements=1;
+ weight= 1 + (next_key_part? next_key_part->weight : 0);
}
SEL_ARG::SEL_ARG(Field *f, const uchar *min_value_arg,
@@ -9862,12 +9864,14 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
return key2;
key1->right= key1->left= &null_element;
key1->next= key1->prev= 0;
+ key1->weight= 1 + (key1->next_key_part? key1->next_key_part->weight: 0);
}
for (next=key1->first(); next ; next=next->next)
{
if (next->next_key_part)
{
+ uint old_weight= next->next_key_part->weight;
SEL_ARG *tmp= key_and(param, next->next_key_part, key2, clone_flag);
if (tmp && tmp->type == SEL_ARG::IMPOSSIBLE)
{
@@ -9875,21 +9879,22 @@ and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
continue;
}
next->next_key_part=tmp;
+ key1->weight+= (tmp? tmp->weight: 0) - old_weight;
if (use_count)
next->increment_use_count(use_count);
if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS)
break;
}
else
+ {
next->next_key_part=key2;
+ key1->weight += key2->weight;
+ }
}
if (!key1)
return &null_element; // Impossible ranges
key1->use_count++;
- /* Re-compute the result tree's weight. */
- key1->update_weight_locally();
-
key1->max_part_no= MY_MAX(key2->max_part_no, key2->part+1);
return key1;
}
@@ -10053,29 +10058,6 @@ get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1)
return 0;
}
-/*
- @brief
- Update the tree weight.
-
- @detail
- Utility function to be called on a SEL_ARG tree root after doing local
- modifications concerning changes at this key part.
- Assumes that the weight of the graphs connected via next_key_part is
- up to dayte.
-*/
-void SEL_ARG::update_weight_locally()
-{
- uint new_weight= 0;
- const SEL_ARG *sl;
- for (sl= first(); sl ; sl= sl->next)
- {
- new_weight++;
- if (sl->next_key_part)
- new_weight += sl->next_key_part->weight;
- }
- weight= new_weight;
-}
-
#ifndef DBUG_OFF
/*
@@ -10835,9 +10817,6 @@ end:
}
key1->use_count++;
- /* Re-compute the result tree's weight. */
- key1->update_weight_locally();
-
key1->max_part_no= max_part_no;
return key1;
}
@@ -16258,6 +16237,7 @@ const char *dbug_print_sel_arg(SEL_ARG *sel_arg)
out.append(STRING_WITH_LEN("+inf"));
else
{
+ buf.length(0);
print_sel_arg_key(sel_arg->field, sel_arg->max_value, &buf);
out.append(buf);
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index f3ccd4d8311..1f4d3f1cd1f 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -346,7 +346,6 @@ public:
uint weight;
enum { MAX_WEIGHT = 32000 };
- void update_weight_locally();
#ifndef DBUG_OFF
uint verify_weight();
#endif
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index e83f340ea77..cdc4d54b9df 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -8257,9 +8257,8 @@ ER_INVALID_YEAR_COLUMN_LENGTH
spa "El tipo de columna YEAR(%lu) está obsoleto. Creando columna YEAR(4) en su lugar"
ER_NOT_VALID_PASSWORD
- chi "您的密码不满足当前的政策要求"
- eng "Your password does not satisfy the current policy requirements"
- spa "Su contraseña no satisface los requerimientos de la política en curso"
+ eng "Your password does not satisfy the current policy requirements (%s)"
+ ukr "Ваш пароль не відповідає поточним правилам (%s)"
ER_MUST_CHANGE_PASSWORD
bgn "Трябва първо да си смените паролата със SET PASSWORD за да можете да изпълните тази команда"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 141245979e5..7f33ad5145a 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -424,7 +424,7 @@ Item *THD::sp_fix_func_item_for_assignment(const Field *to, Item **it_addr)
{
DBUG_ENTER("THD::sp_fix_func_item_for_assignment");
Item *res= sp_fix_func_item(it_addr);
- if (res && (!res->check_assignability_to(to)))
+ if (res && (!res->check_assignability_to(to, false)))
DBUG_RETURN(res);
DBUG_RETURN(NULL);
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7d97b1c1b0f..601cae2e945 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2175,7 +2175,12 @@ static my_bool do_validate(THD *, plugin_ref plugin, void *arg)
struct validation_data *data= (struct validation_data *)arg;
struct st_mariadb_password_validation *handler=
(st_mariadb_password_validation *)plugin_decl(plugin)->info;
- return handler->validate_password(data->user, data->password, data->host);
+ if (handler->validate_password(data->user, data->password, data->host))
+ {
+ my_error(ER_NOT_VALID_PASSWORD, MYF(0), plugin_ref_to_int(plugin)->name.str);
+ return true;
+ }
+ return false;
}
@@ -2191,7 +2196,6 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user,
if (plugin_foreach(NULL, do_validate,
MariaDB_PASSWORD_VALIDATION_PLUGIN, &data))
{
- my_error(ER_NOT_VALID_PASSWORD, MYF(0));
return true;
}
}
@@ -10758,24 +10762,21 @@ static int handle_grant_data(THD *thd, Grant_tables& tables, bool drop,
}
/* Handle roles_mapping table. */
- if (tables.roles_mapping_table().table_exists())
+ if (tables.roles_mapping_table().table_exists() &&
+ (found= handle_grant_table(thd, tables.roles_mapping_table(),
+ ROLES_MAPPING_TABLE, drop, user_from, user_to)) < 0)
{
- if ((found= handle_grant_table(thd, tables.roles_mapping_table(),
- ROLES_MAPPING_TABLE, drop,
- user_from, user_to)) < 0)
- {
- /* Handle of table failed, don't touch the in-memory array. */
- result= -1;
- }
- else
- {
- /* Handle acl_roles_mappings array */
- if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) || found)
- && ! result)
- result= 1; /* At least one record/element found */
- if (search_only)
- goto end;
- }
+ /* Handle of table failed, don't touch the in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle acl_roles_mappings array */
+ if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) || found)
+ && ! result)
+ result= 1; /* At least one record/element found */
+ if (search_only)
+ goto end;
}
/* Handle user table. */
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 95adf17987c..e64dd847dcd 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1310,7 +1310,9 @@ multi_delete::initialize_tables(JOIN *join)
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
}
- init_ftfuncs(thd, thd->lex->current_select, 1);
+ if (init_ftfuncs(thd, thd->lex->current_select, 1))
+ DBUG_RETURN(true);
+
DBUG_RETURN(thd->is_fatal_error);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 9507aaf3ab7..0d4eabd2d06 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -768,7 +768,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
value_count= values->elements;
if ((res= mysql_prepare_insert(thd, table_list, fields, values,
- update_fields, update_values, duplic,
+ update_fields, update_values, duplic, ignore,
&unused_conds, FALSE)))
{
retval= thd->is_error();
@@ -839,7 +839,8 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
behaviour for non-transactional tables.
*/
if (values->elements &&
- table_list->table->check_assignability_opt_fields(fields, *values))
+ table_list->table->check_assignability_opt_fields(fields, *values,
+ ignore))
goto abort;
while ((values= its++))
@@ -1638,7 +1639,8 @@ static void prepare_for_positional_update(TABLE *table, TABLE_LIST *tables)
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
- enum_duplicates duplic, COND **where,
+ enum_duplicates duplic, bool ignore,
+ COND **where,
bool select_insert)
{
SELECT_LEX *select_lex= thd->lex->first_select_lex();
@@ -1713,7 +1715,8 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
ON DUPLICATE KEY UPDATE col=expr [, col=expr];
*/
TABLE::check_assignability_explicit_fields(update_fields,
- update_values);
+ update_values,
+ ignore);
select_lex->no_wrap_view_item= FALSE;
}
@@ -3814,7 +3817,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res)
if ((res= mysql_prepare_insert(thd, lex->query_tables, lex->field_list, 0,
lex->update_list, lex->value_list,
- lex->duplicates,
+ lex->duplicates, lex->ignore,
&select_lex->where, TRUE)))
DBUG_RETURN(res);
@@ -3915,7 +3918,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
INSERT INTO t1 (col1, col2) VALUES (expr1, expr2);
INSERT INTO t1 SET col1=expr1, col2=expr2;
*/
- res= table_list->table->check_assignability_opt_fields(*fields, values);
+ res= table_list->table->check_assignability_opt_fields(*fields, values,
+ lex->ignore);
}
if (!res && fields->elements)
@@ -3978,7 +3982,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
ON DUPLICATE KEY UPDATE col=expr [, col=expr]
*/
TABLE::check_assignability_explicit_fields(*info.update_fields,
- *info.update_values);
+ *info.update_values,
+ lex->ignore);
if (!res)
{
/*
@@ -4493,7 +4498,7 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
tmp_table.maybe_null= 0;
tmp_table.in_use= thd;
- if (!opt_explicit_defaults_for_timestamp)
+ if (!(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP))
promote_first_timestamp_column(&alter_info->create_list);
if (create_info->fix_create_fields(thd, alter_info, *create_table))
diff --git a/sql/sql_insert.h b/sql/sql_insert.h
index 80666a81c50..8b034c25877 100644
--- a/sql/sql_insert.h
+++ b/sql/sql_insert.h
@@ -27,6 +27,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
List<Item> &fields, List_item *values,
List<Item> &update_fields,
List<Item> &update_values, enum_duplicates duplic,
+ bool ignore,
COND **where, bool select_insert);
bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
List<List_item> &values, List<Item> &update_fields,
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 4d675e61a4c..c9264916de1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3184,6 +3184,7 @@ void st_select_lex_node::fast_exclude()
for (; slave; slave= slave->next)
slave->fast_exclude();
+ prev= NULL; // to ensure correct behavior of st_select_lex_unit::is_excluded()
}
@@ -3258,9 +3259,7 @@ void st_select_lex_node::exclude_from_tree()
*/
void st_select_lex_node::exclude()
{
- /* exclude from global list */
- fast_exclude();
- /* exclude from other structures */
+ /* exclude the node from the tree */
exclude_from_tree();
/*
We do not need following statements, because prev pointer of first
@@ -3268,6 +3267,8 @@ void st_select_lex_node::exclude()
if (master->slave == this)
master->slave= next;
*/
+ /* exclude all nodes under this excluded node */
+ fast_exclude();
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index dd7ca5d877a..5c02bf43351 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1040,9 +1040,9 @@ int bootstrap(MYSQL_FILE *file)
break;
case READ_BOOTSTRAP_QUERY_SIZE:
- my_printf_error(ER_UNKNOWN_ERROR, "Boostrap file error. Query size "
+ my_printf_error(ER_UNKNOWN_ERROR, "Bootstrap file error. Query size "
"exceeded %d bytes near '%s'.", MYF(0),
- MAX_BOOTSTRAP_LINE_SIZE, err_ptr);
+ MAX_BOOTSTRAP_QUERY_SIZE, err_ptr);
break;
default:
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 66781caac3e..901aee0b0c1 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2532,7 +2532,7 @@ static bool plugin_dl_foreach_internal(THD *thd, st_plugin_dl *plugin_dl,
tmp.plugin_dl= plugin_dl;
mysql_mutex_lock(&LOCK_plugin);
- if ((plugin= plugin_find_internal(&tmp.name, MYSQL_ANY_PLUGIN)) &&
+ if ((plugin= plugin_find_internal(&tmp.name, plug->type)) &&
plugin->plugin == plug)
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 8606bc10dbc..9631fdd331d 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1288,7 +1288,8 @@ static bool mysql_test_insert_common(Prepared_statement *stmt,
List<List_item> &values_list,
List<Item> &update_fields,
List<Item> &update_values,
- enum_duplicates duplic)
+ enum_duplicates duplic,
+ bool ignore)
{
THD *thd= stmt->thd;
List_iterator_fast<List_item> its(values_list);
@@ -1324,7 +1325,8 @@ static bool mysql_test_insert_common(Prepared_statement *stmt,
}
if (mysql_prepare_insert(thd, table_list, fields, values, update_fields,
- update_values, duplic, &unused_conds, FALSE))
+ update_values, duplic, ignore,
+ &unused_conds, FALSE))
goto error;
value_count= values->elements;
@@ -1379,7 +1381,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
List<List_item> &values_list,
List<Item> &update_fields,
List<Item> &update_values,
- enum_duplicates duplic)
+ enum_duplicates duplic, bool ignore)
{
THD *thd= stmt->thd;
@@ -1395,7 +1397,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
}
return mysql_test_insert_common(stmt, table_list, fields, values_list,
- update_fields, update_values, duplic);
+ update_fields, update_values, duplic, ignore);
}
@@ -2473,14 +2475,14 @@ static bool check_prepared_statement(Prepared_statement *stmt)
res= mysql_test_insert(stmt, tables, lex->field_list,
lex->many_values,
lex->update_list, lex->value_list,
- lex->duplicates);
+ lex->duplicates, lex->ignore);
break;
case SQLCOM_LOAD:
res= mysql_test_insert_common(stmt, tables, lex->field_list,
lex->many_values,
lex->update_list, lex->value_list,
- lex->duplicates);
+ lex->duplicates, lex->ignore);
break;
case SQLCOM_UPDATE:
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index b5efe53dfa4..1299f6157ac 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -136,8 +136,7 @@
#define OPTION_QUICK (1ULL << 22) // SELECT (for DELETE)
#define OPTION_KEEP_LOG (1ULL << 23) // THD, user
-/* The following is used to detect a conflict with DISTINCT */
-#define SELECT_ALL (1ULL << 24) // SELECT, user, parser
+#define OPTION_EXPLICIT_DEF_TIMESTAMP (1ULL << 24) // THD, user
#define OPTION_GTID_BEGIN (1ULL << 25) // GTID BEGIN found in log
/** The following can be set when importing tables in a 'wrong order'
@@ -180,10 +179,11 @@
#define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user
#define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage
#define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern
-#define SELECT_NO_UNLOCK (1ULL << 41) // SELECT, intern
#define OPTION_BIN_TMP_LOG_OFF (1ULL << 42) // disable binlog, intern
/* Disable commit of binlog. Used to combine many DDL's and DML's as one */
#define OPTION_BIN_COMMIT_OFF (1ULL << 43)
+/* The following is used to detect a conflict with DISTINCT */
+#define SELECT_ALL (1ULL << 44) // SELECT, user, parser
#define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 48f75f89dd1..9bd6aa4d5d3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1996,6 +1996,9 @@ JOIN::optimize_inner()
DEBUG_SYNC(thd, "before_join_optimize");
THD_STAGE_INFO(thd, stage_optimizing);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= 0;
+#endif
// rownum used somewhere in query, no limits and it is derived
if (unlikely(thd->lex->with_rownum &&
@@ -3289,6 +3292,9 @@ setup_subq_exit:
{
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
DBUG_RETURN(1);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= 1;
+#endif
need_tmp= 1;
}
if (make_aggr_tables_info())
@@ -3602,6 +3608,7 @@ bool JOIN::make_aggr_tables_info()
{
aggr_tables++;
curr_tab= join_tab + exec_join_tab_cnt();
+ DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
bzero((void*)curr_tab, sizeof(JOIN_TAB));
curr_tab->ref.key= -1;
if (only_const_tables())
@@ -3730,6 +3737,7 @@ bool JOIN::make_aggr_tables_info()
curr_tab++;
aggr_tables++;
+ DBUG_ASSERT(curr_tab - join_tab < dbug_join_tab_array_size);
bzero((void*)curr_tab, sizeof(JOIN_TAB));
curr_tab->ref.key= -1;
@@ -10882,6 +10890,21 @@ bool JOIN::get_best_combination()
fix_semijoin_strategies_for_picked_join_order(this);
top_join_tab_count= get_number_of_tables_at_top_level(this);
+#ifndef DBUG_OFF
+ dbug_join_tab_array_size= top_join_tab_count + aggr_tables;
+#endif
+ /*
+ NOTE: The above computation of aggr_tables can produce wrong result because some
+ of the variables it uses may change their values after we leave this function.
+ Known examples:
+ - Dangerous: using_outer_summary_function=false at this point. Added
+ DBUG_ASSERT below to demonstrate. Can this cause us to allocate less
+ space than we would need?
+ - Not dangerous: select_distinct can be true here but be assigned false
+ afterwards.
+ */
+ aggr_tables= 2;
+ DBUG_ASSERT(!tmp_table_param.using_outer_summary_function);
if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*
(top_join_tab_count + aggr_tables))))
DBUG_RETURN(TRUE);
diff --git a/sql/sql_select.h b/sql/sql_select.h
index d72fc82be81..3a28c431df5 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1317,6 +1317,7 @@ public:
#ifndef DBUG_OFF
void dbug_verify_sj_inner_tables(uint n_positions) const;
+ int dbug_join_tab_array_size;
#endif
/* We also maintain a stack of join optimization states in * join->positions[] */
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 9238d169fee..3af5771edc3 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2292,13 +2292,17 @@ bool Column_definition::prepare_stage2(handler *file,
void promote_first_timestamp_column(List<Create_field> *column_definitions)
{
+ bool first= true;
for (Create_field &column_definition : *column_definitions)
{
if (column_definition.is_timestamp_type() || // TIMESTAMP
column_definition.unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
{
+ if (!column_definition.explicitly_nullable)
+ column_definition.flags|= NOT_NULL_FLAG;
DBUG_PRINT("info", ("field-ptr:%p", column_definition.field));
- if ((column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
+ if (first &&
+ (column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
column_definition.default_value == NULL && // no constant default,
column_definition.unireg_check == Field::NONE && // no function default
column_definition.vcol_info == NULL &&
@@ -2312,7 +2316,7 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
));
column_definition.unireg_check= Field::TIMESTAMP_DNUN_FIELD;
}
- return;
+ first= false;
}
}
}
@@ -3637,7 +3641,7 @@ without_overlaps_err:
!sql_field->has_default_function() &&
(sql_field->flags & NOT_NULL_FLAG) &&
(!sql_field->is_timestamp_type() ||
- opt_explicit_defaults_for_timestamp)&&
+ (thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP))&&
!sql_field->vers_sys_field())
{
sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
@@ -3648,7 +3652,7 @@ without_overlaps_err:
!sql_field->default_value && !sql_field->vcol_info &&
!sql_field->vers_sys_field() &&
sql_field->is_timestamp_type() &&
- !opt_explicit_defaults_for_timestamp &&
+ !(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP) &&
(sql_field->flags & NOT_NULL_FLAG) &&
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
{
@@ -4811,7 +4815,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
else
create_table_mode= C_ASSISTED_DISCOVERY;
- if (!opt_explicit_defaults_for_timestamp)
+ if (!(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP))
promote_first_timestamp_column(&alter_info->create_list);
/* We can abort create table for any table type */
@@ -10358,7 +10362,7 @@ do_continue:;
create_info->fix_period_fields(thd, alter_info))
DBUG_RETURN(true);
- if (!opt_explicit_defaults_for_timestamp)
+ if (!(thd->variables.option_bits & OPTION_EXPLICIT_DEF_TIMESTAMP))
promote_first_timestamp_column(&alter_info->create_list);
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -11461,7 +11465,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (!(*ptr)->vcol_info)
{
bitmap_set_bit(from->read_set, def->field->field_index);
- if ((*ptr)->check_assignability_from(def->field))
+ if ((*ptr)->check_assignability_from(def->field, ignore))
goto err;
(copy_end++)->set(*ptr,def->field,0);
}
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index e33c8766ed0..bac93373ccb 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -4264,19 +4264,6 @@ void Type_handler_temporal_with_date::Item_update_null_value(Item *item) const
(void) item->get_date(thd, &ltime, Datetime::Options(thd));
}
-bool
-Type_handler_timestamp_common::
-Column_definition_set_attributes(THD *thd,
- Column_definition *def,
- const Lex_field_type_st &attr,
- CHARSET_INFO *cs,
- column_definition_type_t type) const
-{
- Type_handler::Column_definition_set_attributes(thd, def, attr, cs, type);
- if (!opt_explicit_defaults_for_timestamp)
- def->flags|= NOT_NULL_FLAG;
- return false;
-}
void Type_handler_string_result::Item_update_null_value(Item *item) const
{
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 0f74489719a..17605c72a4a 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -6663,12 +6663,6 @@ public:
bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*,
MYSQL_TIME *, date_mode_t fuzzydate)
const override;
- bool Column_definition_set_attributes(THD *thd,
- Column_definition *def,
- const Lex_field_type_st &attr,
- CHARSET_INFO *cs,
- column_definition_type_t type)
- const override;
};
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index e8f10920504..eda1eb8ef9e 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -523,7 +523,8 @@ int mysql_update(THD *thd,
DBUG_RETURN(1); /* purecov: inspected */
}
- if (table_list->table->check_assignability_explicit_fields(fields, values))
+ if (table_list->table->check_assignability_explicit_fields(fields, values,
+ ignore))
DBUG_RETURN(true);
if (check_unique_table(thd, table_list))
@@ -2086,7 +2087,8 @@ int multi_update::prepare(List<Item> &not_used_values,
int error= setup_fields(thd, Ref_ptr_array(),
*values, MARK_COLUMNS_READ, 0, NULL, 0) ||
- TABLE::check_assignability_explicit_fields(*fields, *values);
+ TABLE::check_assignability_explicit_fields(*fields, *values,
+ ignore);
ti.rewind();
while ((table_ref= ti++))
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d19dedf0edb..c709dd30ae6 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5817,7 +5817,6 @@ field_def:
| opt_generated_always AS virtual_column_func
{
Lex->last_field->vcol_info= $3;
- Lex->last_field->flags&= ~NOT_NULL_FLAG; // undo automatic NOT NULL for timestamps
}
vcol_opt_specifier vcol_opt_attribute
| opt_generated_always AS ROW_SYM START_SYM opt_asrow_attribute
@@ -6292,7 +6291,11 @@ attribute_list:
;
attribute:
- NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
+ NULL_SYM
+ {
+ Lex->last_field->flags&= ~NOT_NULL_FLAG;
+ Lex->last_field->explicitly_nullable= true;
+ }
| DEFAULT column_default_expr { Lex->last_field->default_value= $2; }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index aed3726e4cb..b2f5d492aaf 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -719,15 +719,13 @@ Sys_binlog_direct(
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_direct_check));
-
-static Sys_var_mybool Sys_explicit_defaults_for_timestamp(
+static Sys_var_bit Sys_explicit_defaults_for_timestamp(
"explicit_defaults_for_timestamp",
"This option causes CREATE TABLE to create all TIMESTAMP columns "
"as NULL with DEFAULT NULL attribute, Without this option, "
"TIMESTAMP columns are NOT NULL and have implicit DEFAULT clauses.",
- READ_ONLY GLOBAL_VAR(opt_explicit_defaults_for_timestamp),
- CMD_LINE(OPT_ARG), DEFAULT(FALSE));
-
+ SESSION_VAR(option_bits), CMD_LINE(OPT_ARG),
+ OPTION_EXPLICIT_DEF_TIMESTAMP, DEFAULT(FALSE), NO_MUTEX_GUARD, IN_BINLOG);
static Sys_var_ulonglong Sys_bulk_insert_buff_size(
"bulk_insert_buffer_size", "Size of tree cache used in bulk "
diff --git a/sql/table.cc b/sql/table.cc
index 3adb8575fc0..d3a2c396e80 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -9250,7 +9250,8 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const
INSERT INTO t1 (a,b) VALUES (1,2);
*/
bool TABLE::check_assignability_explicit_fields(List<Item> fields,
- List<Item> values)
+ List<Item> values,
+ bool ignore)
{
DBUG_ENTER("TABLE::check_assignability_explicit_fields");
DBUG_ASSERT(fields.elements == values.elements);
@@ -9270,7 +9271,7 @@ bool TABLE::check_assignability_explicit_fields(List<Item> fields,
*/
continue;
}
- if (value->check_assignability_to(item_field->field))
+ if (value->check_assignability_to(item_field->field, ignore))
DBUG_RETURN(true);
}
DBUG_RETURN(false);
@@ -9282,7 +9283,8 @@ bool TABLE::check_assignability_explicit_fields(List<Item> fields,
all visible fields of the table, e.g.
INSERT INTO t1 VALUES (1,2);
*/
-bool TABLE::check_assignability_all_visible_fields(List<Item> &values) const
+bool TABLE::check_assignability_all_visible_fields(List<Item> &values,
+ bool ignore) const
{
DBUG_ENTER("TABLE::check_assignability_all_visible_fields");
DBUG_ASSERT(s->visible_fields == values.elements);
@@ -9291,7 +9293,7 @@ bool TABLE::check_assignability_all_visible_fields(List<Item> &values) const
for (uint i= 0; i < s->fields; i++)
{
if (!field[i]->invisible &&
- (vi++)->check_assignability_to(field[i]))
+ (vi++)->check_assignability_to(field[i], ignore))
DBUG_RETURN(true);
}
DBUG_RETURN(false);
diff --git a/sql/table.h b/sql/table.h
index 380ce0c0416..31b8616de64 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1693,9 +1693,11 @@ public:
// Check if the value list is assignable to the explicit field list
static bool check_assignability_explicit_fields(List<Item> fields,
- List<Item> values);
+ List<Item> values,
+ bool ignore);
// Check if the value list is assignable to all visible fields
- bool check_assignability_all_visible_fields(List<Item> &values) const;
+ bool check_assignability_all_visible_fields(List<Item> &values,
+ bool ignore) const;
/*
Check if the value list is assignable to:
- The explicit field list if fields.elements > 0, e.g.
@@ -1704,12 +1706,13 @@ public:
INSERT INTO t1 VALUES (1,2);
*/
bool check_assignability_opt_fields(List<Item> fields,
- List<Item> values) const
+ List<Item> values,
+ bool ignore) const
{
DBUG_ASSERT(values.elements);
return fields.elements ?
- check_assignability_explicit_fields(fields, values) :
- check_assignability_all_visible_fields(values);
+ check_assignability_explicit_fields(fields, values, ignore) :
+ check_assignability_all_visible_fields(values, ignore);
}
bool insert_all_rows_into_tmp_table(THD *thd,