diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 7 | ||||
-rw-r--r-- | sql/ha_partition.cc | 27 | ||||
-rw-r--r-- | sql/ha_sequence.cc | 4 | ||||
-rw-r--r-- | sql/handler.cc | 13 | ||||
-rw-r--r-- | sql/handler.h | 8 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_xmlfunc.cc | 34 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/opt_range.h | 1 | ||||
-rw-r--r-- | sql/opt_range_mrr.cc | 1 | ||||
-rw-r--r-- | sql/rpl_parallel.cc | 6 | ||||
-rw-r--r-- | sql/rpl_rli.cc | 65 | ||||
-rw-r--r-- | sql/rpl_rli.h | 21 | ||||
-rw-r--r-- | sql/service_wsrep.cc | 1 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 354 | ||||
-rw-r--r-- | sql/slave.cc | 31 | ||||
-rw-r--r-- | sql/sql_admin.cc | 4 | ||||
-rw-r--r-- | sql/sql_base.cc | 77 | ||||
-rw-r--r-- | sql/sql_class.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 13 | ||||
-rw-r--r-- | sql/sql_parse.cc | 3 | ||||
-rw-r--r-- | sql/sql_partition.cc | 56 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 23 | ||||
-rw-r--r-- | sql/sql_select.h | 4 | ||||
-rw-r--r-- | sql/sql_sequence.cc | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 47 | ||||
-rw-r--r-- | sql/sql_udf.cc | 4 | ||||
-rw-r--r-- | sql/table.cc | 184 | ||||
-rw-r--r-- | sql/table.h | 12 | ||||
-rw-r--r-- | sql/temporary_tables.cc | 2 | ||||
-rw-r--r-- | sql/tztime.cc | 2 | ||||
-rw-r--r-- | sql/unireg.cc | 32 |
34 files changed, 685 insertions, 374 deletions
diff --git a/sql/field.cc b/sql/field.cc index 0f5caed57f6..7a2d67876e6 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10957,6 +10957,13 @@ bool Field::save_in_field_default_value(bool view_error_processing) { THD *thd= table->in_use; + /* + TODO: MDEV-19597 Refactor TABLE::vers_update_fields() via stored virtual columns + This condition will go away as well as other conditions with vers_sys_field(). + */ + if (vers_sys_field()) + return false; + if (unlikely(flags & NO_DEFAULT_VALUE_FLAG && real_type() != MYSQL_TYPE_ENUM)) { diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 18d10710e45..123e89f8846 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2270,7 +2270,8 @@ void ha_partition::update_create_info(HA_CREATE_INFO *create_info) sub_elem= subpart_it++; DBUG_ASSERT(sub_elem); part= i * num_subparts + j; - DBUG_ASSERT(part < m_file_tot_parts && m_file[part]); + DBUG_ASSERT(part < m_file_tot_parts); + DBUG_ASSERT(m_file[part]); dummy_info.data_file_name= dummy_info.index_file_name = NULL; m_file[part]->update_create_info(&dummy_info); sub_elem->data_file_name = (char*) dummy_info.data_file_name; @@ -3725,11 +3726,13 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) err_handler: DEBUG_SYNC(ha_thd(), "partition_open_error"); - file= &m_file[m_tot_parts - 1]; - while (file-- != m_file) + DBUG_ASSERT(m_tot_parts > 0); + for (uint i= m_tot_parts - 1; ; --i) { - if (bitmap_is_set(&m_opened_partitions, (uint)(file - m_file))) - (*file)->ha_close(); + if (bitmap_is_set(&m_opened_partitions, i)) + m_file[i]->ha_close(); + if (!i) + break; } err_alloc: free_partition_bitmaps(); @@ -3993,7 +3996,8 @@ int ha_partition::external_lock(THD *thd, int lock_type) MY_BITMAP *used_partitions; DBUG_ENTER("ha_partition::external_lock"); - DBUG_ASSERT(!auto_increment_lock && !auto_increment_safe_stmt_log_lock); + DBUG_ASSERT(!auto_increment_lock); + DBUG_ASSERT(!auto_increment_safe_stmt_log_lock); if (lock_type == F_UNLCK) used_partitions= &m_locked_partitions; @@ -4272,8 +4276,8 @@ void ha_partition::unlock_row() bool ha_partition::was_semi_consistent_read() { DBUG_ENTER("ha_partition::was_semi_consistent_read"); - DBUG_ASSERT(m_last_part < m_tot_parts && - bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); + DBUG_ASSERT(m_last_part < m_tot_parts); + DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), m_last_part)); DBUG_RETURN(m_file[m_last_part]->was_semi_consistent_read()); } @@ -7175,8 +7179,8 @@ int ha_partition::partition_scan_set_up(uchar * buf, bool idx_read_flag) DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); m_ordered_scan_ongoing= m_ordered; } - DBUG_ASSERT(m_part_spec.start_part < m_tot_parts && - m_part_spec.end_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.start_part < m_tot_parts); + DBUG_ASSERT(m_part_spec.end_part < m_tot_parts); DBUG_RETURN(0); } @@ -10619,7 +10623,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, DBUG_PRINT("enter", ("offset: %lu inc: %lu desired_values: %lu " "first_value: %lu", (ulong) offset, (ulong) increment, (ulong) nb_desired_values, (ulong) *first_value)); - DBUG_ASSERT(increment && nb_desired_values); + DBUG_ASSERT(increment); + DBUG_ASSERT(nb_desired_values); *first_value= 0; if (table->s->next_number_keypart) { diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 71da208d775..5362dd2fc73 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2017, Aliyun and/or its affiliates. - Copyright (c) 2017, MariaDB corporation + Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,7 +115,7 @@ int ha_sequence::open(const char *name, int mode, uint flags) file->ha_close(); } else if (!table->s->tmp_table) - table->m_needs_reopen= true; + table->internal_set_needs_reopen(true); /* The following is needed to fix comparison of rows in diff --git a/sql/handler.cc b/sql/handler.cc index 2c8a8fab82a..eac029fd5ac 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4532,6 +4532,19 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) /** + End bulk insert +*/ + +int handler::ha_end_bulk_insert() +{ + DBUG_ENTER("handler::ha_end_bulk_insert"); + DBUG_EXECUTE_IF("crash_end_bulk_insert", + { extra(HA_EXTRA_FLUSH) ; DBUG_SUICIDE();}); + estimation_rows_to_insert= 0; + DBUG_RETURN(end_bulk_insert()); +} + +/** Bulk update row: public interface. @sa handler::bulk_update_row() diff --git a/sql/handler.h b/sql/handler.h index 6eaaf0f3256..1fd9a1c6fe0 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3431,13 +3431,7 @@ public: start_bulk_insert(rows, flags); DBUG_VOID_RETURN; } - int ha_end_bulk_insert() - { - DBUG_ENTER("handler::ha_end_bulk_insert"); - estimation_rows_to_insert= 0; - int ret= end_bulk_insert(); - DBUG_RETURN(ret); - } + int ha_end_bulk_insert(); int ha_bulk_update_row(const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found); int ha_delete_all_rows(); diff --git a/sql/item.cc b/sql/item.cc index 5c9b8b3ea3f..8ea6366e6c4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6857,8 +6857,8 @@ Item_float::Item_float(THD *thd, const char *str_arg, size_t length): value= my_charset_bin.strntod((char*) str_arg, length, &end_not_used, &error); if (unlikely(error)) { - char tmp[NAME_LEN + 1]; - my_snprintf(tmp, sizeof(tmp), "%.*s", (int)length, str_arg); + char tmp[NAME_LEN + 2]; + my_snprintf(tmp, sizeof(tmp), "%.*s", static_cast<int>(length), str_arg); my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp); } presentation= name.str= str_arg; diff --git a/sql/item.h b/sql/item.h index 4534e57376f..deb398299fc 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3679,9 +3679,11 @@ public: Field *result_field; Item_null_result(THD *thd): Item_null(thd), result_field(0) {} bool is_result_field() { return result_field != 0; } - enum_field_types field_type() const + const Type_handler *type_handler() const { - return result_field->type(); + if (result_field) + return result_field->type_handler(); + return &type_handler_null; } Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, const Tmp_field_param *param) diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index b5eda985eb2..fff8c33ac21 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -970,11 +970,16 @@ static Item *create_comparator(MY_XPATH *xpath, b->fixed_type_handler() == &type_handler_xpath_nodeset) { uint len= (uint)(xpath->query.end - context->beg); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, - "XPATH error: " - "comparison of two nodesets is not supported: '%.*s'", - MYF(0), len, context->beg); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.*s'", + MYF(0), len, context->beg); + else + my_printf_error(ER_UNKNOWN_ERROR, + "XPATH error: " + "comparison of two nodesets is not supported: '%.32T'", + MYF(0), context->beg); return 0; // TODO: Comparison of two nodesets } @@ -2627,9 +2632,12 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath) xpath->item= NULL; DBUG_ASSERT(xpath->query.end > dollar_pos); uint len= (uint)(xpath->query.end - dollar_pos); - set_if_smaller(len, 32); - my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", - MYF(0), len, dollar_pos); + if (len <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", + MYF(0), len, dollar_pos); + else + my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.32T'", + MYF(0), dollar_pos); } } return xpath->item ? 1 : 0; @@ -2760,9 +2768,13 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) if (!rc) { uint clen= (uint)(xpath.query.end - xpath.lasttok.beg); - set_if_smaller(clen, 32); - my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", - MYF(0), clen, xpath.lasttok.beg); + if (clen <= 32) + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", + MYF(0), clen, xpath.lasttok.beg); + else + my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.32T'", + MYF(0), xpath.lasttok.beg); + return true; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2ed732329d2..ebac83bc00d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -327,7 +327,6 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0, opt_silent_startup= 0; -bool my_disable_leak_check= false; ulong max_used_connections; static char *mysqld_user, *mysqld_chroot; diff --git a/sql/opt_range.h b/sql/opt_range.h index a504e35bf45..664e821f8d1 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -673,6 +673,7 @@ public: bool statement_should_be_aborted() const { return + thd->killed || thd->is_fatal_error || thd->is_error() || alloced_sel_args > SEL_ARG::MAX_SEL_ARGS; diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc index 267d764bb3b..20413f5df63 100644 --- a/sql/opt_range_mrr.cc +++ b/sql/opt_range_mrr.cc @@ -79,6 +79,7 @@ range_seq_t sel_arg_range_seq_init(void *init_param, uint n_ranges, uint flags) SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param; seq->param->range_count=0; seq->at_start= TRUE; + seq->param->max_key_parts= 0; seq->stack[0].key_tree= NULL; seq->stack[0].min_key= seq->param->min_key; seq->stack[0].min_key_flag= 0; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index d33e26d2ecc..af84c9e6f18 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -93,18 +93,18 @@ handle_queued_pos_update(THD *thd, rpl_parallel_thread::queued_event *qev) /* Do not update position if an earlier event group caused an error abort. */ DBUG_ASSERT(qev->typ == rpl_parallel_thread::queued_event::QUEUED_POS_UPDATE); + rli= qev->rgi->rli; e= qev->entry_for_queued; - if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || e->force_abort) + if (e->stop_on_error_sub_id < (uint64)ULONGLONG_MAX || + (e->force_abort && !rli->stop_for_until)) return; - rli= qev->rgi->rli; mysql_mutex_lock(&rli->data_lock); cmp= strcmp(rli->group_relay_log_name, qev->event_relay_log_name); if (cmp < 0) { rli->group_relay_log_pos= qev->future_event_relay_log_pos; strmake_buf(rli->group_relay_log_name, qev->event_relay_log_name); - rli->notify_group_relay_log_name_update(); } else if (cmp == 0 && rli->group_relay_log_pos < qev->future_event_relay_log_pos) rli->group_relay_log_pos= qev->future_event_relay_log_pos; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index fbda0f57f74..c11889a08cd 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -62,6 +62,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), executed_entries(0), sql_delay(0), sql_delay_end(0), + until_relay_log_names_defer(false), m_flags(0) { DBUG_ENTER("Relay_log_info::Relay_log_info"); @@ -505,6 +506,8 @@ void Relay_log_info::clear_until_condition() until_condition= Relay_log_info::UNTIL_NONE; until_log_name[0]= 0; until_log_pos= 0; + until_relay_log_names_defer= false; + DBUG_VOID_RETURN; } @@ -995,7 +998,6 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, { group_relay_log_pos= rgi->future_event_relay_log_pos; strmake_buf(group_relay_log_name, rgi->event_relay_log_name); - notify_group_relay_log_name_update(); } else if (cmp == 0 && group_relay_log_pos < rgi->future_event_relay_log_pos) group_relay_log_pos= rgi->future_event_relay_log_pos; @@ -1285,29 +1287,78 @@ err: autoincrement or if we have transactions). Should be called ONLY if until_condition != UNTIL_NONE ! + + In the parallel execution mode and UNTIL_MASTER_POS the file name is + presented by future_event_master_log_name which may be ahead of + group_master_log_name. Log_event::log_pos does relate to it nevertheless + so the pair comprises a correct binlog coordinate. + Internal group events and events that have zero log_pos also + produce the zero for the local log_pos which may not lead to the + function falsely return true. + In UNTIL_RELAY_POS the original caching and notification are simplified + to straightforward files comparison when the current event can't be + a part of an event group. + RETURN VALUE true - condition met or error happened (condition seems to have bad log file name) false - condition not met */ -bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool Relay_log_info::is_until_satisfied(Log_event *ev) { const char *log_name; ulonglong log_pos; + /* Prevents stopping within transaction; needed solely for Relay UNTIL. */ + bool in_trans= false; + DBUG_ENTER("Relay_log_info::is_until_satisfied"); if (until_condition == UNTIL_MASTER_POS) { log_name= (mi->using_parallel() ? future_event_master_log_name : group_master_log_name); - log_pos= master_beg_pos; + log_pos= (get_flag(Relay_log_info::IN_TRANSACTION) || !ev || !ev->log_pos) ? + (mi->using_parallel() ? 0 : group_master_log_pos) : + ev->log_pos - ev->data_written; } else { DBUG_ASSERT(until_condition == UNTIL_RELAY_POS); - log_name= group_relay_log_name; - log_pos= group_relay_log_pos; + if (!mi->using_parallel()) + { + log_name= group_relay_log_name; + log_pos= group_relay_log_pos; + } + else + { + log_name= event_relay_log_name; + log_pos= event_relay_log_pos; + in_trans= get_flag(Relay_log_info::IN_TRANSACTION); + /* + until_log_names_cmp_result is set to UNKNOWN either + - by a non-group event *and* only when it is in the middle of a group + - or by a group event when the preceding group made the above + non-group event to defer the resetting. + */ + if ((ev && !Log_event::is_group_event(ev->get_type_code()))) + { + if (in_trans) + { + until_relay_log_names_defer= true; + } + else + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } + else if (!in_trans && until_relay_log_names_defer) + { + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; + until_relay_log_names_defer= false; + } + } } DBUG_PRINT("info", ("group_master_log_name='%s', group_master_log_pos=%llu", @@ -1361,8 +1412,8 @@ bool Relay_log_info::is_until_satisfied(my_off_t master_beg_pos) } DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && - log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); + (log_pos >= until_log_pos && !in_trans)) || + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); } diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fafe8ead63d..f89b40b1efc 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -219,7 +219,7 @@ public: */ char future_event_master_log_name[FN_REFLEN]; - /* + /* Original log name and position of the group we're currently executing (whose coordinates are group_relay_log_name/pos in the relay log) in the master's binlog. These concern the *group*, because in the master's @@ -419,7 +419,7 @@ public: void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t); + bool is_until_satisfied(Log_event *ev); inline ulonglong until_pos() { DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || @@ -427,7 +427,13 @@ public: return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : group_relay_log_pos); } - + inline char *until_name() + { + DBUG_ASSERT(until_condition == UNTIL_MASTER_POS || + until_condition == UNTIL_RELAY_POS); + return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_name : + group_relay_log_name); + } /** Helper function to do after statement completion. @@ -564,6 +570,15 @@ private: relay_log.info had 4 lines. Now it has 5 lines. */ static const int LINES_IN_RELAY_LOG_INFO_WITH_DELAY= 5; + /* + Hint for when to stop event distribution by sql driver thread. + The flag is set ON by a non-group event when this event is in the middle + of a group (e.g a transaction group) so it's too early + to refresh the current-relay-log vs until-log cached comparison result. + And it is checked and to decide whether it's a right time to do so + when the being processed group has been fully scheduled. + */ + bool until_relay_log_names_defer; /* Holds the state of the data in the relay log. diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index ce18410d9af..4137454e19b 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -315,6 +315,7 @@ extern "C" void wsrep_commit_ordered(THD *thd) } if (!wsrep_commit_will_write_binlog(thd)) { + DEBUG_SYNC(thd, "before_wsrep_ordered_commit"); thd->wsrep_cs().ordered_commit(); } } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 55dc2eeea22..49cabec9916 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1197,30 +1197,30 @@ ER_TABLE_EXISTS_ERROR 42S01 swe "Tabellen '%-.192s' finns redan" ukr "Таблиця '%-.192s' вже існує" ER_BAD_TABLE_ERROR 42S02 - cze "Neznámá tabulka '%-.100s'" - dan "Ukendt tabel '%-.100s'" - nla "Onbekende tabel '%-.100s'" - eng "Unknown table '%-.100s'" - est "Tundmatu tabel '%-.100s'" - fre "Table '%-.100s' inconnue" - ger "Unbekannte Tabelle '%-.100s'" - greek "Αγνωστος πίνακας '%-.100s'" - hindi "अज्ञात टेबल '%-.100s'" - hun "Ervenytelen tabla: '%-.100s'" - ita "Tabella '%-.100s' sconosciuta" - jpn "'%-.100s' は不明な表です。" - kor "테이블 '%-.100s'는 알수 없음" - nor "Ukjent tabell '%-.100s'" - norwegian-ny "Ukjent tabell '%-.100s'" - pol "Nieznana tabela '%-.100s'" - por "Tabela '%-.100s' desconhecida" - rum "Tabela '%-.100s' este invalida" - rus "Неизвестная таблица '%-.100s'" - serbian "Nepoznata tabela '%-.100s'" - slo "Neznáma tabuľka '%-.100s'" - spa "Tabla '%-.100s' desconocida" - swe "Okänd tabell '%-.100s'" - ukr "Невідома таблиця '%-.100s'" + cze "Neznámá tabulka '%-.100T'" + dan "Ukendt tabel '%-.100T'" + nla "Onbekende tabel '%-.100T'" + eng "Unknown table '%-.100T'" + est "Tundmatu tabel '%-.100T'" + fre "Table '%-.100T' inconnue" + ger "Unbekannte Tabelle '%-.100T'" + greek "Αγνωστος πίνακας '%-.100T'" + hindi "अज्ञात टेबल '%-.100T'" + hun "Ervenytelen tabla: '%-.100T'" + ita "Tabella '%-.100T' sconosciuta" + jpn "'%-.100T' は不明な表です。" + kor "테이블 '%-.100T'는 알수 없음" + nor "Ukjent tabell '%-.100T'" + norwegian-ny "Ukjent tabell '%-.100T'" + pol "Nieznana tabela '%-.100T'" + por "Tabela '%-.100T' desconhecida" + rum "Tabela '%-.100T' este invalida" + rus "Неизвестная таблица '%-.100T'" + serbian "Nepoznata tabela '%-.100T'" + slo "Neznáma tabuľka '%-.100T'" + spa "Tabla '%-.100T' desconocida" + swe "Okänd tabell '%-.100T'" + ukr "Невідома таблиця '%-.100T'" ER_NON_UNIQ_ERROR 23000 cze "Sloupec '%-.192s' v %-.192s není zcela jasný" dan "Felt: '%-.192s' i tabel %-.192s er ikke entydigt" @@ -1394,30 +1394,30 @@ ER_WRONG_VALUE_COUNT 21S01 swe "Antalet kolumner motsvarar inte antalet värden" ukr "Кількість стовбців не співпадає з кількістю значень" ER_TOO_LONG_IDENT 42000 S1009 - cze "Jméno identifikátoru '%-.100s' je příliš dlouhé" - dan "Navnet '%-.100s' er for langt" - nla "Naam voor herkenning '%-.100s' is te lang" - eng "Identifier name '%-.100s' is too long" - est "Identifikaatori '%-.100s' nimi on liiga pikk" - fre "Le nom de l'identificateur '%-.100s' est trop long" - ger "Name des Bezeichners '%-.100s' ist zu lang" - greek "Το identifier name '%-.100s' είναι πολύ μεγάλο" - hindi "पहचानकर्ता का नाम '%-.100s' बहुत लंबा है" - hun "A(z) '%-.100s' azonositonev tul hosszu" - ita "Il nome dell'identificatore '%-.100s' e` troppo lungo" - jpn "識別子名 '%-.100s' は長すぎます。" - kor "Identifier '%-.100s'는 너무 길군요." - nor "Identifikator '%-.100s' er for lang" - norwegian-ny "Identifikator '%-.100s' er for lang" - pol "Nazwa identyfikatora '%-.100s' jest zbyt długa" - por "Nome identificador '%-.100s' é longo demais" - rum "Numele indentificatorului '%-.100s' este prea lung" - rus "Слишком длинный идентификатор '%-.100s'" - serbian "Ime '%-.100s' je predugačko" - slo "Meno identifikátora '%-.100s' je príliš dlhé" - spa "El nombre del identificador '%-.100s' es demasiado grande" - swe "Kolumnnamn '%-.100s' är för långt" - ukr "Ім'я ідентифікатора '%-.100s' задовге" + cze "Jméno identifikátoru '%-.100T' je příliš dlouhé" + dan "Navnet '%-.100T' er for langt" + nla "Naam voor herkenning '%-.100T' is te lang" + eng "Identifier name '%-.100T' is too long" + est "Identifikaatori '%-.100T' nimi on liiga pikk" + fre "Le nom de l'identificateur '%-.100T' est trop long" + ger "Name des Bezeichners '%-.100T' ist zu lang" + greek "Το identifier name '%-.100T' είναι πολύ μεγάλο" + hindi "पहचानकर्ता का नाम '%-.100T' बहुत लंबा है" + hun "A(z) '%-.100T' azonositonev tul hosszu" + ita "Il nome dell'identificatore '%-.100T' e` troppo lungo" + jpn "識別子名 '%-.100T' は長すぎます。" + kor "Identifier '%-.100T'는 너무 길군요." + nor "Identifikator '%-.100T' er for lang" + norwegian-ny "Identifikator '%-.100T' er for lang" + pol "Nazwa identyfikatora '%-.100T' jest zbyt długa" + por "Nome identificador '%-.100T' é longo demais" + rum "Numele indentificatorului '%-.100T' este prea lung" + rus "Слишком длинный идентификатор '%-.100T'" + serbian "Ime '%-.100T' je predugačko" + slo "Meno identifikátora '%-.100T' je príliš dlhé" + spa "El nombre del identificador '%-.100T' es demasiado grande" + swe "Kolumnnamn '%-.100T' är för långt" + ukr "Ім'я ідентифікатора '%-.100T' задовге" ER_DUP_FIELDNAME 42S21 S1009 cze "Zdvojené jméno sloupce '%-.192s'" dan "Feltnavnet '%-.192s' findes allerede" @@ -1471,30 +1471,30 @@ ER_DUP_KEYNAME 42000 S1009 # When using this error code, please use ER(ER_DUP_ENTRY_WITH_KEY_NAME) # for the message string. See, for example, code in handler.cc. ER_DUP_ENTRY 23000 S1009 - cze "Zdvojený klíč '%-.192s' (číslo klíče %d)" - dan "Ens værdier '%-.192s' for indeks %d" - nla "Dubbele ingang '%-.192s' voor zoeksleutel %d" - eng "Duplicate entry '%-.192s' for key %d" - est "Kattuv väärtus '%-.192s' võtmele %d" - fre "Duplicata du champ '%-.192s' pour la clef %d" - ger "Doppelter Eintrag '%-.192s' für Schlüssel %d" - greek "Διπλή εγγραφή '%-.192s' για το κλειδί %d" - hindi "सामान प्रवेश '%-.192s' KEY %d के लिए" - hun "Duplikalt bejegyzes '%-.192s' a %d kulcs szerint" - ita "Valore duplicato '%-.192s' per la chiave %d" - jpn "'%-.192s' は索引 %d で重複しています。" - kor "중복된 입력 값 '%-.192s': key %d" - nor "Like verdier '%-.192s' for nøkkel %d" - norwegian-ny "Like verdiar '%-.192s' for nykkel %d" - pol "Powtórzone wystąpienie '%-.192s' dla klucza %d" - por "Entrada '%-.192s' duplicada para a chave %d" - rum "Cimpul '%-.192s' e duplicat pentru cheia %d" - rus "Дублирующаяся запись '%-.192s' по ключу %d" - serbian "Dupliran unos '%-.192s' za ključ '%d'" - slo "Opakovaný kľúč '%-.192s' (číslo kľúča %d)" - spa "Entrada duplicada '%-.192s' para la clave %d" - swe "Dublett '%-.192s' för nyckel %d" - ukr "Дублюючий запис '%-.192s' для ключа %d" + cze "Zdvojený klíč '%-.192T' (číslo klíče %d)" + dan "Ens værdier '%-.192T' for indeks %d" + nla "Dubbele ingang '%-.192T' voor zoeksleutel %d" + eng "Duplicate entry '%-.192T' for key %d" + est "Kattuv väärtus '%-.192T' võtmele %d" + fre "Duplicata du champ '%-.192T' pour la clef %d" + ger "Doppelter Eintrag '%-.192T' für Schlüssel %d" + greek "Διπλή εγγραφή '%-.192T' για το κλειδί %d" + hindi "सामान प्रवेश '%-.192T' KEY %d के लिए" + hun "Duplikalt bejegyzes '%-.192T' a %d kulcs szerint" + ita "Valore duplicato '%-.192T' per la chiave %d" + jpn "'%-.192T' は索引 %d で重複しています。" + kor "중복된 입력 값 '%-.192T': key %d" + nor "Like verdier '%-.192T' for nøkkel %d" + norwegian-ny "Like verdiar '%-.192T' for nykkel %d" + pol "Powtórzone wystąpienie '%-.192T' dla klucza %d" + por "Entrada '%-.192T' duplicada para a chave %d" + rum "Cimpul '%-.192T' e duplicat pentru cheia %d" + rus "Дублирующаяся запись '%-.192T' по ключу %d" + serbian "Dupliran unos '%-.192T' za ključ '%d'" + slo "Opakovaný kľúč '%-.192T' (číslo kľúča %d)" + spa "Entrada duplicada '%-.192T' para la clave %d" + swe "Dublett '%-.192T' för nyckel %d" + ukr "Дублюючий запис '%-.192T' для ключа %d" ER_WRONG_FIELD_SPEC 42000 S1009 cze "Chybná specifikace sloupce '%-.192s'" dan "Forkert kolonnespecifikaton for felt '%-.192s'" @@ -1521,30 +1521,30 @@ ER_WRONG_FIELD_SPEC 42000 S1009 swe "Felaktigt kolumntyp för kolumn '%-.192s'" ukr "Невірний специфікатор стовбця '%-.192s'" ER_PARSE_ERROR 42000 s1009 - cze "%s blízko '%-.80s' na řádku %d" - dan "%s nær '%-.80s' på linje %d" - nla "%s bij '%-.80s' in regel %d" - eng "%s near '%-.80s' at line %d" - est "%s '%-.80s' ligidal real %d" - fre "%s près de '%-.80s' à la ligne %d" - ger "%s bei '%-.80s' in Zeile %d" - greek "%s πλησίον '%-.80s' στη γραμμή %d" - hindi "%s के पास '%-.80s' लाइन %d में" - hun "A %s a '%-.80s'-hez kozeli a %d sorban" - ita "%s vicino a '%-.80s' linea %d" - jpn "%s : '%-.80s' 付近 %d 行目" - kor "'%s' 에러 같읍니다. ('%-.80s' 명령어 라인 %d)" - nor "%s nær '%-.80s' på linje %d" - norwegian-ny "%s attmed '%-.80s' på line %d" - pol "%s obok '%-.80s' w linii %d" - por "%s próximo a '%-.80s' na linha %d" - rum "%s linga '%-.80s' pe linia %d" - rus "%s около '%-.80s' на строке %d" - serbian "'%s' u iskazu '%-.80s' na liniji %d" - slo "%s blízko '%-.80s' na riadku %d" - spa "%s cerca '%-.80s' en la linea %d" - swe "%s nära '%-.80s' på rad %d" - ukr "%s біля '%-.80s' в строці %d" + cze "%s blízko '%-.80T' na řádku %d" + dan "%s nær '%-.80T' på linje %d" + nla "%s bij '%-.80T' in regel %d" + eng "%s near '%-.80T' at line %d" + est "%s '%-.80T' ligidal real %d" + fre "%s près de '%-.80T' à la ligne %d" + ger "%s bei '%-.80T' in Zeile %d" + greek "%s πλησίον '%-.80T' στη γραμμή %d" + hindi "%s के पास '%-.80T' लाइन %d में" + hun "A %s a '%-.80T'-hez kozeli a %d sorban" + ita "%s vicino a '%-.80T' linea %d" + jpn "%s : '%-.80T' 付近 %d 行目" + kor "'%s' 에러 같읍니다. ('%-.80T' 명령어 라인 %d)" + nor "%s nær '%-.80T' på linje %d" + norwegian-ny "%s attmed '%-.80T' på line %d" + pol "%s obok '%-.80T' w linii %d" + por "%s próximo a '%-.80T' na linha %d" + rum "%s linga '%-.80T' pe linia %d" + rus "%s около '%-.80T' на строке %d" + serbian "'%s' u iskazu '%-.80T' na liniji %d" + slo "%s blízko '%-.80T' na riadku %d" + spa "%s cerca '%-.80T' en la linea %d" + swe "%s nära '%-.80T' på rad %d" + ukr "%s біля '%-.80T' в строці %d" ER_EMPTY_QUERY 42000 cze "Výsledek dotazu je prázdný" dan "Forespørgsel var tom" @@ -2380,30 +2380,30 @@ ER_TABLE_NOT_LOCKED ER_UNUSED_17 eng "You should never see it" ER_WRONG_DB_NAME 42000 - cze "Nepřípustné jméno databáze '%-.100s'" - dan "Ugyldigt database navn '%-.100s'" - nla "Databasenaam '%-.100s' is niet getoegestaan" - eng "Incorrect database name '%-.100s'" - est "Vigane andmebaasi nimi '%-.100s'" - fre "Nom de base de donnée illégal: '%-.100s'" - ger "Unerlaubter Datenbankname '%-.100s'" - greek "Λάθος όνομα βάσης δεδομένων '%-.100s'" - hindi "डेटाबेस नाम '%-.100s' गलत है" - hun "Hibas adatbazisnev: '%-.100s'" - ita "Nome database errato '%-.100s'" - jpn "データベース名 '%-.100s' は不正です。" - kor "'%-.100s' 데이타베이스의 이름이 부정확합니다." - nor "Ugyldig database navn '%-.100s'" - norwegian-ny "Ugyldig database namn '%-.100s'" - pol "Niedozwolona nazwa bazy danych '%-.100s'" - por "Nome de banco de dados '%-.100s' incorreto" - rum "Numele bazei de date este incorect '%-.100s'" - rus "Некорректное имя базы данных '%-.100s'" - serbian "Pogrešno ime baze '%-.100s'" - slo "Neprípustné meno databázy '%-.100s'" - spa "Nombre de base de datos ilegal '%-.100s'" - swe "Felaktigt databasnamn '%-.100s'" - ukr "Невірне ім'я бази данних '%-.100s'" + cze "Nepřípustné jméno databáze '%-.100T'" + dan "Ugyldigt database navn '%-.100T'" + nla "Databasenaam '%-.100T' is niet getoegestaan" + eng "Incorrect database name '%-.100T'" + est "Vigane andmebaasi nimi '%-.100T'" + fre "Nom de base de donnée illégal: '%-.100T'" + ger "Unerlaubter Datenbankname '%-.100T'" + greek "Λάθος όνομα βάσης δεδομένων '%-.100T'" + hindi "डेटाबेस नाम '%-.100T' गलत है" + hun "Hibas adatbazisnev: '%-.100T'" + ita "Nome database errato '%-.100T'" + jpn "データベース名 '%-.100T' は不正です。" + kor "'%-.100T' 데이타베이스의 이름이 부정확합니다." + nor "Ugyldig database navn '%-.100T'" + norwegian-ny "Ugyldig database namn '%-.100T'" + pol "Niedozwolona nazwa bazy danych '%-.100T'" + por "Nome de banco de dados '%-.100T' incorreto" + rum "Numele bazei de date este incorect '%-.100T'" + rus "Некорректное имя базы данных '%-.100T'" + serbian "Pogrešno ime baze '%-.100T'" + slo "Neprípustné meno databázy '%-.100T'" + spa "Nombre de base de datos ilegal '%-.100T'" + swe "Felaktigt databasnamn '%-.100T'" + ukr "Невірне ім'я бази данних '%-.100T'" ER_WRONG_TABLE_NAME 42000 cze "Nepřípustné jméno tabulky '%-.100s'" dan "Ugyldigt tabel navn '%-.100s'" @@ -4688,15 +4688,15 @@ ER_NO_DEFAULT 42000 spa "Variable '%-.64s' no tiene un valor patrón" swe "Variabel '%-.64s' har inte ett DEFAULT-värde" ER_WRONG_VALUE_FOR_VAR 42000 - nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200s'" - eng "Variable '%-.64s' can't be set to the value of '%-.200s'" - ger "Variable '%-.64s' kann nicht auf '%-.200s' gesetzt werden" - ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200s'" - jpn "変数 '%-.64s' に値 '%-.200s' を設定できません。" - por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200s'" - rus "Переменная '%-.64s' не может быть установлена в значение '%-.200s'" - spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200s'" - swe "Variabel '%-.64s' kan inte sättas till '%-.200s'" + nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200T'" + eng "Variable '%-.64s' can't be set to the value of '%-.200T'" + ger "Variable '%-.64s' kann nicht auf '%-.200T' gesetzt werden" + ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200T'" + jpn "変数 '%-.64s' に値 '%-.200T' を設定できません。" + por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200T'" + rus "Переменная '%-.64s' не может быть установлена в значение '%-.200T'" + spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200T'" + swe "Variabel '%-.64s' kan inte sättas till '%-.200T'" ER_WRONG_TYPE_FOR_VAR 42000 nla "Foutief argumenttype voor variabele '%-.64s'" eng "Incorrect argument type to variable '%-.64s'" @@ -5140,11 +5140,11 @@ ER_DUPLICATED_VALUE_IN_TYPE por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s" spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s" ER_TRUNCATED_WRONG_VALUE 22007 - eng "Truncated incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert gekürzt: '%-.128s'" - jpn "不正な %-.32s の値が切り捨てられました。: '%-.128s'" - por "Truncado errado %-.32s valor: '%-.128s'" - spa "Equivocado truncado %-.32s valor: '%-.128s'" + eng "Truncated incorrect %-.32T value: '%-.128T'" + ger "Falscher %-.32T-Wert gekürzt: '%-.128T'" + jpn "不正な %-.32T の値が切り捨てられました。: '%-.128T'" + por "Truncado errado %-.32T valor: '%-.128T'" + spa "Equivocado truncado %-.32T valor: '%-.128T'" ER_TOO_MUCH_AUTO_TIMESTAMP_COLS eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" ger "Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben" @@ -5181,8 +5181,8 @@ ER_WARN_INVALID_TIMESTAMP eng "Invalid TIMESTAMP value in column '%s' at row %lu" ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %lu" ER_INVALID_CHARACTER_STRING - eng "Invalid %s character string: '%.64s'" - ger "Ungültiger %s-Zeichen-String: '%.64s'" + eng "Invalid %s character string: '%.64T'" + ger "Ungültiger %s-Zeichen-String: '%.64T'" ER_WARN_ALLOWED_PACKET_OVERFLOWED eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated" ger "Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt" @@ -5426,11 +5426,11 @@ ER_DIVISION_BY_ZERO 22012 ger "Division durch 0" hindi "0 से विभाजन" ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 22007 - eng "Incorrect %-.32s value: '%-.128s' for column `%.192s`.`%.192s`.`%.192s` at row %lu" - ger "Falscher %-.32s-Wert: '%-.128s' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" + eng "Incorrect %-.32s value: '%-.128T' for column `%.192s`.`%.192s`.`%.192s` at row %lu" + ger "Falscher %-.32s-Wert: '%-.128T' für Feld '`%.192s`.`%.192s`.`%.192s` in Zeile %lu" ER_ILLEGAL_VALUE_FOR_TYPE 22007 - eng "Illegal %s '%-.192s' value found during parsing" - ger "Nicht zulässiger %s-Wert '%-.192s' beim Parsen gefunden" + eng "Illegal %s '%-.192T' value found during parsing" + ger "Nicht zulässiger %s-Wert '%-.192T' beim Parsen gefunden" ER_VIEW_NONUPD_CHECK eng "CHECK OPTION on non-updatable view %`-.192s.%`-.192s" ger "CHECK OPTION auf nicht-aktualisierbarem View %`-.192s.%`-.192s" @@ -5576,8 +5576,8 @@ ER_CANT_CREATE_USER_WITH_GRANT 42000 eng "You are not allowed to create a user with GRANT" ger "Sie dürfen keinen Benutzer mit GRANT anlegen" ER_WRONG_VALUE_FOR_TYPE - eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" - ger "Falscher %-.32s-Wert: '%-.128s' für Funktion %-.32s" + eng "Incorrect %-.32s value: '%-.128T' for function %-.32s" + ger "Falscher %-.32s-Wert: '%-.128T' für Funktion %-.32s" ER_TABLE_DEF_CHANGED eng "Table definition has changed, please retry transaction" ger "Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu" @@ -5756,8 +5756,8 @@ ER_HOSTNAME ger "Hostname" hindi "होस्ट का नाम" ER_WRONG_STRING_LENGTH - eng "String '%-.70s' is too long for %s (should be no longer than %d)" - ger "String '%-.70s' ist zu lang für %s (sollte nicht länger sein als %d)" + eng "String '%-.70T' is too long for %s (should be no longer than %d)" + ger "String '%-.70T' ist zu lang für %s (sollte nicht länger sein als %d)" ER_NON_INSERTABLE_TABLE eng "The target table %-.100s of the %s is not insertable-into" ger "Die Zieltabelle %-.100s von %s ist nicht einfügbar" @@ -5962,8 +5962,8 @@ ER_PLUGIN_IS_NOT_LOADED eng "Plugin '%-.192s' is not loaded" ger "Plugin '%-.192s' ist nicht geladen" ER_WRONG_VALUE - eng "Incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert: '%-.128s'" + eng "Incorrect %-.32s value: '%-.128T'" + ger "Falscher %-.32s-Wert: '%-.128T'" ER_NO_PARTITION_FOR_GIVEN_VALUE eng "Table has no partition for value %-.64s" ger "Tabelle hat für den Wert %-.64s keine Partition" @@ -6106,8 +6106,8 @@ ER_WRONG_PARTITION_NAME ER_CANT_CHANGE_TX_CHARACTERISTICS 25001 eng "Transaction characteristics can't be changed while a transaction is in progress" ER_DUP_ENTRY_AUTOINCREMENT_CASE - eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'" - ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192s' für Schlüssel '%-.192s' auftritt" + eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192T' for key '%-.192s'" + ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192T' für Schlüssel '%-.192s' auftritt" ER_EVENT_MODIFY_QUEUE_ERROR eng "Internal scheduler error %d" ger "Interner Scheduler-Fehler %d" @@ -6162,29 +6162,29 @@ ER_NATIVE_FCT_NAME_COLLISION # When using this error message, use the ER_DUP_ENTRY error code. See, for # example, code in handler.cc. ER_DUP_ENTRY_WITH_KEY_NAME 23000 S1009 - cze "Zvojený klíč '%-.64s' (číslo klíče '%-.192s')" - dan "Ens værdier '%-.64s' for indeks '%-.192s'" - nla "Dubbele ingang '%-.64s' voor zoeksleutel '%-.192s'" - eng "Duplicate entry '%-.64s' for key '%-.192s'" - est "Kattuv väärtus '%-.64s' võtmele '%-.192s'" - fre "Duplicata du champ '%-.64s' pour la clef '%-.192s'" - ger "Doppelter Eintrag '%-.64s' für Schlüssel '%-.192s'" - greek "Διπλή εγγραφή '%-.64s' για το κλειδί '%-.192s'" - hun "Duplikalt bejegyzes '%-.64s' a '%-.192s' kulcs szerint" - ita "Valore duplicato '%-.64s' per la chiave '%-.192s'" - jpn "'%-.64s' は索引 '%-.192s' で重複しています。" - kor "중복된 입력 값 '%-.64s': key '%-.192s'" - nor "Like verdier '%-.64s' for nøkkel '%-.192s'" - norwegian-ny "Like verdiar '%-.64s' for nykkel '%-.192s'" - pol "Powtórzone wystąpienie '%-.64s' dla klucza '%-.192s'" - por "Entrada '%-.64s' duplicada para a chave '%-.192s'" - rum "Cimpul '%-.64s' e duplicat pentru cheia '%-.192s'" - rus "Дублирующаяся запись '%-.64s' по ключу '%-.192s'" - serbian "Dupliran unos '%-.64s' za ključ '%-.192s'" - slo "Opakovaný kľúč '%-.64s' (číslo kľúča '%-.192s')" - spa "Entrada duplicada '%-.64s' para la clave '%-.192s'" - swe "Dublett '%-.64s' för nyckel '%-.192s'" - ukr "Дублюючий запис '%-.64s' для ключа '%-.192s'" + cze "Zvojený klíč '%-.64T' (číslo klíče '%-.192s')" + dan "Ens værdier '%-.64T' for indeks '%-.192s'" + nla "Dubbele ingang '%-.64T' voor zoeksleutel '%-.192s'" + eng "Duplicate entry '%-.64T' for key '%-.192s'" + est "Kattuv väärtus '%-.64T' võtmele '%-.192s'" + fre "Duplicata du champ '%-.64T' pour la clef '%-.192s'" + ger "Doppelter Eintrag '%-.64T' für Schlüssel '%-.192s'" + greek "Διπλή εγγραφή '%-.64T' για το κλειδί '%-.192s'" + hun "Duplikalt bejegyzes '%-.64T' a '%-.192s' kulcs szerint" + ita "Valore duplicato '%-.64T' per la chiave '%-.192s'" + jpn "'%-.64T' は索引 '%-.192s' で重複しています。" + kor "중복된 입력 값 '%-.64T': key '%-.192s'" + nor "Like verdier '%-.64T' for nøkkel '%-.192s'" + norwegian-ny "Like verdiar '%-.64T' for nykkel '%-.192s'" + pol "Powtórzone wystąpienie '%-.64T' dla klucza '%-.192s'" + por "Entrada '%-.64T' duplicada para a chave '%-.192s'" + rum "Cimpul '%-.64T' e duplicat pentru cheia '%-.192s'" + rus "Дублирующаяся запись '%-.64T' по ключу '%-.192s'" + serbian "Dupliran unos '%-.64T' za ključ '%-.192s'" + slo "Opakovaný kľúč '%-.64T' (číslo kľúča '%-.192s')" + spa "Entrada duplicada '%-.64T' para la clave '%-.192s'" + swe "Dublett '%-.64T' för nyckel '%-.192s'" + ukr "Дублюючий запис '%-.64T' для ключа '%-.192s'" ER_BINLOG_PURGE_EMFILE eng "Too many files opened, please execute the command again" ger "Zu viele offene Dateien, bitte führen Sie den Befehl noch einmal aus" @@ -6465,8 +6465,8 @@ ER_SLAVE_CANT_CREATE_CONVERSION ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT eng "Cannot modify @@session.binlog_format inside a transaction" ER_PATH_LENGTH - eng "The path specified for %.64s is too long" - hindi "%.64s के लिए निर्दिष्ट पथ बहुत लंबा है" + eng "The path specified for %.64T is too long" + hindi "%.64T के लिए निर्दिष्ट पथ बहुत लंबा है" ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT eng "'%s' is deprecated and will be removed in a future release" ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden" @@ -7166,8 +7166,8 @@ ER_UNKNOWN_OPTION eng "Unknown option '%-.64s'" hindi "अज्ञात विकल्प '%-.64s'" ER_BAD_OPTION_VALUE - eng "Incorrect value '%-.64s' for option '%-.64s'" - hindi "गलत मान '%-.64s' विकल्प '%-.64s' के लिए" + eng "Incorrect value '%-.64T' for option '%-.64s'" + hindi "गलत मान '%-.64T' विकल्प '%-.64s' के लिए" ER_UNUSED_6 eng "You should never see it" ER_UNUSED_7 @@ -7324,8 +7324,8 @@ ER_ROLE_DROP_EXISTS ER_CANNOT_CONVERT_CHARACTER eng "Cannot convert '%s' character 0x%-.64s to '%s'" ER_INVALID_DEFAULT_VALUE_FOR_FIELD 22007 - eng "Incorrect default value '%-.128s' for column '%.192s'" - hindi "गलत डिफ़ॉल्ट मान '%-.128s' कॉलम '%.192s' के लिए" + eng "Incorrect default value '%-.128T' for column '%.192s'" + hindi "गलत डिफ़ॉल्ट मान '%-.128T' कॉलम '%.192s' के लिए" ER_KILL_QUERY_DENIED_ERROR eng "You are not owner of query %lu" ger "Sie sind nicht Eigentümer von Abfrage %lu" diff --git a/sql/slave.cc b/sql/slave.cc index 1902a3681a5..0b5e8e912cf 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4355,12 +4355,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && (ev->server_id != global_system_variables.server_id || rli->replicate_same_server_id) && - rli->is_until_satisfied((rli->get_flag(Relay_log_info::IN_TRANSACTION) || !ev->log_pos) - ? rli->group_master_log_pos - : ev->log_pos - ev->data_written)) + rli->is_until_satisfied(ev)) { - sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); /* Setting abort_slave flag because we do not want additional message about error in query execution to be printed. @@ -5607,10 +5603,14 @@ pthread_handler_t handle_slave_sql(void *arg) } if ((rli->until_condition == Relay_log_info::UNTIL_MASTER_POS || rli->until_condition == Relay_log_info::UNTIL_RELAY_POS) && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(NULL)) { sql_print_information("Slave SQL thread stopped because it reached its" - " UNTIL position %llu", rli->until_pos()); + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); mysql_mutex_unlock(&rli->data_lock); goto err; } @@ -5689,7 +5689,24 @@ pthread_handler_t handle_slave_sql(void *arg) err: if (mi->using_parallel()) rli->parallel.wait_for_done(thd, rli); + /* Gtid_list_log_event::do_apply_event has already reported the GTID until */ + if (rli->stop_for_until && rli->until_condition != Relay_log_info::UNTIL_GTID) + { + if (global_system_variables.log_warnings > 2) + sql_print_information("Slave SQL thread UNTIL stop was requested at position " + "%llu in %s %s file", + rli->until_log_pos, rli->until_log_name, + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + sql_print_information("Slave SQL thread stopped because it reached its" + " UNTIL position %llu in %s %s file", + rli->until_pos(), rli->until_name(), + rli->until_condition == + Relay_log_info::UNTIL_MASTER_POS ? + "binlog" : "relaylog"); + }; /* Thread stopped. Print the current replication position to the log */ { StringBuffer<100> tmp; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 0274a51ff26..03822acf564 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1089,7 +1089,7 @@ send_result_message: } /* Make sure this table instance is not reused after the operation. */ if (table->table) - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); } result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; table->next_local= save_next_local; @@ -1213,7 +1213,7 @@ err: trans_rollback(thd); if (table && table->table) { - table->table->m_needs_reopen= true; + table->table->mark_table_for_reopen(); table->table= 0; } close_thread_tables(thd); // Shouldn't be needed diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c9865394e93..39fdefbc189 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2296,9 +2296,9 @@ Locked_tables_list::init_locked_tables(THD *thd) in reopen_tables(). reopen_tables() is a critical path and we don't want to complicate it with extra allocations. */ - m_reopen_array= (TABLE**)alloc_root(&m_locked_tables_root, - sizeof(TABLE*) * - (m_locked_tables_count+1)); + m_reopen_array= (TABLE_LIST**)alloc_root(&m_locked_tables_root, + sizeof(TABLE_LIST*) * + (m_locked_tables_count+1)); if (m_reopen_array == NULL) { reset(); @@ -2411,6 +2411,7 @@ void Locked_tables_list::reset() m_locked_tables_last= &m_locked_tables; m_reopen_array= NULL; m_locked_tables_count= 0; + some_table_marked_for_reopen= 0; } @@ -2506,7 +2507,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) in reopen_tables() always links the opened table to the beginning of the open_tables list. */ - DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]); + DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]->table); thd->open_tables->pos_in_locked_tables->table= NULL; thd->open_tables->pos_in_locked_tables= NULL; @@ -2536,10 +2537,36 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count) } +/* + Mark all instances of the table to be reopened + + This is only needed when LOCK TABLES is active +*/ + +void Locked_tables_list::mark_table_for_reopen(THD *thd, TABLE *table) +{ + TABLE_SHARE *share= table->s; + + for (TABLE_LIST *table_list= m_locked_tables; + table_list; table_list= table_list->next_global) + { + if (table_list->table->s == share) + table_list->table->internal_set_needs_reopen(true); + } + /* This is needed in the case where lock tables where not used */ + table->internal_set_needs_reopen(true); + some_table_marked_for_reopen= 1; +} + + /** Reopen the tables locked with LOCK TABLES and temporarily closed by a DDL statement or FLUSH TABLES. + @param need_reopen If set, reopen open tables that are marked with + for reopen. + If not set, reopen tables that where closed. + @note This function is a no-op if we're not under LOCK TABLES. @return TRUE if an error reopening the tables. May happen in @@ -2557,6 +2584,12 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) MYSQL_LOCK *merged_lock; DBUG_ENTER("Locked_tables_list::reopen_tables"); + DBUG_ASSERT(some_table_marked_for_reopen || !need_reopen); + + + /* Reset flag that some table was marked for reopen */ + some_table_marked_for_reopen= 0; + for (TABLE_LIST *table_list= m_locked_tables; table_list; table_list= table_list->next_global) { @@ -2580,24 +2613,32 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) else { if (table_list->table) /* The table was not closed */ - continue; - } - - /* Links into thd->open_tables upon success */ - if (open_table(thd, table_list, &ot_ctx)) - { - unlink_all_closed_tables(thd, 0, reopen_count); - DBUG_RETURN(TRUE); + continue; } - table_list->table->pos_in_locked_tables= table_list; - /* See also the comment on lock type in init_locked_tables(). */ - table_list->table->reginfo.lock_type= table_list->lock_type; DBUG_ASSERT(reopen_count < m_locked_tables_count); - m_reopen_array[reopen_count++]= table_list->table; + m_reopen_array[reopen_count++]= table_list; } if (reopen_count) { + TABLE **tables= (TABLE**) my_alloca(reopen_count * sizeof(TABLE*)); + + for (uint i= 0 ; i < reopen_count ; i++) + { + TABLE_LIST *table_list= m_reopen_array[i]; + /* Links into thd->open_tables upon success */ + if (open_table(thd, table_list, &ot_ctx)) + { + unlink_all_closed_tables(thd, 0, i); + my_afree((void*) tables); + DBUG_RETURN(TRUE); + } + tables[i]= table_list->table; + table_list->table->pos_in_locked_tables= table_list; + /* See also the comment on lock type in init_locked_tables(). */ + table_list->table->reginfo.lock_type= table_list->lock_type; + } + thd->in_lock_tables= 1; /* We re-lock all tables with mysql_lock_tables() at once rather @@ -2610,7 +2651,7 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) works fine. Patching legacy code of thr_lock.c is risking to break something else. */ - lock= mysql_lock_tables(thd, m_reopen_array, reopen_count, + lock= mysql_lock_tables(thd, tables, reopen_count, MYSQL_OPEN_REOPEN | MYSQL_LOCK_USE_MALLOC); thd->in_lock_tables= 0; if (lock == NULL || (merged_lock= @@ -2619,9 +2660,11 @@ Locked_tables_list::reopen_tables(THD *thd, bool need_reopen) unlink_all_closed_tables(thd, lock, reopen_count); if (! thd->killed) my_error(ER_LOCK_DEADLOCK, MYF(0)); + my_afree((void*) tables); DBUG_RETURN(TRUE); } thd->lock= merged_lock; + my_afree((void*) tables); } DBUG_RETURN(FALSE); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3423e978a41..83ef31dc05b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5946,7 +5946,9 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ #ifdef WITH_WSREP - if (WSREP_CLIENT_NNULL(this) && wsrep_thd_is_local(this) && + if (WSREP_CLIENT_NNULL(this) && + wsrep_thd_is_local(this) && + wsrep_is_active(this) && variables.wsrep_trx_fragment_size > 0) { if (!is_current_stmt_binlog_format_row()) diff --git a/sql/sql_class.h b/sql/sql_class.h index 6f23ff52076..2b28f7ba158 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1951,20 +1951,23 @@ private: TABLE_LIST *m_locked_tables; TABLE_LIST **m_locked_tables_last; /** An auxiliary array used only in reopen_tables(). */ - TABLE **m_reopen_array; + TABLE_LIST **m_reopen_array; /** Count the number of tables in m_locked_tables list. We can't rely on thd->lock->table_count because it excludes non-transactional temporary tables. We need to know an exact number of TABLE objects. */ - size_t m_locked_tables_count; + uint m_locked_tables_count; public: + bool some_table_marked_for_reopen; + Locked_tables_list() :m_locked_tables(NULL), m_locked_tables_last(&m_locked_tables), m_reopen_array(NULL), - m_locked_tables_count(0) + m_locked_tables_count(0), + some_table_marked_for_reopen(0) { init_sql_alloc(key_memory_locked_table_list, &m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); @@ -1987,6 +1990,7 @@ public: bool restore_lock(THD *thd, TABLE_LIST *dst_table_list, TABLE *table, MYSQL_LOCK *lock); void add_back_last_deleted_lock(TABLE_LIST *dst_table_list); + void mark_table_for_reopen(THD *thd, TABLE *table); }; @@ -4146,7 +4150,8 @@ public: The worst things that can happen is that we get a suboptimal error message. */ - if (likely((killed_err= (err_info*) alloc(sizeof(*killed_err))))) + killed_err= (err_info*) alloc_root(&main_mem_root, sizeof(*killed_err)); + if (likely(killed_err)) { killed_err->no= killed_errno_arg; ::strmake((char*) killed_err->msg, killed_err_msg_arg, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9d3ed11725c..86f81dd001a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5979,7 +5979,8 @@ finish: lex->unit.cleanup(); /* close/reopen tables that were marked to need reopen under LOCK TABLES */ - if (! thd->lex->requires_prelocking()) + if (unlikely(thd->locked_tables_list.some_table_marked_for_reopen) && + !thd->lex->requires_prelocking()) thd->locked_tables_list.reopen_tables(thd, true); if (! thd->in_sub_stmt) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index bf93047885e..34e4d6e8ea7 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4936,7 +4936,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, { *fast_alter_table= true; /* Force table re-open for consistency with the main case. */ - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -4984,7 +4984,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, must be reopened. */ *fast_alter_table= true; - table->m_needs_reopen= true; + table->mark_table_for_reopen(); } else { @@ -5885,6 +5885,37 @@ the generated partition syntax in a correct manner. *partition_changed= TRUE; } } + /* + Prohibit inplace when partitioned by primary key and the primary key is changed. + */ + if (!*partition_changed && + tab_part_info->part_field_array && + !tab_part_info->part_field_list.elements && + table->s->primary_key != MAX_KEY) + { + + if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | + ALTER_ADD_SYSTEM_VERSIONING)) + { + *partition_changed= true; + } + else + { + KEY *primary_key= table->key_info + table->s->primary_key; + List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list); + const char *primary_name= primary_key->name.str; + const Alter_drop *drop; + drop_it.rewind(); + while ((drop= drop_it++)) + { + if (drop->type == Alter_drop::KEY && + 0 == my_strcasecmp(system_charset_info, primary_name, drop->name)) + break; + } + if (drop) + *partition_changed= TRUE; + } + } } if (thd->work_part_info) { @@ -5917,23 +5948,6 @@ the generated partition syntax in a correct manner. } } - // In case of PARTITION BY KEY(), check if primary key has changed - // System versioning also implicitly adds/removes primary key parts - if (alter_info->partition_flags == 0 && part_info->list_of_part_fields - && part_info->part_field_list.elements == 0) - { - if (alter_info->flags & (ALTER_DROP_SYSTEM_VERSIONING | - ALTER_ADD_SYSTEM_VERSIONING)) - *partition_changed= true; - - List_iterator<Key> it(alter_info->key_list); - Key *key; - while((key= it++) && !*partition_changed) - { - if (key->type == Key::PRIMARY) - *partition_changed= true; - } - } /* Set up partition default_engine_type either from the create_info or from the previus table @@ -6834,7 +6848,7 @@ static void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt, partition_info *part_info= lpt->part_info->get_clone(thd); TABLE *table= lpt->table; DBUG_ENTER("handle_alter_part_error"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); /* All instances of this table needs to be closed. @@ -7050,7 +7064,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, /* option_bits is used to mark if we should log the query with IF EXISTS */ ulonglong save_option_bits= thd->variables.option_bits; DBUG_ENTER("fast_alter_partition_table"); - DBUG_ASSERT(table->m_needs_reopen); + DBUG_ASSERT(table->needs_reopen()); part_info= table->part_info; lpt->thd= thd; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0ccabf87ff5..4750be99d30 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1897,7 +1897,7 @@ static void plugin_load(MEM_ROOT *tmp_root) sql_print_error(ER_THD(new_thd, ER_GET_ERRNO), my_errno, table->file->table_type()); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + table->mark_table_for_reopen(); close_mysql_tables(new_thd); end: new_thd->db= null_clex_str; // Avoid free on thd->db diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0774dc15ef8..2347162ff84 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1036,10 +1036,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) if (vers_conditions.is_set()) { + if (vers_conditions.was_set() && + table->lock_type > TL_READ_NO_INSERT && + !vers_conditions.delete_history) + { + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table->alias.str); + DBUG_RETURN(-1); + } + if (vers_conditions.type == SYSTEM_TIME_ALL) continue; - - lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway } bool timestamps_only= table->table->versioned(VERS_TIMESTAMP); @@ -2768,11 +2774,16 @@ int JOIN::optimize_stage2() } need_tmp= test_if_need_tmp_table(); - //TODO this could probably go in test_if_need_tmp_table. - if (this->select_lex->window_specs.elements > 0) { - need_tmp= TRUE; + + /* + If window functions are present then we can't have simple_order set to + TRUE as the window function needs a temp table for computation. + ORDER BY is computed after the window function computation is done, so + the sort will be done on the temp table. + */ + if (select_lex->have_window_funcs()) simple_order= FALSE; - } + /* If the hint FORCE INDEX FOR ORDER BY/GROUP BY is used for the table diff --git a/sql/sql_select.h b/sql/sql_select.h index 46c84b9df7b..0c832f6d1ff 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1748,6 +1748,7 @@ public: - We are using an ORDER BY or GROUP BY on fields not in the first table - We are using different ORDER BY and GROUP BY orders - The user wants us to buffer the result. + - We are using WINDOW functions. When the WITH ROLLUP modifier is present, we cannot skip temporary table creation for the DISTINCT clause just because there are only const tables. */ @@ -1757,7 +1758,8 @@ public: ((select_distinct || !simple_order || !simple_group) || (group_list && order) || MY_TEST(select_options & OPTION_BUFFER_RESULT))) || - (rollup.state != ROLLUP::STATE_NONE && select_distinct)); + (rollup.state != ROLLUP::STATE_NONE && select_distinct) || + select_lex->have_window_funcs()); } bool choose_subquery_plan(table_map join_tables); void get_partial_cost_and_fanout(int end_tab_idx, diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index dd12cb85558..e351a0332e6 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -354,8 +354,10 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list) seq->reserved_until= seq->start; error= seq->write_initial_sequence(table); - trans_commit_stmt(thd); - trans_commit_implicit(thd); + if (trans_commit_stmt(thd)) + error= 1; + if (trans_commit_implicit(thd)) + error= 1; if (!temporary_table) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c90b8699b80..d748bd959bc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4331,6 +4331,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && + !sql_field->vers_sys_field() && sql_field->is_timestamp_type() && !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && @@ -4470,6 +4471,21 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, Well_formed_prefix(system_charset_info, *comment, max_len).length(); if (tmp_len < comment->length) { + if (comment->length <= max_len) + { + if (thd->is_strict_mode()) + { + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + system_charset_info->csname, comment->str); + DBUG_RETURN(true); + } + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_INVALID_CHARACTER_STRING, + ER_THD(thd, ER_INVALID_CHARACTER_STRING), + system_charset_info->csname, comment->str); + comment->length= tmp_len; + DBUG_RETURN(false); + } if (thd->is_strict_mode()) { my_error(err_code, MYF(0), name, static_cast<ulong>(max_len)); @@ -8056,16 +8072,13 @@ blob_length_by_type(enum_field_types type) } -static void append_drop_column(THD *thd, bool dont, String *str, - Field *field) +static inline +void append_drop_column(THD *thd, String *str, Field *field) { - if (!dont) - { - if (str->length()) - str->append(STRING_WITH_LEN(", ")); - str->append(STRING_WITH_LEN("DROP COLUMN ")); - append_identifier(thd, str, &field->field_name); - } + if (str->length()) + str->append(STRING_WITH_LEN(", ")); + str->append(STRING_WITH_LEN("DROP COLUMN ")); + append_identifier(thd, str, &field->field_name); } @@ -8310,7 +8323,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->invisible < INVISIBLE_SYSTEM) { StringBuffer<NAME_LEN*3> tmp; - append_drop_column(thd, false, &tmp, field); + append_drop_column(thd, &tmp, field); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8406,7 +8419,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, field->default_value->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); } - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } dropped_sys_vers_fields &= VERS_SYSTEM_FIELD; @@ -8416,10 +8430,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, !vers_system_invisible) { StringBuffer<NAME_LEN*3> tmp; - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_START_FLAG, - &tmp, table->vers_start_field()); - append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_END_FLAG, - &tmp, table->vers_end_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_START_FLAG)) + append_drop_column(thd, &tmp, table->vers_start_field()); + if (!(dropped_sys_vers_fields & VERS_SYS_END_FLAG)) + append_drop_column(thd, &tmp, table->vers_end_field()); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); goto err; } @@ -8905,7 +8919,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, { check->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param); - table->m_needs_reopen= 1; // because new column name is on thd->mem_root + // Force reopen because new column name is on thd->mem_root + table->mark_table_for_reopen(); } new_constraint_list.push_back(check, thd->mem_root); } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 4da85de7852..5df9e7dd47d 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -268,7 +268,9 @@ void udf_init() if (unlikely(error > 0)) sql_print_error("Got unknown error: %d", my_errno); end_read_record(&read_record_info); - table->m_needs_reopen= TRUE; // Force close to free memory + + // Force close to free memory + table->mark_table_for_reopen(); end: close_mysql_tables(new_thd); diff --git a/sql/table.cc b/sql/table.cc index 98d299afb37..9273e01572e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -98,8 +98,11 @@ static std::atomic<ulong> last_table_id; /* Functions defined in this file */ -static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, - uint types, char **names); +static bool fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *names, size_t names_length); + static uint find_field(Field **fields, uchar *record, uint start, uint length); inline bool is_system_table_name(const char *name, size_t length); @@ -731,7 +734,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, uint keys, KEY *keyinfo, uint new_frm_ver, uint *ext_key_parts, TABLE_SHARE *share, uint len, - KEY *first_keyinfo, char** keynames) + KEY *first_keyinfo, + LEX_STRING *keynames) { uint i, j, n_length; KEY_PART_INFO *key_part= NULL; @@ -883,10 +887,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end, share->ext_key_parts++; share->ext_key_parts+= keyinfo->ext_key_parts; } - *keynames=(char*) key_part; - strpos+= strnmov(*keynames, (char *) strpos, frm_image_end - strpos) - *keynames; + keynames->str= (char*) key_part; + keynames->length= strnmov(keynames->str, (char *) strpos, + frm_image_end - strpos) - keynames->str; + strpos+= keynames->length; if (*strpos++) // key names are \0-terminated return 1; + keynames->length++; // Include '\0', to make fix_type_pointers() happy. //reading index comments for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++) @@ -1698,11 +1705,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, TABLE_SHARE *share= this; uint new_frm_ver, field_pack_length, new_field_pack_flag; uint interval_count, interval_parts, read_length, int_length; + uint total_typelib_value_count; uint db_create_options, keys, key_parts, n_length; uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i, hash_fields= 0; bool use_hash, mysql57_null_bits= 0; - char *keynames, *names, *comment_pos; + LEX_STRING keynames= {NULL, 0}; + char *names, *comment_pos; const uchar *forminfo; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos); @@ -1714,6 +1723,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, KEY_PART_INFO *key_part= NULL; Field **field_ptr, *reg_field; const char **interval_array; + uint *typelib_value_lengths= NULL; enum legacy_db_type legacy_db_type; my_bitmap_map *bitmaps; bool null_bits_are_used; @@ -2133,11 +2143,34 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length)); + /* + We load the following things into TYPELIBs: + - One TYPELIB for field names + - interval_count TYPELIBs for ENUM/SET values + - One TYPELIB for key names + Every TYPELIB requires one extra value with a NULL pointer and zero length, + which is the end-of-values marker. + TODO-10.5+: + Note, we should eventually reuse this total_typelib_value_count + to allocate interval_array. The below code reserves less space + than total_typelib_value_count pointers. So it seems `interval_array` + and `names` overlap in the memory. Too dangerous to fix in 10.1. + */ + total_typelib_value_count= + (share->fields + 1/*end-of-values marker*/) + + (interval_parts + interval_count/*end-of-values markers*/) + + (keys + 1/*end-of-values marker*/); + if (!multi_alloc_root(&share->mem_root, &share->field, (uint)(share->fields+1)*sizeof(Field*), &share->intervals, (uint)interval_count*sizeof(TYPELIB), &share->check_constraints, (uint) share->table_check_constraints * sizeof(Virtual_column_info*), + /* + This looks wrong: shouldn't it be (+2+interval_count) + instread of (+3) ? + */ &interval_array, (uint) (share->fields+interval_parts+ keys+3)*sizeof(char *), + &typelib_value_lengths, total_typelib_value_count * sizeof(uint *), &names, (uint) (n_length+int_length), &comment_pos, (uint) com_length, &vcol_screen_pos, vcol_screen_length, @@ -2164,33 +2197,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length, vcol_screen_length); - fix_type_pointers(&interval_array, &share->fieldnames, 1, &names); - if (share->fieldnames.count != share->fields) + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->fieldnames, 1, names, n_length) || + share->fieldnames.count != share->fields) goto err; - fix_type_pointers(&interval_array, share->intervals, interval_count, &names); - { - /* Set ENUM and SET lengths */ - TYPELIB *interval; - for (interval= share->intervals; - interval < share->intervals + interval_count; - interval++) - { - uint count= (uint) (interval->count + 1) * sizeof(uint); - if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root, - count))) - goto err; - for (count= 0; count < interval->count; count++) - { - char *val= (char*) interval->type_names[count]; - interval->type_lengths[count]= (uint)strlen(val); - } - interval->type_lengths[count]= 0; - } - } + if (fix_type_pointers(&interval_array, &typelib_value_lengths, + share->intervals, interval_count, + names + n_length, int_length)) + goto err; - if (keynames) - fix_type_pointers(&interval_array, &share->keynames, 1, &keynames); + if (keynames.length && + (fix_type_pointers(&interval_array, &typelib_value_lengths, + &share->keynames, 1, keynames.str, keynames.length) || + share->keynames.count != keys)) + goto err; /* Allocate handler */ if (!(handler_file= get_new_handler(share, thd->mem_root, @@ -4403,37 +4424,81 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error, ** with a '\0' */ -static void -fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, - char **names) +static bool +fix_type_pointers(const char ***typelib_value_names, + uint **typelib_value_lengths, + TYPELIB *point_to_type, uint types, + char *ptr, size_t length) { - char *type_name, *ptr; - char chr; + const char *end= ptr + length; - ptr= *names; while (types--) { + char sep; point_to_type->name=0; - point_to_type->type_names= *array; + point_to_type->type_names= *typelib_value_names; + point_to_type->type_lengths= *typelib_value_lengths; - if ((chr= *ptr)) /* Test if empty type */ + /* + Typelib can be encoded as: + 1) 0x00 - empty typelib + 2) 0xFF 0x00 - empty typelib (index names) + 3) sep (value sep)... 0x00 - non-empty typelib (where sep is a separator) + */ + if (length == 2 && ptr[0] == (char) 0xFF && ptr[1] == '\0') + { + /* + This is a special case #2. + If there are no indexes at all, index names can be encoded + as a two byte sequence: 0xFF 0x00 + TODO: Check if it's a bug in the FRM packing routine. + It should probably write just 0x00 instead of 0xFF00. + */ + ptr+= 2; + } + else if ((sep= *ptr++)) // A non-empty typelib { - while ((type_name=strchr(ptr+1,chr)) != NullS) + for ( ; ptr < end; ) { - *((*array)++) = ptr+1; - *type_name= '\0'; /* End string */ - ptr=type_name; + // Now scan the next value+sep pair + char *vend= (char*) memchr(ptr, sep, end - ptr); + if (!vend) + return true; // Bad format + *((*typelib_value_names)++)= ptr; + *((*typelib_value_lengths)++)= (uint) (vend - ptr); + *vend= '\0'; // Change sep to '\0' + ptr= vend + 1; // Shift from sep to the next byte + /* + Now we can have either: + - the end-of-typelib marker (0x00) + - more value+sep pairs + */ + if (!*ptr) + { + /* + We have an ambiguity here. 0x00 can be an end-of-typelib marker, + but it can also be a part of the next value: + CREATE TABLE t1 (a ENUM(0x61, 0x0062) CHARACTER SET BINARY); + If this is the last ENUM/SET in the table and there is still more + packed data left after 0x00, then we know for sure that 0x00 + is a part of the next value. + TODO-10.5+: we should eventually introduce a new unambiguous + typelib encoding for FRM. + */ + if (!types && ptr + 1 < end) + continue; // A binary value starting with 0x00 + ptr++; // Consume the end-of-typelib marker + break; // End of the current typelib + } } - ptr+=2; /* Skip end mark and last 0 */ } - else - ptr++; - point_to_type->count= (uint) (*array - point_to_type->type_names); + point_to_type->count= (uint) (*typelib_value_names - + point_to_type->type_names); point_to_type++; - *((*array)++)= NullS; /* End of type */ + *((*typelib_value_names)++)= NullS; /* End of type */ + *((*typelib_value_lengths)++)= 0; /* End of type */ } - *names=ptr; /* Update end */ - return; + return ptr != end; } /* fix_type_pointers */ @@ -8523,9 +8588,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) int TABLE::update_virtual_field(Field *vf) { - DBUG_ASSERT(!in_use->is_error()); - Query_arena backup_arena; DBUG_ENTER("TABLE::update_virtual_field"); + Query_arena backup_arena; + Counting_error_handler count_errors; + in_use->push_internal_handler(&count_errors); in_use->set_n_backup_active_arena(expr_arena, &backup_arena); bitmap_clear_all(&tmp_set); vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); @@ -8533,7 +8599,8 @@ int TABLE::update_virtual_field(Field *vf) vf->vcol_info->expr->save_in_field(vf, 0); DBUG_RESTORE_WRITE_SET(vf); in_use->restore_active_arena(expr_arena, &backup_arena); - DBUG_RETURN(in_use->is_error()); + in_use->pop_internal_handler(); + DBUG_RETURN(count_errors.errors); } @@ -8858,7 +8925,7 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const for (Field **fld= field; *fld; fld++) { if (!bitmap_is_set(write_set, (*fld)->field_index) && - !((*fld)->flags & NO_DEFAULT_VALUE_FLAG)) + !((*fld)->flags & (NO_DEFAULT_VALUE_FLAG | VERS_SYSTEM_FIELD))) { if (!(*fld)->is_null_in_record(s->default_values) && (*fld)->validate_value_in_record_with_warn(thd, s->default_values) && @@ -9847,3 +9914,14 @@ void TABLE::initialize_quick_structures() bzero(quick_costs, sizeof(quick_costs)); bzero(quick_n_ranges, sizeof(quick_n_ranges)); } + +/* + Mark table to be reopened after query +*/ + +void TABLE::mark_table_for_reopen() +{ + THD *thd= in_use; + DBUG_ASSERT(thd); + thd->locked_tables_list.mark_table_for_reopen(thd, this); +} diff --git a/sql/table.h b/sql/table.h index b1c23337cce..2c7a042be69 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1395,8 +1395,8 @@ public: bool insert_or_update; /* Can be used by the handler */ bool alias_name_used; /* true if table_name is alias */ bool get_fields_in_item_tree; /* Signal to fix_field */ - bool m_needs_reopen; private: + bool m_needs_reopen; bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: #ifdef HAVE_REPLICATION @@ -1507,6 +1507,16 @@ public: /** Should this instance of the table be reopened? */ inline bool needs_reopen() { return !db_stat || m_needs_reopen; } + /* + Mark that all current connection instances of the table should be + reopen at end of statement + */ + void mark_table_for_reopen(); + /* Should only be called from Locked_tables_list::mark_table_for_reopen() */ + void internal_set_needs_reopen(bool value) + { + m_needs_reopen= value; + } bool alloc_keys(uint key_count); bool check_tmp_key(uint key, uint key_parts, diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 521b9c8973f..203571441fc 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -1070,7 +1070,7 @@ TABLE *THD::find_temporary_table(const char *key, uint key_length, case TMP_TABLE_ANY: found= true; break; } } - if (table && unlikely(table->m_needs_reopen)) + if (table && unlikely(table->needs_reopen())) { share->all_tmp_tables.remove(table); free_temporary_table(table); diff --git a/sql/tztime.cc b/sql/tztime.cc index 9797b1d4a22..b1c0c79d5d7 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1699,7 +1699,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) { tl->table->use_all_columns(); /* Force close at the end of the function to free memory. */ - tl->table->m_needs_reopen= TRUE; + tl->table->mark_table_for_reopen(); } /* diff --git a/sql/unireg.cc b/sql/unireg.cc index 6860d2c6347..fa193a7712d 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB Corporation + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -787,6 +787,18 @@ static bool pack_vcols(String *buf, List<Create_field> &create_fields, } +static uint typelib_values_packed_length(const TYPELIB *t) +{ + uint length= 0; + for (uint i= 0; t->type_names[i]; i++) + { + length+= t->type_lengths[i]; + length++; /* Separator */ + } + return length; +} + + /* Make formheader */ static bool pack_header(THD *thd, uchar *forminfo, @@ -881,9 +893,8 @@ static bool pack_header(THD *thd, uchar *forminfo, field->interval_id=get_interval_id(&int_count,create_fields,field); if (old_int_count != int_count) { - for (const char **pos=field->interval->type_names ; *pos ; pos++) - int_length+=(uint) strlen(*pos)+1; // field + suffix prefix - int_parts+=field->interval->count+1; + int_length+= typelib_values_packed_length(field->interval); + int_parts+= field->interval->count + 1; } } if (f_maybe_null(field->pack_flag)) @@ -972,11 +983,7 @@ static size_t packed_fields_length(List<Create_field> &create_fields) { int_count= field->interval_id; length++; - for (int i=0; field->interval->type_names[i]; i++) - { - length+= field->interval->type_lengths[i]; - length++; - } + length+= typelib_values_packed_length(field->interval); length++; } @@ -1100,9 +1107,10 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, static bool make_empty_rec_store_default(THD *thd, Field *regfield, - Virtual_column_info *default_value) + Create_field *field) { - if (default_value && !default_value->flags) + Virtual_column_info *default_value= field->default_value; + if (!field->vers_sys_field() && default_value && !default_value->flags) { Item *expr= default_value->expr; // may be already fixed if ALTER TABLE @@ -1184,7 +1192,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, !f_bit_as_char(field->pack_flag)) null_count+= field->length & 7; - error= make_empty_rec_store_default(thd, regfield, field->default_value); + error= make_empty_rec_store_default(thd, regfield, field); delete regfield; // Avoid memory leaks if (error) goto err; |