List:Internals« Previous MessageNext Message »
From:lars Date:April 8 2005 1:27pm
Subject:bk commit into 5.1 tree (mysqldev:1.1854)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mysqldev. When mysqldev 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
  1.1854 05/04/08 13:27:31 mysqldev@stripped +34 -0
  Merge

  sql/ha_ndbcluster.cc
    1.200 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_table.cc
    1.230 05/04/08 11:24:26 mysqldev@stripped +0 -0
    Auto merged

  sql/handler.h
    1.134 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/handler.cc
    1.155 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/ha_ndbcluster.h
    1.85 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_update.cc
    1.153 05/04/08 11:24:26 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_union.cc
    1.115 05/04/08 11:24:26 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_insert.cc
    1.146 05/04/08 11:24:25 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.229 05/04/08 11:24:25 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_class.cc
    1.175 05/04/08 11:24:25 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_acl.h
    1.35 05/04/08 11:24:25 mysqldev@stripped +0 -0
    Auto merged

  sql/sql_acl.cc
    1.136 05/04/08 11:24:25 mysqldev@stripped +0 -0
    Auto merged

  sql/slave.cc
    1.244 05/04/08 11:24:25 mysqldev@stripped +0 -1
    Auto merged

  sql/mysqld.cc
    1.446 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/mysql_priv.h
    1.285 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/log_event.h
    1.110 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/log_event.cc
    1.172 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/log.cc
    1.160 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  sql/item_sum.cc
    1.136 05/04/08 11:24:24 mysqldev@stripped +0 -0
    Auto merged

  scripts/mysql_fix_privilege_tables.sql
    1.17 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  scripts/mysql_create_system_tables.sh
    1.20 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  ndb/src/kernel/blocks/dbdict/Dbdict.cpp
    1.44 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/t/user_var.test
    1.26 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/t/ctype_ucs.test
    1.29 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/user_var.result
    1.32 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/show_check.result
    1.65 05/04/08 11:24:23 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/rpl_timezone.result
    1.13 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/rpl_temporary.result
    1.22 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/ps_1general.result
    1.32 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/information_schema.result
    1.41 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/r/ctype_ucs.result
    1.36 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.sh
    1.256 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  configure.in
    1.256 05/04/08 11:24:22 mysqldev@stripped +0 -0
    Auto merged

  BitKeeper/etc/logging_ok
    1.282 05/04/08 11:24:14 mysqldev@stripped +0 -0
    auto-union

# 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:	mysqldev
# Host:	production.mysql.com
# Root:	/data0/mysqldev/lars/RESYNC

--- 1.255/configure.in	2005-04-05 18:18:05 +02:00
+++ 1.256/configure.in	2005-04-08 11:24:22 +02:00
@@ -19,7 +19,6 @@
 NDB_VERSION_MAJOR=5
 NDB_VERSION_MINOR=1
 NDB_VERSION_BUILD=0
-NDB_VERSION_STATUS="alpha"
 
 # Set all version vars based on $VERSION. How do we do this more elegant ?
 # Remember that regexps needs to quote [ and ] since this is run through m4
@@ -38,6 +37,7 @@
 sinclude(config/ac-macros/compiler_flag.m4)
 sinclude(config/ac-macros/ha_archive.m4)
 sinclude(config/ac-macros/ha_berkeley.m4)
+sinclude(config/ac-macros/ha_blackhole.m4)
 sinclude(config/ac-macros/ha_example.m4)
 sinclude(config/ac-macros/ha_federated.m4)
 sinclude(config/ac-macros/ha_innodb.m4)
@@ -353,7 +353,8 @@
   then
     if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
     then
-      CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL"
+     # Statically link the language support function's found in libsupc++.a
+     LIBS="$LIBS -lsupc++"
     fi
   fi
 fi
@@ -2373,11 +2374,13 @@
 AC_SUBST(readline_link)
 AC_SUBST(readline_h_ln_cmd)
 
+MYSQL_CHECK_BIG_TABLES
 MYSQL_CHECK_BDB
 MYSQL_CHECK_INNODB
 MYSQL_CHECK_EXAMPLEDB
 MYSQL_CHECK_ARCHIVEDB
 MYSQL_CHECK_CSVDB
+MYSQL_CHECK_BLACKHOLEDB
 MYSQL_CHECK_NDBCLUSTER
 MYSQL_CHECK_FEDERATED
 

--- 1.255/mysql-test/mysql-test-run.sh	2005-03-22 12:30:42 +01:00
+++ 1.256/mysql-test/mysql-test-run.sh	2005-04-08 11:24:22 +02:00
@@ -222,6 +222,7 @@
 EXTRA_MASTER_OPT=""
 EXTRA_MYSQL_TEST_OPT=""
 EXTRA_MYSQLDUMP_OPT=""
+EXTRA_MYSQLSHOW_OPT=""
 EXTRA_MYSQLBINLOG_OPT=""
 USE_RUNNING_SERVER=0
 USE_NDBCLUSTER=@USE_NDBCLUSTER@
@@ -238,7 +239,7 @@
 SLEEP_TIME_FOR_FIRST_MASTER=400		# Enough time to create innodb tables
 SLEEP_TIME_FOR_SECOND_MASTER=400
 SLEEP_TIME_FOR_FIRST_SLAVE=400
-SLEEP_TIME_FOR_SECOND_SLAVE=30
+SLEEP_TIME_FOR_SECOND_SLAVE=300
 CHARACTER_SET=latin1
 DBUSER=""
 START_WAIT_TIMEOUT=10
@@ -453,6 +454,8 @@
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
       EXTRA_MYSQLDUMP_OPT="$EXTRA_MYSQLDUMP_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace"
+      EXTRA_MYSQLSHOW_OPT="$EXTRA_MYSQLSHOW_OPT \
+       --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlshow.trace"
       EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlbinlog.trace"
      
EXTRA_MYSQL_CLIENT_TEST_OPT="--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysql_client_test.trace"
@@ -556,6 +559,11 @@
  else
    MYSQL_DUMP="$BASEDIR/client/mysqldump"
  fi
+ if [ -f "$BASEDIR/client/.libs/mysqlshow" ] ; then
+   MYSQL_SHOW="$BASEDIR/client/.libs/mysqlshow"
+ else
+   MYSQL_SHOW="$BASEDIR/client/mysqlshow"
+ fi
  if [ -f "$BASEDIR/client/.libs/mysqlbinlog" ] ; then
    MYSQL_BINLOG="$BASEDIR/client/.libs/mysqlbinlog"
  else
@@ -627,6 +635,7 @@
  fi
  MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
  MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
  MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
  MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
  WAIT_PID="$CLIENT_BINDIR/mysql_waitpid"
@@ -697,10 +706,11 @@
 
 MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root
--socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT"
 MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLDUMP_OPT"
+MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLSHOW_OPT"
 MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR 
--character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
 MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost
--port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD
--basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
 MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root
--password=$DBPASSWD"
-export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
 export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR
 export NDB_TOOLS_DIR
 export NDB_MGM
@@ -731,7 +741,7 @@
   XTERM=`which xterm`
 fi
 
-export MYSQL MYSQL_DUMP MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR MASTER_MYSOCK
+export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES CLIENT_BINDIR
MASTER_MYSOCK
 
 #++
 # Function Definitions

--- 1.154/sql/handler.cc	2005-03-30 15:00:27 +02:00
+++ 1.155/sql/handler.cc	2005-04-08 11:24:24 +02:00
@@ -25,6 +25,7 @@
 #include "ha_heap.h"
 #include "ha_myisam.h"
 #include "ha_myisammrg.h"
+#include "bitvector.h"
 #ifdef HAVE_ISAM
 #include "ha_isam.h"
 #include "ha_isammrg.h"
@@ -1738,6 +1739,13 @@
     #   Error
 */
 
+#ifdef USE_PREPARE_CODE
+int handler::prepare_delete_table(const char *name)
+{
+  return 0;
+}
+#endif
+
 int handler::delete_table(const char *name)
 {
   int error= 0;
@@ -1760,6 +1768,13 @@
 }
 
 
+#ifdef USE_PREPARE_CODE
+int handler::prepare_rename_table(const char * from, const char * to)
+{
+  return 0;
+}
+#endif
+
 int handler::rename_table(const char * from, const char * to)
 {
   DBUG_ENTER("handler::rename_table");
@@ -2400,4 +2415,125 @@
     *ext= 0;
   }
   return &known_extensions;
+}
+
+int handler::
+ha_write_row(byte *buf) 
+{
+  DBUG_ENTER("ha_write_row");
+  DBUG_PRINT("enter", ("row: 0x%0x", buf));
+#ifndef DBUG_OFF
+  THD* thd = current_thd;
+  DBUG_PRINT("info", ("thd->query_id=%lu", thd->query_id));
+  for (size_t i = 0 ; i < table->s->fields ; ++i) 
+  {
+    DBUG_PRINT("info", ("Field '%s': query_id=%lu, offset=%d, ptr=%p",
+			table->field[i]->field_name,
+			table->field[i]->query_id,
+			table->field[i]->offset(),
+			table->field[i]->ptr));
+  }
+#endif
+  DBUG_PRINT("info", ("Writing row to actual handler"));
+  if (int error = write_row(buf)) {
+    DBUG_PRINT("exit", ("error = %d", error));
+    DBUG_RETURN(error);
+  }
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  DBUG_PRINT("info", ("Writing row to THD"));
+  if (table->s->tmp_table == NO_TMP_TABLE 
+      && !this->is_injective()) 
+  {
+    bitvector const cols(table->s->fields, true);
+    thd->write_row(table, cols, buf);
+  }
+#endif
+  DBUG_PRINT("exit", ("error = %d", 0));
+  DBUG_RETURN(0);
+}
+  
+int handler::
+ha_update_row(const byte *old_data, byte *new_data) 
+{
+  DBUG_ENTER("ha_update_row");
+  DBUG_PRINT("enter", ("before: 0x%0x; after: 0x%0x", old_data, new_data));
+#ifndef DBUG_OFF
+  THD* thd = current_thd;
+  DBUG_PRINT("info", ("thd->query_id=%lu", thd->query_id));
+  for (size_t i = 0 ; i < table->s->fields ; ++i) 
+  {
+    DBUG_PRINT("info", ("Field '%s': query_id=%lu, offset=%d, ptr=%p",
+			table->field[i]->field_name,
+			table->field[i]->query_id,
+			table->field[i]->offset(),
+			table->field[i]->ptr));
+  }
+#endif
+  if (int error = update_row(old_data, new_data)) {
+    DBUG_PRINT("exit", ("error = %d", error));
+    DBUG_RETURN(error);
+  }
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  if (table->s->tmp_table == NO_TMP_TABLE
+      && !this->is_injective()) 
+  {
+    bitvector const cols(table->s->fields, true);
+    thd->update_row(table, cols, old_data, new_data);
+  }
+#endif
+  DBUG_PRINT("exit", ("error = %d", 0));
+  DBUG_RETURN(0);
+}
+  
+int handler::
+ha_delete_row(const byte *buf) 
+{
+  DBUG_ENTER("ha_delete_row");
+  DBUG_PRINT("enter", ("row: 0x%0x", buf));
+#ifndef DBUG_OFF
+  THD* thd = current_thd;
+  DBUG_PRINT("info", ("thd->query_id=%lu", thd->query_id));
+  for (size_t i = 0 ; i < table->s->fields ; ++i) 
+  {
+    DBUG_PRINT("info", ("Field '%s': query_id=%lu, offset=%d, ptr=%p",
+			table->field[i]->field_name,
+			table->field[i]->query_id,
+			table->field[i]->offset(),
+			table->field[i]->ptr));
+  }
+#endif
+  if (int error = delete_row(buf)) {
+    DBUG_PRINT("exit", ("error = %d", error));
+    DBUG_RETURN(error);
+  }
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  if (table->s->tmp_table == NO_TMP_TABLE
+      && !this->is_injective()) 
+  {
+    bitvector const cols(table->s->fields, true);
+    thd->delete_row(table, cols, buf);
+  }
+#endif
+  DBUG_PRINT("exit", ("error = %d", 0));
+  DBUG_RETURN(0);
+}    
+  
+int handler::
+ha_stmt_begin() 
+{ 
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  return current_thd->transaction_begin(); 
+#else
+  return 0;
+#endif
+}
+
+int handler::
+ha_stmt_end()
+{ 
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  return current_thd->transaction_end(); 
+#else
+  return 0;
+#endif
 }

--- 1.133/sql/handler.h	2005-03-25 21:38:03 +01:00
+++ 1.134/sql/handler.h	2005-04-08 11:24:24 +02:00
@@ -150,6 +150,9 @@
 /* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
 #define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
 
+// Forward declarations
+class bitvector;
+
 enum db_type
 {
   DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
@@ -406,6 +409,7 @@
 } HANDLER_BUFFER;
 
 
+
 class handler :public Sql_alloc
 {
  protected:
@@ -543,11 +547,21 @@
   uint get_index(void) const { return active_index; }
   virtual int open(const char *name, int mode, uint test_if_locked)=0;
   virtual int close(void)=0;
-  virtual int write_row(byte * buf) { return  HA_ERR_WRONG_COMMAND; }
-  virtual int update_row(const byte * old_data, byte * new_data)
-   { return  HA_ERR_WRONG_COMMAND; }
-  virtual int delete_row(const byte * buf)
-   { return  HA_ERR_WRONG_COMMAND; }
+
+  int ha_write_row(byte *buf);  
+  int ha_update_row(const byte *old_data, byte *new_data);
+  int ha_delete_row(const byte *buf);
+  
+  int ha_stmt_begin();
+  int ha_stmt_end();
+
+  /*
+    If the handler does it's own injection of the rows, this member function
+    should return 'true'. An alternative would be to use a set of replication
+    flags, which might be implemented to be faster.
+  */
+  virtual bool is_injective() const { return false; }
+
   virtual int index_read(byte * buf, const byte * key,
 			 uint key_len, enum ha_rkey_function find_flag)
    { return  HA_ERR_WRONG_COMMAND; }
@@ -698,9 +712,14 @@
     default rename_table() and delete_table() rename/delete files with a
     given name and extensions from bas_ext()
   */
-  virtual int rename_table(const char *from, const char *to);
+#define USE_PREPARE_CODE
+#ifdef USE_PREPARE_CODE
+  virtual int prepare_rename_table(const char *from, const char *to);  
+  virtual int prepare_delete_table(const char *name);
+#endif
+  virtual int rename_table(const char *from, const char *to);  
   virtual int delete_table(const char *name);
-  
+
   virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
 
   /* lock_count() can be more than one if the table is a MERGE */
@@ -732,7 +751,7 @@
  {
    return memcmp(ref1, ref2, ref_length);
  }
- 
+
  /*
    Condition pushdown to storage engines
  */
@@ -766,6 +785,18 @@
      Pops the top if condition stack, if stack is not empty
  */
  virtual void cond_pop() { return; };
+
+private:
+  /*
+    Row-level primitives for storage engines. 
+    These should be overridden by the storage engine class. To call
+    these methods, use the corresponding 'ha_*' method above.
+  */
+  virtual int write_row(byte * buf) { return  HA_ERR_WRONG_COMMAND; }
+  virtual int update_row(const byte * old_data, byte * new_data)
+  { return  HA_ERR_WRONG_COMMAND; }
+  virtual int delete_row(const byte * buf)
+  { return  HA_ERR_WRONG_COMMAND; }
 };
 
 	/* Some extern variables used with handlers */

--- 1.135/sql/item_sum.cc	2005-03-30 15:57:49 +02:00
+++ 1.136/sql/item_sum.cc	2005-04-08 11:24:24 +02:00
@@ -2370,7 +2370,7 @@
     */
     return tree->unique_add(table->record[0] + table->s->null_bytes);
   }
