List:Commits« Previous MessageNext Message »
From:Andrei Elkin Date:March 23 2007 4:15pm
Subject:bk commit into 5.0 tree (aelkin:1.2488) BUG#27395
View as plain text  
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-03-23 17:12:58+02:00, aelkin@andrepl.(none) +14 -0
  Bug #27395 OPTION_STATUS_NO_TRANS_UPDATE is not preserved at the end of SF()
  
  thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit was not restored at the end of SF()
invocation, where
  SF() modified non-ta table.
  As the result of this artifact it was not possible to detect whether there were any
side-effects when
  top-level query ends. 
  If the top level query table was not modified and the bit is lost there would be no
binlogging.
  
  Fixed with preserving the bit inside of thd->no_trans_update struct. The struct
agregates two bool flags
  telling whether the current query and the current transaction modified any non-ta table.
  The flags stmt, all are dropped at the end of the query and the transaction.

  mysql-test/r/sp_trans.result@stripped, 2007-03-23 17:12:55+02:00, aelkin@andrepl.(none) +32
-0
    results will be changed once again after bug#23333 will be fixed.

  mysql-test/t/sp_trans.test@stripped, 2007-03-23 17:12:55+02:00, aelkin@andrepl.(none) +30 -0
    regression test added

  sql/ha_ndbcluster.cc@stripped, 2007-03-23 17:12:55+02:00, aelkin@andrepl.(none) +1 -2
    replacing thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit and bool
thd->no_trans_update
    with thd->no_trans_update as struct

  sql/handler.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +1 -1
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/log.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +2 -2
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/set_var.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +3 -2
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sp_head.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +3 -3
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_class.h@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +6 -2
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_delete.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +2 -2
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_insert.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +9 -9
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_load.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +8 -8
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_parse.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +18 -13
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_table.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +1 -1
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

  sql/sql_update.cc@stripped, 2007-03-23 17:12:56+02:00, aelkin@andrepl.(none) +24 -24
    replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
    with the member thd->no_trans_update.all;
    converting thd->no_trans_update into struct of bools.

# 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:	andrepl.(none)
# Root:	/home/elkin/MySQL/MAIN/5.0-marvel-bug23333_sf_side_eff_binlog

