List:Internals« Previous MessageNext Message »
From:mikael Date:September 13 2005 12:19pm
Subject:bk commit into 5.1 tree (mronstrom:1.2001)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron 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.2001 05/09/13 14:19:01 mronstrom@stripped +36 -0
  Merge mronstrom@stripped:/home/bk/mysql-5.1-wl2498
  into  mysql.com:/Users/mikron/wl2498

  sql/sql_yacc.yy
    1.375 05/09/13 14:16:09 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_table.cc
    1.232 05/09/13 14:16:08 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_show.cc
    1.263 05/09/13 14:16:08 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_lex.h
    1.185 05/09/13 14:16:06 mronstrom@stripped +0 -0
    Auto merged

  sql/mysql_priv.h
    1.302 05/09/13 14:16:04 mronstrom@stripped +0 -0
    Auto merged

  sql/lock.cc
    1.74 05/09/13 14:16:02 mronstrom@stripped +0 -0
    Auto merged

  sql/lex.h
    1.145 05/09/13 14:16:02 mronstrom@stripped +0 -0
    Auto merged

  sql/handler.h
    1.145 05/09/13 14:16:00 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
    1.99 05/09/13 14:18:50 mronstrom@stripped +0 -0
    SCCS merged

  storage/ndb/test/src/UtilTransactions.cpp
    1.25 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/test/src/NDBT_Test.cpp
    1.28 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/test/ndbapi/bank/Bank.hpp
    1.9 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/test/ndbapi/bank/Bank.cpp
    1.12 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/test/ndbapi/Makefile.am
    1.24 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/test/include/NDBT_Test.hpp
    1.16 05/09/13 14:16:12 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/ndbapi/NdbTransaction.cpp
    1.49 05/09/13 14:16:11 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/mgmapi/mgmapi.cpp
    1.53 05/09/13 14:16:11 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
    1.53 05/09/13 14:16:10 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/kernel/blocks/backup/Backup.hpp
    1.18 05/09/13 14:16:10 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/kernel/blocks/backup/Backup.cpp
    1.50 05/09/13 14:16:10 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/src/common/portlib/NdbThread.c
    1.29 05/09/13 14:16:09 mronstrom@stripped +0 -0
    Auto merged

  storage/ndb/include/kernel/signaldata/BackupImpl.hpp
    1.7 05/09/13 14:16:09 mronstrom@stripped +0 -0
    Auto merged

  storage/heap/hp_hash.c
    1.43 05/09/13 14:16:09 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_select.cc
    1.331 05/09/13 14:16:07 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_parse.cc
    1.436 05/09/13 14:16:06 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_class.h
    1.237 05/09/13 14:16:05 mronstrom@stripped +0 -0
    Auto merged

  sql/sql_class.cc
    1.181 05/09/13 14:16:05 mronstrom@stripped +0 -0
    Auto merged

  sql/set_var.h
    1.72 05/09/13 14:16:05 mronstrom@stripped +0 -0
    Auto merged

  sql/set_var.cc
    1.135 05/09/13 14:16:04 mronstrom@stripped +0 -0
    Auto merged

  sql/log.cc
    1.162 05/09/13 14:16:03 mronstrom@stripped +0 -0
    Auto merged

  sql/item.cc
    1.123 05/09/13 14:16:01 mronstrom@stripped +0 -0
    Auto merged

  sql/handler.cc
    1.154 05/09/13 14:15:59 mronstrom@stripped +0 -0
    Auto merged

  sql/ha_ndbcluster.cc
    1.150 05/09/13 14:15:58 mronstrom@stripped +0 -0
    Auto merged

  mysql-test/r/ndb_autodiscover.result
    1.25 05/09/13 14:15:54 mronstrom@stripped +0 -0
    Auto merged

  mysql-test/mysql-test-run.sh
    1.270 05/09/13 14:15:54 mronstrom@stripped +0 -0
    Auto merged

  configure.in
    1.275 05/09/13 14:15:53 mronstrom@stripped +0 -0
    Auto merged

# 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:	mronstrom
# Host:	mikael-ronstr-ms-dator.local
# Root:	/Users/mikron/wl2498/RESYNC

--- 1.274/configure.in	2005-09-09 13:45:39 +02:00
+++ 1.275/configure.in	2005-09-13 14:15:53 +02:00
@@ -323,19 +323,19 @@
        ;;
      esac
   ;;
-  sysv5UnixWare*) 
+  sysv5UnixWare* | sysv5OpenUNIX8*) 
     if test "$GCC" != "yes"; then
-      # We are using built-in inline function
+      # Use the built-in alloca()
       CFLAGS="$CFLAGS -Kalloca"
     fi
     CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
   ;;
-  sysv5OpenUNIX8*) 
+  sysv5SCO_SV6.0.0*)
     if test "$GCC" != "yes"; then
-      # We are using built-in inline function
+      # Use the built-in alloca()
       CFLAGS="$CFLAGS -Kalloca"
+      CXXFLAGS="$CFLAGS -Kalloca"
     fi
-    CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
   ;;
 esac
 AC_SUBST(CC)
@@ -1048,6 +1048,15 @@
       MAX_C_OPTIMIZE="-O"
     fi
     ;;
+  *darwin9*)
+    if test "$ac_cv_prog_gcc" = "yes"
+    then
+      FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
+      CFLAGS="$CFLAGS $FLAGS"
+      CXXFLAGS="$CXXFLAGS $FLAGS"
+      MAX_C_OPTIMIZE="-O"
+    fi
+    ;;
   *freebsd*)
     AC_MSG_WARN([Adding fix for interrupted reads])
     OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
@@ -1360,8 +1369,6 @@
           if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
           then
             AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
-          else
-            AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
           fi
           AC_MSG_RESULT("yes")
           # We must have cc
@@ -1387,87 +1394,40 @@
     AC_MSG_RESULT("no")
   fi
 fi
-# Hack for SCO UnixWare7
-#
-if test "$with_named_thread" = "no"
-then
-  AC_MSG_CHECKING("SCO UnixWare7 native threads")
-  if expr "$SYSTEM_TYPE" : ".*UnixWare*" > /dev/null
-  then
-    if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
-    then
-      MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
-      if expr "$CC" : ".*gcc.*"
-        then
-          with_named_thread="-pthread -lsocket -lnsl"
-      else
-        with_named_thread="-Kthread -lsocket -lnsl"
-      fi
-      if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
-      then
-        AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
-      else
-        AC_DEFINE(HAVE_UNIXWARE7_POSIX, [1])
-      fi
-      # We must have cc
-      AC_MSG_CHECKING("for gcc")
-      if expr "$CC" : ".*gcc.*"
-      then
-	CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-	CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-      else
-	CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-	CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-      fi
-      AC_MSG_RESULT("yes")
-    else
-      AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) 
-    fi
-  else
-    AC_MSG_RESULT("no")
-  fi
-fi
 
-# Hack for Caldera OpenUNIX8
+#
+# Check for SCO threading libraries
 #
 if test "$with_named_thread" = "no"
 then
-  AC_MSG_CHECKING("OpenUNIX8 native threads")
-  if expr "$SYSTEM_TYPE" : ".*OpenUNIX*" > /dev/null
+  AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads])
+  if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \
+     expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \
+     expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null
   then
     if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
     then
       MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
-      if expr "$CC" : ".*gcc.*"
+      if expr "$CC" : ".*gcc.*" > /dev/null
       then
-          with_named_thread="-pthread -lsocket -lnsl"
+        with_named_thread="-pthread -lsocket -lnsl"
+	CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
+	CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
       else
         with_named_thread="-Kthread -lsocket -lnsl"
+	CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
+	CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
       fi
       if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
       then
-        AC_DEFINE([HAVE_UNIXWARE7_THREADS], [1],
-                  [UNIXWARE7 threads are not posix])
-      else
-        AC_DEFINE([HAVE_UNIXWARE7_POSIX], [1],
-                  [new UNIXWARE7 threads that are not yet posix])
+        AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library])
       fi
-      # We must have cc
-      AC_MSG_CHECKING("for gcc")
-      if expr "$CC" : ".*gcc.*"
-      then
-	CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-	CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-      else
- 	CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
- 	CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
-      fi
-      AC_MSG_RESULT("yes")
+      AC_MSG_RESULT(yes)
     else
-      AC_MSG_ERROR([configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual.]) 
+      AC_MSG_ERROR([configure: error: Can't find thread library on SCO/Caldera system. See the Installation chapter in the Reference Manual.]) 
     fi
   else
-    AC_MSG_RESULT("no")
+    AC_MSG_RESULT(no)
   fi
 fi
 
@@ -2511,7 +2471,7 @@
       AC_CONFIG_FILES(storage/bdb/Makefile)
 
       echo "CONFIGURING FOR BERKELEY DB" 
-      bdb_conf_flags="--disable-shared"
+      bdb_conf_flags="--disable-shared --build=$build_alias"
       if test $with_debug = "yes"
       then
         bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic"

--- 1.42/storage/heap/hp_hash.c	2005-07-21 15:33:43 +02:00
+++ 1.43/storage/heap/hp_hash.c	2005-09-13 14:16:09 +02:00
@@ -551,11 +551,13 @@
       }
       if (cs->mbmaxlen > 1)
       {
+        uint safe_length1= char_length1;
+        uint safe_length2= char_length2;
         uint char_length= seg->length / cs->mbmaxlen;
-        char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length1);
-        set_if_smaller(char_length1, seg->length);
-        char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length2);
-        set_if_smaller(char_length2, seg->length);
+        char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
+        set_if_smaller(char_length1, safe_length1);
+        char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
+        set_if_smaller(char_length2, safe_length2);
       }
 
       if (cs->coll->strnncollsp(seg->charset,

--- 1.269/mysql-test/mysql-test-run.sh	2005-09-06 12:58:28 +02:00
+++ 1.270/mysql-test/mysql-test-run.sh	2005-09-13 14:15:54 +02:00
@@ -575,6 +575,7 @@
  CLIENT_BINDIR="$BASEDIR/client"
  MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
  WAIT_PID="$BASEDIR/extra/mysql_waitpid"
+ MYSQL_MY_PRINT_DEFAULTS="$BASEDIR/extra/my_print_defaults"
  MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
  MYSQL_MANAGER="$BASEDIR/tools/mysqltestmanager"
  MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
@@ -635,6 +636,7 @@
  MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
  MYSQLADMIN="$CLIENT_BINDIR/mysqladmin"
  WAIT_PID="$CLIENT_BINDIR/mysql_waitpid"
+ MYSQL_MY_PRINT_DEFAULTS="$CLIENT_BINDIR/my_print_defaults"
  MYSQL_MANAGER="$CLIENT_BINDIR/mysqltestmanager"
  MYSQL_MANAGER_CLIENT="$CLIENT_BINDIR/mysqltestmanagerc"
  MYSQL_MANAGER_PWGEN="$CLIENT_BINDIR/mysqltestmanager-pwgen"
@@ -716,7 +718,7 @@
 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 --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
 export MYSQL MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
-export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR
+export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS
 export NDB_TOOLS_DIR
 export NDB_MGM
 export NDB_BACKUP_DIR

--- 1.153/sql/handler.cc	2005-08-27 07:49:55 +02:00
+++ 1.154/sql/handler.cc	2005-09-13 14:15:59 +02:00
@@ -632,12 +632,20 @@
     {
       int err;
       statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
-      if ((err= (*(*ht)->prepare)(thd, all)))
+      if ((*ht)->prepare)
       {
-        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
-        ha_rollback_trans(thd, all);
-        error=1;
-        break;
+        if ((err= (*(*ht)->prepare)(thd, all)))
+        {
+          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
+          ha_rollback_trans(thd, all);
+          error=1;
+          break;
+        }
+      }
+      else
+      {
+        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name);
       }
     }
   }

--- 1.144/sql/handler.h	2005-09-06 12:58:28 +02:00
+++ 1.145/sql/handler.h	2005-09-13 14:16:00 +02:00
@@ -106,6 +106,10 @@
 /* bits in alter_table_flags */
 #define HA_ONLINE_ADD_EMPTY_PARTITION 1
 #define HA_ONLINE_DROP_PARTITION 2
+#define HA_ONLINE_ADD_HASH_PARTITION 4
+#define HA_ONLINE_COALESCE_PARTITION 8
+#define HA_ONLINE_REORG_PARTITION 16
+#define HA_ONLINE_DOUBLE_WRITE 32
 
 /* operations for disable/enable indexes */
 #define HA_KEY_SWITCH_NONUNIQ      0
@@ -412,10 +416,11 @@
   PART_NORMAL= 0,
   PART_IS_DROPPED= 1,
   PART_TO_BE_DROPPED= 2,
-  PART_DROPPING= 3,
-  PART_IS_ADDED= 4,
-  PART_ADDING= 5,
-  PART_ADDED= 6
+  PART_TO_BE_ADDED= 3,
+  PART_TO_BE_REORGED= 4,
+  PART_REORGED_DROPPED= 5,
+  PART_CHANGED= 6,
+  PART_IS_CHANGED= 7
 };
 
 #define UNDEF_NODEGROUP 65535