-  if ((error= table->file->write_row(table->record[0])) &&
+  if ((error= table->file->ha_write_row(table->record[0])) &&
       error != HA_ERR_FOUND_DUPP_KEY &&
       error != HA_ERR_FOUND_DUPP_UNIQUE)
     return TRUE;

--- 1.159/sql/log.cc	2005-04-01 22:17:22 +02:00
+++ 1.160/sql/log.cc	2005-04-08 11:24:24 +02:00
@@ -348,8 +348,9 @@
 MYSQL_LOG::MYSQL_LOG()
   :bytes_written(0), last_time(0), query_start(0), name(0),
    file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
-   need_start_event(1), prepared_xids(0), description_event_for_exec(0),
-   description_event_for_queue(0)
+   need_start_event(1), prepared_xids(0), 
+   m_table_map(NULL), m_next_table_id(0), 
+   description_event_for_exec(0), description_event_for_queue(0)
 {
   /*
     We don't want to initialize LOCK_Log here as such initialization depends on
@@ -410,6 +411,7 @@
   no_auto_events = no_auto_events_arg;
   max_size=max_size_arg;
   DBUG_PRINT("info",("log_type: %d max_size: %lu", log_type, max_size));
+
   DBUG_VOID_RETURN;
 }
 
@@ -1550,9 +1552,15 @@
 
 bool MYSQL_LOG::write(Log_event *event_info)
 {
-  THD *thd= event_info->thd;
+  THD *thd=event_info->thd;
   bool error= 1;
-  DBUG_ENTER("MYSQL_LOG::write(Log_event *)");
+  DBUG_ENTER("MYSQL_LOG::write(Log_event*)");
+  
+  /*
+    Let the event decide if it want to go to the binlog.
+  */
+  if (!event_info->write_to_binlog())
+    DBUG_RETURN(0);		// Silently succeed
 
   pthread_mutex_lock(&LOCK_log);
 
@@ -1583,15 +1591,21 @@
 
 #ifdef USING_TRANSACTIONS
     /*
-      Should we write to the binlog cache or to the binlog on disk?
-      Write to the binlog cache if:
-      - it is already not empty (meaning we're in a transaction; note that the
-     present event could be about a non-transactional table, but still we need
-     to write to the binlog cache in that case to handle updates to mixed
-     trans/non-trans table types the best possible in binlogging)
+      Should we write to the binlog cache or to the binlog on disk?  Write to
+      the binlog cache if the statement can be cached (can_be_cached() ==
+      true) and the binlog cache:
+      - is already not empty (meaning we're in a transaction; note that the
+        present event could be about a non-transactional table, but still we
+        need to write to the binlog cache in that case to handle updates to
+        mixed trans/non-trans table types the best possible in binlogging)
       - or if the event asks for it (cache_stmt == true).
     */
+#if 0
+    // Disabled writing directly to the log, since it doesn't work right now.
+    if (opt_using_transactions && thd && event_info->can_be_cached())
+#else
     if (opt_using_transactions && thd)
+#endif
     {
       IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot];
 
@@ -1686,6 +1700,7 @@
 
     if (file == &log_file) // we are writing to the real log (disk)
     {
+      DBUG_PRINT("info", ("Flushing cache %p", file));
       if (flush_io_cache(file) || sync_binlog(file))
 	goto err;
     }
@@ -2244,6 +2259,61 @@
   DBUG_VOID_RETURN;
 }
 
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+
+ulong MYSQL_LOG::
+get_table_id(TABLE* table)
+{
+  DBUG_ENTER("MYSQL_LOG::get_table_id(TABLE*)");
+  DBUG_PRINT("enter", ("table=%p", table)); 
+  DBUG_ASSERT(table != NULL);
+
+  // Have to create it here since it relies on my_malloc, which requires
+  // my_init() to have been executed prior to this.
+  if (m_table_map == NULL)
+    m_table_map = new table_mapping;
+
+  DBUG_ASSERT(m_table_map != NULL);
+
+  ulong tid = m_table_map->get_table_id(table);
+  if (tid == table_mapping::NO_TABLE) {
+    // We can't use the number of tables in the list since the highest table
+    // id might be larger than the number of elements in the list. 
+    tid = m_next_table_id++;
+
+    // There is one reserved number that cannot be used.
+    if (tid == table_mapping::NO_TABLE)
+	tid = m_next_table_id++;
+	
+    m_table_map->set_table(tid, table);
+  }
+  DBUG_PRINT("return", ("table_id=%d", tid));
+  DBUG_RETURN(tid);
+}
+
+int MYSQL_LOG::
+is_table_mapped(TABLE* table) const
+{
+  DBUG_ASSERT(table != NULL);
+
+  // Have to create it here since it relies on my_malloc, which requires
+  // my_init() to have been executed prior to this.
+  if (m_table_map == NULL)
+    m_table_map = new table_mapping;
+
+  DBUG_ASSERT(m_table_map != NULL);
+  return m_table_map->get_table_id(table) != table_mapping::NO_TABLE;
+}
+
+void MYSQL_LOG::
+clear_table_mappings()
+{
+  DBUG_ASSERT(m_table_map != NULL);
+  m_table_map->clear_tables();
+}
+
+#endif // !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 
 #ifdef __NT__
 void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,

--- 1.171/sql/log_event.cc	2005-04-01 13:40:13 +02:00
+++ 1.172/sql/log_event.cc	2005-04-08 11:24:24 +02:00
@@ -21,6 +21,7 @@
 #endif
 #include  "mysql_priv.h"
 #include "slave.h"
+#include "rpl_filter.h"
 #include <my_dir.h>
 #endif /* MYSQL_CLIENT */
 
@@ -510,8 +511,6 @@
   field_list->push_back(new Item_empty_string("Info", 20));
 }
 
-#endif /* !MYSQL_CLIENT */
-
 
 /*
   Log_event::write()
@@ -599,7 +598,6 @@
 
 */
 
-#ifndef MYSQL_CLIENT
 int Log_event::read_log_event(IO_CACHE* file, String* packet,
 			      pthread_mutex_t* log_lock)
 {
@@ -981,6 +979,7 @@
 }
 #endif
 
+#ifndef MYSQL_CLIENT
 
 /*
   Query_log_event::write()
@@ -998,7 +997,8 @@
             1+8+           // code of sql_mode and sql_mode
             1+1+FN_REFLEN+ // code of catalog and catalog length and catalog
             1+4+           // code of autoinc and the 2 autoinc variables
-            1+6            // code of charset and charset
+            1+6+           // code of charset and charset
+            1+1+MAX_TIME_ZONE_NAME_LENGTH // code of tz and tz length and tz name
             ], *start, *start_of_status;
   ulong event_length;
 
@@ -1055,37 +1055,40 @@
   start_of_status= start= buf+QUERY_HEADER_LEN;
   if (flags2_inited)
   {
-    *(start++)= Q_FLAGS2_CODE;
+    *start++= Q_FLAGS2_CODE;
     int4store(start, flags2);
     start+= 4;
   }
   if (sql_mode_inited)
   {
-    *(start++)= Q_SQL_MODE_CODE;
+    *start++= Q_SQL_MODE_CODE;
     int8store(start, (ulonglong)sql_mode);
     start+= 8;
   }
-  if (catalog_len >= 0) // i.e. "catalog inited" (false for 4.0 events)
+  if (catalog_len) // i.e. "catalog inited" (false for 4.0 events)
   {
-    *(start++)= Q_CATALOG_CODE;
-    *(start++)= (uchar) catalog_len;
+    *start++= Q_CATALOG_NZ_CODE;
+    *start++= (uchar) catalog_len;
     bmove(start, catalog, catalog_len);
     start+= catalog_len;
     /*
-      We write a \0 at the end. As we also have written the length, it's
-      apparently useless; but in fact it enables us to just do
-      catalog= a_pointer_to_the_buffer_of_the_read_event
-      later in the slave SQL thread.
-      If we didn't have the \0, we would need to memdup to build the catalog in
-      the slave SQL thread. 
-      And still the interest of having the length too is that in the slave SQL
-      thread we immediately know at which position the catalog ends (no need to
-      search for '\0'. In other words: length saves search, \0 saves mem alloc,
-      at the cost of 1 redundant byte on the disk.
-      Note that this is only a fix until we change 'catalog' to LEX_STRING
-      (then we won't need the \0).
+      In 5.0.x where x<4 masters we used to store the end zero here. This was
+      a waste of one byte so we don't do it in x>=4 masters. We change code to
+      Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
+      of this x>=4 master segfault (expecting a zero when there is
+      none). Remaining compatibility problems are: the older slave will not
+      find the catalog; but it is will not crash, and it's not an issue
+      that it does not find the catalog as catalogs were not used in these
+      older MySQL versions (we store it in binlog and read it from relay log
+      but do nothing useful with it). What is an issue is that the older slave
+      will stop processing the Q_* blocks (and jumps to the db/query) as soon
+      as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
+      Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
+      various ways. Documented that you should not mix alpha/beta versions if
+      they are not exactly the same version, with example of 5.0.3->5.0.2 and
+      5.0.4->5.0.3. If replication is from older to new, the new will
+      recognize Q_CATALOG_CODE and have no problem.
     */
-    *(start++)= '\0';
   }
   if (auto_increment_increment != 1)
   {
@@ -1096,15 +1099,24 @@
   }
   if (charset_inited)
   {
-    *(start++)= Q_CHARSET_CODE;
+    *start++= Q_CHARSET_CODE;
     memcpy(start, charset, 6);
     start+= 6;
   }
+  if (time_zone_len)
+  {
+    /* In the TZ sys table, column Name is of length 64 so this should be ok */
+    DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
+    *start++= Q_TIME_ZONE_CODE;
+    *start++= time_zone_len;
+    memcpy(start, time_zone_str, time_zone_len);
+    start+= time_zone_len;
+  }
   /*
     Here there could be code like
     if (command-line-option-which-says-"log_this_variable" && inited)
     {
-    *(start++)= Q_THIS_VARIABLE_CODE;
+    *start++= Q_THIS_VARIABLE_CODE;
     int4store(start, this_variable);
     start+= 4;
     }
@@ -1133,8 +1145,6 @@
 /*
   Query_log_event::Query_log_event()
 */
-
-#ifndef MYSQL_CLIENT
 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
 				 ulong query_length, bool using_trans,
 				 bool suppress_use)
@@ -1175,6 +1185,18 @@
   int2store(charset, thd_arg->variables.character_set_client->number);
   int2store(charset+2, thd_arg->variables.collation_connection->number);
   int2store(charset+4, thd_arg->variables.collation_server->number);
+  if (thd_arg->time_zone_used)
+  {
+    /*
+      Note that our event becomes dependent on the Time_zone object
+      representing the time zone. Fortunately such objects are never deleted
+      or changed during mysqld's lifetime.
+    */
+    time_zone_len= thd_arg->variables.time_zone->get_name()->length();
+    time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
+  }
+  else
+    time_zone_len= 0;
   DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
 }
 #endif /* MYSQL_CLIENT */
@@ -1188,15 +1210,18 @@
 Query_log_event::Query_log_event(const char* buf, uint event_len,
                                  const Format_description_log_event *description_event,
                                  Log_event_type event_type)
-  :Log_event(buf, description_event), data_buf(0), query(NullS), catalog(NullS), 
+  :Log_event(buf, description_event), data_buf(0), query(NullS),
    db(NullS), catalog_len(0), status_vars_len(0),
    flags2_inited(0), sql_mode_inited(0), charset_inited(0),
-   auto_increment_increment(1), auto_increment_offset(1)
+   auto_increment_increment(1), auto_increment_offset(1),
+   time_zone_len(0)
 {
   ulong data_len;
   uint32 tmp;
   uint8 common_header_len, post_header_len;
-  const char *start, *end;
+  char *start;
+  const char *end;
+  bool catalog_nz= 1;
   DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
 
   common_header_len= description_event->common_header_len;
@@ -1216,7 +1241,7 @@
   
   slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
   exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
-  db_len = (uint)buf[Q_DB_LEN_OFFSET];
+  db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
   error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
 
   /*
@@ -1242,7 +1267,7 @@
   /* variable-part: the status vars; only in MySQL 5.0  */
   
   start= (char*) (buf+post_header_len);
-  end= (char*) (start+status_vars_len);
+  end= (const char*) (start+status_vars_len);
   for (const uchar* pos= (const uchar*) start; pos < (const uchar*) end;)
   {
     switch (*pos++) {
@@ -1264,11 +1289,10 @@
       pos+= 8;
       break;
     }
-    case Q_CATALOG_CODE:
-      catalog_len= *pos;
-      if (catalog_len)
-        catalog= (char*) pos+1;                           // Will be copied later
-      pos+= catalog_len+2;
+    case Q_CATALOG_NZ_CODE:
+      if ((catalog_len= *pos))
+        catalog= (char*) pos+1;                 // Will be copied later
+      pos+= catalog_len+1;
       break;
     case Q_AUTO_INCREMENT:
       auto_increment_increment= uint2korr(pos);
@@ -1282,32 +1306,60 @@
       pos+= 6;
       break;
     }
+    case Q_TIME_ZONE_CODE:
+    {
+      if ((time_zone_len= *pos))
+        time_zone_str= (char *)(pos+1);
+      pos+= time_zone_len+1;
+      break;
+    }
+    case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */
+      if ((catalog_len= *pos))
+        catalog= (char*) pos+1;                           // Will be copied later
+      pos+= catalog_len+2; // leap over end 0
+      catalog_nz= 0; // catalog has end 0 in event
+      break;
     default:
       /* That's why you must write status vars in growing order of code */
       DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
  code: %u), skipping the rest of them", (uint) *(pos-1)));
-      pos= (const uchar*) end;                         // Break look
+      pos= (const uchar*) end;                         // Break loop
     }
   }
   
-  /* A 2nd variable part; this is common to all versions */ 
-  
-  if (!(start= data_buf = (char*) my_malloc(catalog_len + data_len +2, MYF(MY_WME))))
+  if (!(start= data_buf = (char*) my_malloc(catalog_len + 1 +
+                                            time_zone_len + 1 +
+                                            data_len + 1, MYF(MY_WME))))
     DBUG_VOID_RETURN;
-  if (catalog)                                  // If catalog is given
+  if (catalog_len)                                  // If catalog is given
+  {
+    if (likely(catalog_nz)) // true except if event comes from 5.0.0|1|2|3.
+    {
+      memcpy(start, catalog, catalog_len);
+      catalog= start;
+      start+= catalog_len;
+      *start++= 0;
+    }
+    else
+    {
+      memcpy(start, catalog, catalog_len+1); // copy end 0
+      catalog= start;
+      start+= catalog_len+1;
+    }
+  }
+  if (time_zone_len)
   {
-    memcpy((char*) start, catalog, catalog_len+1);      // Copy name and end \0
-    catalog= start;
-    start+= catalog_len+1;
+    memcpy(start, time_zone_str, time_zone_len);
+    time_zone_str= start;
+    start+= time_zone_len;
+    *start++= 0;
   }
+  /* A 2nd variable part; this is common to all versions */ 
   memcpy((char*) start, end, data_len);          // Copy db and query
-  ((char*) start)[data_len]= '\0';              // End query with \0 (For safetly)
+  start[data_len]= '\0';              // End query with \0 (For safetly)
   db= start;
   query= start + db_len + 1;
   q_len= data_len - db_len -1;
-  /* This is used to detect wrong parsing. Could be removed in the future. */
-  DBUG_PRINT("info", ("catalog: '%s'  len: %u   db: '%s'  len:  %u  q_len: %lu",
-                      catalog, (uint) catalog_len, db, (uint) db_len,q_len));
   DBUG_VOID_RETURN;
 }
 
@@ -1415,6 +1467,8 @@
     last_event_info->auto_increment_offset=    auto_increment_offset;
   }
 
+  /* TODO: print the catalog when we feature SET CATALOG */
+
   if (likely(charset_inited))
   {
     if (unlikely(!last_event_info->charset_inited)) /* first Query event */
@@ -1435,6 +1489,14 @@
       memcpy(last_event_info->charset, charset, 6);
     }
   }
+  if (time_zone_len)
+  {
+    if (bcmp(last_event_info->time_zone_str, time_zone_str, time_zone_len+1))
+    {
+      fprintf(file,"SET @@session.time_zone='%s';\n", time_zone_str);
+      memcpy(last_event_info->time_zone_str, time_zone_str, time_zone_len+1);
+    }
+  }
 }
 
 
@@ -1468,9 +1530,9 @@
     alloced block (see Query_log_event::exec_event()). Same for thd->db.
     Thank you.
   */
-  thd->catalog= (char*) catalog;
+  thd->catalog= catalog_len ? (char *) catalog : (char *)"";
   thd->db_length= db_len;
-  thd->db= (char*) rewrite_db(db, &thd->db_length);
+  thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
   thd->variables.auto_increment_increment= auto_increment_increment;
   thd->variables.auto_increment_offset=    auto_increment_offset;
 
@@ -1489,7 +1551,7 @@
 
   clear_all_errors(thd, rli);
 
-  if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+  if (rpl_filter->db_ok(thd->db))
   {
     thd->set_time((time_t)when);
     thd->query_length= q_len_arg;
@@ -1538,20 +1600,28 @@
                 get_charset(uint2korr(charset+4), MYF(MY_WME))))
           {
             /*
-              We updated the thd->variables with nonsensical values (0), and the
-              thread is not guaranteed to terminate now (as it may be configured
-              to ignore EE_UNKNOWN_CHARSET);if we're going to execute a next
-              statement we'll have a new charset info with it, so no problem to
-              have stored 0 in thd->variables. But we invalidate cached
-              charset to force a check next time (otherwise if next time
-              charset is unknown again we won't detect it).
+              We updated the thd->variables with nonsensical values (0). Let's
+              set them to something safe (i.e. which avoids crash), and we'll
+              stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
+              ignore this error).
             */
-            rli->cached_charset_invalidate();
+            set_slave_thread_default_charset(thd, rli);
             goto compare_errors;
           }
           thd->update_charset(); // for the charset change to take effect
         }
       }
+      if (time_zone_len)
+      {
+        String tmp(time_zone_str, time_zone_len, &my_charset_bin);
+        if (!(thd->variables.time_zone=
+              my_tz_find_with_opening_tz_tables(thd, &tmp)))
+        {
+          my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
+          thd->variables.time_zone= global_system_variables.time_zone;
+          goto compare_errors;
+        }
+      }
 
       /* Execute the query (note that we bypass dispatch_command()) */
       mysql_parse(thd, thd->query, thd->query_length);
@@ -1776,6 +1846,7 @@
   Start_log_event_v3::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Start_log_event_v3::write(IO_CACHE* file)
 {
   char buff[START_V3_HEADER_LEN];
@@ -1785,6 +1856,7 @@
   return (write_header(file, sizeof(buff)) ||
           my_b_safe_write(file, (byte*) buff, sizeof(buff)));
 }