--- 1.228/sql/handler.cc	2007-02-21 13:04:59 +02:00
+++ 1.229/sql/handler.cc	2007-03-23 17:12:56 +02:00
@@ -830,7 +830,7 @@ int ha_rollback_trans(THD *thd, bool all
     the error log; but we don't want users to wonder why they have this
     message in the error log, so we don't send it.
   */
-  if (is_real_trans && (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
&&
+  if (is_real_trans && thd->no_trans_update.all &&
       !thd->slave_thread)
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                  ER_WARNING_NOT_COMPLETE_ROLLBACK,

--- 1.206/sql/log.cc	2007-03-01 18:59:52 +02:00
+++ 1.207/sql/log.cc	2007-03-23 17:12:56 +02:00
@@ -162,7 +162,7 @@ static int binlog_rollback(THD *thd, boo
     table. Such cases should be rare (updating a
     non-transactional table inside a transaction...)
   */
-  if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
+  if (unlikely(thd->no_trans_update.all))
   {
     Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
     qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
@@ -217,7 +217,7 @@ static int binlog_savepoint_rollback(THD
     non-transactional table. Otherwise, truncate the binlog cache starting
     from the SAVEPOINT command.
   */
-  if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
+  if (unlikely(thd->no_trans_update.all))
   {
     Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
     DBUG_RETURN(mysql_bin_log.write(&qinfo));

--- 1.325/sql/sql_class.h	2007-03-15 22:20:57 +02:00
+++ 1.326/sql/sql_class.h	2007-03-23 17:12:56 +02:00
@@ -1440,7 +1440,11 @@ public:
   bool	     charset_is_system_charset, charset_is_collation_connection;
   bool       charset_is_character_set_filesystem;
   bool       enable_slow_log;   /* enable slow log for current statement */
-  bool	     no_trans_update, abort_on_warning;
+  struct {
+    bool all:1;
+    bool stmt:1;
+  } no_trans_update;
+  bool	     abort_on_warning;
   bool 	     got_warning;       /* Set on call to push_warning() */
   bool	     no_warnings_for_error; /* no warnings on call to my_error() */
   /* set during loop of derived table processing */
@@ -1664,7 +1668,7 @@ public:
   inline bool really_abort_on_warning()
   {
     return (abort_on_warning &&
-            (!no_trans_update ||
+            (!no_trans_update.stmt ||
              (variables.sql_mode & MODE_STRICT_ALL_TABLES)));
   }
   void set_status_var_init();

--- 1.193/sql/sql_delete.cc	2007-03-01 23:10:23 +02:00
+++ 1.194/sql/sql_delete.cc	2007-03-23 17:12:56 +02:00
@@ -311,7 +311,7 @@ cleanup:
 	error=1;
     }
     if (!transactional_table)
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
   free_underlaid_joins(thd, select_lex);
   if (transactional_table)
@@ -791,7 +791,7 @@ bool multi_delete::send_eof()
 	local_error=1;  // Log write failed: roll back the SQL statement
     }
     if (!transactional_tables)
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
   /* Commit or rollback the current SQL statement */
   if (transactional_tables)

--- 1.225/sql/sql_insert.cc	2007-03-19 23:39:47 +02:00
+++ 1.226/sql/sql_insert.cc	2007-03-23 17:12:56 +02:00
@@ -584,7 +584,7 @@ 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= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
                                        (MODE_STRICT_TRANS_TABLES |
                                         MODE_STRICT_ALL_TABLES)));
@@ -731,7 +731,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
             error=1;
         }
         if (!transactional_table)
-          thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+          thd->no_trans_update.all= TRUE;
       }
     }
     if (transactional_table)
@@ -1129,7 +1129,7 @@ static int last_uniq_key(TABLE *table,ui
     then both on update triggers will work instead. Similarly both on
     delete triggers will be invoked if we will delete conflicting records.
 
-    Sets thd->no_trans_update if table which is updated didn't have
+    Sets thd->no_trans_update.stmt to TRUE if table which is updated didn't have
     transactions.
 
   RETURN VALUE
@@ -1295,7 +1295,7 @@ int write_record(THD *thd, TABLE *table,
             goto err;
           info->deleted++;
           if (!table->file->has_transactions())
-            thd->no_trans_update= 1;
+            thd->no_trans_update.stmt= TRUE;
           if (table->triggers &&
               table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
                                                 TRG_ACTION_AFTER, TRUE))
@@ -1327,7 +1327,7 @@ ok_or_after_trg_err:
   if (key)
     my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
   if (!table->file->has_transactions())
-    thd->no_trans_update= 1;
+    thd->no_trans_update.stmt= TRUE;
   DBUG_RETURN(trg_error);
 
 err:
@@ -2518,7 +2518,7 @@ select_insert::prepare(List<Item> &value
       table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
     table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   }
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= (!info.ignore &&
                           (thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES |
@@ -2676,7 +2676,7 @@ void select_insert::send_error(uint errc
       mysql_bin_log.write(&qinfo);
     }
     if (!table->s->tmp_table)
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
   if (info.copied || info.deleted || info.updated)
   {
@@ -2705,7 +2705,7 @@ bool select_insert::send_eof()
   {
     query_cache_invalidate3(thd, table, 1);
     if (!(table->file->has_transactions() || table->s->tmp_table))
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
 
   if (last_insert_id)
@@ -2931,7 +2931,7 @@ select_create::prepare(List<Item> &value
   }
   if (!thd->prelocked_mode)
     table->file->start_bulk_insert((ha_rows) 0);
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= (!info.ignore &&
                           (thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES |

--- 1.109/sql/sql_load.cc	2007-03-08 19:29:58 +02:00
+++ 1.110/sql/sql_load.cc	2007-03-23 17:12:56 +02:00
@@ -377,7 +377,7 @@ bool mysql_load(THD *thd,sql_exchange *e
       table->file->start_bulk_insert((ha_rows) 0);
     table->copy_blobs=1;
 
-    thd->no_trans_update= 0;
+    thd->no_trans_update.stmt= FALSE;
     thd->abort_on_warning= (!ignore &&
                             (thd->variables.sql_mode &
                              (MODE_STRICT_TRANS_TABLES |
@@ -467,7 +467,7 @@ bool mysql_load(THD *thd,sql_exchange *e
 	  (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
 
   if (!transactional_table)
-    thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+    thd->no_trans_update.all= TRUE;
 #ifndef EMBEDDED_LIBRARY
   if (mysql_bin_log.is_open())
   {
@@ -531,7 +531,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
   Item_field *sql_field;
   TABLE *table= table_list->table;
   ulonglong id;
-  bool no_trans_update;
+  bool no_trans_update_stmt;
   DBUG_ENTER("read_fixed_length");
 
   id= 0;
@@ -559,7 +559,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
 #ifdef HAVE_purify
     read_info.row_end[0]=0;
 #endif
-    no_trans_update= !table->file->has_transactions();
+    no_trans_update_stmt= !table->file->has_transactions();
 
     restore_record(table, s->default_values);
     /*
@@ -627,7 +627,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
 
     if (write_record(thd, table, &info))
       DBUG_RETURN(1);
-    thd->no_trans_update= no_trans_update;
+    thd->no_trans_update.stmt= no_trans_update_stmt;
    
     /*
       If auto_increment values are used, save the first one for
@@ -670,12 +670,12 @@ read_sep_field(THD *thd, COPY_INFO &info
   TABLE *table= table_list->table;
   uint enclosed_length;
   ulonglong id;
-  bool no_trans_update;
+  bool no_trans_update_stmt;
   DBUG_ENTER("read_sep_field");
 
   enclosed_length=enclosed.length();
   id= 0;
-  no_trans_update= !table->file->has_transactions();
+  no_trans_update_stmt= !table->file->has_transactions();
 
   for (;;it.rewind())
   {
@@ -817,7 +817,7 @@ 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= no_trans_update;
+    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.612/sql/sql_parse.cc	2007-03-16 09:55:14 +02:00
+++ 1.613/sql/sql_parse.cc	2007-03-23 17:12:56 +02:00
@@ -147,7 +147,8 @@ static bool end_active_trans(THD *thd)
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     if (ha_commit(thd))
       error=1;
-    thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    thd->options&= ~(ulong) OPTION_BEGIN;
+    thd->no_trans_update.all= FALSE;
   }
   DBUG_RETURN(error);
 }
@@ -171,8 +172,8 @@ static bool begin_trans(THD *thd)
   else
   {
     LEX *lex= thd->lex;
-    thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
-		   OPTION_BEGIN);
+    thd->no_trans_update.all= FALSE;
+    thd->options|= (ulong) OPTION_BEGIN;
     thd->server_status|= SERVER_STATUS_IN_TRANS;
     if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
       error= ha_start_consistent_snapshot(thd);
@@ -1463,7 +1464,8 @@ int end_trans(THD *thd, enum enum_mysql_
     */
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     res= ha_commit(thd);
-    thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    thd->options&= ~(ulong) OPTION_BEGIN;
+    thd->no_trans_update.all= FALSE;
     break;
   case COMMIT_RELEASE:
     do_release= 1; /* fall through */
@@ -1480,7 +1482,8 @@ int end_trans(THD *thd, enum enum_mysql_
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     if (ha_rollback(thd))
       res= -1;
-    thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    thd->options&= ~(ulong) OPTION_BEGIN;
+    thd->no_trans_update.all= FALSE;
     if (!res && (completion == ROLLBACK_AND_CHAIN))
       res= begin_trans(thd);
     break;
@@ -2933,7 +2936,7 @@ mysql_execute_command(THD *thd)
     else 
     {
       /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
-      thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
     }
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     bool link_to_local;
@@ -3707,10 +3710,10 @@ end_with_restore_list:
 	we silently add IF EXISTS if TEMPORARY was used.
       */
       if (thd->slave_thread)
-	lex->drop_if_exists= 1;
+        lex->drop_if_exists= 1;
 
       /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
-      thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
     }
     /* DDL and binlog write order protected by LOCK_open */
     res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
@@ -4296,7 +4299,7 @@ end_with_restore_list:
         res= TRUE; // cannot happen
       else
       {
-        if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
+        if (thd->no_trans_update.all &&
             !thd->slave_thread)
           push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                        ER_WARNING_NOT_COMPLETE_ROLLBACK,
@@ -4939,8 +4942,8 @@ create_sp_error:
     thd->transaction.xid_state.xa_state=XA_ACTIVE;
     thd->transaction.xid_state.xid.set(thd->lex->xid);
     xid_cache_insert(&thd->transaction.xid_state);
-    thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
-                   OPTION_BEGIN);
+    thd->no_trans_update.all= FALSE;
+    thd->options|= (ulong) OPTION_BEGIN;
     thd->server_status|= SERVER_STATUS_IN_TRANS;
     send_ok(thd);
     break;
@@ -5033,7 +5036,8 @@ create_sp_error:
                xa_state_names[thd->transaction.xid_state.xa_state]);
       break;
     }
-    thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    thd->options&= ~(ulong) OPTION_BEGIN;
+    thd->no_trans_update.all= FALSE;
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     xid_cache_delete(&thd->transaction.xid_state);
     thd->transaction.xid_state.xa_state=XA_NOTR;
@@ -5063,7 +5067,8 @@ create_sp_error:
       my_error(ER_XAER_RMERR, MYF(0));
     else
       send_ok(thd);
-    thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+    thd->options&= ~(ulong) OPTION_BEGIN;
+    thd->no_trans_update.all= FALSE;
     thd->server_status&= ~SERVER_STATUS_IN_TRANS;
     xid_cache_delete(&thd->transaction.xid_state);
     thd->transaction.xid_state.xa_state=XA_NOTR;

--- 1.335/sql/sql_table.cc	2007-03-14 15:58:13 +02:00
+++ 1.336/sql/sql_table.cc	2007-03-23 17:12:56 +02:00
@@ -3968,7 +3968,7 @@ copy_data_between_tables(TABLE *from,TAB
   alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
 
   /* We can abort alter table for any table type */
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
                                          (MODE_STRICT_TRANS_TABLES |
                                           MODE_STRICT_ALL_TABLES));

--- 1.212/sql/sql_update.cc	2007-03-08 19:29:59 +02:00
+++ 1.213/sql/sql_update.cc	2007-03-23 17:12:56 +02:00
@@ -429,7 +429,7 @@ int mysql_update(THD *thd,
   query_id=thd->query_id;
 
   transactional_table= table->file->has_transactions();
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= test(!ignore &&
                               (thd->variables.sql_mode &
                                (MODE_STRICT_TRANS_TABLES |
@@ -452,7 +452,7 @@ int mysql_update(THD *thd,
       if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
                                                table->triggers,
                                                TRG_EVENT_UPDATE))
-	break; /* purecov: inspected */
+        break; /* purecov: inspected */
 
       found++;
 
@@ -470,12 +470,12 @@ int mysql_update(THD *thd,
             break;
           }
         }
-	if (!(error=table->file->update_row((byte*) table->record[1],
-					    (byte*) table->record[0])))
-	{
-	  updated++;
-          thd->no_trans_update= !transactional_table;
-
+        if (!(error=table->file->update_row((byte*) table->record[1],
+                                            (byte*) table->record[0])))
+        {
+          updated++;
+          thd->no_trans_update.stmt= !transactional_table;
+          
           if (table->triggers &&
               table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
                                                 TRG_ACTION_AFTER, TRUE))
@@ -483,25 +483,25 @@ int mysql_update(THD *thd,
             error= 1;
             break;
           }
-	}
- 	else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
-	{
+        }
+        else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
+        {
           /*
             If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to
             do anything; otherwise...
           */
           if (error != HA_ERR_FOUND_DUPP_KEY)
             thd->fatal_error(); /* Other handler errors are fatal */
-	  table->file->print_error(error,MYF(0));
-	  error= 1;
-	  break;
-	}
+          table->file->print_error(error,MYF(0));
+          error= 1;
+          break;
+        }
       }
-
+      
       if (!--limit && using_limit)
       {
-	error= -1;				// Simulate end of file
-	break;
+        error= -1;				// Simulate end of file
+        break;
       }
     }
     else
@@ -546,7 +546,7 @@ int mysql_update(THD *thd,
 	error=1;				// Rollback update
     }
     if (!transactional_table)
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
   free_underlaid_joins(thd, select_lex);
   if (transactional_table)
@@ -910,7 +910,7 @@ bool mysql_multi_update(THD *thd,
 				 handle_duplicates, ignore)))
     DBUG_RETURN(TRUE);
 
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
   thd->abort_on_warning= test(thd->variables.sql_mode &
                               (MODE_STRICT_TRANS_TABLES |
                                MODE_STRICT_ALL_TABLES));
@@ -1224,7 +1224,7 @@ multi_update::~multi_update()
     delete [] copy_field;
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;		// Restore this setting
   if (!trans_safe)
-    thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+    thd->no_trans_update.all= TRUE;
 }
 
 
@@ -1311,7 +1311,7 @@ bool multi_update::send_data(List<Item> 
         else
         {
           if (!table->file->has_transactions())
-            thd->no_trans_update= 1;
+            thd->no_trans_update.stmt= TRUE;
           if (table->triggers &&
               table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
                                                 TRG_ACTION_AFTER, TRUE))
@@ -1541,10 +1541,10 @@ bool multi_update::send_eof()
       Query_log_event qinfo(thd, thd->query, thd->query_length,
 			    transactional_tables, FALSE);
       if (mysql_bin_log.write(&qinfo) && trans_safe)
-	local_error= 1;				// Rollback update
+        local_error= 1;				// Rollback update
     }
     if (!transactional_tables)
-      thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+      thd->no_trans_update.all= TRUE;
   }
 
   if (transactional_tables)

--- 1.300/sql/ha_ndbcluster.cc	2007-02-28 22:23:33 +02:00
+++ 1.301/sql/ha_ndbcluster.cc	2007-03-23 17:12:55 +02:00
@@ -3636,8 +3636,7 @@ int ha_ndbcluster::external_lock(THD *th
     {
       m_transaction_on= FALSE;
       /* Would be simpler if has_transactions() didn't always say "yes" */
-      thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
-      thd->no_trans_update= TRUE;
+      thd->no_trans_update= {TRUE, TRUE};
     }
     else if (!thd->transaction.on)
       m_transaction_on= FALSE;

--- 1.181/sql/set_var.cc	2007-03-05 12:50:57 +02:00
+++ 1.182/sql/set_var.cc	2007-03-23 17:12:56 +02:00
@@ -2873,14 +2873,15 @@ static bool set_option_autocommit(THD *t
     if ((org_options & OPTION_NOT_AUTOCOMMIT))
     {
       /* We changed to auto_commit mode */
-      thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+      thd->options&= ~(ulong) OPTION_BEGIN;
+      thd->no_trans_update.all= FALSE;
       thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
       if (ha_commit(thd))
 	return 1;
     }
     else
     {
-      thd->options&= ~(ulong) (OPTION_STATUS_NO_TRANS_UPDATE);
+      thd->no_trans_update.all= FALSE;
       thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
     }
   }

--- 1.237/sql/sp_head.cc	2007-03-15 10:51:33 +02:00
+++ 1.238/sql/sp_head.cc	2007-03-23 17:12:56 +02:00
@@ -337,13 +337,13 @@ sp_eval_expr(THD *thd, Field *result_fie
   
   enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
   bool save_abort_on_warning= thd->abort_on_warning;
-  bool save_no_trans_update= thd->no_trans_update;
+  bool save_no_trans_update_stmt= thd->no_trans_update.stmt;
 
   thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
   thd->abort_on_warning=
     thd->variables.sql_mode &
     (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES);
-  thd->no_trans_update= 0;
+  thd->no_trans_update.stmt= FALSE;
 
   /* Save the value in the field. Convert the value if needed. */
 
@@ -351,7 +351,7 @@ sp_eval_expr(THD *thd, Field *result_fie
 
   thd->count_cuted_fields= save_count_cuted_fields;
   thd->abort_on_warning= save_abort_on_warning;
-  thd->no_trans_update= save_no_trans_update;
+  thd->no_trans_update.stmt= save_no_trans_update_stmt;
 
   if (thd->net.report_error)
   {

--- 1.9/mysql-test/r/sp_trans.result	2006-05-12 19:58:48 +03:00
+++ 1.10/mysql-test/r/sp_trans.result	2007-03-23 17:12:55 +02:00
@@ -530,3 +530,35 @@ count(*)
 drop table t3, t4|
 drop procedure bug14210|
 set @@session.max_heap_table_size=default|
+drop function if exists bug23333|
+drop table if exists t1,t2|
+CREATE TABLE t1 (a int  NOT NULL auto_increment primary key) ENGINE=MyISAM|
+CREATE TABLE t2 (a int  NOT NULL auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB|
+reset master|
+insert into t2 values (1,1)|
+create function bug23333() 
+RETURNS int(11)
+DETERMINISTIC
+begin
+insert into t1 values (null);
+select count(*) from t1 into @a;
+return @a;
+end|
+insert into t2 values (bug23333(),1)|
+ERROR 23000: Duplicate entry '1' for key 1
+show binlog events /* must show the insert */|
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	4	Format_desc	1	98	Server ver: 5.0.40-debug-log, Binlog ver: 4
+master-bin.000001	98	Query	1	90	use `test`; insert into t2 values (1,1)
+master-bin.000001	188	Xid	1	215	COMMIT /* xid=1165 */
+master-bin.000001	215	Query	1	446	use `test`; CREATE DEFINER=`root`@`localhost` function
bug23333() 
+RETURNS int(11)
+DETERMINISTIC
+begin
+insert into t1 values (null);
+select count(*) from t1 into @a;
+return @a;
+end
+select count(*),@a from t1 /* must be 1,1 */|
+count(*)	@a
+1	1

--- 1.9/mysql-test/t/sp_trans.test	2006-05-12 19:58:53 +03:00
+++ 1.10/mysql-test/t/sp_trans.test	2007-03-23 17:12:55 +02:00
@@ -554,6 +554,36 @@ set @@session.max_heap_table_size=defaul
 
 
 #
+# Bug #13270 INSERT,UPDATE,etc that calls func with side-effect does not binlog
+# Bug #23333 stored function + non-transac table + transac table =
+#            breaks stmt-based binlog
+# Bug #27395 OPTION_STATUS_NO_TRANS_UPDATE is not preserved at the end of SF()
+#
+--disable_warnings
+drop function if exists bug23333|
+drop table if exists t1,t2|
+--enable_warnings
+ CREATE TABLE t1 (a int  NOT NULL auto_increment primary key) ENGINE=MyISAM|
+ CREATE TABLE t2 (a int  NOT NULL auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB|
+
+reset master|
+insert into t2 values (1,1)|
+
+create function bug23333() 
+RETURNS int(11)
+DETERMINISTIC
+begin
+  insert into t1 values (null);
+  select count(*) from t1 into @a;
+  return @a;
+end|
+
+--error ER_DUP_ENTRY
+insert into t2 values (bug23333(),1)| 
+show binlog events /* must show the insert */|
+select count(*),@a from t1 /* must be 1,1 */|
+
+#
 # BUG#NNNN: New bug synopsis
 #
 #--disable_warnings
Thread
bk commit into 5.0 tree (aelkin:1.2488) BUG#27395Andrei Elkin23 Mar