@@ -674,7 +679,8 @@
                           handler *file, ulonglong max_rows);
 bool fix_partition_func(THD *thd, const char *name, TABLE *table);
 char *generate_partition_syntax(partition_info *part_info,
-                                uint *buf_length, bool use_sql_alloc);
+                                uint *buf_length, bool use_sql_alloc,
+                                bool write_part_state);
 bool partition_key_modified(TABLE *table, List<Item> &fields);
 void get_partition_set(const TABLE *table, byte *buf, const uint index,
                        const key_range *key_spec,
@@ -1324,6 +1330,25 @@
 
   /*
     SYNOPSIS
+      add_partitions()
+      table                       Table object where partitions are added
+      create_info                 HA_CREATE_INFO object describing all fields
+                                  and indexes in table
+      path                        Complete path of db and table name
+    RETURN VALUE
+      TRUE                        Failure
+      FALSE                       Success
+    DESCRIPTION
+      Add a number of partitions, during this operation no other operation
+      is ongoing in the server. This is used by ADD PARTITION all types
+      as well as by REORGANISE PARTITION.
+  */
+  virtual int add_partitions(HA_CREATE_INFO *create_info,
+                             const char *path)
+  { return HA_ERR_WRONG_COMMAND; }
+
+  /*
+    SYNOPSIS
       drop_partitions()
       path                        Complete path of db and table name
     RETURN VALUE
@@ -1335,6 +1360,38 @@
   */
   virtual int drop_partitions(const char *path)
   { return HA_ERR_WRONG_COMMAND; }
+
+  /*
+    SYNOPSIS
+      rename_partitions()
+      path                        Complete path of db and table name
+    RETURN VALUE
+      TRUE                        Failure
+      FALSE                       Success
+    DESCRIPTION
+      When reorganising partitions, adding hash partitions and coalescing
+      partitions it can be necessary to rename partitions while holding
+      an exclusive lock on the table.
+  */
+  virtual int rename_partitions(const char *path)
+  { return HA_ERR_WRONG_COMMAND; }
+
+  /*
+    SYNOPSIS
+      copy_partitions()
+      copied                      Output parameter where number of copied
+                                  records are added
+      deleted                     Output parameter where number of deleted
+                                  records are added
+    RETURN VALUES
+      TRUE                        Failure
+      FALSE                       Success
+    DESCRIPTION
+      Copy from reorged partitions to the new partitions
+  */
+  virtual int copy_partitions(ulonglong &copied, ulonglong &deleted)
+  { return HA_ERR_WRONG_COMMAND; }
+
   /* lock_count() can be more than one if the table is a MERGE */
   virtual uint lock_count(void) const { return 1; }
   virtual THR_LOCK_DATA **store_lock(THD *thd,

--- 1.122/sql/item.cc	2005-09-06 12:58:28 +02:00
+++ 1.123/sql/item.cc	2005-09-13 14:16:01 +02:00
@@ -818,8 +818,25 @@
   DBUG_ASSERT(fixed);
   Item *it= this_item();
   String *ret= it->val_str(sp);
+  /*
+    This way we mark returned value of val_str as const,
+    so that various functions (e.g. CONCAT) won't try to
+    modify the value of the Item. Analogous mechanism is
+    implemented for Item_param.
+    Without this trick Item_splocal could be changed as a
+    side-effect of expression computation. Here is an example
+    of what happens without it: suppose x is varchar local
+    variable in a SP with initial value 'ab' Then
+      select concat(x,'c');
+    would change x's value to 'abc', as Item_func_concat::val_str()
+    would use x's internal buffer to compute the result.
+    This is intended behaviour of Item_func_concat. Comments to
+    Item_param class contain some more details on the topic.
+  */
+  str_value_ptr.set(ret->ptr(), ret->length(),
+                    ret->charset());
   null_value= it->null_value;
-  return ret;
+  return &str_value_ptr;
 }
 
 
@@ -1022,9 +1039,9 @@
     /* Will split complicated items and ignore simple ones */
     split_sum_func(thd, ref_pointer_array, fields);
   }
-  else if ((type() == SUM_FUNC_ITEM ||
-            (used_tables() & ~PARAM_TABLE_BIT)) &&
-           type() != REF_ITEM)
+  else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) &&
+           (type() != REF_ITEM ||
+           ((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF))
   {
     /*
       Replace item with a reference so that we can easily calculate
@@ -1033,15 +1050,17 @@
       The test above is to ensure we don't do a reference for things
       that are constants (PARAM_TABLE_BIT is in effect a constant)
       or already referenced (for example an item in HAVING)
+      Exception is Item_direct_view_ref which we need to convert to
+      Item_ref to allow fields from view being stored in tmp table.
     */
     uint el= fields.elements;
-    Item *new_item;    
-    ref_pointer_array[el]= this;
+    Item *new_item, *real_itm= real_item();
+
+    ref_pointer_array[el]= real_itm;
     if (!(new_item= new Item_ref(&thd->lex->current_select->context,
                                  ref_pointer_array + el, 0, name)))
       return;                                   // fatal_error is set
-    fields.push_front(this);
-    ref_pointer_array[el]= this;
+    fields.push_front(real_itm);
     thd->change_item_tree(ref, new_item);
   }
 }

--- 1.144/sql/lex.h	2005-09-06 12:58:28 +02:00
+++ 1.145/sql/lex.h	2005-09-13 14:16:02 +02:00
@@ -385,6 +385,7 @@
   { "PARTITION",        SYM(PARTITION_SYM)},
 #endif
   { "PARTITIONS",       SYM(PARTITIONS_SYM)},
+  { "PART_STATE",       SYM(PART_STATE_SYM)},
   { "PASSWORD",		SYM(PASSWORD)},
   { "PHASE",            SYM(PHASE_SYM)},
   { "POINT",		SYM(POINT_SYM)},

--- 1.73/sql/lock.cc	2005-08-27 07:49:55 +02:00
+++ 1.74/sql/lock.cc	2005-09-13 14:16:02 +02:00
@@ -333,16 +333,32 @@
   }
 }
 
+/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
+
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+                                thr_lock_type new_lock_type)
+{
+  MYSQL_LOCK *locked;
+  TABLE *write_lock_used;
+  if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
+  {
+    for (uint i=0; i < locked->lock_count; i++)
+      thr_downgrade_write_lock(locked->locks[i], new_lock_type);
+    my_free((gptr) locked,MYF(0));
+  }
+}
+
+
 /* abort all other threads waiting to get lock in table */
 
-void mysql_lock_abort(THD *thd, TABLE *table)
+void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
 {
   MYSQL_LOCK *locked;
   TABLE *write_lock_used;
   if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
   {
     for (uint i=0; i < locked->lock_count; i++)
-      thr_abort_locks(locked->locks[i]->lock);
+      thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
     my_free((gptr) locked,MYF(0));
   }
 }

--- 1.161/sql/log.cc	2005-09-06 12:58:28 +02:00
+++ 1.162/sql/log.cc	2005-09-13 14:16:03 +02:00
@@ -1560,12 +1560,19 @@
   thd->binlog_evt_union.do_union= TRUE;
   thd->binlog_evt_union.unioned_events= FALSE;
   thd->binlog_evt_union.unioned_events_trans= FALSE;
+  thd->binlog_evt_union.first_query_id= thd->query_id;
 }
 
 void MYSQL_LOG::stop_union_events(THD *thd)
 {
   DBUG_ASSERT(thd->binlog_evt_union.do_union);
   thd->binlog_evt_union.do_union= FALSE;
+}
+
+bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
+{
+  return (thd->binlog_evt_union.do_union && 
+          query_id_param >= thd->binlog_evt_union.first_query_id);
 }
 
 /*

--- 1.301/sql/mysql_priv.h	2005-09-07 14:59:30 +02:00
+++ 1.302/sql/mysql_priv.h	2005-09-13 14:16:04 +02:00
@@ -579,6 +579,10 @@
 #define query_cache_invalidate_by_MyISAM_filename_ref NULL
 #endif /*HAVE_QUERY_CACHE*/
 
+uint build_table_path(char *buff, size_t bufflen, const char *db,
+                      const char *table, const char *ext);
+void write_bin_log(THD *thd, bool clear_error);
+
 bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
 bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
 bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
@@ -994,6 +998,19 @@
 void flush_tables();
 bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
 
+#ifdef HAVE_PARTITION_DB
+uint online_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
+                             HA_CREATE_INFO *create_info,
+                             TABLE_LIST *table_list,
+                             List<create_field> *create_list,
+                             List<Key> *key_list, const char *db,
+                             const char *table_name);
+uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
+                           HA_CREATE_INFO *create_info,
+                           enum db_type old_db_type,
+                           bool &partition_changed, bool &online_alter_part);
+#endif
+
 /* bits for last argument to remove_table_from_cache() */
 #define RTFC_NO_FLAG                0x0000
 #define RTFC_OWNED_BY_THD_FLAG      0x0001
@@ -1002,6 +1019,28 @@
 bool remove_table_from_cache(THD *thd, const char *db, const char *table,
                              uint flags);
 
+typedef struct st_lock_param_type
+{
+  THD *thd;
+  HA_CREATE_INFO *create_info;
+  List<create_field> *create_list;
+  List<Key> *key_list;
+  TABLE *table;
+  KEY *key_info_buffer;
+  const char *db;
+  const char *table_name;
+  enum thr_lock_type old_lock_type;
+  uint key_count;
+  uint db_options;
+} LOCK_PARAM_TYPE;
+
+void mem_alloc_error();
+bool mysql_write_frm(LOCK_PARAM_TYPE *lpt, bool initial_write,
+                     bool create_handler_files);
+bool abort_and_upgrade_lock(LOCK_PARAM_TYPE *lpt);
+void close_open_tables_and_downgrade(LOCK_PARAM_TYPE *lpt);
+void mysql_wait_completed_table(LOCK_PARAM_TYPE *lpt, TABLE *my_table);
+
 bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
 void copy_field_from_tmp_record(Field *field,int offset);
 bool fill_record(THD *thd, Field **field, List<Item> &values,
@@ -1268,7 +1307,9 @@
 void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
 void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
 void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
-void mysql_lock_abort(THD *thd, TABLE *table);
+void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock);
+void mysql_lock_downgrade_write(THD *thd, TABLE *table,
+                                thr_lock_type new_lock_type);
 bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
 MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
 bool lock_global_read_lock(THD *thd);

--- 1.180/sql/sql_class.cc	2005-09-06 12:58:29 +02:00
+++ 1.181/sql/sql_class.cc	2005-09-13 14:16:05 +02:00
@@ -377,14 +377,16 @@
   mysql_ha_flush(this, (TABLE_LIST*) 0,
                  MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
   hash_free(&handler_tables_hash);
+  delete_dynamic(&user_var_events);
+  hash_free(&user_vars);
   close_temporary_tables(this);
   my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
   my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
   my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
-  delete_dynamic(&user_var_events);
-  hash_free(&user_vars);
+  
   sp_cache_clear(&sp_proc_cache);
   sp_cache_clear(&sp_func_cache);
+
   if (global_read_lock)
     unlock_global_read_lock(this);
   if (ull)
@@ -423,9 +425,6 @@
     cleanup();
 
   ha_close_connection(this);
-
-  sp_cache_clear(&sp_proc_cache);
-  sp_cache_clear(&sp_func_cache);
 
   DBUG_PRINT("info", ("freeing host"));
   if (host != my_localhost)			// If not pointer to constant

--- 1.236/sql/sql_class.h	2005-09-06 12:58:29 +02:00
+++ 1.237/sql/sql_class.h	2005-09-13 14:16:05 +02:00
@@ -313,6 +313,7 @@
 
   void start_union_events(THD *thd);
   void stop_union_events(THD *thd);
+  bool is_query_in_union(THD *thd, query_id_t query_id_param);
 
   /*
     v stands for vector
@@ -1312,8 +1313,9 @@
   /* variables.transaction_isolation is reset to this after each commit */
   enum_tx_isolation session_tx_isolation;
   enum_check_fields count_cuted_fields;
-  /* for user variables replication*/
-  DYNAMIC_ARRAY user_var_events;
+
+  DYNAMIC_ARRAY user_var_events;        /* For user variables replication */
+  MEM_ROOT      *user_var_events_alloc; /* Allocate above array elements here */
 
   enum killed_state { NOT_KILLED=0, KILL_BAD_DATA=1, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED };
   killed_state volatile killed;
@@ -1375,6 +1377,12 @@
       mysql_bin_log.start_union_events() call.
     */
     bool unioned_events_trans;
+    
+    /* 
+      'queries' (actually SP statements) that run under inside this binlog
+      union have thd->query_id >= first_query_id.
+    */
+    query_id_t first_query_id;
   } binlog_evt_union;
   
   THD();