+#endif
 
 
 /*
@@ -2004,7 +2076,7 @@
   DBUG_VOID_RETURN;
 }
 
-
+#ifndef MYSQL_CLIENT
 bool Format_description_log_event::write(IO_CACHE* file)
 {
   /*
@@ -2021,6 +2093,7 @@
   return (write_header(file, sizeof(buff)) ||
           my_b_safe_write(file, buff, sizeof(buff)));
 }
+#endif
 
 /*
   SYNOPSIS
@@ -2041,6 +2114,7 @@
   delete rli->relay_log.description_event_for_exec;
   rli->relay_log.description_event_for_exec= this;
 
+#ifdef USING_TRANSACTIONS
   /*
     As a transaction NEVER spans on 2 or more binlogs:
     if we have an active transaction at this point, the master died
@@ -2062,6 +2136,7 @@
                       "to its binary log.");
     end_trans(thd, ROLLBACK);
   }
+#endif
   /*
     If this event comes from ourselves, there is no cleaning task to perform,
     we don't call Start_log_event_v3::exec_event() (this was just to update the
@@ -2237,6 +2312,8 @@
 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
 
 
+#ifndef MYSQL_CLIENT
+
 /*
   Load_log_event::write_data_header()
 */
@@ -2278,7 +2355,6 @@
   Load_log_event::Load_log_event()
 */
 
-#ifndef MYSQL_CLIENT
 Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
 			       const char *db_arg, const char *table_name_arg,
 			       List<Item> &fields_arg,
@@ -2598,7 +2674,7 @@
 			       bool use_rli_only_for_errors)
 {
   thd->db_length= db_len;
-  thd->db= (char*) rewrite_db(db, &thd->db_length);
+  thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
   DBUG_ASSERT(thd->query == 0);
   thd->query_length= 0;                         // Should not be needed
   thd->query_error= 0;
@@ -2627,7 +2703,7 @@
     al. Another way is do the filtering in the I/O thread (more efficient: no
     disk writes at all).
   */
-  if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
+  if (rpl_filter->db_ok(thd->db))
   {
     thd->set_time((time_t)when);
     VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -2649,7 +2725,7 @@
     tables.updating= 1;
 
     // the table will be opened in mysql_load    
-    if (table_rules_on && !tables_ok(thd, &tables))
+    if (rpl_filter->is_on() && !rpl_filter->tables_ok(thd->db,
&tables))
     {
       // TODO: this is a bug - this needs to be moved to the I/O thread
       if (net)
@@ -2892,6 +2968,7 @@
   Rotate_log_event::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Rotate_log_event::write(IO_CACHE* file)
 {
   char buf[ROTATE_HEADER_LEN];
@@ -2900,7 +2977,7 @@
           my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
           my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
 }
-
+#endif
 
 /*
   Rotate_log_event::exec_event()
@@ -2958,17 +3035,10 @@
       master is 4.0 then the events are in the slave's format (conversion).
     */
     set_slave_thread_options(thd);
+    set_slave_thread_default_charset(thd, rli);
     thd->variables.sql_mode= global_system_variables.sql_mode;
     thd->variables.auto_increment_increment=
       thd->variables.auto_increment_offset= 1;
-    thd->variables.character_set_client=
-      global_system_variables.character_set_client;
-    thd->variables.collation_connection=
-      global_system_variables.collation_connection;
-    thd->variables.collation_server=
-      global_system_variables.collation_server;
-    thd->update_charset();
-    rli->cached_charset_invalidate();
   }
   pthread_mutex_unlock(&rli->data_lock);
   pthread_cond_broadcast(&rli->data_cond);
@@ -3030,6 +3100,7 @@
   Intvar_log_event::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Intvar_log_event::write(IO_CACHE* file)
 {
   byte buf[9];
@@ -3038,6 +3109,7 @@
   return (write_header(file, sizeof(buf)) ||
           my_b_safe_write(file, buf, sizeof(buf)));
 }
+#endif
 
 
 /*
@@ -3122,6 +3194,7 @@
 }
 
 
+#ifndef MYSQL_CLIENT
 bool Rand_log_event::write(IO_CACHE* file)
 {
   byte buf[16];
@@ -3130,6 +3203,7 @@
   return (write_header(file, sizeof(buf)) ||
           my_b_safe_write(file, buf, sizeof(buf)));
 }
+#endif
 
 
 #ifdef MYSQL_CLIENT
@@ -3193,11 +3267,13 @@
 }
 
 
+#ifndef MYSQL_CLIENT
 bool Xid_log_event::write(IO_CACHE* file)
 {
   return write_header(file, sizeof(xid)) ||
          my_b_safe_write(file, (byte*) &xid, sizeof(xid));
 }
+#endif
 
 
 #ifdef MYSQL_CLIENT
@@ -3331,6 +3407,7 @@
 }
 
 
+#ifndef MYSQL_CLIENT
 bool User_var_log_event::write(IO_CACHE* file)
 {
   char buf[UV_NAME_LEN_SIZE];
@@ -3365,7 +3442,7 @@
       dec->fix_buffer_pointer();
       buf2[0]= (char)(dec->intg + dec->frac);
       buf2[1]= (char)dec->frac;
-      decimal2bin((decimal*)val, buf2+2, buf2[0], buf2[1]);
+      decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]);
       val_len= decimal_bin_size(buf2[0], buf2[1]) + 2;
       break;
     }
@@ -3390,6 +3467,7 @@
 	  my_b_safe_write(file, (byte*) buf1, buf1_length) ||
 	  my_b_safe_write(file, (byte*) pos, val_len));
 }
+#endif
 
 
 /*
@@ -3432,8 +3510,8 @@
       int str_len= sizeof(str_buf) - 1;
       int precision= (int)val[0];
       int scale= (int)val[1];
-      decimal_digit dec_buf[10];
-      decimal dec;
+      decimal_digit_t dec_buf[10];
+      decimal_t dec;
       dec.len= 10;
       dec.buf= dec_buf;
 
@@ -3663,6 +3741,7 @@
 }
 
 
+#ifndef MYSQL_CLIENT
 bool Slave_log_event::write(IO_CACHE* file)
 {
   ulong event_length= get_data_size();
@@ -3673,6 +3752,7 @@
   return (write_header(file, event_length) ||
           my_b_safe_write(file, (byte*) mem_pool, event_length));
 }
+#endif
 
 
 void Slave_log_event::init_from_mem_pool(int data_size)
@@ -3799,7 +3879,6 @@
   sql_ex.force_new_format();
   DBUG_VOID_RETURN;
 }
-#endif /* !MYSQL_CLIENT */
 
 
 /*
@@ -3844,6 +3923,7 @@
   return res;
 }
 
+#endif /* !MYSQL_CLIENT */
 
 /*
   Create_file_log_event ctor
@@ -3976,8 +4056,10 @@
   strmov(p, ".info");			// strmov takes less code than memcpy
   strnmov(proc_info, "Making temp file ", 17); // no end 0
   thd->proc_info= proc_info;
-  if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
-		    MYF(MY_WME))) < 0 ||
+  my_delete(fname_buf, MYF(0)); // old copy may exist already
+  if ((fd= my_create(fname_buf, CREATE_MODE,
+		     O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
+		     MYF(MY_WME))) < 0 ||
       init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
 		    MYF(MY_WME|MY_NABP)))
   {
@@ -4001,8 +4083,10 @@
   my_close(fd, MYF(0));
   
   // fname_buf now already has .data, not .info, because we did our trick
-  if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
-		    MYF(MY_WME))) < 0)
+  my_delete(fname_buf, MYF(0)); // old copy may exist already
+  if ((fd= my_create(fname_buf, CREATE_MODE,
+		     O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
+		     MYF(MY_WME))) < 0)
   {
     slave_print_error(rli,my_errno, "Error in Create_file event: could not open file
'%s'", fname_buf);
     goto err;
@@ -4071,6 +4155,7 @@
   Append_block_log_event::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Append_block_log_event::write(IO_CACHE* file)
 {
   byte buf[APPEND_BLOCK_HEADER_LEN];
@@ -4079,6 +4164,7 @@
           my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
 	  my_b_safe_write(file, (byte*) block, block_len));
 }
+#endif
 
 
 /*
@@ -4116,12 +4202,12 @@
 
 
 /*
-  Append_block_log_event::get_open_mode()
+  Append_block_log_event::get_create_or_append()
 */
 
-int Append_block_log_event::get_open_mode() const
+int Append_block_log_event::get_create_or_append() const
 {
-  return O_WRONLY | O_APPEND | O_BINARY;
+  return 0; /* append to the file, fail if not exists */
 }
 
 /*
@@ -4139,7 +4225,21 @@
   memcpy(p, ".data", 6);
   strnmov(proc_info, "Making temp file ", 17); // no end 0
   thd->proc_info= proc_info;
-  if ((fd = my_open(fname, get_open_mode(), MYF(MY_WME))) < 0)
+  if (get_create_or_append())
+  {
+    my_delete(fname, MYF(0)); // old copy may exist already
+    if ((fd= my_create(fname, CREATE_MODE,
+		       O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
+		       MYF(MY_WME))) < 0)
+    {
+      slave_print_error(rli, my_errno,
+			"Error in %s event: could not create file '%s'",
+			get_type_str(), fname);
+      goto err;
+    }
+  }
+  else if ((fd = my_open(fname, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW,
+                         MYF(MY_WME))) < 0)
   {
     slave_print_error(rli, my_errno,
                       "Error in %s event: could not open file '%s'",
@@ -4200,6 +4300,7 @@
   Delete_file_log_event::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Delete_file_log_event::write(IO_CACHE* file)
 {
  byte buf[DELETE_FILE_HEADER_LEN];
@@ -4207,6 +4308,7 @@
  return (write_header(file, sizeof(buf)) ||
          my_b_safe_write(file, buf, sizeof(buf)));
 }
+#endif
 
 
 /*
@@ -4294,6 +4396,7 @@
   Execute_load_log_event::write()
 */
 
+#ifndef MYSQL_CLIENT
 bool Execute_load_log_event::write(IO_CACHE* file)
 {
   byte buf[EXEC_LOAD_HEADER_LEN];
@@ -4301,6 +4404,7 @@
   return (write_header(file, sizeof(buf)) || 
           my_b_safe_write(file, buf, sizeof(buf)));
 }
+#endif
 
 
 /*
@@ -4348,7 +4452,8 @@
   Load_log_event* lev = 0;
 
   memcpy(p, ".info", 6);
-  if ((fd = my_open(fname, O_RDONLY|O_BINARY, MYF(MY_WME))) < 0 ||
+  if ((fd = my_open(fname, O_RDONLY | O_BINARY | O_NOFOLLOW,
+                    MYF(MY_WME))) < 0 ||
       init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
 		    MYF(MY_WME|MY_NABP)))
   {
@@ -4447,9 +4552,9 @@
 
 
 #if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-int Begin_load_query_log_event::get_open_mode() const
+int Begin_load_query_log_event::get_create_or_append() const
 {
-  return O_CREAT | O_WRONLY | O_BINARY | O_TRUNC;
+  return 1; /* create the file */
 }
 #endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
 
@@ -4504,6 +4609,7 @@
 }
 
 
+#ifndef MYSQL_CLIENT
 bool
 Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
 {
@@ -4514,6 +4620,7 @@
   *(buf + 4 + 4 + 4)= (char)dup_handling;
   return my_b_safe_write(file, (byte*) buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
 }
+#endif
 
 
 #ifdef MYSQL_CLIENT
@@ -4624,7 +4731,12 @@
   /* Forging file name for deletion in same buffer */
   *fname_end= 0;
 
-  (void) my_delete(fname, MYF(MY_WME));
+  /*
+    If there was an error the slave is going to stop, leave the
+    file so that we can re-execute this event at START SLAVE.
+  */
+  if (!error)
+    (void) my_delete(fname, MYF(MY_WME));
 
   my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
   return error;

--- 1.109/sql/log_event.h	2005-04-01 13:32:29 +02:00
+++ 1.110/sql/log_event.h	2005-04-08 11:24:24 +02:00
@@ -243,9 +243,24 @@
 /* these are codes, not offsets; not more than 256 values (1 byte). */
 #define Q_FLAGS2_CODE           0
 #define Q_SQL_MODE_CODE         1
+#ifndef TO_BE_DELETED
+/*
+  Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL
+  5.0.x where 0<=x<=3.
+*/
 #define Q_CATALOG_CODE          2
+#endif
 #define Q_AUTO_INCREMENT	3
 #define Q_CHARSET_CODE          4
+#define Q_TIME_ZONE_CODE        5
+/*
+  Q_CATALOG_NZ_CODE is catalog withOUT end zero stored; it is used by MySQL
+  5.0.x where x>=4. Saves one byte in every Query_log_event in binlog,
+  compared to Q_CATALOG_CODE. The reason we didn't simply re-use
+  Q_CATALOG_CODE is that then a 5.0.3 slave of this 5.0.x (x>=4) master would
+  crash (segfault etc) because it would expect a 0 when there is none.
+*/
+#define Q_CATALOG_NZ_CODE       6
 
 /* Intvar event post-header */
 
@@ -468,6 +483,7 @@
   ulong auto_increment_increment, auto_increment_offset;
   bool charset_inited;
   char charset[6]; // 3 variables, each of them storable in 2 bytes
+  char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
   st_last_event_info()
     :flags2_inited(0), sql_mode_inited(0),
      auto_increment_increment(1),auto_increment_offset(1), charset_inited(0)
@@ -479,6 +495,7 @@
       */
       bzero(db, sizeof(db));
       bzero(charset, sizeof(charset));
+      bzero(time_zone_str, sizeof(time_zone_str));
     }
 } LAST_EVENT_INFO;
 #endif
@@ -603,6 +620,7 @@
     my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
   }
 
+#ifndef MYSQL_CLIENT
   bool write_header(IO_CACHE* file, ulong data_length);
   virtual bool write(IO_CACHE* file)
   {
@@ -610,13 +628,14 @@
             write_data_header(file) ||
             write_data_body(file));
   }
-  virtual bool is_artificial_event() { return 0; }
   virtual bool write_data_header(IO_CACHE* file)
   { return 0; }
   virtual bool write_data_body(IO_CACHE* file __attribute__((unused)))
   { return 0; }
+#endif
   virtual Log_event_type get_type_code() = 0;
   virtual bool is_valid() const = 0;
+  virtual bool is_artificial_event() { return 0; }
   inline bool get_cache_stmt() { return cache_stmt; }
   Log_event(const char* buf, const Format_description_log_event* description_event);
   virtual ~Log_event() { free_temp_buf();}
@@ -744,7 +763,7 @@
     concerned) from here.
   */
 
-  int catalog_len;			// <= 255 char; -1 means uninited
+  uint catalog_len;			// <= 255 char; 0 means uninited
 
   /*
     We want to be able to store a variable number of N-bit status vars:
@@ -786,6 +805,8 @@
   ulong sql_mode;
   ulong auto_increment_increment, auto_increment_offset;
   char charset[6];
+  uint time_zone_len; /* 0 means uninited */
+  const char *time_zone_str;
 
 #ifndef MYSQL_CLIENT
 
@@ -809,12 +830,13 @@
   ~Query_log_event()
   {
     if (data_buf)
-    {
       my_free((gptr) data_buf, MYF(0));
-    }
   }
   Log_event_type get_type_code() { return QUERY_EVENT; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+  virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
+#endif
   bool is_valid() const { return query != 0; }
 
   /*
@@ -823,7 +845,6 @@
   */
   virtual ulong get_post_header_size_for_derived() { return 0; }
   /* Writes derived event-specific part of post header. */
-  virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
 };
 
 #ifdef HAVE_REPLICATION
@@ -862,7 +883,9 @@
   int get_data_size();
   bool is_valid() const { return master_host != 0; }
   Log_event_type get_type_code() { return SLAVE_EVENT; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
 };
 
 #endif /* HAVE_REPLICATION */
@@ -957,8 +980,10 @@
   {
     return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
   }
+#ifndef MYSQL_CLIENT
   bool write_data_header(IO_CACHE* file);
   bool write_data_body(IO_CACHE* file);
+#endif
   bool is_valid() const { return table_name != 0; }
   int get_data_size()
   {
@@ -1034,7 +1059,9 @@
                      const Format_description_log_event* description_event);
   ~Start_log_event_v3() {}
   Log_event_type get_type_code() { return START_EVENT_V3;}
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const { return 1; }
   int get_data_size()
   {
@@ -1076,7 +1103,9 @@
                                const Format_description_log_event* description_event);
   ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); }
   Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;}
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const
   {
     return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN :
@@ -1126,7 +1155,9 @@
   Log_event_type get_type_code() { return INTVAR_EVENT;}
   const char* get_var_type_name();
   int get_data_size() { return  9; /* sizeof(type) + sizeof(val) */;}
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const { return 1; }
 };
 
@@ -1164,7 +1195,9 @@
   ~Rand_log_event() {}
   Log_event_type get_type_code() { return RAND_EVENT;}
   int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const { return 1; }
 };
 
@@ -1199,7 +1232,9 @@
   ~Xid_log_event() {}
   Log_event_type get_type_code() { return XID_EVENT;}
   int get_data_size() { return sizeof(xid); }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const { return 1; }
 };
 
@@ -1241,7 +1276,9 @@
   User_var_log_event(const char* buf, const Format_description_log_event*
description_event);
   ~User_var_log_event() {}
   Log_event_type get_type_code() { return USER_VAR_EVENT;}
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   bool is_valid() const { return 1; }
 };
 
@@ -1311,7 +1348,9 @@
   Log_event_type get_type_code() { return ROTATE_EVENT;}
   int get_data_size() { return  ident_len + ROTATE_HEADER_LEN;}
   bool is_valid() const { return new_log_ident != 0; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
 };
 
 
@@ -1371,6 +1410,7 @@
 	    4 + 1 + block_len);
   }
   bool is_valid() const { return inited_from_old || block != 0; }
+#ifndef MYSQL_CLIENT
   bool write_data_header(IO_CACHE* file);
   bool write_data_body(IO_CACHE* file);
   /*
@@ -1378,6 +1418,7 @@
     write it as Load event - used on the slave
   */
   bool write_base(IO_CACHE* file);
