From: Date: May 15 2007 8:40am Subject: bk commit into 5.0 tree (aelkin:1.2439) BUG#27417 List-Archive: http://lists.mysql.com/commits/26662 X-Bug: 27417 Message-Id: <200705150640.l4F6eZ7v012924@dsl-hkibras-fe31f900-164.dhcp.inet.fi> Below is the list of changes that have just been committed into a local 5.0 repository of elkin. When elkin does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-05-15 09:40:26+03:00, aelkin@stripped +4 -0 Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack Once had been set the flag might later got reset inside of a stored routine execution stack. The reason was in that there was no check if a new statement started at time of resetting. The artifact affects most of binlogable DML queries. Fixed with checking thd->in_sub_stmt to know precisely about the new statement. Couple of minor issues refined along the fix, see per-file comments. Test is delayed till related bug#13270, bug#23333. sql/sql_delete.cc@stripped, 2007-05-15 09:40:21+03:00, aelkin@stripped +27 -14 correcting delete and multi-delete queries to set and reset thd->no_trans_update.stmt sql/sql_insert.cc@stripped, 2007-05-15 09:40:22+03:00, aelkin@stripped +6 -3 correcting insert and insert .. select to set and reset the flag correctly sql/sql_load.cc@stripped, 2007-05-15 09:40:22+03:00, aelkin@stripped +4 -7 correcting load data to set and reset the flag; eliminating a separate issue where the flag was stored and re-stored after write_record which can change it and the change should remain permanent. sql/sql_update.cc@stripped, 2007-05-15 09:40:22+03:00, aelkin@stripped +26 -18 correcting update and multi-update to set and reset the flag; eliminating a separate issue in multi_update::do_updates where either one of the class members trans_safe, transactional_tables was set after the per-table loop whereas both should be calculated during looping. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: aelkin # Host: dsl-hkibras-fe31f900-164.dhcp.inet.fi # Root: /home/elkin/MySQL/TEAM/FIXES/5.0/bug27417-no_trans_update__stmt --- 1.197/sql/sql_delete.cc 2007-04-17 16:51:56 +03:00 +++ 1.198/sql/sql_delete.cc 2007-05-15 09:40:21 +03:00 @@ -216,6 +216,9 @@ bool mysql_delete(THD *thd, TABLE_LIST * init_ftfuncs(thd, select_lex, 1); thd->proc_info="updating"; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; + if (table->triggers) { table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE); @@ -245,10 +248,13 @@ bool mysql_delete(THD *thd, TABLE_LIST * error= 1; break; } - + if (!(error=table->file->delete_row(table->record[0]))) { - deleted++; + deleted++; + if (!transactional_table) + thd->no_trans_update.stmt= TRUE; + if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) @@ -256,11 +262,11 @@ bool mysql_delete(THD *thd, TABLE_LIST * error= 1; break; } - if (!--limit && using_limit) - { - error= -1; - break; - } + if (!--limit && using_limit) + { + error= -1; + break; + } } else { @@ -579,6 +585,9 @@ multi_delete::initialize_tables(JOIN *jo delete_while_scanning= 0; } } + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; + walk= delete_tables; tempfiles_ptr= tempfiles; if (delete_while_scanning) @@ -644,20 +653,22 @@ bool multi_delete::send_data(List if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) - DBUG_RETURN(1); + DBUG_RETURN(1); table->status|= STATUS_DELETED; if (!(error=table->file->delete_row(table->record[0]))) { - deleted++; + deleted++; + if (!table->file->has_transactions()) + thd->no_trans_update.stmt= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) - DBUG_RETURN(1); + DBUG_RETURN(1); } else { - table->file->print_error(error,MYF(0)); - DBUG_RETURN(1); + table->file->print_error(error,MYF(0)); + DBUG_RETURN(1); } } else @@ -759,10 +770,12 @@ int multi_delete::do_deletes() } if ((local_error=table->file->delete_row(table->record[0]))) { - table->file->print_error(local_error,MYF(0)); - break; + table->file->print_error(local_error,MYF(0)); + break; } deleted++; + if (!table->file->has_transactions()) + thd->no_trans_update.stmt= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) --- 1.230/sql/sql_insert.cc 2007-04-12 12:46:07 +03:00 +++ 1.231/sql/sql_insert.cc 2007-05-15 09:40:22 +03:00 @@ -629,7 +629,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode) table->file->start_bulk_insert(values_list.elements); - thd->no_trans_update.stmt= FALSE; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -2564,7 +2565,8 @@ select_insert::prepare(List &value table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); } - thd->no_trans_update.stmt= FALSE; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -2978,7 +2980,8 @@ select_create::prepare(List &value } if (!thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); - thd->no_trans_update.stmt= FALSE; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | --- 1.113/sql/sql_load.cc 2007-05-08 03:43:16 +03:00 +++ 1.114/sql/sql_load.cc 2007-05-15 09:40:22 +03:00 @@ -377,7 +377,8 @@ bool mysql_load(THD *thd,sql_exchange *e table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; - thd->no_trans_update.stmt= FALSE; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -532,7 +533,7 @@ read_fixed_length(THD *thd, COPY_INFO &i Item_field *sql_field; TABLE *table= table_list->table; ulonglong id; - bool no_trans_update_stmt, err; + bool err; DBUG_ENTER("read_fixed_length"); id= 0; @@ -560,7 +561,6 @@ read_fixed_length(THD *thd, COPY_INFO &i #ifdef HAVE_purify read_info.row_end[0]=0; #endif - no_trans_update_stmt= !table->file->has_transactions(); restore_record(table, s->default_values); /* @@ -628,7 +628,6 @@ read_fixed_length(THD *thd, COPY_INFO &i table->auto_increment_field_not_null= FALSE; if (err) DBUG_RETURN(1); - thd->no_trans_update.stmt= no_trans_update_stmt; /* If auto_increment values are used, save the first one for @@ -671,12 +670,11 @@ read_sep_field(THD *thd, COPY_INFO &info TABLE *table= table_list->table; uint enclosed_length; ulonglong id; - bool no_trans_update_stmt, err; + bool err; DBUG_ENTER("read_sep_field"); enclosed_length=enclosed.length(); id= 0; - no_trans_update_stmt= !table->file->has_transactions(); for (;;it.rewind()) { @@ -817,7 +815,6 @@ read_sep_field(THD *thd, COPY_INFO &info We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. */ - thd->no_trans_update.stmt= no_trans_update_stmt; if (read_info.next_line()) // Skip to next line break; if (read_info.line_cuted) --- 1.215/sql/sql_update.cc 2007-04-12 12:46:07 +03:00 +++ 1.216/sql/sql_update.cc 2007-05-15 09:40:22 +03:00 @@ -429,7 +429,8 @@ int mysql_update(THD *thd, query_id=thd->query_id; transactional_table= table->file->has_transactions(); - thd->no_trans_update.stmt= FALSE; + if (!thd->in_sub_stmt) + thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= test(!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -486,7 +487,8 @@ int mysql_update(THD *thd, (byte*) table->record[0]))) { updated++; - thd->no_trans_update.stmt= !transactional_table; + if (!transactional_table) + thd->no_trans_update.stmt= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, @@ -1484,28 +1486,28 @@ int multi_update::do_updates(bool from_s else if (error == VIEW_CHECK_ERROR) goto err; } - if ((local_error=table->file->update_row(table->record[1], - table->record[0]))) - { - if (!ignore || local_error != HA_ERR_FOUND_DUPP_KEY) - goto err; - } - updated++; - + if ((local_error=table->file->update_row(table->record[1], + table->record[0]))) + { + if (!ignore || local_error != HA_ERR_FOUND_DUPP_KEY) + goto err; + } + updated++; + if (table->file->has_transactions()) + transactional_tables= 1; + else + { + trans_safe= 0; // Can't do safe rollback + thd->no_trans_update.stmt= TRUE; + } + if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)) goto err2; } } - - if (updated != org_updated) - { - if (table->file->has_transactions()) - transactional_tables= 1; - else - trans_safe= 0; // Can't do safe rollback - } + DBUG_ASSERT(updated == org_updated || transactional_tables || trans_safe == 0); (void) table->file->ha_rnd_end(); (void) tmp_table->file->ha_rnd_end(); } @@ -1527,7 +1529,10 @@ err2: if (table->file->has_transactions()) transactional_tables= 1; else + { trans_safe= 0; + thd->no_trans_update.stmt= TRUE; + } } DBUG_RETURN(1); } @@ -1570,7 +1575,10 @@ bool multi_update::send_eof() local_error= 1; // Rollback update } if (!transactional_tables) + { + DBUG_ASSERT(thd->no_trans_update.stmt); thd->no_trans_update.all= TRUE; + } } if (transactional_tables)