--- 1.184/sql/sql_lex.h	2005-09-06 12:58:29 +02:00
+++ 1.185/sql/sql_lex.h	2005-09-13 14:16:06 +02:00
@@ -663,6 +663,7 @@
 #define ALTER_DROP_PARTITION    16384
 #define ALTER_COALESCE_PARTITION 32768
 #define ALTER_REORGANISE_PARTITION   65536
+#define ALTER_PARTITION          131072
 
 typedef struct st_alter_info
 {

--- 1.435/sql/sql_parse.cc	2005-09-07 14:59:31 +02:00
+++ 1.436/sql/sql_parse.cc	2005-09-13 14:16:06 +02:00
@@ -2442,6 +2442,12 @@
     {
       if (lex->describe)
       {
+        /*
+          We always use select_send for EXPLAIN, even if it's an EXPLAIN
+          for SELECT ... INTO OUTFILE: a user application should be able
+          to prepend EXPLAIN to any query and receive output for it,
+          even if the query itself redirects the output.
+        */
 	if (!(result= new select_send()))
 	  goto error;
 	else
@@ -3514,7 +3520,6 @@
 	 !rpl_filter->db_ok_with_wild_table(lex->name)))
     {
       my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
-      reset_one_shot_variables(thd);
       break;
     }
 #endif
@@ -3549,7 +3554,6 @@
 	 !rpl_filter->db_ok_with_wild_table(lex->name)))
     {
       my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
-      reset_one_shot_variables(thd);
       break;
     }
 #endif
@@ -3590,7 +3594,6 @@
 	 !rpl_filter->db_ok_with_wild_table(lex->name)))
     {
       my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
-      reset_one_shot_variables(thd);
       break;
     }
 #endif
@@ -5172,7 +5175,10 @@
   if (!thd->in_sub_stmt)
   {
     if (opt_bin_log)
+    {
       reset_dynamic(&thd->user_var_events);
+      thd->user_var_events_alloc= thd->mem_root;
+    }
     thd->clear_error();
     thd->total_warn_count=0;			// Warnings for this query
     thd->rand_used= 0;
@@ -6364,7 +6370,7 @@
   SYNOPSIS
     make_join_on_context()
     thd       pointer to current thread
-    left_op   lefto operand of the JOIN
+    left_op   left  operand of the JOIN
     right_op  rigth operand of the JOIN
 
   DESCRIPTION

--- 1.330/sql/sql_select.cc	2005-09-07 14:59:31 +02:00
+++ 1.331/sql/sql_select.cc	2005-09-13 14:16:07 +02:00
@@ -2874,19 +2874,6 @@
   if (cond->type() != Item::FUNC_ITEM)
     return;
   Item_func *cond_func= (Item_func*) cond;
-  if (cond_func->functype() == Item_func::NOT_FUNC)
-  {
-    Item *item= cond_func->arguments()[0];
-    /*
-      At this moment all NOT before simple comparison predicates
-      are eliminated. NOT IN and NOT BETWEEN are treated similar
-      IN and BETWEEN respectively.
-    */
-    if (item->type() == Item::FUNC_ITEM &&
-        ((Item_func *) item)->select_optimize() == Item_func::OPTIMIZE_KEY)
-      add_key_fields(key_fields,and_level,item,usable_tables);
-    return;
-  }
   switch (cond_func->select_optimize()) {
   case Item_func::OPTIMIZE_NONE:
     break;
@@ -8069,7 +8056,7 @@
                         bool table_cant_handle_bit_fields,
                         uint convert_blob_length)
 {
-  Item::Type orig_type;
+  Item::Type orig_type= type;
   Item *orig_item;
 
   if (type != Item::FIELD_ITEM &&
@@ -8079,7 +8066,6 @@
   {
     orig_item= item;
     item= item->real_item();
-    orig_type= type;
     type= Item::FIELD_ITEM;
   }
   switch (type) {
@@ -13087,6 +13073,8 @@
     The function replaces occurrences of group by fields in expr
     by ref objects for these fields unless they are under aggregate
     functions.
+    The function also corrects value of the the maybe_null attribute
+    for the items of all subexpressions containing group by fields.
 
   IMPLEMENTATION
     The function recursively traverses the tree of the expr expression,
@@ -13097,6 +13085,9 @@
     This substitution is needed GROUP BY queries with ROLLUP if
     SELECT list contains expressions over group by attributes.
 
+  TODO: Some functions are not null-preserving. For those functions
+    updating of the maybe_null attribute is an overkill. 
+
   EXAMPLES
     SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
     SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP 
@@ -13113,6 +13104,7 @@
   {
     Name_resolution_context *context= &thd->lex->current_select->context;
     Item **arg,**arg_end;
+    bool arg_changed= FALSE;
     for (arg= expr->arguments(),
          arg_end= expr->arguments()+expr->arg_count;
          arg != arg_end; arg++)
@@ -13130,16 +13122,21 @@
                                         item->name)))
               return 1;                                 // fatal_error is set
             thd->change_item_tree(arg, new_item);
-            *changed= TRUE;
+            arg_changed= TRUE;
           }
         }
       }
       else if (item->type() == Item::FUNC_ITEM)
       {
-        if (change_group_ref(thd, (Item_func *) item, group_list, changed))
+        if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
           return 1;
       }
     }
+    if (arg_changed)
+    {
+      expr->maybe_null= 1;
+      *changed= TRUE;
+    }
   }
   return 0;
 }
@@ -13201,7 +13198,7 @@
     }
     if (item->type() == Item::FUNC_ITEM)
     {
-      bool changed= 0;
+      bool changed= FALSE;
       if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
         return 1;
       /*

--- 1.262/sql/sql_show.cc	2005-09-09 13:30:33 +02:00
+++ 1.263/sql/sql_show.cc	2005-09-13 14:16:08 +02:00
@@ -1057,7 +1057,7 @@
     if (table->s->part_info &&
         ((part_syntax= generate_partition_syntax(table->s->part_info,
                                                   &part_syntax_len,
-                                                  FALSE))))
+                                                  FALSE, FALSE))))
     {
        packet->append(part_syntax, part_syntax_len);
        my_free(part_syntax, MYF(0));

--- 1.231/sql/sql_table.cc	2005-09-06 12:58:30 +02:00
+++ 1.232/sql/sql_table.cc	2005-09-13 14:16:08 +02:00
@@ -43,66 +43,14 @@
 				    ha_rows *copied,ha_rows *deleted);
 static bool prepare_blob_field(THD *thd, create_field *sql_field);
 static bool check_engine(THD *thd, const char *table_name,
-                         enum db_type *new_engine);                             
-
-/*
-  SYNOPSIS
-    write_bin_log()
-    thd                           Thread object
-    clear_error                   is clear_error to be called
-  RETURN VALUES
-    NONE
-  DESCRIPTION
-    Write the binlog if open, routine used in multiple places in this
-    file
-*/
-
-static void write_bin_log(THD *thd, bool clear_error)
-{
-  if (mysql_bin_log.is_open())
-  {
-    if (clear_error)
-      thd->clear_error();
-    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
-    mysql_bin_log.write(&qinfo);
-  }
-}
-
-/*
-  SYNOPSIS
-    abort_and_upgrade_lock()
-    thd                           Thread object
-    table                         Table object
-    db                            Database name
-    table_name                    Table name
-    old_lock_level                Old lock level
-  RETURN VALUES
-    TRUE                          Failure
-    FALSE                         Success
-  DESCRIPTION
-    Remember old lock level (for possible downgrade later on), abort all
-    waiting threads and ensure that all keeping locks currently are
-    completed such that we own the lock exclusively and no other interaction
-    is ongoing.
-*/
-
-static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
-                                   const char *table_name,
-                                   uint *old_lock_level)
-{
-  uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
-  DBUG_ENTER("abort_and_upgrade_locks");
-
-  *old_lock_level= table->reginfo.lock_type;
-  mysql_lock_abort(thd, table);
-  VOID(remove_table_from_cache(thd, db, table_name, flags));
-  if (thd->killed)
-  {
-    thd->no_warnings_for_error= 0;
-    DBUG_RETURN(TRUE);
-  }
-  DBUG_RETURN(FALSE);
-}
+                         enum db_type *new_engine);
+static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+                               List<create_field> *fields,
+                               List<Key> *keys, bool tmp_table,
+                               uint *db_options,
+                               handler *file, KEY **key_info_buffer,
+                               uint *key_count, int select_field_count);
+ 
 
 /*
  Build the path to a file for a table (or the base path that can
@@ -121,8 +69,8 @@
     #                   Size of path
  */
 
-static uint build_table_path(char *buff, size_t bufflen, const char *db,
-                             const char *table, const char *ext)
+uint build_table_path(char *buff, size_t bufflen, const char *db,
+                      const char *table, const char *ext)
 {
   strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
            NullS);
@@ -130,6 +78,105 @@
 }
 
 
+/*
+  SYNOPSIS
+    mysql_write_frm()
+    lpt                    Struct carrying many parameters needed for this
+                           method
+    initial_write          If set we need to prepare table before creating the
+                           frm file
+    create_handler_files   If set we need to create the handler file as part
+                           of the creation of the frm file
+  RETURN VALUES
+    TRUE                   Error
+    FALSE                  Success
+  DESCRIPTION
+    A support method that creates a new frm file and in this process it
+    regenerates the partition data.
+*/
+
+bool mysql_write_frm(LOCK_PARAM_TYPE *lpt,
+                            bool initial_write,
+                            bool create_handler_files)
+{
+  /*
+    Prepare table to prepare for writing a new frm file where the
+    partitions in add/drop state have temporarily changed their state
+  */
+  char path[FN_REFLEN+1];
+  DBUG_ENTER("mysql_write_frm");
+
+  if (initial_write && 
+      (mysql_prepare_table(lpt->thd, lpt->create_info, lpt->create_list,
+                           lpt->key_list,/*tmp_table*/ 0, &lpt->db_options,
+                           lpt->table->file, &lpt->key_info_buffer,
+                           &lpt->key_count, /*select_field_count*/ 0)))
+  {
+    DBUG_RETURN(TRUE);
+  }
+#ifdef HAVE_PARTITION_DB
+  {
+    partition_info *part_info= lpt->table->s->part_info;
+    char *part_syntax_buf;
+    uint syntax_len;
+
+    if (part_info)
+    {
+      if (!(part_syntax_buf= generate_partition_syntax(part_info,
+                                                       &syntax_len,
+                                                       TRUE, TRUE)))
+      {
+        DBUG_RETURN(TRUE);
+      }
+      part_info->part_info_string= part_syntax_buf;
+      part_info->part_info_len= syntax_len;
+    }
+  }
+#endif
+  build_table_path(path, sizeof(path), lpt->db, lpt->table_name, reg_ext);
+  if ((mysql_create_frm(lpt->thd, path, lpt->db, lpt->table_name,
+                        lpt->create_info, *lpt->create_list, lpt->key_count,
+                        lpt->key_info_buffer, lpt->table->file)) ||
+      (create_handler_files &&
+       lpt->table->file->create_handler_files(path)))
+  {
+    DBUG_RETURN(TRUE);
+  }
+#ifdef HAVE_PARTITION_DB
+  /*
+     We need to restore part_info reference on thd object after calling
+     mysql_create_frm
+  */
+  lpt->thd->lex->part_info= lpt->table->s->part_info;
+#endif
+  /* Frm file have been updated to reflect the change about to happen.  */
+  DBUG_RETURN(FALSE);
+}
+
+
+/*
+  SYNOPSIS
+    write_bin_log()
+    thd                           Thread object
+    clear_error                   is clear_error to be called
+  RETURN VALUES
+    NONE
+  DESCRIPTION
+    Write the binlog if open, routine used in multiple places in this
+    file
+*/
+
+void write_bin_log(THD *thd, bool clear_error)
+{
+  if (mysql_bin_log.is_open())
+  {
+    if (clear_error)
+      thd->clear_error();
+    Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+    mysql_bin_log.write(&qinfo);
+  }
+}
+
 
 /*
  delete (drop) tables.
@@ -1629,7 +1676,7 @@
     */
     if (!(part_syntax_buf= generate_partition_syntax(part_info,
                                                      &syntax_len,
-                                                     TRUE)))
+                                                     TRUE, FALSE)))
       DBUG_RETURN(TRUE);
     part_info->part_info_string= part_syntax_buf;
     part_info->part_info_len= syntax_len;
@@ -1695,6 +1742,9 @@
     if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
     {
       create_info->table_existed= 1;		// Mark that table existed
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+                          alias);
       goto no_err;
     }
     my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -1708,12 +1758,8 @@
     if (!access(path,F_OK))
     {
       if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
-      {
-	create_info->table_existed= 1;		// Mark that table existed
-	error= FALSE;
-      }
-      else
-	my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+        goto warn;
+      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
       goto end;
     }
   }
@@ -1736,12 +1782,8 @@
       DBUG_PRINT("info", ("Table with same name already existed in handler"));
 
       if (create_if_not_exists)
-      {
-        create_info->table_existed= 1;   // Mark that table existed
-        error= FALSE;
-      }
-      else
-       my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+        goto warn;
+      my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
       goto end;
     }
   }
@@ -1774,6 +1816,14 @@
     mysql_bin_log.write(&qinfo);
   }
   error= FALSE;