+#endif
 };
 
 
@@ -1412,7 +1453,7 @@
 #ifdef HAVE_REPLICATION
   int exec_event(struct st_relay_log_info* rli);
   void pack_info(Protocol* protocol);
-  virtual int get_open_mode() const;
+  virtual int get_create_or_append() const;
 #endif /* HAVE_REPLICATION */
 #else
   void print(FILE* file, bool short_form = 0, LAST_EVENT_INFO* last_event_info= 0);
@@ -1424,7 +1465,9 @@
   Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
   int get_data_size() { return  block_len + APPEND_BLOCK_HEADER_LEN ;}
   bool is_valid() const { return block != 0; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   const char* get_db() { return db; }
 };
 
@@ -1458,7 +1501,9 @@
   Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
   int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
   bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   const char* get_db() { return db; }
 };
 
@@ -1491,7 +1536,9 @@
   Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
   int get_data_size() { return  EXEC_LOAD_HEADER_LEN ;}
   bool is_valid() const { return file_id != 0; }
+#ifndef MYSQL_CLIENT
   bool write(IO_CACHE* file);
+#endif
   const char* get_db() { return db; }
 };
 
@@ -1514,7 +1561,7 @@
                              bool using_trans);
 #ifdef HAVE_REPLICATION
   Begin_load_query_log_event(THD* thd);
-  int get_open_mode() const;
+  int get_create_or_append() const;
 #endif /* HAVE_REPLICATION */
 #endif
   Begin_load_query_log_event(const char* buf, uint event_len,
@@ -1579,7 +1626,9 @@
   bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; }
 
   ulong get_post_header_size_for_derived();
+#ifndef MYSQL_CLIENT
   bool write_post_header_for_derived(IO_CACHE* file);
+#endif
  };
 
 

--- 1.284/sql/mysql_priv.h	2005-04-01 22:17:23 +02:00
+++ 1.285/sql/mysql_priv.h	2005-04-08 11:24:24 +02:00
@@ -1076,6 +1076,8 @@
 extern ulong query_buff_size, thread_stack,thread_stack_min;
 extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
 extern ulong max_binlog_size, max_relay_log_size;
+extern my_bool opt_binlog_row_level;
+extern ulong opt_binlog_row_event_max_size; 
 extern ulong rpl_recovery_rank, thread_cache_size;
 extern ulong back_log;
 extern ulong specialflag, current_pid;

--- 1.445/sql/mysqld.cc	2005-04-05 05:26:15 +02:00
+++ 1.446/sql/mysqld.cc	2005-04-08 11:24:24 +02:00
@@ -19,6 +19,7 @@
 #include <my_dir.h>
 #include "slave.h"
 #include "sql_repl.h"
+#include "rpl_filter.h"
 #include "repl_failsafe.h"
 #include "stacktrace.h"
 #include "mysqld_suffix.h"
@@ -400,12 +401,10 @@
 FILE *bootstrap_file;
 int bootstrap_error;
 
-I_List<i_string_pair> replicate_rewrite_db;
-I_List<i_string> replicate_do_db, replicate_ignore_db;
-// allow the user to tell us which db to replicate and which to ignore
-I_List<i_string> binlog_do_db, binlog_ignore_db;
 I_List<THD> threads,thread_cache;
 I_List<NAMED_LIST> key_caches;
+Rpl_filter* rpl_filter;
+Rpl_filter* binlog_filter;
 
 struct system_variables global_system_variables;
 struct system_variables max_system_variables;
@@ -423,6 +422,7 @@
 SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
 SHOW_COMP_OPTION have_crypt, have_compress;
+SHOW_COMP_OPTION have_blackhole_db;
 
 /* Thread specific variables */
 
@@ -1016,12 +1016,9 @@
   free_max_user_conn();
 #ifdef HAVE_REPLICATION
   end_slave_list();
-  free_list(&replicate_do_db);
-  free_list(&replicate_ignore_db);
-  free_list(&binlog_do_db);
-  free_list(&binlog_ignore_db);
-  free_list(&replicate_rewrite_db);
 #endif
+  delete binlog_filter;
+  delete rpl_filter;
 #ifdef HAVE_OPENSSL
   if (ssl_acceptor_fd)
     my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
@@ -2973,9 +2970,16 @@
 int main(int argc, char **argv)
 #endif
 {
-
   DEBUGGER_OFF;
 
+  rpl_filter= new Rpl_filter;
+  binlog_filter= new Rpl_filter;
+  if (!rpl_filter || !binlog_filter) 
+  {
+    sql_perror("Could not allocate replication and binlog filters");
+    exit(1);
+  }
+
   MY_INIT(argv[0]);		// init my_sys library & pthreads
 
 #ifdef _CUSTOMSTARTUPCONFIG_
@@ -3137,8 +3141,17 @@
 #endif
   if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
     opt_skip_slave_start= 1;
-  /* init_slave() must be called after the thread keys are created */
-  init_slave();
+  /*
+    init_slave() must be called after the thread keys are created.
+    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
+    places) assume that active_mi != 0, so let's fail if it's 0 (out of
+    memory); a message has already been printed.
+  */
+  if (init_slave() && !active_mi)
+  {
+    end_thr_alarm(1);				// Don't allow alarms
+    unireg_abort(1);
+  }
 
   if (opt_bootstrap)
   {
@@ -3312,10 +3325,10 @@
 
 int main(int argc, char **argv)
 {
-
-  /* When several instances are running on the same machine, we
-     need to have an  unique  named  hEventShudown  through the
-     application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
+  /*
+    When several instances are running on the same machine, we
+    need to have an  unique  named  hEventShudown  through the
+    application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
   */
   int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
                                                   "MySQLShutdown"), 10);
@@ -3894,10 +3907,19 @@
   char *suffix_pos;
   char connect_number_char[22], *p;
   const char *errmsg= 0;
+  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
   my_thread_init();
   DBUG_ENTER("handle_connections_shared_memorys");
   DBUG_PRINT("general",("Waiting for allocated shared memory."));
 
+  if (my_security_attr_create(&sa_event, &errmsg,
+                              GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
+    goto error;
+
+  if (my_security_attr_create(&sa_mapping, &errmsg,
+                             GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
+    goto error;
+
   /*
     The name of event and file-mapping events create agree next rule:
       shared_memory_base_name+unique_part
@@ -3907,22 +3929,22 @@
   */
   suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
   strmov(suffix_pos, "CONNECT_REQUEST");
-  if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+  if ((smem_event_connect_request= CreateEvent(sa_event,
+                                               FALSE, FALSE, tmp)) == 0)
   {
     errmsg= "Could not create request event";
     goto error;
   }
   strmov(suffix_pos, "CONNECT_ANSWER");
-  if ((event_connect_answer= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
   {
     errmsg="Could not create answer event";
     goto error;
   }
   strmov(suffix_pos, "CONNECT_DATA");
-  if ((handle_connect_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
-						   PAGE_READWRITE,
-						   0,sizeof(connect_number),
-						   tmp)) == 0)
+  if ((handle_connect_file_map=
+       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
+                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
   {
     errmsg= "Could not create file mapping";
     goto error;
@@ -3967,10 +3989,9 @@
     suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
 			 "_",NullS);
     strmov(suffix_pos, "DATA");
-    if ((handle_client_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
-						    PAGE_READWRITE,0,
-						    smem_buffer_length,
-						    tmp)) == 0)
+    if ((handle_client_file_map=
+         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
+                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
     {
       errmsg= "Could not create file mapping";
       goto errorconn;
@@ -3983,31 +4004,33 @@
       goto errorconn;
     }
     strmov(suffix_pos, "CLIENT_WROTE");
-    if ((event_client_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create client write event";
       goto errorconn;
     }
     strmov(suffix_pos, "CLIENT_READ");
-    if ((event_client_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create client read event";
       goto errorconn;
     }
     strmov(suffix_pos, "SERVER_READ");
-    if ((event_server_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create server read event";
       goto errorconn;
     }
     strmov(suffix_pos, "SERVER_WROTE");
-    if ((event_server_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
+    if ((event_server_wrote= CreateEvent(sa_event,
+                                         FALSE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create server write event";
       goto errorconn;
     }
     strmov(suffix_pos, "CONNECTION_CLOSED");
-    if ((event_conn_closed= CreateEvent(0, TRUE , FALSE, tmp)) == 0)
+    if ((event_conn_closed= CreateEvent(sa_event,
+                                        TRUE, FALSE, tmp)) == 0)
     {
       errmsg= "Could not create closed connection event";
       goto errorconn;
@@ -4082,6 +4105,8 @@
     strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
     sql_perror(buff);
   }
+  my_security_attr_free(sa_event);
+  my_security_attr_free(sa_mapping);
   if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
   if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
   if (event_connect_answer)	CloseHandle(event_connect_answer);
@@ -5243,7 +5268,7 @@
    "Max number of errors/warnings to store for a statement.",
    (gptr*) &global_system_variables.max_error_count,
    (gptr*) &max_system_variables.max_error_count,
-   0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 1, 65535, 0, 1, 0},
+   0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
   {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
    "Don't allow creation of heap tables bigger than this.",
    (gptr*) &global_system_variables.max_heap_table_size,
@@ -5707,7 +5732,8 @@
   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count),
SHOW_LONG_STATUS},
   {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count),
SHOW_LONG_STATUS},
   {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
-  {"Slave_running",            (char*) 0, SHOW_SLAVE_RUNNING},
+  {"Slave_running",            (char*) 0,                       SHOW_SLAVE_RUNNING},
+  {"Slave_retried_transactions",(char*) 0,                     
SHOW_SLAVE_RETRIED_TRANS},
   {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count),
SHOW_LONG_STATUS},
   {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes),
SHOW_LONG_STATUS},
@@ -5901,13 +5927,6 @@
     exit(1);
   multi_keycache_init(); /* set key_cache_hash.default_value = dflt_key_cache */
 
-  /* Initialize structures that is used when processing options */
-  replicate_rewrite_db.empty();
-  replicate_do_db.empty();
-  replicate_ignore_db.empty();
-  binlog_do_db.empty();
-  binlog_ignore_db.empty();
-
   /* Set directory paths */
   strmake(language, LANGUAGE, sizeof(language)-1);
   strmake(mysql_real_data_home, get_relative_path(DATADIR),
@@ -5972,6 +5991,11 @@
 #else
   have_archive_db= SHOW_OPTION_NO;
 #endif
+#ifdef HAVE_BLACKHOLE_DB
+  have_blackhole_db= SHOW_OPTION_YES;
+#else
+  have_blackhole_db= SHOW_OPTION_NO;
+#endif
 #ifdef HAVE_FEDERATED_DB
   have_federated_db= SHOW_OPTION_YES;
 #else
@@ -6162,14 +6186,12 @@
   }
   case (int)OPT_REPLICATE_IGNORE_DB:
   {
-    i_string *db = new i_string(argument);
-    replicate_ignore_db.push_back(db);
+    rpl_filter->add_ignore_db(argument);
     break;
   }
   case (int)OPT_REPLICATE_DO_DB:
   {
-    i_string *db = new i_string(argument);
-    replicate_do_db.push_back(db);
+    rpl_filter->add_do_db(argument);
     break;
   }
   case (int)OPT_REPLICATE_REWRITE_DB:
@@ -6202,15 +6224,13 @@
       exit(1);
     }
 
-    i_string_pair *db_pair = new i_string_pair(key, val);
-    replicate_rewrite_db.push_back(db_pair);
+    rpl_filter->add_db_rewrite(key, val);
     break;
   }
 
   case (int)OPT_BINLOG_IGNORE_DB:
   {
-    i_string *db = new i_string(argument);
-    binlog_ignore_db.push_back(db);
+    binlog_filter->add_ignore_db(argument);
     break;
   }
   case OPT_BINLOG_FORMAT:
@@ -6235,58 +6255,43 @@
 
   case (int)OPT_BINLOG_DO_DB:
   {
-    i_string *db = new i_string(argument);
-    binlog_do_db.push_back(db);
+    binlog_filter->add_do_db(argument);
     break;
   }
   case (int)OPT_REPLICATE_DO_TABLE:
   {
-    if (!do_table_inited)
-      init_table_rule_hash(&replicate_do_table, &do_table_inited);
-    if (add_table_rule(&replicate_do_table, argument))
+    if (rpl_filter->add_do_table(argument))
     {
       fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
       exit(1);
     }
-    table_rules_on = 1;
     break;
   }
   case (int)OPT_REPLICATE_WILD_DO_TABLE:
   {
-    if (!wild_do_table_inited)
-      init_table_rule_array(&replicate_wild_do_table,
-			    &wild_do_table_inited);
-    if (add_wild_table_rule(&replicate_wild_do_table, argument))
+    if (rpl_filter->add_wild_do_table(argument))
     {
       fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
       exit(1);
     }
-    table_rules_on = 1;
     break;
   }
   case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
   {
-    if (!wild_ignore_table_inited)
-      init_table_rule_array(&replicate_wild_ignore_table,
-			    &wild_ignore_table_inited);
-    if (add_wild_table_rule(&replicate_wild_ignore_table, argument))
+    if (rpl_filter->add_wild_ignore_table(argument))
     {
       fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
       exit(1);
     }
-    table_rules_on = 1;
     break;
   }
   case (int)OPT_REPLICATE_IGNORE_TABLE:
   {
-    if (!ignore_table_inited)
-      init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
-    if (add_table_rule(&replicate_ignore_table, argument))
+    if (rpl_filter->add_ignore_table(argument))
     {
       fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
       exit(1);
     }
-    table_rules_on = 1;
     break;
   }
 #endif /* HAVE_REPLICATION */

--- 1.243/sql/slave.cc	2005-04-01 13:32:30 +02:00
+++ 1.244/sql/slave.cc	2005-04-08 11:24:25 +02:00
@@ -22,12 +22,14 @@
 #include <myisam.h>
 #include "slave.h"
 #include "sql_repl.h"
+#include "rpl_filter.h"
 #include "repl_failsafe.h"
 #include <thr_alarm.h>
 #include <my_dir.h>
 #include <sql_common.h>
 #include "rpl_tblmap.h"
 
+#define MAX_SLAVE_RETRY_PAUSE 5
 bool use_slave_mask = 0;
 MY_BITMAP slave_error_mask;
 
@@ -36,11 +38,7 @@
 volatile bool slave_sql_running = 0, slave_io_running = 0;
 char* slave_load_tmpdir = 0;
 MASTER_INFO *active_mi;
-HASH replicate_do_table, replicate_ignore_table;
-DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
-bool do_table_inited = 0, ignore_table_inited = 0;
-bool wild_do_table_inited = 0, wild_ignore_table_inited = 0;
-bool table_rules_on= 0, replicate_same_server_id;
+bool replicate_same_server_id;
 ulonglong relay_log_space_limit = 0;
 
 /*
@@ -194,20 +192,6 @@
 }
 
 
-static void free_table_ent(TABLE_RULE_ENT* e)
-{
-  my_free((gptr) e, MYF(0));
-}
-
-
-static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
-			   my_bool not_used __attribute__((unused)))
-{
-  *len = e->key_len;
-  return (byte*)e->db;
-}
-
-
 /*
   Open the given relay log
 
@@ -809,228 +793,6 @@
 }
 
 
-void init_table_rule_hash(HASH* h, bool* h_inited)
-{
-  hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
-	    (hash_get_key) get_table_key,
-	    (hash_free_key) free_table_ent, 0);
-  *h_inited = 1;
-}
-
-
-void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
-{
-  my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE,
-		     TABLE_RULE_ARR_SIZE);
-  *a_inited = 1;
-}
-
-
-static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
-{
-  uint i;
-  const char* key_end = key + len;
-  
-  for (i = 0; i < a->elements; i++)
-    {
-      TABLE_RULE_ENT* e ;
-      get_dynamic(a, (gptr)&e, i);
-      if (!my_wildcmp(system_charset_info, key, key_end, 
-                            (const char*)e->db,
-			    (const char*)(e->db + e->key_len),
-			    '\\',wild_one,wild_many))
-	return e;
-    }
-  
-  return 0;
-}
-
-
-/*
-  Checks whether tables match some (wild_)do_table and (wild_)ignore_table
-  rules (for replication)
-
-  SYNOPSIS
-    tables_ok()
-    thd             thread (SQL slave thread normally)
-    tables          list of tables to check
-
-  NOTES
-    Note that changing the order of the tables in the list can lead to
-    different results. Note also the order of precedence of the do/ignore 
-    rules (see code below). For that reason, users should not set conflicting 
-    rules because they may get unpredicted results (precedence order is
-    explained in the manual).
-    If no table of the list is marked "updating" (so far this can only happen
-    if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
-    is the tables in the FROM): then we always return 0, because there is no
-    reason we play this statement on this slave if it updates nothing. In the
-    case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
-    with tables having "updating==TRUE" (those after the DELETE), so this
-    second call will make the decision (because
-    all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
-
-    Thought which arose from a question of a big customer "I want to include
-    all tables like "abc.%" except the "%.EFG"". This can't be done now. If we
-    supported Perl regexps we could do it with this pattern: /^abc\.(?!EFG)/
-    (I could not find an equivalent in the regex library MySQL uses).
-
-  RETURN VALUES
-    0           should not be logged/replicated
-    1           should be logged/replicated                  
-*/
-
-bool tables_ok(THD* thd, TABLE_LIST* tables)
-{
-  bool some_tables_updating= 0;
-  DBUG_ENTER("tables_ok");
-
-  for (; tables; tables= tables->next_global)
-  {
-    char hash_key[2*NAME_LEN+2];
-    char *end;
-    uint len;
-
-    if (!tables->updating) 
-      continue;
-    some_tables_updating= 1;
-    end= strmov(hash_key, tables->db ? tables->db : thd->db);
-    *end++= '.';
-    len= (uint) (strmov(end, tables->table_name) - hash_key);
-    if (do_table_inited) // if there are any do's
-    {
-      if (hash_search(&replicate_do_table, (byte*) hash_key, len))
-	DBUG_RETURN(1);
-    }
-    if (ignore_table_inited) // if there are any ignores
-    {
-      if (hash_search(&replicate_ignore_table, (byte*) hash_key, len))
-	DBUG_RETURN(0); 
-    }
-    if (wild_do_table_inited && find_wild(&replicate_wild_do_table,
-					  hash_key, len))
-      DBUG_RETURN(1);
-    if (wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
-					      hash_key, len))
-      DBUG_RETURN(0);
-  }
-
-  /*
-    If no table was to be updated, ignore statement (no reason we play it on
-    slave, slave is supposed to replicate _changes_ only).
-    If no explicit rule found and there was a do list, do not replicate.
-    If there was no do list, go ahead
-  */
-  DBUG_RETURN(some_tables_updating &&
-              !do_table_inited && !wild_do_table_inited);
-}
-
-
-/*
-  Checks whether a db matches wild_do_table and wild_ignore_table
-  rules (for replication)
-
-  SYNOPSIS
-    db_ok_with_wild_table()
-    db		name of the db to check.
-		Is tested with check_db_name() before calling this function.
-
-  NOTES
-    Here is the reason for this function.
-    We advise users who want to exclude a database 'db1' safely to do it
-    with replicate_wild_ignore_table='db1.%' instead of binlog_ignore_db or
-    replicate_ignore_db because the two lasts only check for the selected db,
-    which won't work in that case:
-    USE db2;
-    UPDATE db1.t SET ... #this will be replicated and should not
-    whereas replicate_wild_ignore_table will work in all cases.
-    With replicate_wild_ignore_table, we only check tables. When
-    one does 'DROP DATABASE db1', tables are not involved and the
-    statement will be replicated, while users could expect it would not (as it
-    rougly means 'DROP db1.first_table, DROP db1.second_table...').
-    In other words, we want to interpret 'db1.%' as "everything touching db1".
-    That is why we want to match 'db1' against 'db1.%' wild table rules.
-
-  RETURN VALUES
-    0           should not be logged/replicated
-    1           should be logged/replicated
- */
-
-int db_ok_with_wild_table(const char *db)
-{
-  char hash_key[NAME_LEN+2];
-  char *end;
-  int len;
-  end= strmov(hash_key, db);
-  *end++= '.';
-  len= end - hash_key ;
-  if (wild_do_table_inited && find_wild(&replicate_wild_do_table,
-                                        hash_key, len))
-    return 1;
-  if (wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
-                                            hash_key, len))
-    return 0;
-  
-  /*
-    If no explicit rule found and there was a do list, do not replicate.
-    If there was no do list, go ahead
-  */
-  return !wild_do_table_inited;
-}
-
-
-int add_table_rule(HASH* h, const char* table_spec)
-{
-  const char* dot = strchr(table_spec, '.');
-  if (!dot) return 1;
-  // len is always > 0 because we know the there exists a '.'
-  uint len = (uint)strlen(table_spec);
-  TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
-						 + len, MYF(MY_WME));
-  if (!e) return 1;
-  e->db = (char*)e + sizeof(TABLE_RULE_ENT);
-  e->tbl_name = e->db + (dot - table_spec) + 1;
-  e->key_len = len;
-  memcpy(e->db, table_spec, len);
-  (void)my_hash_insert(h, (byte*)e);
-  return 0;
-}
-
-
-/*
-  Add table expression with wildcards to dynamic array
-*/
-
-int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
-{
-  const char* dot = strchr(table_spec, '.');
-  if (!dot) return 1;
-  uint len = (uint)strlen(table_spec);
-  TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
-						 + len, MYF(MY_WME));
-  if (!e) return 1;
-  e->db = (char*)e + sizeof(TABLE_RULE_ENT);
-  e->tbl_name = e->db + (dot - table_spec) + 1;
-  e->key_len = len;
-  memcpy(e->db, table_spec, len);
-  insert_dynamic(a, (gptr)&e);
-  return 0;
-}
-
-
-static void free_string_array(DYNAMIC_ARRAY *a)
-{
-  uint i;
-  for (i = 0; i < a->elements; i++)
-    {
-      char* p;
-      get_dynamic(a, (gptr) &p, i);
-      my_free(p, MYF(MY_WME));
-    }
-  delete_dynamic(a);
-}
-
-
 #ifdef NOT_USED_YET
 static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
 {
@@ -1066,14 +828,6 @@
     */
     terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
     end_master_info(active_mi);
-    if (do_table_inited)
-      hash_free(&replicate_do_table);
-    if (ignore_table_inited)
-      hash_free(&replicate_ignore_table);
-    if (wild_do_table_inited)
-      free_string_array(&replicate_wild_do_table);
-    if (wild_ignore_table_inited)
-      free_string_array(&replicate_wild_ignore_table);
     delete active_mi;
     active_mi= 0;
   }
@@ -1153,24 +907,6 @@
 }
 
 
-const char *rewrite_db(const char* db, uint32 *new_len)
-{
-  if (replicate_rewrite_db.is_empty() || !db)
-    return db;
-  I_List_iterator<i_string_pair> it(replicate_rewrite_db);
-  i_string_pair* tmp;
-
-  while ((tmp=it++))
-  {
-    if (!strcmp(tmp->key, db))
-    {
-      *new_len= (uint32)strlen(tmp->val);
-      return tmp->val;
-    }
-  }
-  return db;
-}
-
 /*
   From other comments and tests in code, it looks like
   sometimes Query_log_event and Load_log_event can have db == 0
@@ -1183,60 +919,6 @@
   return (db ? db : "");
 }
 
-/*
-  Checks whether a db matches some do_db and ignore_db rules
-  (for logging or replication)
-
-  SYNOPSIS
-    db_ok()
-    db              name of the db to check
-    do_list         either binlog_do_db or replicate_do_db
-    ignore_list     either binlog_ignore_db or replicate_ignore_db
-
-  RETURN VALUES
-    0           should not be logged/replicated
-    1           should be logged/replicated                  
-*/
-
-int db_ok(const char* db, I_List<i_string> &do_list,
-	  I_List<i_string> &ignore_list )
-{
-  if (do_list.is_empty() && ignore_list.is_empty())
-    return 1; // ok to replicate if the user puts no constraints
-
-  /*
-    If the user has specified restrictions on which databases to replicate
-    and db was not selected, do not replicate.
-  */
-  if (!db)
-    return 0;
-
-  if (!do_list.is_empty()) // if the do's are not empty
-  {
-    I_List_iterator<i_string> it(do_list);
-    i_string* tmp;
-
-    while ((tmp=it++))
-    {
-      if (!strcmp(tmp->ptr, db))
-	return 1; // match
-    }
-    return 0;
-  }
-  else // there are some elements in the don't, otherwise we cannot get here
-  {
-    I_List_iterator<i_string> it(ignore_list);
-    i_string* tmp;
-
-    while ((tmp=it++))
-    {
-      if (!strcmp(tmp->ptr, db))
-	return 0; // match
-    }
-    return 1;
-  }
-}
-
 
 static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
 				 const char *default_val)
@@ -1457,11 +1139,10 @@
     such check will broke everything for them. (And now everything will 
     work for them because by default both their master and slave will have 
     'SYSTEM' time zone).
-
-    TODO: when the new replication of timezones is sorted out with Dmitri,
-    change >= '4' to == '4'.
+    This check is only necessary for 4.x masters (and < 5.0.4 masters but
+    those were alpha).
   */
-  if ((*mysql->server_version >= '4') &&
+  if ((*mysql->server_version == '4') &&
       !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
       (master_res= mysql_store_result(mysql)))
   {
@@ -2246,48 +1927,6 @@
 }
 
 
-/*
-  Builds a String from a HASH of TABLE_RULE_ENT. Cannot be used for any other 
-  hash, as it assumes that the hash entries are TABLE_RULE_ENT.
-
-  SYNOPSIS
-    table_rule_ent_hash_to_str()
-    s               pointer to the String to fill
-    h               pointer to the HASH to read
-
-  RETURN VALUES
-    none
-*/
-
-void table_rule_ent_hash_to_str(String* s, HASH* h)
-{
-  s->length(0);
-  for (uint i=0 ; i < h->records ; i++)
-  {
-    TABLE_RULE_ENT* e= (TABLE_RULE_ENT*) hash_element(h, i);
-    if (s->length())
-      s->append(',');
-    s->append(e->db,e->key_len);
-  }
-}
-
-/*
-  Mostly the same thing as above
-*/
-
-void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a)
-{
-  s->length(0);
-  for (uint i=0 ; i < a->elements ; i++)
-  {
-    TABLE_RULE_ENT* e;
-    get_dynamic(a, (gptr)&e, i);
-    if (s->length())
-      s->append(',');
-    s->append(e->db,e->key_len);
-  }
-}
-
 bool show_master_info(THD* thd, MASTER_INFO* mi)
 {
   // TODO: fix this for multi-master
@@ -2382,23 +2021,18 @@
     protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
     protocol->store(mi->slave_running ? "Yes":"No", &my_charset_bin);
     protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
-    protocol->store(&replicate_do_db);
-    protocol->store(&replicate_ignore_db);
-    /*
-      We can't directly use some protocol->store for 
-      replicate_*_table,
-      as Protocol doesn't know the TABLE_RULE_ENT struct.
-      We first build Strings and then pass them to protocol->store.
-    */
+    protocol->store(rpl_filter->get_do_db());
+    protocol->store(rpl_filter->get_ignore_db());
+
     char buf[256];
     String tmp(buf, sizeof(buf), &my_charset_bin);
-    table_rule_ent_hash_to_str(&tmp, &replicate_do_table);
+    rpl_filter->get_do_table(&tmp);
     protocol->store(&tmp);
-    table_rule_ent_hash_to_str(&tmp, &replicate_ignore_table);
+    rpl_filter->get_ignore_table(&tmp);
     protocol->store(&tmp);
-    table_rule_ent_dynamic_array_to_str(&tmp, &replicate_wild_do_table);
+    rpl_filter->get_wild_do_table(&tmp);
     protocol->store(&tmp);
-    table_rule_ent_dynamic_array_to_str(&tmp, &replicate_wild_ignore_table);
+    rpl_filter->get_wild_ignore_table(&tmp);
     protocol->store(&tmp);
 
     protocol->store((uint32) mi->rli.last_slave_errno);
@@ -2530,7 +2164,7 @@
    ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0),
    abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0),
    inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
-   until_log_pos(0)
+   until_log_pos(0), retried_trans(0)
 {
   group_relay_log_name[0]= event_relay_log_name[0]=
     group_master_log_name[0]= 0;
@@ -2770,6 +2404,18 @@
   thd->variables.completion_type= 0;
 }
 
+void set_slave_thread_default_charset(THD* thd, RELAY_LOG_INFO *rli)
+{
+  thd->variables.character_set_client=
+    global_system_variables.character_set_client;
+  thd->variables.collation_connection=
+    global_system_variables.collation_connection;
+  thd->variables.collation_server=
+    global_system_variables.collation_server;
+  thd->update_charset();
+  rli->cached_charset_invalidate();
+}
+
 /*
   init_slave_thread()
 */
@@ -3250,9 +2896,8 @@
           init_master_info()).
           b) init_relay_log_pos(), because the BEGIN may be an older relay log.
         */
-        if (rli->trans_retries--)
+        if (rli->trans_retries < slave_trans_retries)
         {
-          sql_print_information("Slave SQL thread retries transaction");
           if (init_master_info(rli->mi, 0, 0, 0, SLAVE_SQL))
             sql_print_error("Failed to initialize the master info structure");
           else if (init_relay_log_pos(rli,
@@ -3264,8 +2909,16 @@
           else
           {
             exec_res= 0;
-            sleep(2); // chance for concurrent connection to get more locks
-          }
+	    /* chance for concurrent connection to get more locks */
+            safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
+		       (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
+            pthread_mutex_lock(&rli->data_lock); // because of SHOW STATUS
+	    rli->trans_retries++;
+            rli->retried_trans++;
+            pthread_mutex_unlock(&rli->data_lock);
+            DBUG_PRINT("info", ("Slave retries transaction "
+                                "rli->trans_retries: %lu", rli->trans_retries));
+	  }
         }
         else
           sql_print_error("Slave SQL thread retried transaction %lu time(s) "
@@ -3274,8 +2927,8 @@
                           slave_trans_retries);
       }
       if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
-        rli->trans_retries= slave_trans_retries; // restart from fresh
-    }
+         rli->trans_retries= 0; // restart from fresh
+     }
     return exec_res;
   }
   else
