From 5af12e463549e4bbc2ce6ab720d78937d5e5db4e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 12 Mar 2020 23:50:20 -0700 Subject: MDEV-21932 A fast plan with ROR index-merge is ignored when 'index_merge_sort_union=off' When index_merge_sort_union is set to 'off' and index_merge_union is set to 'on' then any evaluated index merge scan must consist only of ROR scans. The cheapest out of such index merges must be chosen. This index merge might not be the cheapest index merge. --- sql/opt_range.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ca6f500fec6..70c1786dd83 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6802,6 +6802,13 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, update_tbl_stats, &mrr_flags, &buf_size, &cost); + if (!param->is_ror_scan && + !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) + { + /* The scan is not a ROR-scan, just skip it */ + continue; + } + if (found_records != HA_POS_ERROR && tree->index_scans && (index_scan= (INDEX_SCAN_INFO *)alloc_root(param->mem_root, sizeof(INDEX_SCAN_INFO)))) -- cgit v1.2.1 From 407b0a6ae7c300f34535be59dcdb8ba8f84d1ce5 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 14 Mar 2020 19:58:57 -0700 Subject: MDEV-10466 Server crashed in SEL_ARG::store_min() with extended_keys=on This bug could manifest itself in a very rare cases when the optimizer chose an execution plan by which a joined table was accessed by a table scan and the optimizer was checking whether ranges checked for each record could improve this plan. In such cases the optimizer evaluates range conditions over a table that depend on other tables. For such conditions the constructed SEL_ARG trees are marked as MAYBE_KEY. If a SEL_ARG object constructed for a sargable condition marked as RANGE_KEY had the same first key part as a MAYBE_KEY SEL_ARG object and the key_and() function was called for this pair of SEL_ARG objects then an invalid SEL_ARG object could be constructed that ultimately could lead to a crash before the execution phase. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 70c1786dd83..37ca3a22c77 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8837,7 +8837,7 @@ key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag) if (key2->next_key_part) { key1->use_count--; // Incremented in and_all_keys - return and_all_keys(param, key1, key2, clone_flag); + return and_all_keys(param, key1, key2->next_key_part, clone_flag); } key2->use_count--; // Key2 doesn't have a tree } -- cgit v1.2.1 From 2d16452a31e7c2c99d191f34897e519928541cda Mon Sep 17 00:00:00 2001 From: mkaruza Date: Thu, 26 Mar 2020 09:45:03 +0100 Subject: MDEV-22021: Galera database could get inconsistent with rollback to savepoint When binlog is disabled, WSREP will not behave correctly when SAVEPOINT ROLLBACK is executed since we don't register handlers for such case. Fixed by registering WSREP handlerton for SAVEPOINT related commands. --- sql/log.cc | 6 ------ sql/transaction.cc | 6 ++++++ sql/wsrep_binlog.cc | 14 -------------- sql/wsrep_binlog.h | 2 -- sql/wsrep_hton.cc | 24 ++++++------------------ 5 files changed, 12 insertions(+), 40 deletions(-) (limited to 'sql') diff --git a/sql/log.cc b/sql/log.cc index 64da45bfcea..5a6d2fbe24e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2209,9 +2209,6 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) int error= 1; DBUG_ENTER("binlog_savepoint_set"); - if (wsrep_emulate_bin_log) - DBUG_RETURN(0); - char buf[1024]; String log_query(buf, sizeof(buf), &my_charset_bin); @@ -2245,9 +2242,6 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("binlog_savepoint_rollback"); - if (wsrep_emulate_bin_log) - DBUG_RETURN(0); - /* Write ROLLBACK TO SAVEPOINT to the binlog cache if we have updated some non-transactional table. Otherwise, truncate the binlog cache starting diff --git a/sql/transaction.cc b/sql/transaction.cc index 7cb6e132932..72b7f8e6fe4 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -614,6 +614,9 @@ bool trans_savepoint(THD *thd, LEX_STRING name) if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); + if (WSREP_ON) + wsrep_register_hton(thd, thd->in_multi_stmt_transaction_mode()); + sv= find_savepoint(thd, name); if (*sv) /* old savepoint of the same name exists */ @@ -690,6 +693,9 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name) if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); + if (WSREP_ON) + wsrep_register_hton(thd, thd->in_multi_stmt_transaction_mode()); + /** Checking whether it is safe to release metadata locks acquired after savepoint, if rollback to savepoint is successful. diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index 6e4e9f50e31..9602dd698eb 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -376,20 +376,6 @@ int wsrep_binlog_close_connection(THD* thd) DBUG_RETURN(0); } -int wsrep_binlog_savepoint_set(THD *thd, void *sv) -{ - if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_set(binlog_hton, thd, sv); - return rcode; -} - -int wsrep_binlog_savepoint_rollback(THD *thd, void *sv) -{ - if (!wsrep_emulate_bin_log) return 0; - int rcode = binlog_hton->savepoint_rollback(binlog_hton, thd, sv); - return rcode; -} - #if 0 void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache) { diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h index c2ccacdc180..ed8e19ed651 100644 --- a/sql/wsrep_binlog.h +++ b/sql/wsrep_binlog.h @@ -54,7 +54,5 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, size_t buf_len); int wsrep_binlog_close_connection(THD* thd); -int wsrep_binlog_savepoint_set(THD *thd, void *sv); -int wsrep_binlog_savepoint_rollback(THD *thd, void *sv); #endif /* WSREP_BINLOG_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 7c154d6ce6f..459cd368355 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -219,32 +219,20 @@ static int wsrep_prepare(handlerton *hton, THD *thd, bool all) DBUG_RETURN(0); } +/* + Empty callbacks to support SAVEPOINT callbacks. +*/ + static int wsrep_savepoint_set(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("wsrep_savepoint_set"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - if (!wsrep_emulate_bin_log) DBUG_RETURN(0); - int rcode = wsrep_binlog_savepoint_set(thd, sv); - DBUG_RETURN(rcode); + DBUG_RETURN(0); } static int wsrep_savepoint_rollback(handlerton *hton, THD *thd, void *sv) { DBUG_ENTER("wsrep_savepoint_rollback"); - - if (thd->wsrep_exec_mode == REPL_RECV) - { - DBUG_RETURN(0); - } - - if (!wsrep_emulate_bin_log) DBUG_RETURN(0); - int rcode = wsrep_binlog_savepoint_rollback(thd, sv); - DBUG_RETURN(rcode); + DBUG_RETURN(0); } static int wsrep_rollback(handlerton *hton, THD *thd, bool all) -- cgit v1.2.1 From b40b3720cbba133ee76ef336bf89bbf5c03ac403 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 2 Apr 2020 00:39:54 +0400 Subject: MDEV-21348 - column compression memory leak The Storage-Engine Independent Column Compression does not call deflateEnd() when deflate() does not return Z_STREAM_END. This for instance happens when the data is already (externally) compressed and deflate() needs more space than the original data. This patch is based on contribution by Martijn Broenland. --- sql/field_comp.cc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/field_comp.cc b/sql/field_comp.cc index eb4ae42aa4d..ab97c8ccf08 100644 --- a/sql/field_comp.cc +++ b/sql/field_comp.cc @@ -67,10 +67,12 @@ static uint compress_zlib(THD *thd, char *to, const char *from, uint length) stream.zfree= 0; stream.opaque= 0; - if (deflateInit2(&stream, level, Z_DEFLATED, wbits, 8, strategy) == Z_OK && - deflate(&stream, Z_FINISH) == Z_STREAM_END && - deflateEnd(&stream) == Z_OK) - return (uint) (stream.next_out - (Bytef*) to); + if (deflateInit2(&stream, level, Z_DEFLATED, wbits, 8, strategy) == Z_OK) + { + int res= deflate(&stream, Z_FINISH); + if (deflateEnd(&stream) == Z_OK && res == Z_STREAM_END) + return (uint) (stream.next_out - (Bytef*) to); + } } return 0; } @@ -117,12 +119,14 @@ static int uncompress_zlib(String *to, const uchar *from, uint from_length, stream.zfree= 0; stream.opaque= 0; - if (inflateInit2(&stream, wbits) == Z_OK && - inflate(&stream, Z_FINISH) == Z_STREAM_END && - inflateEnd(&stream) == Z_OK) + if (inflateInit2(&stream, wbits) == Z_OK) { - to->length(stream.total_out); - return 0; + int res= inflate(&stream, Z_FINISH); + if (inflateEnd(&stream) == Z_OK && res == Z_STREAM_END) + { + to->length(stream.total_out); + return 0; + } } my_error(ER_ZLIB_Z_DATA_ERROR, MYF(0)); return 1; -- cgit v1.2.1 From 9149017bb838e9efbef40c5f2807894c38b3412f Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Thu, 2 Apr 2020 22:37:36 +1000 Subject: MDEV-17091 - Assertion failed after dropping versioning Assertion `old_part_id == m_last_part' failed in ha_partition::update_row or `part_id == m_last_part' in ha_partition::delete_row upon UPDATE/DELETE after dropping versioning PRIMARY KEY change hadn't been treated as partition reorganization in case of partitioning by KEY() (without parameters). * set `*partition_changed= true` in the described case. * since add/drop system versioning does not affect alter_info->key_list, it required separate attention --- sql/sql_partition.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sql') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index febd88c4b9b..5fdca153ef7 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6016,6 +6016,24 @@ the generated partition syntax in a correct manner. *partition_changed= true; } } + + // 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 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 -- cgit v1.2.1 From 44c6c7a9236dbbe35e8fda22b36466b6000038d6 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 2 Apr 2020 20:48:38 +0300 Subject: MDEV-21342 Assertion in set_ok_status() upon spatial field error on system-versioned table SQL_SELECT::check_quick() returns error status only test_quick_select() returns -1. Fix error handling when lower frames throw error, but it is ignored by test_quick_select(). Fix return status for out-of-memory errors which are obviously must be processed as error in upper frames. --- sql/opt_range.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index bd5f25d67c2..38b52f96704 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2386,7 +2386,7 @@ static int fill_used_fields_bitmap(PARAM *param) force_quick_range is really needed. RETURN - -1 if impossible select (i.e. certainly no rows will be selected) + -1 if error or impossible select (i.e. certainly no rows will be selected) 0 if can't use quick_select 1 if found usable ranges and quick select has been successfully created. */ @@ -2473,7 +2473,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { thd->no_errors=0; free_root(&alloc,MYF(0)); // Return memory & allocator - DBUG_RETURN(0); // Can't use range + DBUG_RETURN(-1); // Error } key_parts= param.key_parts; @@ -2524,7 +2524,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { thd->no_errors=0; free_root(&alloc,MYF(0)); // Return memory & allocator - DBUG_RETURN(0); // Can't use range + DBUG_RETURN(-1); // Error } thd->mem_root= &alloc; @@ -2561,6 +2561,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER) tree= NULL; } + else if (thd->is_error()) + { + thd->no_errors=0; + thd->mem_root= param.old_root; + free_root(&alloc, MYF(0)); + DBUG_RETURN(-1); + } } /* -- cgit v1.2.1 From ba34f409ad104471d1f642a86bf192f1d9c3537d Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 2 Apr 2020 20:48:38 +0300 Subject: MDEV-21688 Assertion or ER_WARN_DATA_OUT_OF_RANGE upon ALTER on previously versioned table Earlier skip of history row. Cleanup of dead code for VTMD. --- sql/sql_table.cc | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'sql') diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 690ff1efcca..13c23b323e5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10379,7 +10379,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool make_versioned= !from->versioned() && to->versioned(); bool make_unversioned= from->versioned() && !to->versioned(); bool keep_versioned= from->versioned() && to->versioned(); - bool drop_history= false; // XXX Field *to_row_start= NULL, *to_row_end= NULL, *from_row_end= NULL; MYSQL_TIME query_start; DBUG_ENTER("copy_data_between_tables"); @@ -10507,10 +10506,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, { from_row_end= from->vers_end_field(); } - else if (keep_versioned && drop_history) - { - from_row_end= from->vers_end_field(); - } THD_STAGE_INFO(thd, stage_copy_to_tmp_table); /* Tell handler that we have values for all columns in the to table */ @@ -10542,6 +10537,13 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, error= 1; break; } + + if (make_unversioned) + { + if (!from_row_end->is_max()) + continue; // Drop history rows. + } + if (unlikely(++thd->progress.counter >= time_to_report_progress)) { time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10; @@ -10561,20 +10563,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, copy_ptr->do_copy(copy_ptr); } - if (drop_history && from_row_end && !from_row_end->is_max()) - continue; - if (make_versioned) { to_row_start->set_notnull(); to_row_start->store_time(&query_start); to_row_end->set_max(); } - else if (make_unversioned) - { - if (!from_row_end->is_max()) - continue; // Drop history rows. - } prev_insert_id= to->file->next_insert_id; if (to->default_field) -- cgit v1.2.1 From 0932c5804d720e1e1ee1d632ad424883dddfeea0 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 2 Apr 2020 20:48:38 +0300 Subject: MDEV-20515 multi-update tries to position updated table by null reference Cause Join tmp table inserts null row because of OUTER JOIN, that's expected. Since `multi_update::prepare2()` converted `Item_temptable_rowid` into `Item_field` (28dbdf3) `multi_update::send_data()` accesses join tmp record directly and treats it as a normal row ignoring null status of ref field. NULL ref field is then treated as normal in `multi_update::do_updates()` which tries to position updated table by reference 0. Note that reference 0 may be valid reference and the first row of table can be wrongly updated (see multi_update.test). Fix Do not add row into multi-update tmp table in case of null ref field. Join tmp table does not have null_row status at this time (as well as `STATUS_NULL_ROW`) and cannot be skipped by these properties (see first comment in multi_update::send_data()). But it has all null fields (including the ref field). --- sql/sql_update.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sql') diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 10b62af3d6f..56ff0ee4b34 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2467,6 +2467,9 @@ int multi_update::send_data(List ¬_used_values) TABLE *tmp_table= tmp_tables[offset]; if (copy_funcs(tmp_table_param[offset].items_to_copy, thd)) DBUG_RETURN(1); + /* rowid field is NULL if join tmp table has null row from outer join */ + if (tmp_table->field[0]->is_null()) + continue; /* Store regular updated fields in the row. */ DBUG_ASSERT(1 + unupdated_check_opt_tables.elements == tmp_table_param[offset].func_count); @@ -2671,6 +2674,7 @@ int multi_update::do_updates() uint field_num= 0; do { + DBUG_ASSERT(!tmp_table->field[field_num]->is_null()); if (unlikely((local_error= tbl->file->ha_rnd_pos(tbl->record[0], (uchar *) tmp_table-> -- cgit v1.2.1 From fbef428645e01113521824c2eb0a42fe4163699c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 3 Apr 2020 12:33:31 +0200 Subject: MDEV-22137 correct documentation of tcp_keepalive_time system variable --- sql/sys_vars.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 824b6583404..f132395b7d2 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5679,7 +5679,7 @@ vio_keepalive_opts opt_vio_keepalive; static Sys_var_int Sys_keepalive_time( "tcp_keepalive_time", - "Timeout, in milliseconds, with no activity until the first TCP keep-alive packet is sent." + "Timeout, in seconds, with no activity until the first TCP keep-alive packet is sent." "If set to 0, system dependent default is used.", AUTO_SET GLOBAL_VAR(opt_vio_keepalive.idle), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), -- cgit v1.2.1 From 21b87437340c403794f100d1af50dcd9c19e123c Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 4 Apr 2020 09:24:22 -0700 Subject: MDEV-21673 Calling stored procedure twice in the same session causes MariaDB to crash This bug could happen only with a stored procedure containing queries with more than one reference to a CTE that used local variables / parameters. This bug was the result of an incomplete merge of the fix for the bug MDEV-17154. The merge covered usage of parameter markers occurred in a CTE that was referenced more than once, but missed coverage of local variables. --- sql/sql_lex.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 58c91ab21e7..00fca6c6bf9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -7066,7 +7066,8 @@ Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca) if (unlikely(!(item= new (thd->mem_root) Item_splocal(thd, rh, &sa, spv->offset, spv->type_handler(), - pos.pos(), pos.length())))) + clone_spec_offset ? 0 : pos.pos(), + clone_spec_offset ? 0 : pos.length())))) return NULL; #ifdef DBUG_ASSERT_EXISTS item->m_sp= sphead; @@ -7165,14 +7166,15 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name, } Query_fragment pos(thd, sphead, start, end); + uint f_pos= clone_spec_offset ? 0 : pos.pos(); + uint f_length= clone_spec_offset ? 0 : pos.length(); Item_splocal *splocal= spv->field_def.is_column_type_ref() ? new (thd->mem_root) Item_splocal_with_delayed_data_type(thd, rh, name, spv->offset, - pos.pos(), - pos.length()) : + f_pos, f_length) : new (thd->mem_root) Item_splocal(thd, rh, name, spv->offset, spv->type_handler(), - pos.pos(), pos.length()); + f_pos, f_length); if (unlikely(splocal == NULL)) return NULL; #ifdef DBUG_ASSERT_EXISTS -- cgit v1.2.1 From 5836191c8f0658d5d75484766fdcc3d838b0a5c1 Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Fri, 3 Apr 2020 00:43:09 +0300 Subject: MDEV-21168: Active XA transactions stop slave from working after backup was restored. Optionally rollback prepared XA's on "mariabackup --prepare". The fix MUST NOT be ported on 10.5+, as MDEV-742 fix solves the issue for slaves. --- sql/handler.cc | 34 ++++++++++++++++++++-------------- sql/handler.h | 12 ++++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index 914a4dc07b1..d739ce7cd5b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1806,29 +1806,33 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit) #ifndef DBUG_OFF -/** - @note - This does not need to be multi-byte safe or anything -*/ -static char* xid_to_str(char *buf, XID *xid) +/** Converts XID to string. + +@param[out] buf output buffer +@param[in] xid XID to convert + +@return pointer to converted string + +@note This does not need to be multi-byte safe or anything */ +char *xid_to_str(char *buf, const XID &xid) { int i; char *s=buf; *s++='\''; - for (i=0; i < xid->gtrid_length+xid->bqual_length; i++) + for (i= 0; i < xid.gtrid_length + xid.bqual_length; i++) { - uchar c=(uchar)xid->data[i]; + uchar c= (uchar) xid.data[i]; /* is_next_dig is set if next character is a number */ bool is_next_dig= FALSE; if (i < XIDDATASIZE) { - char ch= xid->data[i+1]; + char ch= xid.data[i + 1]; is_next_dig= (ch >= '0' && ch <='9'); } - if (i == xid->gtrid_length) + if (i == xid.gtrid_length) { *s++='\''; - if (xid->bqual_length) + if (xid.bqual_length) { *s++='.'; *s++='\''; @@ -1949,7 +1953,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, { #ifndef DBUG_OFF char buf[XIDDATASIZE*4+6]; // see xid_to_str - DBUG_PRINT("info", ("ignore xid %s", xid_to_str(buf, info->list+i))); + DBUG_PRINT("info", + ("ignore xid %s", xid_to_str(buf, info->list[i]))); #endif xid_cache_insert(info->list+i, XA_PREPARED); info->found_foreign_xids++; @@ -1979,7 +1984,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, if (rc == 0) { char buf[XIDDATASIZE*4+6]; // see xid_to_str - DBUG_PRINT("info", ("commit xid %s", xid_to_str(buf, info->list+i))); + DBUG_PRINT("info", + ("commit xid %s", xid_to_str(buf, info->list[i]))); } #endif } @@ -1993,8 +1999,8 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, if (rc == 0) { char buf[XIDDATASIZE*4+6]; // see xid_to_str - DBUG_PRINT("info", ("rollback xid %s", - xid_to_str(buf, info->list+i))); + DBUG_PRINT("info", + ("rollback xid %s", xid_to_str(buf, info->list[i]))); } #endif } diff --git a/sql/handler.h b/sql/handler.h index a51d5dae01a..a0a43daf144 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -4387,4 +4387,16 @@ void print_keydup_error(TABLE *table, KEY *key, myf errflag); int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table); +#ifndef DBUG_OFF +/** Converts XID to string. + +@param[out] buf output buffer +@param[in] xid XID to convert + +@return pointer to converted string + +@note This does not need to be multi-byte safe or anything */ +char *xid_to_str(char *buf, const XID &xid); +#endif // !DBUG_OFF + #endif /* HANDLER_INCLUDED */ -- cgit v1.2.1 From c1394ab6b5c0830ec09f6afdae11fa82bae1a123 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Wed, 8 Apr 2020 17:39:27 +0530 Subject: MDEV-22191: Range access is not picked when index_merge_sort_union is turned off When index_merge_sort_union is turned off only ror scans were considered for range scans, which is wrong. To fix the problem ensure both ror scans and non ror scans are considered for range access --- sql/opt_range.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 37ca3a22c77..746f25c57ab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -949,7 +949,8 @@ QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index, static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool index_read_must_be_used, bool update_tbl_stats, - double read_time); + double read_time, + bool ror_scans_required); static TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, double read_time); @@ -3146,7 +3147,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, /* Get best 'range' plan and prepare data for making other plans */ if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE, - best_read_time))) + best_read_time, FALSE))) { best_trp= range_trp; best_read_time= best_trp->read_cost; @@ -4708,7 +4709,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, { DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map, "tree in SEL_IMERGE");); - if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time))) + if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, + read_time, TRUE))) { /* One of index scans in this index_merge is more expensive than entire @@ -5030,7 +5032,7 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, index merge retrievals are not well calibrated */ trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE, - read_time); + read_time, TRUE); } DBUG_RETURN(trp); @@ -6747,6 +6749,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, index_read_must_be_used if TRUE, assume 'index only' option will be set (except for clustered PK indexes) read_time don't create read plans with cost > read_time. + ror_scans_required set to TRUE for index merge RETURN Best range read plan NULL if no plan found or error occurred @@ -6755,7 +6758,8 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool index_read_must_be_used, bool update_tbl_stats, - double read_time) + double read_time, + bool ror_scans_required) { uint idx; SEL_ARG **key,**end, **key_to_read= NULL; @@ -6802,7 +6806,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, update_tbl_stats, &mrr_flags, &buf_size, &cost); - if (!param->is_ror_scan && + if (ror_scans_required && !param->is_ror_scan && !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) { /* The scan is not a ROR-scan, just skip it */ -- cgit v1.2.1 From 6577a7a8f20538df80b851698e21095311aae190 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 15 Apr 2020 13:10:51 +0300 Subject: fix tests related to SQL comment length tests are: engines/funcs.jp_comment_column engines/funcs.jp_comment_index engines/funcs.jp_comment_table --- sql/sql_string.h | 2 +- sql/sql_table.cc | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/sql_string.h b/sql/sql_string.h index 614b54065fd..46b13dabbcc 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -79,7 +79,7 @@ public: Well_formed_prefix(CHARSET_INFO *cs, const char *str, size_t length) :Well_formed_prefix_status(cs, str, str + length, length), m_str(str) { } - Well_formed_prefix(CHARSET_INFO *cs, LEX_STRING str, size_t nchars) + Well_formed_prefix(CHARSET_INFO *cs, LEX_CSTRING str, size_t nchars) :Well_formed_prefix_status(cs, str.str, str.str + str.length, nchars), m_str(str.str) { } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 13c23b323e5..eef7239db4c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4330,11 +4330,8 @@ bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, if (comment->length == 0) DBUG_RETURN(false); - if (max_len > comment->length) - max_len= comment->length; - size_t tmp_len= - Well_formed_prefix(system_charset_info, comment->str, max_len).length(); + Well_formed_prefix(system_charset_info, *comment, max_len).length(); if (tmp_len < comment->length) { if (thd->is_strict_mode()) -- cgit v1.2.1