+  goto end; 
+
+warn:
+  error= 0;
+  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                      ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+                      alias);
+  create_info->table_existed= 1;		// Mark that table existed
 
 end:
   VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2002,7 +2052,7 @@
 
   VOID(table->file->extra(function));
   /* Mark all tables that are in use as 'old' */
-  mysql_lock_abort(thd, table);			// end threads waiting on lock
+  mysql_lock_abort(thd, table, TRUE);	/* end threads waiting on lock */
 
   /* Wait until all there are no other threads that has this table open */
   remove_table_from_cache(thd, table->s->db,
@@ -2392,7 +2442,7 @@
       pthread_mutex_lock(&LOCK_open);
       const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
 					      "Waiting to get writelock");
-      mysql_lock_abort(thd,table->table);
+      mysql_lock_abort(thd,table->table, TRUE);
       remove_table_from_cache(thd, table->table->s->db,
                               table->table->s->table_name,
                               RTFC_WAIT_OTHER_THREAD_FLAG |
@@ -3355,10 +3405,8 @@
   enum db_type old_db_type,new_db_type;
   uint need_copy_table= 0;
 #ifdef HAVE_PARTITION_DB
-  bool online_add_empty_partition= FALSE;
-  bool online_drop_partition= FALSE;
+  bool online_alter_part= FALSE;
   bool partition_changed= FALSE;
-  enum db_type default_engine_type;
 #endif
   DBUG_ENTER("mysql_alter_table");
 
@@ -3437,419 +3485,10 @@
     create_info->db_type= old_db_type;
 
 #ifdef HAVE_PARTITION_DB
-  /*
-   We need to handle both partition management command such as Add Partition
-   and others here as well as an ALTER TABLE that completely changes the
-   partitioning and yet others that don't change anything at all. We start
-   by checking the partition management variants and then check the general
-   change patterns.
-   */
-  if (alter_info->flags & (ALTER_ADD_PARTITION +
-      ALTER_DROP_PARTITION + ALTER_COALESCE_PARTITION +
-      ALTER_REORGANISE_PARTITION))
-  {
-    partition_info *tab_part_info= table->s->part_info;
-    if (!tab_part_info)
-    {
-      my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
-      DBUG_RETURN(TRUE);
-    }
-    {
-      List_iterator<partition_element> t_it(tab_part_info->partitions);
-      partition_element *t_part_elem= t_it++;
-      if (is_sub_partitioned(tab_part_info))
-      {
-        List_iterator<partition_element> s_it(t_part_elem->subpartitions);
-        t_part_elem= s_it++;
-      }
-      default_engine_type= t_part_elem->engine_type;
-    }
-    /*
-      We are going to manipulate the partition info on the table object
-      so we need to ensure that the data structure of the table object
-      is freed by setting version to 0.
-    */
-    table->s->version= 0L;
-    if (alter_info->flags == ALTER_ADD_PARTITION)
-    {
-      /*
-        We start by moving the new partitions to the list of temporary
-        partitions. We will then check that the new partitions fit in the
-        partitioning scheme as currently set-up.
-        Partitions are always added at the end in ADD PARTITION.
-      */
-      partition_info *alt_part_info= thd->lex->part_info;
-      uint no_new_partitions= alt_part_info->no_parts;
-      uint no_orig_partitions= tab_part_info->no_parts;
-      uint check_total_partitions= no_new_partitions + no_orig_partitions;
-      uint new_total_partitions= check_total_partitions;
-      /*
-        We allow quite a lot of values to be supplied by defaults, however we
-        must know the number of new partitions in this case.
-      */ 
-      if (no_new_partitions == 0)
-      {
-        my_error(ER_ADD_PARTITION_NO_NEW_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (is_sub_partitioned(tab_part_info))
-      {
-        if (alt_part_info->no_subparts == 0)
-          alt_part_info->no_subparts= tab_part_info->no_subparts;
-        else if (alt_part_info->no_subparts != tab_part_info->no_subparts)
-        {
-          my_error(ER_ADD_PARTITION_SUBPART_ERROR, MYF(0));
-          DBUG_RETURN(TRUE);
-        }
-        check_total_partitions= new_total_partitions*
-                                alt_part_info->no_subparts;
-      }
-      if (check_total_partitions > MAX_PARTITIONS)
-      {
-        my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      alt_part_info->part_type= tab_part_info->part_type;
-      if (set_up_defaults_for_partitioning(alt_part_info,
-                                           table->file,
-                                           (ulonglong)0ULL,
-                                           tab_part_info->no_parts))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      /*
-        Need to concatenate the lists here to make it possible to check the
-        partition info for correctness using check_partition_info
-      */
-      {
-        List_iterator<partition_element> alt_it(alt_part_info->partitions);
-        uint part_count= 0;
-        do
-        {
-          partition_element *part_elem= alt_it++;
-          tab_part_info->partitions.push_back(part_elem);
-          tab_part_info->temp_partitions.push_back(part_elem);
-        } while (++part_count < no_new_partitions);
-        tab_part_info->no_parts+= no_new_partitions;
-      }
-      {
-        List_iterator<partition_element> tab_it(tab_part_info->partitions);
-        partition_element *part_elem= tab_it++;
-        if (is_sub_partitioned(tab_part_info))
-        {
-          List_iterator<partition_element> sub_it(part_elem->subpartitions);
-          part_elem= sub_it++;
-        }
-        if (check_partition_info(tab_part_info, part_elem->engine_type,
-                                 table->file, (ulonglong)0ULL))
-        {
-          DBUG_RETURN(TRUE);
-        }
-      }
-      create_info->db_type= DB_TYPE_PARTITION_DB;
-      thd->lex->part_info= tab_part_info;
-      if (table->file->alter_table_flags() & HA_ONLINE_ADD_EMPTY_PARTITION &&
-          (tab_part_info->part_type == RANGE_PARTITION ||
-           tab_part_info->part_type == LIST_PARTITION))
-      {
-        /*
-          For range and list partitions add partition is simply adding a new
-          empty partition to the table. If the handler support this we will
-          use the simple method of doing this. In this case we need to break
-          out the new partitions from the list again and only keep them in the
-          temporary list. Added partitions are always added at the end.
-        */
-        {
-          List_iterator<partition_element> tab_it(tab_part_info->partitions);
-          uint part_count= 0;
-          do
-          {
-            tab_it++;
-          } while (++part_count < no_orig_partitions);
-          do
-          {
-            tab_it++;
-            tab_it.remove();
-          } while (++part_count < new_total_partitions);
-        }
-        tab_part_info->no_parts-= no_new_partitions;
-        online_add_empty_partition= TRUE;
-      }
-      else
-      {
-        tab_part_info->temp_partitions.empty();
-      }
-    }
-    else if (alter_info->flags == ALTER_DROP_PARTITION)
-    {
-      /*
-        Drop a partition from a range partition and list partitioning is
-        always safe and can be made more or less immediate. It is necessary
-        however to ensure that the partition to be removed is safely removed
-        and that REPAIR TABLE can remove the partition if for some reason the
-        command to drop the partition failed in the middle.
-      */
-      uint part_count= 0;
-      uint no_parts_dropped= alter_info->partition_names.elements;
-      uint no_parts_found= 0;
-      List_iterator<partition_element> part_it(tab_part_info->partitions);
-      if (!(tab_part_info->part_type == RANGE_PARTITION ||
-            tab_part_info->part_type == LIST_PARTITION))
-      {
-        my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP");
-        DBUG_RETURN(TRUE);
-      }
-      if (no_parts_dropped >= tab_part_info->no_parts)
-      {
-        my_error(ER_DROP_LAST_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      do
-      {
-        partition_element *part_elem= part_it++;
-        if (is_partition_in_list(part_elem->partition_name,
-                                 alter_info->partition_names))
-        {
-          /*
-            Remove the partition from the list and put it instead in the
-            list of temporary partitions with a new state.
-          */
-          no_parts_found++;
-          part_elem->part_state= PART_IS_DROPPED;
-        }
-      } while (++part_count < tab_part_info->no_parts);
-      if (no_parts_found != no_parts_dropped)
-      {
-        my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (!(table->file->alter_table_flags() & HA_ONLINE_DROP_PARTITION))
-      {
-        my_error(ER_DROP_PARTITION_FAILURE, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (table->file->is_fk_defined_on_table_or_index(MAX_KEY))
-      {
-        my_error(ER_DROP_PARTITION_WHEN_FK_DEFINED, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      /*
-        This code needs set-up of structures needed by mysql_create_table
-        before it is called and thus we only set a boolean variable to be
-        checked later down in the code when all needed data structures are
-        prepared.
-      */
-      online_drop_partition= TRUE;
-    }
-    else if (alter_info->flags == ALTER_COALESCE_PARTITION)
-    {
-      /*
-        In this version COALESCE PARTITION is implemented by simply removing
-        a partition from the table and using the normal ALTER TABLE code
-        and ensuring that copy to a new table occurs. Later on we can optimise
-        this function for Linear Hash partitions. In that case we can avoid
-        reorganising the entire table. For normal hash partitions it will
-        be a complete reorganise anyways so that can only be made on-line
-        if it still uses a copy table.
-      */
-      uint part_count= 0;
-      uint no_parts_coalesced= alter_info->no_parts;
-      uint no_parts_remain= tab_part_info->no_parts - no_parts_coalesced;
-      List_iterator<partition_element> part_it(tab_part_info->partitions);
-      if (tab_part_info->part_type != HASH_PARTITION)
-      {
-        my_error(ER_COALESCE_ONLY_ON_HASH_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (no_parts_coalesced == 0)
-      {
-        my_error(ER_COALESCE_PARTITION_NO_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (no_parts_coalesced >= tab_part_info->no_parts)
-      {
-        my_error(ER_DROP_LAST_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      do
-      {
-        part_it++;
-        if (++part_count > no_parts_remain)
-          part_it.remove();
-      } while (part_count < tab_part_info->no_parts);
-      tab_part_info->no_parts= no_parts_remain;
-    }
-    else if (alter_info->flags == ALTER_REORGANISE_PARTITION)
-    {
-      /*
-        Reorganise partitions takes a number of partitions that are next
-        to each other (at least for RANGE PARTITIONS) and then uses those
-        to create a set of new partitions. So data is copied from those
-        partitions into the new set of partitions. Those new partitions
-        can have more values in the LIST value specifications or less both
-        are allowed. The ranges can be different but since they are 
-        changing a set of consecutive partitions they must cover the same
-        range as those changed from.
-        This command can be used on RANGE and LIST partitions.
-      */
-      uint no_parts_reorged= alter_info->partition_names.elements;
-      uint no_parts_new= thd->lex->part_info->partitions.elements;
-      partition_info *alt_part_info= thd->lex->part_info;
-      uint check_total_partitions;
-      if (no_parts_reorged > tab_part_info->no_parts)
-      {
-        my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      if (!(tab_part_info->part_type == RANGE_PARTITION ||
-            tab_part_info->part_type == LIST_PARTITION))
-      {
-        my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "REORGANISE");
-        DBUG_RETURN(TRUE);
-      }
-      if (is_partitions_in_table(alt_part_info, tab_part_info))
-      {
-        my_error(ER_SAME_NAME_PARTITION, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      check_total_partitions= tab_part_info->no_parts + no_parts_new;
-      check_total_partitions-= no_parts_reorged;
-      if (check_total_partitions > MAX_PARTITIONS)
-      {
-        my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      {
-        List_iterator<partition_element> tab_it(tab_part_info->partitions);
-        uint part_count= 0;
-        bool found_first= FALSE, found_last= FALSE;
-        uint drop_count= 0;
-        longlong tab_max_range, alt_max_range;
-        do
-        {
-          partition_element *part_elem= tab_it++;
-          if (is_partition_in_list(part_elem->partition_name,
-                                   alter_info->partition_names))
-          {
-            drop_count++;
-            tab_max_range= part_elem->range_value;
-            if (!found_first)
-            {
-              uint alt_part_count= 0;
-              found_first= TRUE;
-              List_iterator<partition_element> alt_it(alt_part_info->partitions);
-              do
-              {
-                partition_element *alt_part_elem= alt_it++;
-                alt_max_range= alt_part_elem->range_value;
-                if (alt_part_count == 0)
-                  tab_it.replace(alt_part_elem);
-                else
-                  tab_it.after(alt_part_elem);
-              } while (++alt_part_count < no_parts_new);
-            }
-            else if (found_last)
-            {
-              my_error(ER_CONSECUTIVE_REORG_PARTITIONS, MYF(0));
-              DBUG_RETURN(TRUE);
-            }
-            else
-              tab_it.remove();
-          }
-          else
-          {
-            if (found_first)
-              found_last= TRUE;
-          }
-        } while (++part_count < tab_part_info->no_parts);
-        if (drop_count != no_parts_reorged)
-        {
-          my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
-          DBUG_RETURN(TRUE);
-        }
-        if (tab_part_info->part_type == RANGE_PARTITION &&
-            alt_max_range > tab_max_range)
-        {
-          my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
-          DBUG_RETURN(TRUE);
-        }
-      }
-    }
-    partition_changed= TRUE;
-    create_info->db_type= DB_TYPE_PARTITION_DB;
-    thd->lex->part_info= tab_part_info;
-    if (alter_info->flags == ALTER_ADD_PARTITION ||
-        alter_info->flags == ALTER_REORGANISE_PARTITION)
-    {
-      if (check_partition_info(tab_part_info, default_engine_type,
-                               table->file, (ulonglong)0ULL))
-      {
-        DBUG_RETURN(TRUE);
-      }
-    }
-  }
-  else
+  if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type,
+                            partition_changed, online_alter_part))
   {
-    /*
-     When thd->lex->part_info has a reference to a partition_info the
-     ALTER TABLE contained a definition of a partitioning.
-
-     Case I:
-       If there was a partition before and there is a new one defined.
-       We use the new partitioning. The new partitioning is already
-       defined in the correct variable so no work is needed to
-       accomplish this.
-       We do however need to update partition_changed to ensure that not
-       only the frm file is changed in the ALTER TABLE command.
-
-     Case IIa:
-       There was a partitioning before and there is no new one defined.
-       Also the user has not specified an explicit engine to use.
-
-       We use the old partitioning also for the new table. We do this
-       by assigning the partition_info from the table loaded in
-       open_ltable to the partition_info struct used by mysql_create_table
-       later in this method.
-
-     Case IIb:
-       There was a partitioning before and there is no new one defined.
-       The user has specified an explicit engine to use.
-
-       Since the user has specified an explicit engine to use we override
-       the old partitioning info and create a new table using the specified
-       engine. This is the reason for the extra check if old and new engine
-       is equal.
-       In this case the partition also is changed.
-
-     Case III:
-       There was no partitioning before altering the table, there is
-       partitioning defined in the altered table. Use the new partitioning.
-       No work needed since the partitioning info is already in the
-       correct variable.
-       Also here partition has changed and thus a new table must be
-       created.
-
-     Case IV:
-       There was no partitioning before and no partitioning defined.
-       Obviously no work needed.
-    */
-    if (table->s->part_info)
-    {
-      if (!thd->lex->part_info &&
-          create_info->db_type == old_db_type)
-        thd->lex->part_info= table->s->part_info;
-    }
-    if (thd->lex->part_info)
-    {
-      /*
-        Need to cater for engine types that can handle partition without
-        using the partition handler.
-      */
-      if (thd->lex->part_info != table->s->part_info)
-        partition_changed= TRUE;
-      thd->lex->part_info->default_engine_type= create_info->db_type;
-      create_info->db_type= DB_TYPE_PARTITION_DB;
-    }
+    DBUG_RETURN(TRUE);
   }
 #endif
   if (check_engine(thd, new_name, &create_info->db_type))
@@ -4232,98 +3871,11 @@
     create_info->frm_only= 1;
 
 #ifdef HAVE_PARTITION_DB
-  if (partition_changed)
+  if (online_alter_part)
   {
-    if (online_drop_partition)
-    {
-      /*
-        Now after all checks and setting state on dropped partitions we can
-        start the actual dropping of the partitions.
-        1) Lock table in TL_WRITE_ONLY to ensure all other accesses on table
-           are completed and no new ones are started until we have changed
-           the frm file.
-        2) Write the new frm file where state of dropped partitions is
-           changed to PART_IS_DROPPED
-        3) Perform the actual drop of the partition using the handler of the
-           table.
-        4) Write a new frm file of the table where the partitions are dropped
-           from the table.
-
-      */
-      uint old_lock_type;
-      partition_info *part_info= table->s->part_info;
-      char path[FN_REFLEN+1];
-      uint db_options= 0, key_count, syntax_len;
-      KEY *key_info_buffer;
-      char *part_syntax_buf;
-
-      VOID(pthread_mutex_lock(&LOCK_open));
-      if (abort_and_upgrade_lock(thd, table, db, table_name, &old_lock_type))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      VOID(pthread_mutex_unlock(&LOCK_open));
-      mysql_prepare_table(thd, create_info, &create_list,
-                          &key_list, /*tmp_table*/ 0, &db_options,
-                          table->file, &key_info_buffer, &key_count,
-                          /*select_field_count*/ 0);
-      if (!(part_syntax_buf= generate_partition_syntax(part_info,
-                                                       &syntax_len,
-                                                       TRUE)))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      part_info->part_info_string= part_syntax_buf;
-      part_info->part_info_len= syntax_len;
-      build_table_path(path, sizeof(path), db, table_name, reg_ext);
-      if (mysql_create_frm(thd, path, db, table_name, create_info,
-                           create_list, key_count, key_info_buffer,
-                           table->file))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      thd->lex->part_info= part_info;
-      build_table_path(path, sizeof(path), db, table_name, "");
-      if (table->file->drop_partitions(path))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      {
-        List_iterator<partition_element> part_it(part_info->partitions);
-        uint i= 0, remove_count= 0;
-        do
-        {
-          partition_element *part_elem= part_it++;
-          if (is_partition_in_list(part_elem->partition_name,
-                                   alter_info->partition_names))
-          {
-            part_it.remove();
-            remove_count++;
-          }
-        } while (++i < part_info->no_parts);
-        part_info->no_parts-= remove_count;
-      }
-      if (!(part_syntax_buf= generate_partition_syntax(part_info,
-                                                       &syntax_len,
-                                                       TRUE)))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      part_info->part_info_string= part_syntax_buf;
-      part_info->part_info_len= syntax_len;
-      build_table_path(path, sizeof(path), db, table_name, reg_ext);
-      if (mysql_create_frm(thd, path, db, table_name, create_info,
-                           create_list, key_count, key_info_buffer,
-                           table->file)  ||
-          table->file->create_handler_files(path))
-      {
-        DBUG_RETURN(TRUE);
-      }
-      thd->proc_info="end";
-      write_bin_log(thd, FALSE);
-      send_ok(thd);
-      DBUG_RETURN(FALSE);
-    }
+    DBUG_RETURN(online_alter_part_table(thd, table, alter_info, create_info,
+                                        table_list, &create_list, &key_list,
+                                        db, table_name));
   }
 #endif
 
@@ -4560,7 +4112,7 @@
       /* Mark in-use copies old */
       remove_table_from_cache(thd,db,table_name,RTFC_NO_FLAG);
       /* end threads waiting on lock */
-      mysql_lock_abort(thd,table);
+      mysql_lock_abort(thd,table, TRUE);
     }
     VOID(quick_rm_table(old_db_type,db,old_name));
     if (close_data_tables(thd,db,table_name) ||

--- 1.374/sql/sql_yacc.yy	2005-09-07 14:59:31 +02:00
+++ 1.375/sql/sql_yacc.yy	2005-09-13 14:16:09 +02:00
@@ -483,6 +483,7 @@
 %token  PARTIAL
 %token  PARTITION_SYM
 %token  PARTITIONS_SYM
+%token  PART_STATE_SYM
 %token  PASSWORD
 %token  PARAM_MARKER
 %token  PHASE_SYM
@@ -687,6 +688,9 @@
 %token  YEAR_SYM
 %token  ZEROFILL
 
+%left   JOIN_SYM
+/* A dummy token to force the priority of table_ref production in a join. */
+%left   TABLE_REF_PRIORITY
 %left   SET_VAR
 %left	OR_OR_SYM OR_SYM OR2_SYM XOR
 %left	AND_SYM AND_AND_SYM
@@ -3007,9 +3011,13 @@
           lex->part_info= new partition_info();
           if (!lex->part_info)
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+            mem_alloc_error();
             YYABORT;
           }
+          if (lex->sql_command == SQLCOM_ALTER_TABLE)
+          {
+            lex->alter_info.flags|= ALTER_PARTITION;
+          }
         }
         partition
         ;
@@ -3027,7 +3035,7 @@
             lex->part_info= new partition_info();
             if (!lex->part_info)
             {
-              my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+              mem_alloc_error();
               YYABORT;
             }
           }
@@ -3076,7 +3084,11 @@
 part_field_item:
         ident
         {
-          Lex->part_info->part_field_list.push_back($1.str);
+          if (Lex->part_info->part_field_list.push_back($1.str))
+          {
+            mem_alloc_error();
+            YYABORT;
+          }
         }
         ;
 
@@ -3141,7 +3153,13 @@
 
 sub_part_field_item:
         ident
-        { Lex->part_info->subpart_field_list.push_back($1.str); }
+        {
+          if (Lex->part_info->subpart_field_list.push_back($1.str))
+          {
+            mem_alloc_error();
+            YYABORT;
+          }
+        }
         ;
 
 part_func_expr:
@@ -3212,17 +3230,17 @@
           partition_element *p_elem= new partition_element();
           if (!p_elem)
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_element));
+            mem_alloc_error();
             YYABORT;
           }
           part_info->curr_part_elem= p_elem;
           part_info->current_partition= p_elem;
           part_info->use_default_partitions= FALSE;
-          part_info->partitions.push_back(p_elem);
           p_elem->engine_type= DB_TYPE_UNKNOWN;
           part_info->count_curr_parts++;
         }
         part_name {}
+        opt_part_state {} 
         opt_part_values {}
         opt_part_options {}
         opt_sub_partition {}
@@ -3233,6 +3251,114 @@
         { Lex->part_info->curr_part_elem->partition_name= $1.str; }
         ;
 
+opt_part_state:
+        /* empty */
+        { 
+          LEX *lex= Lex;
+          partition_info *part_info= lex->part_info;
+          partition_element *p_elem= part_info->curr_part_elem;
+          p_elem->part_state= PART_NORMAL;
+          if (part_info->partitions.push_back(p_elem))
+          {
+            mem_alloc_error();
+            YYABORT;
+          }
+        }
+        | PART_STATE_SYM opt_equal ident_or_text
+        {
+          LEX *lex= Lex;
+          partition_info *part_info= lex->part_info;
+          partition_element *p_elem= part_info->curr_part_elem;
+          char *part_state= $3.str;
+          bool res;
+
+          if (strcmp(part_state, "PART_TO_BE_DROPPED"))
+          {
+            /*
+              This part is currently removed so we keep it in a
+              temporary list for REPAIR TABLE to be able to handle
+              failures during drop partition process.
+            */
+            if (!(res= part_info->temp_partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_TO_BE_DROPPED;
+              part_info->count_curr_parts--;
+            }
+          }
+          else if (strcmp(part_state, "PART_TO_BE_ADDED"))
+          {
+            /*
+              This part is currently being added so we keep it in a
+              temporary list for REPAIR TABLE to be able to handle
+              failures during add partition process.
+            */
+            if (!(res= part_info->temp_partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_TO_BE_ADDED;
+              part_info->count_curr_parts--;
+            }
+          }
+          else if (strcmp(part_state, "PART_TO_BE_REORGED"))
+          {
+            /*
+              This part is currently reorganised, it is still however
+              used so we keep it in the list of partitions. We do
+              however need the state to be able to handle REPAIR TABLE
+              after failures in the reorganisation process.
+            */
+            if (!(res= part_info->partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_TO_BE_REORGED;
+            }
+          }
+          else if (strcmp(part_state, "PART_REORGED_DROPPED"))
+          {
+            /*
+              This part is currently reorganised as part of a
+              COALESCE PARTITION and it will be dropped without a new
+              replacement partition after completing the reorganisation.
+            */
+            if (!(res= part_info->partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_REORGED_DROPPED;
+            }
+          }
+          else if (strcmp(part_state, "PART_CHANGED"))
+          {
+            /*
+              This part is currently split or merged as part of ADD
+              PARTITION for a hash partition or as part of COALESCE
+              PARTITION for a hash partitioned table.
+            */
+            if (!(res= part_info->partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_CHANGED;
+            }
+          }
+          else if (strcmp(part_state, "PART_IS_CHANGED"))
+          {
+            /*
+              This part has been split or merged as part of ADD
+              PARTITION for a hash partition or as part of COALESCE
+              PARTITION for a hash partitioned table.
+            */
+            if (!(res= part_info->partitions.push_back(p_elem)))
+            {
+              p_elem->part_state= PART_IS_CHANGED;
+            }
+          }
+          else
+          {
+            YYABORT;
+          }
+          if (res)
+          {
+            mem_alloc_error();
+            YYABORT;
+          }
+        }
+        ;
+        
 opt_part_values:
         /* empty */
         {
@@ -3319,13 +3445,13 @@
         part_bit_expr
         {
           longlong *value_ptr;
-          if (!(value_ptr= (longlong*)sql_alloc(sizeof(longlong))))
+          if (!(value_ptr= (longlong*)sql_alloc(sizeof(longlong))) ||
+              ((*value_ptr= $1, FALSE) ||
+     Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr)))
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(longlong));
+            mem_alloc_error();
             YYABORT;
           }
-          *value_ptr= $1;
-          Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr);
         }
         ;
 
@@ -3393,13 +3519,13 @@
           LEX *lex= Lex;
           partition_info *part_info= lex->part_info;
           partition_element *p_elem= new partition_element();
-          if (!p_elem)
+          if (!p_elem ||
+           part_info->current_partition->subpartitions.push_back(p_elem))
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_element));
+            mem_alloc_error();
             YYABORT;
           }
           part_info->curr_part_elem= p_elem;
-          part_info->current_partition->subpartitions.push_back(p_elem);
           part_info->use_default_subpartitions= FALSE;
           part_info->count_curr_subparts++;
           p_elem->engine_type= DB_TYPE_UNKNOWN;
@@ -4347,7 +4473,7 @@
 	| DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
 	| IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; }
         | alter_list
-        opt_partitioning
+          opt_partitioning
         | partitioning
 /*
@@ -4378,7 +4504,7 @@
           lex->part_info= new partition_info();
           if (!lex->part_info)
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+            mem_alloc_error();
             YYABORT;
           }
 	  lex->alter_info.flags|= ALTER_ADD_PARTITION;
@@ -4407,7 +4533,7 @@
           lex->part_info= new partition_info();
           if (!lex->part_info)
           {
-            my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+            mem_alloc_error();
             YYABORT;
           }
 	  lex->alter_info.flags|= ALTER_REORGANISE_PARTITION;
@@ -4427,7 +4553,11 @@
 alt_part_name_item:
         ident
         {
-          Lex->alter_info.partition_names.push_back($1.str);
+          if (Lex->alter_info.partition_names.push_back($1.str))
+          {
+            mem_alloc_error();
+            YYABORT;
+          }
         }
         ;
 
@@ -5278,7 +5408,9 @@
             else
             {
               $5->push_front($1);
-              $$= negate_expression(YYTHD, new Item_func_in(*$5));
+              Item_func_in *item = new Item_func_in(*$5);
+              item->negate();
+              $$= item;
             }            
           }
         | bit_expr IN_SYM in_subselect
@@ -5288,7 +5420,11 @@
 	| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
 	  { $$= new Item_func_between($1,$3,$5); }
 	| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
-	  { $$= negate_expression(YYTHD, new Item_func_between($1,$4,$6)); }
+    {
+      Item_func_between *item= new Item_func_between($1,$4,$6);
+      item->negate();
+      $$= item;
+    }
 	| bit_expr SOUNDS_SYM LIKE bit_expr
 	  { $$= new Item_func_eq(new Item_func_soundex($1),
 				 new Item_func_soundex($4)); }
@@ -6182,7 +6318,13 @@
         ;
 
 join_table:
-        table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); }
+        /*
+          Evaluate production 'table_ref' before 'normal_join' so that
+          [INNER | CROSS] JOIN is properly nested as other left-associative
+          joins.
+        */
+        table_ref %prec TABLE_REF_PRIORITY normal_join table_ref
+        { YYERROR_UNLESS($1 && ($$=$3)); }
 	| table_ref STRAIGHT_JOIN table_factor
 	  { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; }
 	| table_ref normal_join table_ref
@@ -8656,6 +8798,7 @@
 	| PACK_KEYS_SYM		{}
 	| PARTIAL		{}
 	| PARTITIONS_SYM	{}
+	| PART_STATE_SYM	{}
 	| PASSWORD		{}
         | PHASE_SYM             {}
 	| POINT_SYM		{}
@@ -9191,6 +9334,11 @@
 	HANDLER_SYM table_ident OPEN_SYM opt_table_alias
 	{
 	  LEX *lex= Lex;
+	  if (lex->sphead)
+	  {
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+	    YYABORT;
+	  }
 	  lex->sql_command = SQLCOM_HA_OPEN;
 	  if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
 	    YYABORT;
@@ -9198,6 +9346,11 @@
 	| HANDLER_SYM table_ident_nodb CLOSE_SYM
 	{
 	  LEX *lex= Lex;
+	  if (lex->sphead)
+	  {
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+	    YYABORT;
+	  }
 	  lex->sql_command = SQLCOM_HA_CLOSE;
 	  if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
 	    YYABORT;
@@ -9205,6 +9358,11 @@
 	| HANDLER_SYM table_ident_nodb READ_SYM
 	{
 	  LEX *lex=Lex;
+	  if (lex->sphead)
+	  {
+	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
+	    YYABORT;
+	  }
 	  lex->sql_command = SQLCOM_HA_READ;
 	  lex->ha_rkey_mode= HA_READ_KEY_EXACT;	/* Avoid purify warnings */
 	  lex->current_select->select_limit= new Item_int((int32) 1);

--- 1.24/mysql-test/r/ndb_autodiscover.result	2005-07-21 15:33:38 +02:00
+++ 1.25/mysql-test/r/ndb_autodiscover.result	2005-09-13 14:15:54 +02:00
@@ -99,6 +99,8 @@
 id2 int not null,
 name char(20)
 ) engine=ndb;
+Warnings:
+Note	1050	Table 't3' already exists
 show status like 'handler_discover%';
 Variable_name	Value
 Handler_discover	0

--- 1.6/storage/ndb/include/kernel/signaldata/BackupImpl.hpp	2005-04-29 16:30:20 +02:00
+++ 1.7/storage/ndb/include/kernel/signaldata/BackupImpl.hpp	2005-09-13 14:16:09 +02:00
@@ -34,7 +34,7 @@
 
   friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
 public:
-  STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size);
+  STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
 
 private:
   /**
@@ -61,6 +61,13 @@
    * Length of backup data
    */
   Uint32 backupDataLen;
+
+  /**
+   * Backup flags
+   */
+  /* & 0x3 - waitCompleted
+   */
+  Uint32 flags;
 };
 
 class DefineBackupRef {

--- 1.49/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2005-09-11 21:14:31 +02:00
+++ 1.50/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2005-09-13 14:16:10 +02:00
@@ -71,6 +71,9 @@
 
 static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
 
+#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
+#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
+
 void
 Backup::execSTTOR(Signal* signal) 
 {
@@ -868,23 +871,24 @@
   const Uint32 senderData = req->senderData;
   const BlockReference senderRef = signal->senderBlockRef();
   const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
-  
+  const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
+
   if(getOwnNodeId() != getMasterNodeId()) {
     jam();
-    sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
+    sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
     return;
   }//if
 
   if (m_diskless)
   {
-    sendBackupRef(senderRef, signal, senderData, 
+    sendBackupRef(senderRef, flags, signal, senderData, 
 		  BackupRef::CannotBackupDiskless);
     return;
   }
   
   if(dataLen32 != 0) {
     jam();
-    sendBackupRef(senderRef, signal, senderData, 
+    sendBackupRef(senderRef, flags, signal, senderData, 
 		  BackupRef::BackupDefinitionNotImplemented);
     return;
   }//if
@@ -899,7 +903,7 @@
   c_backups.seize(ptr);
   if(ptr.i == RNIL) {
     jam();
-    sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord);
+    sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
     return;
   }//if
 
@@ -910,6 +914,7 @@
   ptr.p->errorCode = 0;
   ptr.p->clientRef = senderRef;
   ptr.p->clientData = senderData;
+  ptr.p->flags = flags;
   ptr.p->masterRef = reference();
   ptr.p->nodes = c_aliveNodes;
   ptr.p->backupId = 0;
@@ -947,20 +952,23 @@
 Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
 {
   jam();
-  sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode);
+  sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
   cleanup(signal, ptr);
 }
 
 void
-Backup::sendBackupRef(BlockReference senderRef, Signal *signal,
+Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
 		      Uint32 senderData, Uint32 errorCode)
 {
   jam();
-  BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
-  ref->senderData = senderData;
-  ref->errorCode = errorCode;
-  ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
-  sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+  if (SEND_BACKUP_STARTED_FLAG(flags))
+  {
+    BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
+    ref->senderData = senderData;
+    ref->errorCode = errorCode;
+    ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
+    sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
+  }
 
   if(errorCode != BackupRef::IAmNotMaster){
     signal->theData[0] = NDB_LE_BackupFailedToStart;
@@ -1114,6 +1122,7 @@
   req->backupKey[1] = ptr.p->backupKey[1];
   req->nodes = ptr.p->nodes;
   req->backupDataLen = ptr.p->backupDataLen;
+  req->flags = ptr.p->flags;
   
   ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
   ptr.p->masterData.sendCounter = ptr.p->nodes;
@@ -1209,13 +1218,18 @@
   /**
    * Reply to client
    */
-  BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
-  conf->backupId = ptr.p->backupId;
-  conf->senderData = ptr.p->clientData;
-  conf->nodes = ptr.p->nodes;
-  sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal, 
-	     BackupConf::SignalLength, JBB);
-  
+  CRASH_INSERTION((10034));
+
+  if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
+  {
+    BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
+    conf->backupId = ptr.p->backupId;
+    conf->senderData = ptr.p->clientData;
+    conf->nodes = ptr.p->nodes;
+    sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal, 
+	       BackupConf::SignalLength, JBB);
+  }
+
   signal->theData[0] = NDB_LE_BackupStarted;
   signal->theData[1] = ptr.p->clientRef;
   signal->theData[2] = ptr.p->backupId;
@@ -2097,19 +2111,22 @@
   
   if(!ptr.p->checkError())
   {
-    BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
-    rep->backupId = ptr.p->backupId;
-    rep->senderData = ptr.p->clientData;
-    rep->startGCP = ptr.p->startGCP;
-    rep->stopGCP = ptr.p->stopGCP;
-    rep->noOfBytes = ptr.p->noOfBytes;
-    rep->noOfRecords = ptr.p->noOfRecords;
-    rep->noOfLogBytes = ptr.p->noOfLogBytes;
-    rep->noOfLogRecords = ptr.p->noOfLogRecords;
-    rep->nodes = ptr.p->nodes;
-    sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
-	       BackupCompleteRep::SignalLength, JBB);
-    
+    if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+    {
+      BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
+      rep->backupId = ptr.p->backupId;
+      rep->senderData = ptr.p->clientData;
+      rep->startGCP = ptr.p->startGCP;
+      rep->stopGCP = ptr.p->stopGCP;
+      rep->noOfBytes = ptr.p->noOfBytes;
+      rep->noOfRecords = ptr.p->noOfRecords;
+      rep->noOfLogBytes = ptr.p->noOfLogBytes;
+      rep->noOfLogRecords = ptr.p->noOfLogRecords;
+      rep->nodes = ptr.p->nodes;
+      sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
+		 BackupCompleteRep::SignalLength, JBB);
+    }
+
     signal->theData[0] = NDB_LE_BackupCompleted;
     signal->theData[1] = ptr.p->clientRef;
     signal->theData[2] = ptr.p->backupId;
@@ -2146,13 +2163,15 @@
     return;
   }
 
-  BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
-  rep->backupId = ptr.p->backupId;
-  rep->senderData = ptr.p->clientData;
-  rep->reason = ptr.p->errorCode;
-  sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, 
-	     BackupAbortRep::SignalLength, JBB);
-  
+  if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
+  {
+    BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
+    rep->backupId = ptr.p->backupId;
+    rep->senderData = ptr.p->clientData;
+    rep->reason = ptr.p->errorCode;
+    sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, 
+	       BackupAbortRep::SignalLength, JBB);
+  }
   signal->theData[0] = NDB_LE_BackupAborted;
   signal->theData[1] = ptr.p->clientRef;
   signal->theData[2] = ptr.p->backupId;
@@ -2305,6 +2324,13 @@
   ptr.p->errorCode = 0;
   ptr.p->clientRef = req->clientRef;
   ptr.p->clientData = req->clientData;
+  if(senderRef == reference())
+    ptr.p->flags = req->flags;
+  else
+    ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
+						 * as non master should never
+						 * reply
+						 */
   ptr.p->masterRef = senderRef;
   ptr.p->nodes = req->nodes;
   ptr.p->backupId = backupId;

--- 1.17/storage/ndb/src/kernel/blocks/backup/Backup.hpp	2005-07-25 10:30:27 +02:00
+++ 1.18/storage/ndb/src/kernel/blocks/backup/Backup.hpp	2005-09-13 14:16:10 +02:00
@@ -425,6 +425,7 @@
     
     Uint32 clientRef;
     Uint32 clientData;
+    Uint32 flags;
     Uint32 backupId;
     Uint32 backupKey[2];
     Uint32 masterRef;
@@ -609,7 +610,7 @@
   
   bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
   void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);
-  void sendBackupRef(BlockReference ref, Signal *signal,
+  void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
 		     Uint32 senderData, Uint32 errorCode);
   void dumpUsedResources();
   void cleanup(Signal*, BackupRecordPtr ptr);

--- 1.52/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2005-09-06 12:58:32 +02:00
+++ 1.53/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2005-09-13 14:16:10 +02:00
@@ -91,6 +91,17 @@
 #define ZCURR_PAGE_INDEX 8
 #define ZLAST_LOG_PREP_REF 10
 #define ZPOS_DIRTY 11
+/* A number of debug items written in the page header of all log files */
+#define ZPOS_LOG_TIMER 12
+#define ZPOS_PAGE_I 13
+#define ZPOS_PLACE_WRITTEN_FROM 14
+#define ZPOS_PAGE_NO 15
+#define ZPOS_PAGE_FILE_NO 16
+#define ZPOS_WORD_WRITTEN 17
+#define ZPOS_IN_WRITING 18
+#define ZPOS_PREV_PAGE_NO 19
+#define ZPOS_IN_FREE_LIST 20
+
 /* ------------------------------------------------------------------------- */
 /*       CONSTANTS FOR THE VARIOUS REPLICA AND NODE TYPES.                   */
 /* ------------------------------------------------------------------------- */
@@ -2240,7 +2251,7 @@
 			  const LogPartRecordPtr &sltLogPartPtr);
   void checkGcpCompleted(Signal* signal, Uint32 pageWritten, Uint32 wordWritten);
   void initFsopenconf(Signal* signal);
-  void initFsrwconf(Signal* signal);
+  void initFsrwconf(Signal* signal, bool write);
   void initLfo(Signal* signal);
   void initLogfile(Signal* signal, Uint32 fileNo);
   void initLogpage(Signal* signal);
@@ -2256,7 +2267,8 @@
   void writeFileDescriptor(Signal* signal);
   void writeFileHeaderOpen(Signal* signal, Uint32 type);
   void writeInitMbyte(Signal* signal);
-  void writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten);
+  void writeSinglePage(Signal* signal, Uint32 pageNo,
+                       Uint32 wordWritten, Uint32 place);
   void buildLinkedLogPageList(Signal* signal);
   void changeMbyte(Signal* signal);
   Uint32 checkIfExecLog(Signal* signal);
@@ -2265,7 +2277,7 @@
   void checkScanTcCompleted(Signal* signal);
   void checkSrCompleted(Signal* signal);
   void closeFile(Signal* signal, LogFileRecordPtr logFilePtr);
-  void completedLogPage(Signal* signal, Uint32 clpType);
+  void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place);
   void deleteFragrec(Uint32 fragId);
   void deleteTransidHash(Signal* signal);
   void findLogfile(Signal* signal,
@@ -2359,7 +2371,9 @@
   void writeAbortLog(Signal* signal);
   void writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
   void writeCompletedGciLog(Signal* signal);
-  void writeDirty(Signal* signal);
+  void writeDbgInfoPageHeader(LogPageRecordPtr logPagePtr, Uint32 place,
+                              Uint32 pageNo, Uint32 wordWritten);
+  void writeDirty(Signal* signal, Uint32 place);
   void writeKey(Signal* signal);
   void writeLogHeader(Signal* signal);
   void writeLogWord(Signal* signal, Uint32 data);

--- 1.98/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2005-09-08 18:20:14 +02:00
+++ 1.99/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2005-09-13 14:18:50 +02:00
@@ -11022,42 +11022,34 @@
     ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
     exitFromInvalidate(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_INIT:
     jam();
     closingInitLab(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_SR:
     jam();
     closingSrLab(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_EXEC_SR:
     jam();
     closeExecSrLab(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_EXEC_SR_COMPLETED:
     jam();
     closeExecSrCompletedLab(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_WRITE_LOG:
     jam();
     closeWriteLogLab(signal);
     return;
-    break;
   case LogFileRecord::CLOSING_EXEC_LOG:
     jam();
     closeExecLogLab(signal);
     return;
-    break;
   default:
     jam();
     systemErrorLab(signal);
     return;
-    break;
   }//switch
 }//Dblqh::execFSCLOSECONF()
 
@@ -11075,77 +11067,64 @@
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     readFileInInvalidate(signal);
     return;
-    break;
   case LogFileRecord::OPENING_INIT:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openFileInitLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_FRONTPAGE:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrFrontpageLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_LAST_FILE:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrLastFileLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_NEXT_FILE:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrNextFileLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_EXEC_SR_START:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openExecSrStartLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_EXEC_SR_NEW_MBYTE:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openExecSrNewMbyteLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_FOURTH_PHASE:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrFourthPhaseLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_FOURTH_NEXT:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrFourthNextLab(signal);
     return;
-    break;
   case LogFileRecord::OPEN_SR_FOURTH_ZERO:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openSrFourthZeroLab(signal);
     return;
-    break;
   case LogFileRecord::OPENING_WRITE_LOG:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     return;
-    break;
   case LogFileRecord::OPEN_EXEC_LOG:
     jam();
     logFilePtr.p->logFileStatus = LogFileRecord::OPEN;
     openExecLogLab(signal);
     return;
-    break;
   default:
     jam();
     systemErrorLab(signal);
     return;
-    break;
   }//switch
 }//Dblqh::execFSOPENCONF()
 
@@ -11156,7 +11135,7 @@
 void Dblqh::execFSREADCONF(Signal* signal) 
 {
   jamEntry();
-  initFsrwconf(signal);
+  initFsrwconf(signal, false);
 
   switch (lfoPtr.p->lfoState) {
   case LogFileOperationRecord::READ_SR_LAST_MBYTE:
@@ -11164,57 +11143,47 @@
     releaseLfo(signal);
     readSrLastMbyteLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_FRONTPAGE:
     jam();
     releaseLfo(signal);
     readSrFrontpageLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_LAST_FILE:
     jam();
     releaseLfo(signal);
     readSrLastFileLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_NEXT_FILE:
     jam();
     releaseLfo(signal);
     readSrNextFileLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_EXEC_SR:
     jam();
     readExecSrLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_EXEC_LOG:
     jam();
     readExecLogLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES:
     jam();
     invalidateLogAfterLastGCI(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_FOURTH_PHASE:
     jam();
     releaseLfo(signal);
     readSrFourthPhaseLab(signal);
     return;
-    break;
   case LogFileOperationRecord::READ_SR_FOURTH_ZERO:
     jam();
     releaseLfo(signal);
     readSrFourthZeroLab(signal);
     return;
-    break;
   default:
     jam();
     systemErrorLab(signal);
     return;
-    break;
   }//switch
 }//Dblqh::execFSREADCONF()
 
@@ -11271,63 +11240,52 @@
 void Dblqh::execFSWRITECONF(Signal* signal) 
 {
   jamEntry();
-  initFsrwconf(signal);
+  initFsrwconf(signal, true);
   switch (lfoPtr.p->lfoState) {
   case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
     jam();
     invalidateLogAfterLastGCI(signal);
     return;
-    break;
   case LogFileOperationRecord::WRITE_PAGE_ZERO:
     jam();
     writePageZeroLab(signal);
     return;
-    break;
   case LogFileOperationRecord::LAST_WRITE_IN_FILE:
     jam();
     lastWriteInFileLab(signal);
     return;
-    break;
   case LogFileOperationRecord::INIT_WRITE_AT_END:
     jam();
     initWriteEndLab(signal);
     return;
-    break;
   case LogFileOperationRecord::INIT_FIRST_PAGE:
     jam();
     initFirstPageLab(signal);
     return;
-    break;
   case LogFileOperationRecord::WRITE_GCI_ZERO:
     jam();
     writeGciZeroLab(signal);
     return;
-    break;
   case LogFileOperationRecord::WRITE_DIRTY:
     jam();
     writeDirtyLab(signal);
     return;
-    break;
   case LogFileOperationRecord::WRITE_INIT_MBYTE:
     jam();
     writeInitMbyteLab(signal);
     return;
-    break;
   case LogFileOperationRecord::ACTIVE_WRITE_LOG:
     jam();
     writeLogfileLab(signal);
     return;
-    break;
   case LogFileOperationRecord::FIRST_PAGE_WRITE_IN_LOGFILE:
     jam();
     firstPageWriteLab(signal);
     return;
-    break;
   default:
     jam();
     systemErrorLab(signal);
     return;
-    break;
   }//switch
 }//Dblqh::execFSWRITECONF()
 
@@ -11403,16 +11361,35 @@
 /* =======       INITIATE WHEN RECEIVING FSREADCONF AND FSWRITECONF  ======= */
 /*                                                                           */
 /* ========================================================================= */
-void Dblqh::initFsrwconf(Signal* signal) 
+void Dblqh::initFsrwconf(Signal* signal, bool write) 
 {
+  LogPageRecordPtr logP;
+  Uint32 noPages, totPages;
   lfoPtr.i = signal->theData[0];
   ptrCheckGuard(lfoPtr, clfoFileSize, logFileOperationRecord);
+  totPages= lfoPtr.p->noPagesRw;
   logFilePtr.i = lfoPtr.p->logFileRec;
   ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
   logPartPtr.i = logFilePtr.p->logPartRec;
   ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
   logPagePtr.i = lfoPtr.p->firstLfoPage;
   ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
+  logP= logPagePtr;
+  noPages= 1;
+  ndbassert(totPages > 0);
+  for (;;)
+  {
+    logP.p->logPageWord[ZPOS_IN_WRITING]= 0;
+    logP.p->logPageWord[ZPOS_IN_FREE_LIST]= 0;
+    if (noPages == totPages)
+      return;
+    if (write)
+      logP.i= logP.p->logPageWord[ZNEXT_PAGE];
+    else
+      logP.i= lfoPtr.p->logPageArray[noPages];
+    ptrCheckGuard(logP, clogPageFileSize, logPageRecord);
+    noPages++;
+  }
 }//Dblqh::initFsrwconf()
 
 /* ######################################################################### */
@@ -11500,7 +11477,7 @@
         ndbrequire(wordWritten < ZPAGE_SIZE);
         if (logFilePtr.p->noLogpagesInBuffer > 0) {
           jam();
-          completedLogPage(signal, ZENFORCE_WRITE);
+          completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
 /*---------------------------------------------------------------------------*/
 /*SINCE WE ARE ONLY WRITING PART OF THE LAST PAGE WE HAVE TO UPDATE THE WORD */
 /*WRITTEN TO REFLECT THE REAL LAST WORD WRITTEN. WE ALSO HAVE TO MOVE THE    */
@@ -11522,7 +11499,8 @@
             releaseLogpage(signal);
           } else {
             jam();
-            writeSinglePage(signal, logFilePtr.p->currentFilepage, wordWritten);
+            writeSinglePage(signal, logFilePtr.p->currentFilepage,
+                            wordWritten, __LINE__);
             lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG;
           }//if
         }//if
@@ -11658,7 +11636,7 @@
       logPagePtr.i = logFilePtr.p->logPageZero;
       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
       logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
-      writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+      writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
       lfoPtr.p->logFileRec = currLogFile;
       lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
       return;
@@ -11747,7 +11725,7 @@
       logPagePtr.i = logFilePtr.p->logPageZero;
       ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
       logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = fileNo;
-      writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+      writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
       lfoPtr.p->logFileRec = currLogFile;
       lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_PAGE_ZERO;
       return;
@@ -11798,7 +11776,8 @@
 {
   logFilePtr.p->logFileStatus = LogFileRecord::OPEN_INIT;
   seizeLogpage(signal);
-  writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1, ZPAGE_SIZE - 1);
+  writeSinglePage(signal, (ZNO_MBYTES_IN_FILE * ZPAGES_IN_MBYTE) - 1,
+                  ZPAGE_SIZE - 1, __LINE__);
   lfoPtr.p->lfoState = LogFileOperationRecord::INIT_WRITE_AT_END;
   return;
 }//Dblqh::openFileInitLab()
@@ -11839,7 +11818,7 @@
     logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 1;
     logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE] = ZCOMPLETED_GCI_TYPE;
     logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + 1] = 1;
-    writeSinglePage(signal, 1, ZPAGE_SIZE - 1);
+    writeSinglePage(signal, 1, ZPAGE_SIZE - 1, __LINE__);
     lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_GCI_ZERO;
     return;
   }//if
@@ -12141,17 +12120,13 @@
 {
 #ifdef VM_TRACE
   // Check that log page isn't already in free list
-  LogPageRecordPtr TlogPagePtr;
-  TlogPagePtr.i = cfirstfreeLogPage;
-  while (TlogPagePtr.i != RNIL){
-    ptrCheckGuard(TlogPagePtr, clogPageFileSize, logPageRecord);
-    ndbrequire(TlogPagePtr.i != logPagePtr.i);
-    TlogPagePtr.i = TlogPagePtr.p->logPageWord[ZNEXT_PAGE];
-  }
+  ndbrequire(logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] == 0);
 #endif
 
   cnoOfLogPages++;
   logPagePtr.p->logPageWord[ZNEXT_PAGE] = cfirstfreeLogPage;
+  logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
+  logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
   cfirstfreeLogPage = logPagePtr.i;
 }//Dblqh::releaseLogpage()
 