@@ -3690,7 +3343,7 @@
   pthread_mutex_lock(&rli->log_space_lock);
   rli->ignore_log_space_limit= 0;
   pthread_mutex_unlock(&rli->log_space_lock);
-  rli->trans_retries= slave_trans_retries; // start from "no error"
+  rli->trans_retries= 0; // start from "no error"
 
   if (init_relay_log_pos(rli,
 			 rli->group_relay_log_name,
@@ -3845,10 +3498,8 @@
 
   if (unlikely(!cev->is_valid()))
     DBUG_RETURN(1);
-  /*
-    TODO: fix to honor table rules, not only db rules
-  */
-  if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
+
+  if (!rpl_filter->db_ok(cev->db))
   {
     skip_load_data_infile(net);
     DBUG_RETURN(0);

--- 1.135/sql/sql_acl.cc	2005-04-01 13:32:31 +02:00
+++ 1.136/sql/sql_acl.cc	2005-04-08 11:24:25 +02:00
@@ -27,9 +27,6 @@
 
 #include "mysql_priv.h"
 #include "hash_filo.h"
-#ifdef HAVE_REPLICATION
-#include "sql_repl.h" //for tables_ok()
-#endif
 #include <m_ctype.h>
 #include <stdarg.h>
 #include "sp_head.h"
@@ -241,7 +238,7 @@
 
   DBUG_PRINT("info",("user table fields: %d, password length: %d",
 		     table->s->fields, table->field[2]->field_length));
-  
+
   pthread_mutex_lock(&LOCK_global_system_variables);
   if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
   {
@@ -325,6 +322,12 @@
       if (table->s->fields <= 33 && (user.access & ALTER_ACL))
         user.access|= ALTER_PROC_ACL;
 
+      /*
+        pre 5.0.3 did not have CREATE_USER_ACL
+      */
+      if (table->s->fields <= 36 && (user.access & GRANT_ACL))
+        user.access|= CREATE_USER_ACL;
+
       user.sort= get_sort(2,user.host.hostname,user.user);
       user.hostname_length= (user.host.hostname ?
                              (uint) strlen(user.host.hostname) : 0);
@@ -1093,6 +1096,9 @@
 
 /*
   Get privilege for a host, user and db combination
+
+  as db_is_pattern changes the semantics of comparison,
+  acl_cache is not used if db_is_pattern is set.
 */
 
 ulong acl_get(const char *host, const char *ip,
@@ -1112,7 +1118,7 @@
     db=tmp_db;
   }
   key_length=(uint) (end-key);
-  if ((entry=(acl_entry*) acl_cache->search(key,key_length)))
+  if (!db_is_pattern && (entry=(acl_entry*)
acl_cache->search(key,key_length)))
   {
     db_access=entry->access;
     VOID(pthread_mutex_unlock(&acl_cache->lock));
@@ -1161,7 +1167,8 @@
   }
 exit:
   /* Save entry in cache for quick retrieval */
-  if ((entry= (acl_entry*) malloc(sizeof(acl_entry)+key_length)))
+  if (!db_is_pattern &&
+      (entry= (acl_entry*) malloc(sizeof(acl_entry)+key_length)))
   {
     entry->access=(db_access & host_access);
     entry->length=key_length;
@@ -1499,7 +1506,7 @@
     GRANT and REVOKE are applied the slave in/exclusion rules as they are
     some kind of updates to the mysql.% tables.
   */
-  if (thd->slave_thread && table_rules_on)
+  if (thd->slave_thread && rpl_filter->is_on())
   {
     /*
       The tables must be marked "updating" so that tables_ok() takes them into
@@ -1507,7 +1514,7 @@
     */
     tables.updating= 1;
     /* Thanks to bzero, tables.next==0 */
-    if (!tables_ok(0, &tables))
+    if (!rpl_filter->tables_ok(0, &tables))
       DBUG_RETURN(0);
   }
 #endif
@@ -1543,18 +1550,26 @@
 }
 
 
-/* Return 1 if we are allowed to create new users */
+/*
+  Return 1 if we are allowed to create new users
+  the logic here is: INSERT_ACL is sufficient.
+  It's also a requirement in opt_safe_user_create,
+  otherwise CREATE_USER_ACL is enough.
+*/
 
 static bool test_if_create_new_users(THD *thd)
 {
-  bool create_new_users=1;    // Assume that we are allowed to create new users
-  if (opt_safe_user_create && !(thd->master_access & INSERT_ACL))
+  bool create_new_users= test(thd->master_access & INSERT_ACL) ||
+                         (!opt_safe_user_create &&
+                          test(thd->master_access & CREATE_USER_ACL));
+  if (!create_new_users)
   {
     TABLE_LIST tl;
     ulong db_access;
     bzero((char*) &tl,sizeof(tl));
     tl.db=	   (char*) "mysql";
     tl.table_name=  (char*) "user";
+    create_new_users= 1;
 
     db_access=acl_get(thd->host, thd->ip,
 		      thd->priv_user, tl.db, 0);
@@ -1574,7 +1589,7 @@
 
 static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
 			      ulong rights, bool revoke_grant,
-			      bool create_user)
+			      bool can_create_user, bool no_auto_create)
 {
   int error = -1;
   bool old_row_exists=0;
@@ -1616,8 +1631,8 @@
       goto end;
     }
     /*
-      There are four options which affect the process of creation of 
-      a new user(mysqld option --safe-create-user, 'insert' privilege
+      There are four options which affect the process of creation of
+      a new user (mysqld option --safe-create-user, 'insert' privilege
       on 'mysql.user' table, using 'GRANT' with 'IDENTIFIED BY' and
       SQL_MODE flag NO_AUTO_CREATE_USER). Below is the simplified rule
       how it should work.
@@ -1625,11 +1640,17 @@
       else if (identified_by) => create
       else if (no_auto_create_user) => reject
       else create
+
+      see also test_if_create_new_users()
     */
-    else if (((thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER) &&
-              !password_len) || !create_user)
+    else if (!password_len && no_auto_create)
     {
-      my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0),
+      my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
+      goto end;
+    }
+    else if (!can_create_user)
+    {
+      my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0),
                thd->user, thd->host_or_ip);
       goto end;
     }
@@ -2670,14 +2691,14 @@
     GRANT and REVOKE are applied the slave in/exclusion rules as they are
     some kind of updates to the mysql.% tables.
   */
-  if (thd->slave_thread && table_rules_on)
+  if (thd->slave_thread && rpl_filter->is_on())
   {
     /*
       The tables must be marked "updating" so that tables_ok() takes them into
       account in tests.
     */
     tables[0].updating= tables[1].updating= tables[2].updating= 1;
-    if (!tables_ok(0, tables))
+    if (!rpl_filter->tables_ok(0, tables))
       DBUG_RETURN(FALSE);
   }
 #endif
@@ -2710,7 +2731,9 @@
     /* Create user if needed */
     pthread_mutex_lock(&acl_cache->lock);
     error=replace_user_table(thd, tables[0].table, *Str,
-			     0, revoke_grant, create_new_users);
+			     0, revoke_grant, create_new_users,
+                             test(thd->variables.sql_mode &
+                                  MODE_NO_AUTO_CREATE_USER));
     pthread_mutex_unlock(&acl_cache->lock);
     if (error)
     {
@@ -2873,14 +2896,14 @@
     GRANT and REVOKE are applied the slave in/exclusion rules as they are
     some kind of updates to the mysql.% tables.
   */
-  if (thd->slave_thread && table_rules_on)
+  if (thd->slave_thread && rpl_filter->is_on())
   {
     /*
       The tables must be marked "updating" so that tables_ok() takes them into
       account in tests.
     */
     tables[0].updating= tables[1].updating= 1;
-    if (!tables_ok(0, tables))
+    if (!rpl_filter->tables_ok(0, tables))
       DBUG_RETURN(FALSE);
   }
 #endif
@@ -2915,7 +2938,9 @@
     /* Create user if needed */
     pthread_mutex_lock(&acl_cache->lock);
     error=replace_user_table(thd, tables[0].table, *Str,
-			     0, revoke_grant, create_new_users);
+			     0, revoke_grant, create_new_users,
+                             test(thd->variables.sql_mode &
+                                  MODE_NO_AUTO_CREATE_USER));
     pthread_mutex_unlock(&acl_cache->lock);
     if (error)
     {
@@ -2927,7 +2952,7 @@
     table_name= table_list->table_name;
 
     grant_name= proc_hash_search(Str->host.str, NullS, db_name,
-    				 Str->user.str, table_name, 1);
+                                 Str->user.str, table_name, 1);
     if (!grant_name)
     {
       if (revoke_grant)
@@ -2948,7 +2973,7 @@
       }
       my_hash_insert(&proc_priv_hash,(byte*) grant_name);
     }
