67
67
#include " sql/iterators/timing_iterator.h"
68
68
#include " sql/iterators/update_rows_iterator.h"
69
69
#include " sql/join_optimizer/access_path.h"
70
+ #include " sql/join_optimizer/bit_utils.h"
70
71
#include " sql/join_optimizer/walk_access_paths.h"
71
72
#include " sql/key.h" // is_key_used
72
73
#include " sql/key_spec.h"
@@ -2114,8 +2115,15 @@ static bool AddRowIdAsTempTableField(THD *thd, TABLE *table,
2114
2115
// / @param table The table to get a row ID from.
2115
2116
// / @param tmp_table The temporary table in which to store the row ID.
2116
2117
// / @param field_num The field of tmp_table in which to store the row ID.
2117
- static void StoreRowId (TABLE *table, TABLE *tmp_table, int field_num) {
2118
- table->file ->position (table->record [0 ]);
2118
+ // / @param hash_join_tables A map of all tables that are part of a hash join.
2119
+ static void StoreRowId (TABLE *table, TABLE *tmp_table, int field_num,
2120
+ table_map hash_join_tables) {
2121
+ // Hash joins have already copied the row ID from the join buffer into
2122
+ // table->file->ref. Nested loop joins have not, so we call position() to get
2123
+ // the row ID from the handler.
2124
+ if (!Overlaps (hash_join_tables, table->pos_in_table_list ->map ())) {
2125
+ table->file ->position (table->record [0 ]);
2126
+ }
2119
2127
tmp_table->visible_field_ptr ()[field_num]->store (
2120
2128
pointer_cast<const char *>(table->file ->ref ), table->file ->ref_length ,
2121
2129
&my_charset_bin);
@@ -2252,14 +2260,6 @@ bool Query_result_update::optimize() {
2252
2260
if (thd->lex ->is_ignore ()) table->file ->ha_extra (HA_EXTRA_IGNORE_DUP_KEY);
2253
2261
if (table == main_table) // First table in join
2254
2262
{
2255
- // As it's the first table in the join, and we're doing a nested loop
2256
- // join thanks to SELECT_NO_JOIN_CACHE, the table is the left argument
2257
- // of that NL join; thus, we can ask for semi-consistent read.
2258
- // It's a bit early to ask for it here, because we're before
2259
- // rnd_init/index_init; but cannot do it later, as we soon
2260
- // hand control over to iterators.
2261
- table->file ->try_semi_consistent_read (true );
2262
-
2263
2263
if (table == table_to_update) {
2264
2264
assert (bitmap_is_clear_all (&table->tmp_set ));
2265
2265
table->mark_columns_needed_for_update (
@@ -2397,10 +2397,6 @@ void Query_result_update::cleanup(THD *thd) {
2397
2397
}
2398
2398
tmp_table_param = nullptr ;
2399
2399
thd->check_for_truncated_fields = CHECK_FIELD_IGNORE; // Restore this setting
2400
-
2401
- if (main_table != nullptr && main_table->is_created ()) {
2402
- main_table->file ->try_semi_consistent_read (false );
2403
- }
2404
2400
main_table = nullptr ;
2405
2401
// Reset state and statistics members:
2406
2402
unupdated_check_opt_tables.clear ();
@@ -2533,9 +2529,9 @@ bool UpdateRowsIterator::DoImmediateUpdatesAndBufferRowIds(
2533
2529
rowids of tables used in the CHECK OPTION condition.
2534
2530
*/
2535
2531
int field_num = 0 ;
2536
- StoreRowId (table, tmp_table, field_num++);
2532
+ StoreRowId (table, tmp_table, field_num++, m_hash_join_tables );
2537
2533
for (TABLE &tbl : m_unupdated_check_opt_tables) {
2538
- StoreRowId (&tbl, tmp_table, field_num++);
2534
+ StoreRowId (&tbl, tmp_table, field_num++, m_hash_join_tables );
2539
2535
}
2540
2536
2541
2537
/*
@@ -2835,7 +2831,26 @@ bool UpdateRowsIterator::DoDelayedUpdates(bool *trans_safe,
2835
2831
return true ;
2836
2832
}
2837
2833
2838
- bool UpdateRowsIterator::Init () { return m_source->Init (); }
2834
+ bool UpdateRowsIterator::Init () {
2835
+ if (m_source->Init ()) return true ;
2836
+
2837
+ if (m_outermost_table != nullptr &&
2838
+ !Overlaps (m_hash_join_tables,
2839
+ m_outermost_table->pos_in_table_list ->map ())) {
2840
+ // As it's the first table in the join, and we're doing a nested loop join,
2841
+ // the table is the left argument of that nested loop join; thus, we can ask
2842
+ // for semi-consistent read.
2843
+ m_outermost_table->file ->try_semi_consistent_read (true );
2844
+ }
2845
+
2846
+ return false ;
2847
+ }
2848
+
2849
+ UpdateRowsIterator::~UpdateRowsIterator () {
2850
+ if (m_outermost_table != nullptr && m_outermost_table->is_created ()) {
2851
+ m_outermost_table->file ->try_semi_consistent_read (false );
2852
+ }
2853
+ }
2839
2854
2840
2855
int UpdateRowsIterator::Read () {
2841
2856
bool local_error = false ;
@@ -3021,7 +3036,8 @@ UpdateRowsIterator::UpdateRowsIterator(
3021
3036
TABLE **tmp_tables, Copy_field *copy_fields,
3022
3037
List<TABLE> unupdated_check_opt_tables, COPY_INFO **update_operations,
3023
3038
mem_root_deque<Item *> **fields_for_table,
3024
- mem_root_deque<Item *> **values_for_table)
3039
+ mem_root_deque<Item *> **values_for_table,
3040
+ table_map tables_with_rowid_in_buffer)
3025
3041
: RowIterator(thd),
3026
3042
m_source(std::move(source)),
3027
3043
m_outermost_table(outermost_table),
@@ -3032,7 +3048,8 @@ UpdateRowsIterator::UpdateRowsIterator(
3032
3048
m_unupdated_check_opt_tables(unupdated_check_opt_tables),
3033
3049
m_update_operations(update_operations),
3034
3050
m_fields_for_table(fields_for_table),
3035
- m_values_for_table(values_for_table) {}
3051
+ m_values_for_table(values_for_table),
3052
+ m_hash_join_tables(tables_with_rowid_in_buffer) {}
3036
3053
3037
3054
unique_ptr_destroy_only<RowIterator> CreateUpdateRowsIterator (
3038
3055
THD *thd, MEM_ROOT *mem_root, JOIN *join,
@@ -3046,5 +3063,9 @@ unique_ptr_destroy_only<RowIterator> Query_result_update::create_iterator(
3046
3063
return NewIterator<UpdateRowsIterator>(
3047
3064
thd, mem_root, std::move (source), main_table, table_to_update,
3048
3065
update_tables, tmp_tables, copy_field, unupdated_check_opt_tables,
3049
- update_operations, fields_for_table, values_for_table);
3066
+ update_operations, fields_for_table, values_for_table,
3067
+ // The old optimizer does not use hash join in UPDATE statements.
3068
+ thd->lex ->using_hypergraph_optimizer
3069
+ ? GetHashJoinTables (unit->root_access_path ())
3070
+ : 0 );
3050
3071
}
0 commit comments