@@ -12197,6 +12172,7 @@
 /* ------------------------------------------------------------------------- */
   cfirstfreeLogPage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
   logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
+  logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST] = 0;
 }//Dblqh::seizeLogpage()
 
 /* ------------------------------------------------------------------------- */
@@ -12304,7 +12280,7 @@
 /*       LOG FILE. THIS HAS SPECIAL SIGNIFANCE TO FIND     */
 /*       THE END OF THE LOG AT SYSTEM RESTART.             */
 /* ------------------------------------------------------- */
-  writeSinglePage(signal, 0, ZPAGE_SIZE - 1);
+  writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__);
   if (wmoType == ZINIT) {
     jam();
     lfoPtr.p->lfoState = LogFileOperationRecord::INIT_FIRST_PAGE;
@@ -12338,7 +12314,8 @@
 void Dblqh::writeInitMbyte(Signal* signal) 
 {
   initLogpage(signal);
-  writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE, ZPAGE_SIZE - 1);
+  writeSinglePage(signal, logFilePtr.p->currentMbyte * ZPAGES_IN_MBYTE,
+                  ZPAGE_SIZE - 1, __LINE__);
   lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_INIT_MBYTE;
 }//Dblqh::writeInitMbyte()
 
@@ -12348,13 +12325,15 @@
 /*       INPUT:          TWSP_PAGE_NO    THE PAGE NUMBER WRITTEN             */
 /*       SUBROUTINE SHORT NAME:  WSP                                         */
 /* ------------------------------------------------------------------------- */