-    
+
     if (replace_proc_table(thd, grant_name, tables[1].table, *Str,
 			   db_name, table_name, rights, revoke_grant))
     {
@@ -3002,14 +3027,14 @@
     GRANT and REVOKE are applied the slave in/exclusion rules as they are
     some kind of updates to the mysql.% tables.
   */
-  if (thd->slave_thread && table_rules_on)
+  if (thd->slave_thread && rpl_filter->is_on())
   {
     /*
       The tables must be marked "updating" so that tables_ok() takes them into
       account in tests.
     */
     tables[0].updating= tables[1].updating= 1;
-    if (!tables_ok(0, tables))
+    if (!rpl_filter->tables_ok(0, tables))
       DBUG_RETURN(FALSE);
   }
 #endif
@@ -3039,11 +3064,10 @@
       result= -1;
       continue;
     }
-    if ((replace_user_table(thd,
-			    tables[0].table,
-			    *Str,
-			    (!db ? rights : 0), revoke_grant,
-			    create_new_users)))
+    if (replace_user_table(thd, tables[0].table, *Str,
+                           (!db ? rights : 0), revoke_grant, create_new_users,
+                           test(thd->variables.sql_mode &
+                                MODE_NO_AUTO_CREATE_USER)))
       result= -1;
     else if (db)
     {
@@ -3690,11 +3714,13 @@
   "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
   "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
   "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE",
+  "CREATE USER"
 };
 
 static uint command_lengths[]=
 {
-  6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9, 14, 13
+  6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9,
+  14, 13, 11
 };
 
 
@@ -4210,7 +4236,7 @@
     GRANT and REVOKE are applied the slave in/exclusion rules as they are
     some kind of updates to the mysql.% tables.
   */
-  if (thd->slave_thread && table_rules_on)
+  if (thd->slave_thread && rpl_filter->is_on())
   {
     /*
       The tables must be marked "updating" so that tables_ok() takes them into
@@ -4218,7 +4244,7 @@
     */
     tables[0].updating=tables[1].updating=tables[2].updating=
       tables[3].updating=tables[4].updating=1;
-    if (!tables_ok(0, tables))
+    if (!rpl_filter->tables_ok(0, tables))
       DBUG_RETURN(1);
     tables[0].updating=tables[1].updating=tables[2].updating=
       tables[3].updating=tables[4].updating=0;;
@@ -4810,13 +4836,11 @@
     }
 
     sql_mode= thd->variables.sql_mode;
-    thd->variables.sql_mode&= ~MODE_NO_AUTO_CREATE_USER;
-    if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1))
+    if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
     {
       append_user(&wrong_users, user_name);
       result= TRUE;
     }
-    thd->variables.sql_mode= sql_mode;
   }
 
   VOID(pthread_mutex_unlock(&acl_cache->lock));
@@ -4972,7 +4996,7 @@
     }
 
     if (replace_user_table(thd, tables[0].table,
-			   *lex_user, ~0, 1, 0))
+                           *lex_user, ~0, 1, 0, 0))
     {
       result= -1;
       continue;

--- 1.34/sql/sql_acl.h	2005-03-21 22:12:10 +01:00
+++ 1.35/sql/sql_acl.h	2005-04-08 11:24:25 +02:00
@@ -14,6 +14,8 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#include "slave.h" // for tables_ok(), rpl_filter
+
 #define SELECT_ACL	(1L << 0)
 #define INSERT_ACL	(1L << 1)
 #define UPDATE_ACL	(1L << 2)
@@ -39,12 +41,17 @@
 #define SHOW_VIEW_ACL	(1L << 22)
 #define CREATE_PROC_ACL	(1L << 23)
 #define ALTER_PROC_ACL  (1L << 24)
+#define CREATE_USER_ACL (1L << 25)
 /*
   don't forget to update
-    static struct show_privileges_st sys_privileges[]
-  in sql_show.cc when adding new privileges!
+  1. static struct show_privileges_st sys_privileges[]
+  2. static const char *command_array[] and static uint command_lengths[]
+  3. mysql_create_system_tables.sh, mysql_fix_privilege_tables.sql
+  4. acl_init() or whatever - to define behaviour for old privilege tables
+  5. sql_yacc.yy - for GRANT/REVOKE to work
 */
-
+#define EXTRA_ACL	(1L << 29)
+#define NO_ACCESS	(1L << 30)
 #define DB_ACLS \
 (UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
  GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | \
@@ -71,10 +78,7 @@
  REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \
  CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \
  EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | CREATE_PROC_ACL | \
- ALTER_PROC_ACL )
-
-#define EXTRA_ACL	(1L << 29)
-#define NO_ACCESS	(1L << 30)
+ ALTER_PROC_ACL | CREATE_USER_ACL)
 
 #define DEFAULT_CREATE_PROC_ACLS \
 (ALTER_PROC_ACL | EXECUTE_ACL)
@@ -84,25 +88,21 @@
   This is needed as the 'host' and 'db' table is missing a few privileges
 */
 
-/* Continius bit-segments that needs to be shifted */
-#define DB_REL1 ((1L << 6) | (1L << 7) | (1L << 8) | (1L << 9))
-#define DB_REL2 ((1L << 10) | (1L << 11))
-#define DB_REL3 ((1L << 12) | (1L << 13) | (1L << 14) | (1L <<
15))
-#define DB_REL4 ((1L << 16))
-
 /* Privileges that needs to be reallocated (in continous chunks) */
+#define DB_CHUNK0 (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | \
+                   CREATE_ACL | DROP_ACL)
 #define DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
 #define DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL)
 #define DB_CHUNK3 (CREATE_VIEW_ACL | SHOW_VIEW_ACL | \
 		   CREATE_PROC_ACL | ALTER_PROC_ACL )
 #define DB_CHUNK4 (EXECUTE_ACL)
 
-#define fix_rights_for_db(A) (((A) & 63) | \
-			      (((A) & DB_REL1) << 4) | \
-			      (((A) & DB_REL2) << 6) | \
-			      (((A) & DB_REL3) << 9) | \
-			      (((A) & DB_REL4) << 2))
-#define get_rights_for_db(A) (((A) & 63) | \
+#define fix_rights_for_db(A)  (((A)       & DB_CHUNK0) | \
+			      (((A) << 4) & DB_CHUNK1) | \
+			      (((A) << 6) & DB_CHUNK2) | \
+			      (((A) << 9) & DB_CHUNK3) | \
+			      (((A) << 2) & DB_CHUNK4))
+#define get_rights_for_db(A)  (((A) & DB_CHUNK0)       | \
 			      (((A) & DB_CHUNK1) >> 4) | \
 			      (((A) & DB_CHUNK2) >> 6) | \
 			      (((A) & DB_CHUNK3) >> 9) | \
@@ -189,8 +189,7 @@
 bool mysql_procedure_grant(THD *thd, TABLE_LIST *table, 
 			   List <LEX_USER> &user_list, ulong rights,
 			   bool revoke, bool no_error);
-ACL_USER *check_acl_user(LEX_USER *user_name,
-			 uint *acl_acl_userdx);
+ACL_USER *check_acl_user(LEX_USER *user_name, uint *acl_acl_userdx);
 my_bool grant_init(THD *thd);
 void grant_free(void);
 void grant_reload(THD *thd);

--- 1.174/sql/sql_class.cc	2005-04-01 13:40:13 +02:00
+++ 1.175/sql/sql_class.cc	2005-04-08 11:24:25 +02:00
@@ -193,6 +193,7 @@
   variables.pseudo_thread_id= 0;
   one_shot_set= 0;
   file_id = 0;
+  query_id= 0;
   warn_id= 0;
   db_charset= global_system_variables.collation_database;
   bzero(ha_data, sizeof(ha_data));

--- 1.228/sql/sql_class.h	2005-04-01 22:17:27 +02:00
+++ 1.229/sql/sql_class.h	2005-04-08 11:24:25 +02:00
@@ -23,12 +23,15 @@
 
 // TODO: create log.h and move all the log header stuff there
 
+#include "rpl_tblmap.h"
+
 class Query_log_event;
 class Load_log_event;
 class Slave_log_event;
 class Format_description_log_event;
 class sp_rcontext;
 class sp_cache;
+class Rows_log_event;
 
 enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
 enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
@@ -54,6 +57,9 @@
 #define TC_HEURISTIC_RECOVER_ROLLBACK 2
 extern uint tc_heuristic_recover;
 
+// Forward declaration
+class THD;
+
 /*
   Transaction Coordinator log - a base abstract class
   for two different implementations
@@ -234,6 +240,11 @@
   pthread_cond_t  COND_prep_xids;
   friend class Log_event;
 
+  // 'Mutable' needed since this class can not be initialized in the
+  // constructor.  
+  mutable table_mapping* m_table_map;
+  ulong m_next_table_id;
+
 public:
   MYSQL_LOG();
   /*
@@ -248,6 +259,18 @@
   void unlog(ulong cookie, my_xid xid);
   int recover(IO_CACHE *log, Format_description_log_event *fdle);
 
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+  // This will return a table id for the table. If the table is not known, a
+  // new table id will be invented and returned. 
+  ulong get_table_id(TABLE* table);
+
+  // This will check if the given table is mapped to any table id
+  int is_table_mapped(TABLE* table) const;
+
+  // This will clear all table mappings
+  void clear_table_mappings();
+
+#endif // !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
   /*
      These describe the log's format. This is used only for relay logs.
      _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
@@ -1078,6 +1101,51 @@
   my_bool    tablespace_op;	/* This is TRUE in DISCARD/IMPORT TABLESPACE */
   /* container for handler's private per-connection data */
   void *ha_data[MAX_HA];
+
+#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+
+  /*
+    Public interface to write rows to the binlog
+  */
+  int write_row(TABLE* table, bitvector const& cols, const byte *buf);
+  int delete_row(TABLE* table, bitvector const& cols, const byte *buf);
+  int update_row(TABLE* table, bitvector const& cols, 
+		 const byte *old_data, const byte *new_data);
+
+  void set_server_id(uint32 sid) { server_id = sid; }
+
+  int transaction_begin() { 
+      return 0;
+  }
+
+  int transaction_end() { 
+    
+    return flush_pending_event(true); 
+  }
+
+private:
+  /*
+    Member functions to handle pending event for row-level logging.
+  */
+  Rows_log_event* get_pending_event() const;
+  int             set_pending_event(Rows_log_event* ev);
+  int             flush_and_set_pending_event(Rows_log_event*);
+
+  template <class RowsEventT>
+    Rows_log_event* 
+      prepare_pending(TABLE* table, uint32 server_id, 
+		      bitvector const& cols, size_t needed);
+
+  size_t max_row_length(TABLE* table, const byte *data) const;
+  size_t pack_row(TABLE* table, byte *row_data, 
+		  size_t max_len, const byte *data) const;
+
+  int flush_pending_event(bool stmt_end);
+  int write_table_map(TABLE*);
+
+#endif
+
+public:
   struct st_transactions {
     SAVEPOINT *savepoints;
     THD_TRANS all;			// Trans since BEGIN WORK
@@ -1085,6 +1153,9 @@
     bool on;                            // see ha_enable_transaction()
     XID  xid;                           // transaction identifier
     enum xa_states xa_state;            // used by external XA only
+
+    Rows_log_event* m_pending_rows_event;
+
     /*
        Tables changed in transaction (that must be invalidated in query cache).
        List contain only transactional tables, that not invalidated in query

--- 1.145/sql/sql_insert.cc	2005-03-19 01:12:22 +01:00
+++ 1.146/sql/sql_insert.cc	2005-04-08 11:24:25 +02:00
@@ -313,6 +313,8 @@
                            (MODE_STRICT_TRANS_TABLES |
                             MODE_STRICT_ALL_TABLES)));
 
+  table->file->ha_stmt_begin();
+
   if (fields.elements && check_that_all_fields_are_given_values(thd, table))
   {
     /* thd->net.report_error is now set, which will abort the next loop */
@@ -404,6 +406,8 @@
       table->triggers->process_triggers(thd, TRG_EVENT_INSERT, TRG_ACTION_AFTER);
   }
 
+  table->file->ha_stmt_end();
+
   /*
     Now all rows are inserted.  Time to update logs and sends response to
     user
@@ -447,7 +451,7 @@
     if ((info.copied || info.deleted || info.updated) &&
 	(error <= 0 || !transactional_table))
     {
-      if (mysql_bin_log.is_open())
+      if (!opt_binlog_row_level && mysql_bin_log.is_open())
       {
         if (error <= 0)
           thd->clear_error();
@@ -743,10 +747,11 @@
   DBUG_ENTER("write_record");
 
   info->records++;
+
   if (info->handle_duplicates == DUP_REPLACE ||
       info->handle_duplicates == DUP_UPDATE)
   {
-    while ((error=table->file->write_row(table->record[0])))
+    while ((error=table->file->ha_write_row(table->record[0])))
     {
       uint key_nr;
       if (error != HA_WRITE_SKIP)
@@ -820,7 +825,7 @@
         if (res == VIEW_CHECK_ERROR)
           goto err;
 
-        if
((error=table->file->update_row(table->record[1],table->record[0])))
+        if
((error=table->file->ha_update_row(table->record[1],table->record[0])))
           goto err;
         info->updated++;
         break;
@@ -840,13 +845,13 @@
             (table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
              table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
         {
-          if ((error=table->file->update_row(table->record[1],
-					     table->record[0])))
+          if ((error=table->file->ha_update_row(table->record[1],
+						table->record[0])))
             goto err;
           info->deleted++;
           break;				/* Update logfile and count */
         }
