diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2022-08-09 09:52:15 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2022-08-09 09:52:15 +0200 |
commit | 75d631f333544de4487a6dd251d6f361e1d55d6b (patch) | |
tree | 4e234afa19a458b9b0727859c53c290c683a502d /sql | |
parent | 9cbf8ccf2990f9db8d9debee42bc9213cbb04457 (diff) | |
parent | 1d480419822b53c840de54542c1d1a0851dbe2c8 (diff) | |
download | mariadb-git-75d631f333544de4487a6dd251d6f361e1d55d6b.tar.gz |
Merge branch '10.7' into 10.8
Diffstat (limited to 'sql')
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, <ime, 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> ¬_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, |