-void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo, Uint32 wordWritten) 
+void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo,
+                            Uint32 wordWritten, Uint32 place) 
 {
   seizeLfo(signal);
   initLfo(signal);
   lfoPtr.p->firstLfoPage = logPagePtr.i;
   logPagePtr.p->logPageWord[ZNEXT_PAGE] = RNIL;
 
+  writeDbgInfoPageHeader(logPagePtr, place, pageNo, wordWritten);
   // Calculate checksum for page
   logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
 
@@ -13717,7 +13696,7 @@
 	 *  IN THIS WE HAVE COMPLETED EXECUTION OF THE CURRENT LOG PAGE
 	 *  AND CAN WRITE IT TO DISK SINCE IT IS DIRTY.
 	 * ----------------------------------------------------------------- */
-        writeDirty(signal);
+        writeDirty(signal, __LINE__);
         return;
         break;
       case LogPartRecord::LES_EXEC_LOG:
@@ -13728,7 +13707,7 @@
        * ------------------------------------------------------------------- */
         if (logFilePtr.p->currentLogpage != logPartPtr.p->prevLogpage) {
           jam();
-          writeDirty(signal);
+          writeDirty(signal, __LINE__);
           return;
         }//if
         break;
@@ -14172,7 +14151,8 @@
       // This page must be invalidated.
       logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 0;
       // Contact NDBFS. Real time break.
-      writeSinglePage(signal, logPartPtr.p->invalidatePageNo, ZPAGE_SIZE - 1);
+      writeSinglePage(signal, logPartPtr.p->invalidatePageNo,
+                      ZPAGE_SIZE - 1, __LINE__);
       lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES;
     } else {
       // We are done with invalidating. Finish start phase 3.4. 
@@ -15095,7 +15075,7 @@
 // logPartPtr
 // Defines lfoPtr
 /* ---------------------------------------------------------------- */
-void Dblqh::completedLogPage(Signal* signal, Uint32 clpType) 
+void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place) 
 {
   LogPageRecordPtr clpLogPagePtr;
   LogPageRecordPtr wlpLogPagePtr;
@@ -15138,6 +15118,9 @@
     twlpNoPages++;
     ptrCheckGuard(wlpLogPagePtr, clogPageFileSize, logPageRecord);
 
+    writeDbgInfoPageHeader(wlpLogPagePtr, place,
+                           logFilePtr.p->filePosition + twlpNoPages - 1,
+                           ZPAGE_SIZE);
     // Calculate checksum for page
     wlpLogPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(wlpLogPagePtr);
     wlpLogPagePtr.i = wlpLogPagePtr.p->logPageWord[ZNEXT_PAGE];
@@ -15510,6 +15493,8 @@
       refresh_watch_dog();
       ptrAss(logPagePtr, logPageRecord);
       logPagePtr.p->logPageWord[ZNEXT_PAGE] = logPagePtr.i + 1;
+      logPagePtr.p->logPageWord[ZPOS_IN_FREE_LIST]= 1;
+      logPagePtr.p->logPageWord[ZPOS_IN_WRITING]= 0;
     }//for
     logPagePtr.i = clogPageFileSize - 1;
     ptrAss(logPagePtr, logPageRecord);