-        else if ((error=table->file->delete_row(table->record[1])))
+        else if ((error=table->file->ha_delete_row(table->record[1])))
           goto err;
         info->deleted++;
         if (!table->file->has_transactions())
@@ -855,7 +860,7 @@
     }
     info->copied++;
   }
-  else if ((error=table->file->write_row(table->record[0])))
+  else if ((error=table->file->ha_write_row(table->record[0])))
   {
     if (!info->ignore ||
 	(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))

--- 1.229/sql/sql_table.cc	2005-03-23 09:32:42 +01:00
+++ 1.230/sql/sql_table.cc	2005-04-08 11:24:26 +02:00
@@ -187,6 +187,29 @@
   bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
   DBUG_ENTER("mysql_rm_table_part2");
 
+#ifdef USE_PREPARE_CODE
+  for (table= tables; table; table= table->next_local)
+  {
+    if (!drop_temporary)
+    {
+      char *db=table->db;
+      alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
+      /* remove form file and isam files */
+      strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
+      (void) unpack_filename(path,path);
+      db_type table_type= get_table_type(path);
+      char *end;
+      *(end=fn_ext(path))=0;			// Remove extension for delete
+
+      TABLE dummy_table;
+      TABLE_SHARE dummy_share;
+      dummy_table.s= &dummy_share;
+      handler *file=get_new_handler(&dummy_table, table_type);
+      file->prepare_delete_table(path);
+    }
+  }
+#endif
+
   if (lock_table_names(thd, tables))
     DBUG_RETURN(1);
 
@@ -3749,7 +3772,7 @@
     {
       copy_ptr->do_copy(copy_ptr);
     }
-    if ((error=to->file->write_row((byte*) to->record[0])))
+    if ((error=to->file->ha_write_row((byte*) to->record[0])))
     {
       if ((!ignore &&
 	   handle_duplicates != DUP_REPLACE) ||

--- 1.152/sql/sql_update.cc	2005-04-01 13:32:33 +02:00
+++ 1.153/sql/sql_update.cc	2005-04-08 11:24:26 +02:00
@@ -29,7 +29,7 @@
 
 /* Return 0 if row hasn't changed */
 
-static bool compare_record(TABLE *table, ulong query_id)
+static bool compare_record(TABLE *table, query_id_t query_id)
 {
   if (table->s->blob_fields + table->s->varchar_fields == 0)
     return cmp_record(table,record[1]);
@@ -125,7 +125,7 @@
   uint		want_privilege;
 #endif
   uint          table_count= 0;
-  ulong		query_id=thd->query_id, timestamp_query_id;
+  query_id_t	query_id=thd->query_id, timestamp_query_id;
   ha_rows	updated, found;
   key_map	old_used_keys;
   TABLE		*table;

--- 1.114/sql/sql_union.cc	2005-03-21 19:24:56 +01:00
+++ 1.115/sql/sql_union.cc	2005-04-08 11:24:26 +02:00
@@ -30,7 +30,7 @@
   DBUG_ENTER("mysql_union");
   bool res;
   if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
-                           setup_tables_done_option)))
+                           setup_tables_done_option, "")))
     res= unit->exec();
   if (!res && thd->cursor && thd->cursor->is_open())
   {
@@ -140,7 +140,8 @@
 
 
 bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
-                                 ulong additional_options)
+                                 ulong additional_options,
+                                 const char *tmp_table_alias)
 {
   SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
   SELECT_LEX *sl, *first_select;
@@ -255,7 +256,7 @@
       while ((item_tmp= it++))
       {
 	/* Error's in 'new' will be detected after loop */
-	types.push_back(new Item_type_holder(thd_arg, item_tmp, empty_table));
+	types.push_back(new Item_type_holder(thd_arg, item_tmp));
       }
 
       if (thd_arg->is_fatal_error)
@@ -274,8 +275,7 @@
       Item *type, *item_tmp;
       while ((type= tp++, item_tmp= it++))
       {
-        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp,
-                                                  empty_table))
+        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
 	  DBUG_RETURN(TRUE);
       }
     }
@@ -308,7 +308,7 @@
 				  (first_select_in_union()->options |
 				   thd_arg->options |
 				   TMP_TABLE_ALL_COLUMNS),
-				  HA_POS_ERROR, (char*) "")))
+				  HA_POS_ERROR, (char *) tmp_table_alias)))
       goto err;
     table->file->extra(HA_EXTRA_WRITE_CACHE);
     table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
@@ -418,7 +418,7 @@
       }
       /* re-enabling indexes for next subselect iteration */
       if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL))
-        DBUG_ASSERT(TRUE);
+        DBUG_ASSERT(0);
     }
     for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
     {

--- 1.35/mysql-test/r/ctype_ucs.result	2005-04-01 13:40:12 +02:00
+++ 1.36/mysql-test/r/ctype_ucs.result	2005-04-08 11:24:22 +02:00
@@ -642,3 +642,11 @@
 Warning	1264	Out of range value adjusted for column 'Field1' at row 1
 DROP TABLE t1;
 SET NAMES latin1;
+CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
+INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
+update t1 set b=a;
+SELECT * FROM t1;
+a	b
+1.1	1.100
+2.1	2.100
+DROP TABLE t1;

--- 1.28/mysql-test/t/ctype_ucs.test	2005-04-01 13:32:24 +02:00
+++ 1.29/mysql-test/t/ctype_ucs.test	2005-04-08 11:24:23 +02:00
@@ -414,3 +414,12 @@
 INSERT INTO t1 VALUES ('-1');
 DROP TABLE t1;
 SET NAMES latin1;
+
+#
+# Conversion from an UCS2 string to a decimal column
+#
+CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
+INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
+update t1 set b=a;
+SELECT * FROM t1;
+DROP TABLE t1;

--- 1.281/BitKeeper/etc/logging_ok	2005-03-21 22:11:48 +01:00
+++ 1.282/BitKeeper/etc/logging_ok	2005-04-08 11:24:14 +02:00
@@ -25,6 +25,7 @@
 bar@stripped
 bar@stripped
 bar@deer.(none)
+bar@stripped
 bar@stripped
 bar@stripped
 bar@stripped
@@ -48,6 +49,7 @@
 dlenev@stripped
 dlenev@stripped
 ejonore@stripped
+gbichot@stripped
 gbichot@stripped
 gbichot@stripped
 georg@stripped
@@ -118,6 +120,7 @@
 lars@stripped
 lenz@stripped
 lenz@stripped
+magnus@stripped
 magnus@neptunus.(none)
 magnus@shellback.(none)
 marko@stripped
@@ -186,6 +189,7 @@
 patg@krsna.
 patg@stripped
 patg@stripped
+patg@stripped
 patg@stripped
 paul@stripped
 paul@stripped
@@ -226,6 +230,7 @@
 sasha@stripped
 serg@stripped
 serg@stripped
+serg@stripped
 serg@stripped
 serg@stripped
 serg@stripped

--- 1.12/mysql-test/r/rpl_timezone.result	2005-04-01 13:32:23 +02:00
+++ 1.13/mysql-test/r/rpl_timezone.result	2005-04-08 11:24:22 +02:00
@@ -4,21 +4,31 @@
 reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 start slave;
+set timestamp=100000000;
 create table t1 (t timestamp);
 create table t2 (t char(32));
 select @@time_zone;
 @@time_zone
+Japan
+select @@time_zone;
+@@time_zone
 Europe/Moscow
+insert into t1 values ('20050101000000'), ('20050611093902');
 set time_zone='UTC';
 insert into t1 values ('20040101000000'), ('20040611093902');
 select * from t1;
 t
+2004-12-31 21:00:00
+2005-06-11 05:39:02
 2004-01-01 00:00:00
 2004-06-11 09:39:02
+set time_zone='UTC';
 select * from t1;
 t
-2004-01-01 03:00:00
-2004-06-11 13:39:02
+2004-12-31 21:00:00
+2005-06-11 05:39:02
+2004-01-01 00:00:00
+2004-06-11 09:39:02
 delete from t1;
 set time_zone='Europe/Moscow';
 insert into t1 values ('20040101000000'), ('20040611093902');
@@ -26,19 +36,51 @@
 t
 2004-01-01 00:00:00
 2004-06-11 09:39:02
+set time_zone='Europe/Moscow';
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+ROLLBACK;
+use test;
+SET TIMESTAMP=100000000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1,
@@session.unique_checks=1;
+SET @@session.sql_mode=0;
+SET
@@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8;
+create table t1 (t timestamp);
+SET TIMESTAMP=100000000;
+create table t2 (t char(32));
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20050101000000'), ('20050611093902');
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='UTC';
+insert into t1 values ('20040101000000'), ('20040611093902');
+SET TIMESTAMP=100000000;
+delete from t1;
+SET TIMESTAMP=100000000;
+SET @@session.time_zone='Europe/Moscow';
+insert into t1 values ('20040101000000'), ('20040611093902');
+ROLLBACK;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+delete from t1;
+set time_zone='UTC';
+load data infile '../../std_data/rpl_timezone.dat' into table t1;
 select * from t1;
 t
 2004-01-01 00:00:00
 2004-06-11 09:39:02
-show binlog events;
-Log_name	Pos	Event_type	Server_id	End_log_pos	Info
-master-bin.000001	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
-master-bin.000001	#	Query	1	#	use `test`; create table t1 (t timestamp)
-master-bin.000001	#	Query	1	#	use `test`; create table t2 (t char(32))
-master-bin.000001	#	Query	1	#	use `test`; SET ONE_SHOT TIME_ZONE='UTC'
-master-bin.000001	#	Query	1	#	use `test`; insert into t1 values ('20040101000000'),
('20040611093902')
-master-bin.000001	#	Query	1	#	use `test`; delete from t1
-master-bin.000001	#	Query	1	#	use `test`; insert into t1 values ('20040101000000'),
('20040611093902')
+set time_zone='UTC';
+select * from t1;
+t
+2004-01-01 00:00:00
+2004-06-11 09:39:02
+set time_zone='Europe/Moscow';
+set time_zone='Europe/Moscow';
+delete from t1;
+insert into t1 values ('20040101000000'), ('20040611093902');
 set time_zone='MET';
 insert into t2 (select t from t1);
 select * from t1;
@@ -52,10 +94,6 @@
 delete from t2;
 set timestamp=1000072000;
 insert into t2 values (current_timestamp), (current_date), (current_time);
-set timestamp=1000072000;
-select current_timestamp, current_date, current_time;
-current_timestamp	current_date	current_time
-2001-09-10 01:46:40	2001-09-10	01:46:40
 select * from t2;
 t
 2001-09-09 23:46:40
@@ -73,5 +111,16 @@
 2001-09-09 03:46:40
 1000000000
 set global time_zone='MET';
-ERROR HY000: Binary logging and replication forbid changing the global server time zone
+delete from t2;
+set time_zone='UTC';
+insert into t2 values(convert_tz('2004-01-01 00:00:00','MET',@@time_zone));
+insert into t2 values(convert_tz('2005-01-01 00:00:00','MET','Japan'));
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
+select * from t2;
+t
+2003-12-31 23:00:00
+2005-01-01 08:00:00
 drop table t1, t2;

--- 1.40/mysql-test/r/information_schema.result	2005-03-21 23:26:17 +01:00
+++ 1.41/mysql-test/r/information_schema.result	2005-04-08 11:24:22 +02:00
@@ -121,8 +121,8 @@
 t3
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t2	MyISAM	9	Fixed	0	0	0	#	1024	0	NULL	#	#	NULL	latin1_swedish_ci	NULL		
-t3	MyISAM	9	Fixed	0	0	0	#	1024	0	NULL	#	#	NULL	latin1_swedish_ci	NULL		
+t2	MyISAM	10	Fixed	0	0	0	#	1024	0	NULL	#	#	NULL	latin1_swedish_ci	NULL		
+t3	MyISAM	10	Fixed	0	0	0	#	1024	0	NULL	#	#	NULL	latin1_swedish_ci	NULL		
 v1	NULL	NULL	NULL	NULL	NULL	NULL	#	NULL	NULL	NULL	#	#	NULL	NULL	NULL	NULL	view
 show full columns from t3 like "a%";
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
@@ -436,7 +436,6 @@
 information_schema.tables;
 s1
 0
-9
 10
 drop table t1;
 SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
@@ -446,7 +445,7 @@
   `DEFAULT_COLLATE_NAME` varchar(64) NOT NULL default '',
   `DESCRIPTION` varchar(60) NOT NULL default '',
   `MAXLEN` bigint(3) NOT NULL default '0'
-) ENGINE=MEMORY DEFAULT CHARSET=utf8 MAX_ROWS=1818
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
 set names latin2;
 SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
 Table	Create Table
@@ -455,7 +454,7 @@
   `DEFAULT_COLLATE_NAME` varchar(64) NOT NULL default '',
   `DESCRIPTION` varchar(60) NOT NULL default '',
   `MAXLEN` bigint(3) NOT NULL default '0'
-) ENGINE=MEMORY DEFAULT CHARSET=utf8 MAX_ROWS=1818
+) ENGINE=MEMORY DEFAULT CHARSET=utf8
 set names latin1;
 create table t1 select * from information_schema.CHARACTER_SETS
 where CHARACTER_SET_NAME like "latin1";
@@ -656,6 +655,8 @@
 CREATE TABLE t_crashme ( f1 BIGINT);
 CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
 CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
+count(*)
+100
 drop view a2, a1;
 drop table t_crashme;
 select table_schema,table_name, column_name from

--- 1.31/mysql-test/r/ps_1general.result	2005-03-21 23:26:17 +01:00
+++ 1.32/mysql-test/r/ps_1general.result	2005-04-08 11:24:22 +02:00
@@ -291,7 +291,7 @@
 prepare stmt4 from ' show table status from test like ''t2%'' ';
 execute stmt4;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t2	MyISAM	9	Fixed	0	0	0	64424509439	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
+t2	MyISAM	10	Fixed	0	0	0	64424509439	1024	0	NULL	#	#	#	latin1_swedish_ci	NULL		
 prepare stmt4 from ' show table status from test like ''t9%'' ';
 execute stmt4;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
@@ -343,6 +343,7 @@
 ARCHIVE	YES/NO	Archive storage engine
 CSV	YES/NO	CSV storage engine
 FEDERATED	YES/NO	Federated MySQL storage engine
+BLACKHOLE	YES/NO	/dev/null storage engine (anything you write to it disappears)
 drop table if exists t5;
 prepare stmt1 from ' drop table if exists t5 ' ;
 execute stmt1 ;
@@ -484,7 +485,7 @@
 ERROR HY000: This command is not supported in the prepared statement protocol yet
 prepare stmt1 from ' explain select a from t1 order by b ';
 execute stmt1;
-Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
 def					id	8	3	1	N	32929	0	63
 def					select_type	253	19	6	N	1	31	8
 def					table	253	64	2	N	1	31	8
@@ -500,7 +501,7 @@
 SET @arg00=1 ;
 prepare stmt1 from ' explain select a from t1 where a > ? order by b ';
 execute stmt1 using @arg00;
-Catalog	Database	Table	Table_alias	Column	Column_alias	Name	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max
length	Is_null	Flags	Decimals	Charsetnr
 def					id	8	3	1	N	32929	0	63
 def					select_type	253	19	6	N	1	31	8
 def					table	253	64	2	N	1	31	8

--- 1.43/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2005-04-06 03:20:07 +02:00
+++ 1.44/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2005-04-08 11:24:23 +02:00
@@ -2465,7 +2465,9 @@
   callback.m_callbackFunction = 
     safe_cast(&Dbdict::restartCreateTab_dihComplete);
   
-  SegmentedSectionPtr fragDataPtr; fragDataPtr.setNull();
+  SegmentedSectionPtr fragDataPtr; 
+  fragDataPtr.sz = 0;
+  fragDataPtr.setNull();
   createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
 }
 

--- 1.199/sql/ha_ndbcluster.cc	2005-04-08 13:00:30 +02:00
+++ 1.200/sql/ha_ndbcluster.cc	2005-04-08 11:24:23 +02:00
@@ -397,7 +397,7 @@
  * manage uncommitted insert/deletes during transactio to get records correct
  */
 
-struct Ndb_table_local_info {
+struct Ndb_local_table_statistics {
   int no_uncommitted_rows_count;
   ulong last_count;
   ha_rows records;
@@ -418,7 +418,8 @@
   if (m_ha_not_exact_count)
     return;
   DBUG_ENTER("ha_ndbcluster::records_update");
-  struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info;
+  struct Ndb_local_table_statistics *info= 
+    (struct Ndb_local_table_statistics *)m_table_info;
   DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
                       ((const NDBTAB *)m_table)->getTableId(),
                       info->no_uncommitted_rows_count));
@@ -455,7 +456,8 @@
   if (m_ha_not_exact_count)
     return;
   DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_init");
-  struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info;
+  struct Ndb_local_table_statistics *info= 
+    (struct Ndb_local_table_statistics *)m_table_info;
   Thd_ndb *thd_ndb= get_thd_ndb(thd);
   if (info->last_count != thd_ndb->count)
   {
@@ -474,8 +476,8 @@
   if (m_ha_not_exact_count)
     return;
   DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_update");
-  struct Ndb_table_local_info *info=
-    (struct Ndb_table_local_info *)m_table_info;
+  struct Ndb_local_table_statistics *info=
+    (struct Ndb_local_table_statistics *)m_table_info;
   info->no_uncommitted_rows_count+= c;
   DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
                       ((const NDBTAB *)m_table)->getTableId(),
@@ -927,10 +929,8 @@
   Get metadata for this table from NDB 
 
   IMPLEMENTATION
-    - save the NdbDictionary::Table for easy access
     - check that frm-file on disk is equal to frm-file
       of table accessed in NDB
-    - build a list of the indexes for the table
 */
 
 int ha_ndbcluster::get_metadata(const char *path)
@@ -994,11 +994,12 @@
 
   if (error)
     DBUG_RETURN(error);
-
-  m_table= NULL;
-  m_table_info= NULL;
   
-  DBUG_RETURN(build_index_list(table, ILBP_OPEN));  
+  m_tableVersion= tab->getObjectVersion();
+  m_table= (void *)tab; 
+  m_table_info= NULL; // Set in external lock
+  
+  DBUG_RETURN(build_index_list(ndb, table, ILBP_OPEN));
 }
 
 static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