@@ -17018,10 +17003,14 @@
  * 
  *     SUBROUTINE SHORT NAME: WD
  * ------------------------------------------------------------------------- */
-void Dblqh::writeDirty(Signal* signal) 
+void Dblqh::writeDirty(Signal* signal, Uint32 place) 
 {
   logPagePtr.p->logPageWord[ZPOS_DIRTY] = ZNOT_DIRTY;
 
+  ndbassert(logPartPtr.p->prevFilepage ==
+            logPagePtr.p->logPageWord[ZPOS_PAGE_NO]);
+  writeDbgInfoPageHeader(logPagePtr, place, logPartPtr.p->prevFilepage,
+                         ZPAGE_SIZE);
   // Calculate checksum for page
   logPagePtr.p->logPageWord[ZPOS_CHECKSUM] = calcPageCheckSum(logPagePtr);
 
@@ -17055,7 +17044,7 @@
   logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = logPos + 1;
   if ((logPos + 1) == ZPAGE_SIZE) {
     jam();
-    completedLogPage(signal, ZNORMAL);
+    completedLogPage(signal, ZNORMAL, __LINE__);
     seizeLogpage(signal);
     initLogpage(signal);
     logFilePtr.p->currentLogpage = logPagePtr.i;
@@ -17113,7 +17102,7 @@
 /* -------------------------------------------------- */
 /*       WE HAVE TO CHANGE LOG FILE                   */
 /* -------------------------------------------------- */
-    completedLogPage(signal, ZLAST_WRITE_IN_FILE);
+    completedLogPage(signal, ZLAST_WRITE_IN_FILE, __LINE__);
     if (wnlNextLogFilePtr.p->fileNo == 0) {
       jam();
 /* -------------------------------------------------- */
@@ -17132,7 +17121,7 @@
 /*       INCREMENT THE CURRENT MBYTE                  */
 /*       SET PAGE INDEX TO PAGE HEADER SIZE           */
 /* -------------------------------------------------- */
-    completedLogPage(signal, ZENFORCE_WRITE);
+    completedLogPage(signal, ZENFORCE_WRITE, __LINE__);
     twnlNewMbyte = logFilePtr.p->currentMbyte + 1;
   }//if
 /* -------------------------------------------------- */
@@ -17735,6 +17724,19 @@
 #endif
     return checkSum;  
   }
+
+void Dblqh::writeDbgInfoPageHeader(LogPageRecordPtr logP, Uint32 place,
+                                   Uint32 pageNo, Uint32 wordWritten)
+{
+  logP.p->logPageWord[ZPOS_LOG_TIMER]= logPartPtr.p->logTimer;
+  logP.p->logPageWord[ZPOS_PREV_PAGE_NO]= logP.p->logPageWord[ZPOS_PAGE_NO];
+  logP.p->logPageWord[ZPOS_PAGE_I]= logP.i;
+  logP.p->logPageWord[ZPOS_PLACE_WRITTEN_FROM]= place;
+  logP.p->logPageWord[ZPOS_PAGE_NO]= pageNo;
+  logP.p->logPageWord[ZPOS_PAGE_FILE_NO]= logFilePtr.p->fileNo;
+  logP.p->logPageWord[ZPOS_WORD_WRITTEN]= wordWritten;
+  logP.p->logPageWord[ZPOS_IN_WRITING]= 1;
+}
 
 #ifdef NDB_DEBUG_FULL
 #ifdef ERROR_INSERT

--- 1.52/storage/ndb/src/mgmapi/mgmapi.cpp	2005-08-27 07:49:59 +02:00
+++ 1.53/storage/ndb/src/mgmapi/mgmapi.cpp	2005-09-13 14:16:11 +02:00
@@ -678,12 +678,10 @@
   Vector<BaseString> split;
   tmp.split(split, ":");
   if(split.size() != 2){
-    abort();
     return NULL;
   }
  
   if(!(split[0].trim() == "nodes")){
-    abort();
     return NULL;
   }
 
@@ -731,7 +729,6 @@
 
   if(i+1 != noOfNodes){
     free(state);
-    abort();
     return NULL;
   }
 

--- 1.48/storage/ndb/src/ndbapi/NdbTransaction.cpp	2005-06-13 15:24:53 +02:00
+++ 1.49/storage/ndb/src/ndbapi/NdbTransaction.cpp	2005-09-13 14:16:11 +02:00
@@ -264,6 +264,7 @@
 		       AbortOption abortOption,
 		       int forceSend)
 {
+  NdbError savedError= theError;
   DBUG_ENTER("NdbTransaction::execute");
   DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", 
 		       aTypeOfExec, abortOption));
@@ -293,7 +294,11 @@
         NdbBlob* tBlob = tPrepOp->theBlobList;
         while (tBlob != NULL) {
           if (tBlob->preExecute(tExecType, batch) == -1)
+	  {
             ret = -1;
+	    if(savedError.code==0)
+	      savedError= theError;
+	  }
           tBlob = tBlob->theNext;
         }
         if (batch) {
@@ -322,7 +327,11 @@
           NdbBlob* tBlob = tOp->theBlobList;
           while (tBlob != NULL) {
             if (tBlob->preCommit() == -1)
-              ret = -1;
+	    {
+	      ret = -1;
+	      if(savedError.code==0)
+		savedError= theError;
+	    }
             tBlob = tBlob->theNext;
           }
         }
@@ -344,7 +353,12 @@
     }
 
     if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
-        ret = -1;
+    {
+      ret = -1;
+      if(savedError.code==0)
+	savedError= theError;
+    }
+
 #ifdef ndb_api_crash_on_complex_blob_abort
     assert(theFirstOpInList == NULL && theLastOpInList == NULL);
 #else
@@ -359,7 +373,11 @@
           while (tBlob != NULL) {
             // may add new operations if batch
             if (tBlob->postExecute(tExecType) == -1)
+	    {
               ret = -1;
+	      if(savedError.code==0)
+		savedError= theError;
+	    }
             tBlob = tBlob->theNext;
           }
         }
@@ -390,6 +408,10 @@
     ndbout << "completed ops: " << n << endl;
   }
 #endif
+
+  if(savedError.code!=0 && theError.code==4350) // Trans already aborted
+      theError= savedError;
+
   DBUG_RETURN(ret);
 }
 

--- 1.149/sql/ha_ndbcluster.cc	2005-09-06 12:58:28 +02:00
+++ 1.150/sql/ha_ndbcluster.cc	2005-09-13 14:15:58 +02:00
@@ -6596,13 +6596,24 @@
           case Item_func::BETWEEN:
           {
             DBUG_PRINT("info", ("BETWEEN, rewriting using AND"));
+            Item_func_between *between_func= (Item_func_between *) func_item;
             Ndb_rewrite_context *rewrite_context= 
               new Ndb_rewrite_context(func_item);
             rewrite_context->next= context->rewrite_stack;
             context->rewrite_stack= rewrite_context;
+            if (between_func->negated)
+            {
+              DBUG_PRINT("info", ("NOT_FUNC"));
+              curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1);
+              prev_cond= curr_cond;
+              curr_cond= context->cond_ptr= new Ndb_cond();
+              curr_cond->prev= prev_cond;
+              prev_cond->next= curr_cond;
+            }
             DBUG_PRINT("info", ("COND_AND_FUNC"));
-            curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC, 
-                                              func_item->argument_count() - 1);
+            curr_cond->ndb_item= 
+              new Ndb_item(Item_func::COND_AND_FUNC, 
+                           func_item->argument_count() - 1);
             context->expect_only(Item::FIELD_ITEM);
             context->expect(Item::INT_ITEM);
             context->expect(Item::STRING_ITEM);
@@ -6613,10 +6624,20 @@
           case Item_func::IN_FUNC:
           {
             DBUG_PRINT("info", ("IN_FUNC, rewriting using OR"));
+            Item_func_in *in_func= (Item_func_in *) func_item;
             Ndb_rewrite_context *rewrite_context= 
               new Ndb_rewrite_context(func_item);
             rewrite_context->next= context->rewrite_stack;
             context->rewrite_stack= rewrite_context;
+            if (in_func->negated)
+            {
+              DBUG_PRINT("info", ("NOT_FUNC"));
+              curr_cond->ndb_item= new Ndb_item(Item_func::NOT_FUNC, 1);
+              prev_cond= curr_cond;
+              curr_cond= context->cond_ptr= new Ndb_cond();
+              curr_cond->prev= prev_cond;
+              prev_cond->next= curr_cond;
+            }
             DBUG_PRINT("info", ("COND_OR_FUNC"));
             curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC, 
                                               func_item->argument_count() - 1);
@@ -6938,6 +6959,7 @@
           DBUG_PRINT("info", ("End of condition group"));
           prev_cond= curr_cond;
           curr_cond= context->cond_ptr= new Ndb_cond();
+          curr_cond->prev= prev_cond;
           prev_cond->next= curr_cond;
           curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
           // Pop rewrite stack
Thread
bk commit into 5.1 tree (mronstrom:1.2001)mikael13 Sep