@@ -1026,7 +1027,7 @@
 #endif
     for (unsigned j= 0; j < sz; j++)
     {
-      const NdbDictionary::Column *c= index->getColumn(j);
+      const NDBCOL *c= index->getColumn(j);
       if (strncmp(field_name, c->getName(), name_sz) == 0)
       {
         data.unique_index_attrid_map[i]= j;
@@ -1038,7 +1039,7 @@
   DBUG_RETURN(0);
 }
 
-int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase)
+int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase)
 {
   uint i;
   int error= 0;
@@ -1047,8 +1048,7 @@
   static const char* unique_suffix= "$unique";
   KEY* key_info= tab->key_info;
   const char **key_name= tab->s->keynames.type_names;
-  Ndb *ndb= get_ndb();
-  NdbDictionary::Dictionary *dict= ndb->getDictionary();
+  NDBDICT *dict= ndb->getDictionary();
   DBUG_ENTER("ha_ndbcluster::build_index_list");
   
   // Save information about all known indexes
@@ -2260,6 +2260,7 @@
   DBUG_ENTER("delete_row");
 
   statistic_increment(thd->status_var.ha_delete_count,&LOCK_status);
+  m_rows_changed++;
 
   if (cursor)
   {
@@ -2310,8 +2311,6 @@
     }
   }
 
-  m_rows_changed++;
-
   // Execute delete operation
   if (execute_no_commit(this,trans) != 0) {
     no_uncommitted_rows_execute_failure();
@@ -3112,12 +3111,8 @@
 }
 
 
-static const char *ha_ndb_bas_ext[]= { ha_ndb_ext, NullS };
-const char**
-ha_ndbcluster::bas_ext() const
-{   
-  return ha_ndb_bas_ext; 
-}
+const char** ha_ndbcluster::bas_ext() const
+{ static const char *ext[]= { ha_ndb_ext, NullS }; return ext; }
 
 
 /*
@@ -3196,6 +3191,10 @@
  
   When a table lock is held one transaction will be started which holds
   the table lock and for each statement a hupp transaction will be started  
+  If we are locking the table then:
+  - save the NdbDictionary::Table for easy access
+  - save reference to table statistics
+  - refresh list of the indexes for the table if needed (if altered)
  */
 
 int ha_ndbcluster::external_lock(THD *thd, int lock_type)
@@ -3301,7 +3300,15 @@
       if (!(tab= dict->getTable(m_tabname, &tab_info)))
         ERR_RETURN(dict->getNdbError());
       DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
-      m_table= (void *)tab;
+      if (m_table != (void *)tab || m_tableVersion != tab->getObjectVersion())
+      {
+        /*
+          The table has been altered, refresh the index list
+        */
+        build_index_list(ndb, table, ILBP_OPEN);  
+        m_table= (void *)tab;
+        m_tableVersion = tab->getObjectVersion();
+      }
       m_table_info= tab_info;
     }
     no_uncommitted_rows_init(thd);
@@ -3990,7 +3997,7 @@
                       m_dbname, m_tabname));
 
   // Create secondary indexes
-  my_errno= build_index_list(form, ILBP_CREATE);
+  my_errno= build_index_list(ndb, form, ILBP_CREATE);
 
   if (!my_errno)
     my_errno= write_ndb_file();
@@ -4332,6 +4339,7 @@
   m_active_trans(NULL),
   m_active_cursor(NULL),
   m_table(NULL),
+  m_tableVersion(-1),
   m_table_info(NULL),
   m_table_flags(HA_REC_NOT_IN_SEQ |
                 HA_NULL_IN_KEY |
@@ -4480,9 +4488,9 @@
   DBUG_ENTER("seize_thd_ndb");
 
   thd_ndb= new Thd_ndb();
- 
thd_ndb->ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_table_local_info));
-
-
+  thd_ndb->ndb->getDictionary()->set_local_table_data_size(
+    sizeof(Ndb_local_table_statistics)
+    );
   if (thd_ndb->ndb->init(max_transactions) != 0)
   {
     ERR_PRINT(thd_ndb->ndb->getNdbError());
@@ -4572,7 +4580,7 @@
   ndb->setDatabaseName(db);
 
   NDBDICT* dict= ndb->getDictionary();
-  dict->set_local_table_data_size(sizeof(Ndb_table_local_info));
+  dict->set_local_table_data_size(sizeof(Ndb_local_table_statistics));
   dict->invalidateTable(name);
   if (!(tab= dict->getTable(name)))
   {    
@@ -4632,7 +4640,7 @@
   ndb->setDatabaseName(db);
 
   NDBDICT* dict= ndb->getDictionary();
-  dict->set_local_table_data_size(sizeof(Ndb_table_local_info));
+  dict->set_local_table_data_size(sizeof(Ndb_local_table_statistics));
   dict->invalidateTable(name);
   if (!(tab= dict->getTable(name)))
   {
@@ -4856,7 +4864,7 @@
     DBUG_PRINT("error", ("failed to create global ndb object"));
     goto ndbcluster_init_error;
   }
-  g_ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_table_local_info));
+ 
g_ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_local_table_statistics));
   if (g_ndb->init() != 0)
   {
     ERR_PRINT (g_ndb->getNdbError());

--- 1.84/sql/ha_ndbcluster.h	2005-04-08 11:26:04 +02:00
+++ 1.85/sql/ha_ndbcluster.h	2005-04-08 11:24:23 +02:00
@@ -524,7 +524,7 @@
   int create_unique_index(const char *name, KEY *key_info);
   int initialize_autoincrement(const void *table);
   enum ILBP {ILBP_CREATE = 0, ILBP_OPEN = 1}; // Index List Build Phase
-  int build_index_list(TABLE *tab, enum ILBP phase);
+  int build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase);
   int get_metadata(const char* path);
   void release_metadata();
   NDB_INDEX_TYPE get_index_type(uint idx_no) const;
@@ -609,6 +609,7 @@
   NdbTransaction *m_active_trans;
   NdbScanOperation *m_active_cursor;
   void *m_table;
+  int m_tableVersion;
   void *m_table_info;
   char m_dbname[FN_HEADLEN];
   //char m_schemaname[FN_HEADLEN];

--- 1.64/mysql-test/r/show_check.result	2005-03-21 23:26:18 +01:00
+++ 1.65/mysql-test/r/show_check.result	2005-04-08 11:24:23 +02:00
@@ -316,57 +316,57 @@
 insert into t3 values (1,1),(2,2);
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	2	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 insert into t1 values (3),(4);
 insert into t2 values (3),(4);
 insert into t3 values (3,3),(4,4);
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	4	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 insert into t1 values (5);
 insert into t2 values (5);
 insert into t3 values (5,5);
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	5	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 delete from t1 where a=3;
 delete from t2 where b=3;
 delete from t3 where a=3;
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	4	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 delete from t1;
 delete from t2;
 delete from t3;
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	0	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 insert into t1 values (5);
 insert into t2 values (5);
 insert into t3 values (5,5);
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	1	#	#	#	#	0	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 delete from t1 where a=5;
 delete from t2 where b=5;
 delete from t3 where a=5;
 show table status;
 Name	Engine	Version	Row_format	Rows	Avg_row_length	Data_length	Max_data_length	Index_length	Data_free	Auto_increment	Create_time	Update_time	Check_time	Collation	Checksum	Create_options	Comment
-t1	MEMORY	9	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t2	MEMORY	9	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
-t3	MEMORY	9	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t1	MEMORY	10	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t2	MEMORY	10	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
+t3	MEMORY	10	Fixed	0	#	#	#	#	#	NULL	NULL	NULL	NULL	latin1_swedish_ci	NULL		
 drop table t1, t2, t3;
 create database mysqltest;
 show create database mysqltest;

--- 1.16/scripts/mysql_fix_privilege_tables.sql	2005-03-21 22:12:09 +01:00
+++ 1.17/scripts/mysql_fix_privilege_tables.sql	2005-04-08 11:24:23 +02:00
@@ -290,6 +290,18 @@
 ALTER TABLE user ADD max_user_connections int(11) unsigned DEFAULT '0' NOT NULL AFTER
max_connections;
 
 #
+# user.Create_user_priv
+#
+
+SET @hadCreateUserPriv:=0;
+SELECT @hadCreateUserPriv:=1 FROM user WHERE Create_user_priv LIKE '%';
+
+ALTER TABLE user ADD Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N'
NOT NULL AFTER Alter_routine_priv;
+UPDATE user LEFT JOIN db USING (Host,User) SET Create_user_priv='Y'
+  WHERE @hadCreateUserPriv = 0 AND
+        (user.Grant_priv = 'Y' OR db.Grant_priv = 'Y');
+
+#
 # Create some possible missing tables
 #
 CREATE TABLE IF NOT EXISTS procs_priv (
@@ -306,19 +318,19 @@
 
 CREATE TABLE IF NOT EXISTS help_topic (
 help_topic_id int unsigned not null,
-name varchar(64) not null,
+name char(64) not null,
 help_category_id smallint unsigned not null,
 description text not null,
 example text not null,
-url varchar(128) not null,
+url char(128) not null,
 primary key (help_topic_id), unique index (name)
 ) CHARACTER SET utf8 comment='help topics';
 
 CREATE TABLE IF NOT EXISTS help_category (
 help_category_id smallint unsigned not null,
-name varchar(64) not null,
+name char(64) not null,
 parent_category_id smallint unsigned null,
-url varchar(128) not null,
+url char(128) not null,
 primary key (help_category_id),
 unique index (name)
 ) CHARACTER SET utf8 comment='help categories';
@@ -331,7 +343,7 @@
 
 CREATE TABLE IF NOT EXISTS help_keyword (
 help_keyword_id int unsigned not null,
-name varchar(64) not null,
+name char(64) not null,
 primary key (help_keyword_id),
 unique index (name)
 ) CHARACTER SET utf8 comment='help keywords';
@@ -478,3 +490,35 @@
                             'NO_AUTO_CREATE_USER',
                             'HIGH_NOT_PRECEDENCE'
                             ) DEFAULT 0 NOT NULL;
+
+#
+# Change all varchar fields in privilege tables to CHAR, to ensure that
+# we can use the privilege tables in MySQL 4.1
+# Note that for this hack to work, we must change all CHAR() columns at
+# the same time
+#
+
+ALTER TABLE mysql.user
+modify Host char(60) binary DEFAULT '' NOT NULL,
+modify User char(16) binary DEFAULT '' NOT NULL,
+modify Password char(41) binary DEFAULT '' NOT NULL;
+
+ALTER TABLE mysql.db
+modify Host char(60) binary DEFAULT '' NOT NULL,
+modify Db char(64) binary DEFAULT '' NOT NULL,
+modify User char(16) binary DEFAULT '' NOT NULL;
+
+ALTER TABLE mysql.host
+modify Host char(60) binary DEFAULT '' NOT NULL,
+modify Db char(64) binary DEFAULT '' NOT NULL;
+
+ALTER TABLE help_topic
+modify name char(64) not null,
+modify url  char(128) not null;
+
+ALTER TABLE help_category
+modify name char(64) not null,
+modify url char(128) not null;
+
+ALTER TABLE help_keyword
+modify name char(64) not null;

--- 1.31/mysql-test/r/user_var.result	2005-04-01 13:32:23 +02:00
+++ 1.32/mysql-test/r/user_var.result	2005-04-08 11:24:23 +02:00
@@ -198,3 +198,10 @@
 select FIELD( @var,'1it','Hit') as my_column;
 my_column
 0
+select @v, coercibility(@v);
+@v	coercibility(@v)
+NULL	2
+set @v1=null, @v2=1, @v3=1.1, @v4=now();
+select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4);
+coercibility(@v1)	coercibility(@v2)	coercibility(@v3)	coercibility(@v4)
+2	2	2	2

--- 1.25/mysql-test/t/user_var.test	2005-04-01 13:32:27 +02:00
+++ 1.26/mysql-test/t/user_var.test	2005-04-08 11:24:23 +02:00
@@ -124,3 +124,10 @@
 #
 set @var= NULL ;
 select FIELD( @var,'1it','Hit') as my_column;
+
+#
+# Bug#9425 A user variable doesn't always have implicit coercibility
+#
+select @v, coercibility(@v);
+set @v1=null, @v2=1, @v3=1.1, @v4=now();
+select coercibility(@v1),coercibility(@v2),coercibility(@v3),coercibility(@v4);

--- 1.21/mysql-test/r/rpl_temporary.result	2005-04-01 13:32:22 +02:00
+++ 1.22/mysql-test/r/rpl_temporary.result	2005-04-08 11:24:22 +02:00
@@ -7,12 +7,12 @@
 reset master;
 SET @save_select_limit=@@session.sql_select_limit;
 SET @@session.sql_select_limit=10, @@session.pseudo_thread_id=100;
-ERROR HY000: Access denied; you need the SUPER privilege for this operation
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
 SELECT @@session.sql_select_limit = @save_select_limit;
 @@session.sql_select_limit = @save_select_limit
 1
 SET @@session.sql_select_limit=10, @@session.sql_log_bin=0;
-ERROR HY000: Access denied; you need the SUPER privilege for this operation
+ERROR 42000: Access denied; you need the SUPER privilege for this operation
 SELECT @@session.sql_select_limit = @save_select_limit;
 @@session.sql_select_limit = @save_select_limit
 1

--- 1.19/scripts/mysql_create_system_tables.sh	2005-04-06 16:02:49 +02:00
+++ 1.20/scripts/mysql_create_system_tables.sh	2005-04-08 11:24:23 +02:00
@@ -146,6 +146,7 @@
   c_u="$c_u   Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,"
   c_u="$c_u   Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT
NULL,"
   c_u="$c_u   Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT
NULL,"
+  c_u="$c_u   Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT
NULL,"
   c_u="$c_u   ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT
'' NOT NULL,"
   c_u="$c_u   ssl_cipher BLOB NOT NULL,"
   c_u="$c_u   x509_issuer BLOB NOT NULL,"
@@ -161,22 +162,22 @@
 
   if test "$1" = "test" 
   then
-    i_u="INSERT INTO user VALUES
('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
-    INSERT INTO user VALUES
('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
-    REPLACE INTO user VALUES
('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+    i_u="INSERT INTO user VALUES
('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+    INSERT INTO user VALUES
('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+    REPLACE INTO user VALUES
('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
     INSERT INTO user (host,user) values ('localhost','');
     INSERT INTO user (host,user) values ('$hostname','');"
   else
-    i_u="INSERT INTO user VALUES
('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);"
+    i_u="INSERT INTO user VALUES
('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);"
     if test "$windows" = "0"
     then
       i_u="$i_u
-           INSERT INTO user VALUES
('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
+           INSERT INTO user VALUES
('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0);
            INSERT INTO user (host,user) values ('$hostname','');
            INSERT INTO user (host,user) values ('localhost','');"
     else
       i_u="$i_u
-	   INSERT INTO user VALUES
('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
+	   INSERT INTO user VALUES
('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
     fi
   fi 
 fi
@@ -269,11 +270,11 @@
 
   c_ht="$c_ht CREATE TABLE help_topic ("
   c_ht="$c_ht   help_topic_id    int unsigned not null,"
-  c_ht="$c_ht   name             varchar(64) not null,"
+  c_ht="$c_ht   name             char(64) not null,"
   c_ht="$c_ht   help_category_id smallint unsigned not null,"
   c_ht="$c_ht   description      text not null,"
   c_ht="$c_ht   example          text not null,"
-  c_ht="$c_ht   url              varchar(128) not null,"
+  c_ht="$c_ht   url              char(128) not null,"
   c_ht="$c_ht   primary key      (help_topic_id),"
   c_ht="$c_ht   unique index     (name)"
   c_ht="$c_ht ) engine=MyISAM"
@@ -291,9 +292,9 @@
   
   c_hc="$c_hc CREATE TABLE help_category ("
   c_hc="$c_hc   help_category_id   smallint unsigned not null,"
-  c_hc="$c_hc   name               varchar(64) not null,"
+  c_hc="$c_hc   name               char(64) not null,"
   c_hc="$c_hc   parent_category_id smallint unsigned null,"
-  c_hc="$c_hc   url                varchar(128) not null,"
+  c_hc="$c_hc   url                char(128) not null,"
   c_hc="$c_hc   primary key        (help_category_id),"
   c_hc="$c_hc   unique index       (name)"
   c_hc="$c_hc ) engine=MyISAM"
@@ -309,7 +310,7 @@
 
   c_hk="$c_hk CREATE TABLE help_keyword ("
   c_hk="$c_hk   help_keyword_id  int unsigned not null,"
-  c_hk="$c_hk   name             varchar(64) not null,"
+  c_hk="$c_hk   name             char(64) not null,"
   c_hk="$c_hk   primary key      (help_keyword_id),"
   c_hk="$c_hk   unique index     (name)"
   c_hk="$c_hk ) engine=MyISAM"
Thread
bk commit into 5.1 tree (mysqldev:1.1854)lars8 Apr