=== added directory '.bzr-mysql'
=== added file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	1970-01-01 00:00:00 +0000
+++ b/.bzr-mysql/default.conf	2008-06-03 15:55:53 +0000
@@ -0,0 +1,3 @@
+[MYSQL]
+post_commit_to = commits@lists.mysql.com
+tree_name = mysql-5.1-telco-6.2-merge

=== modified file 'client/mysqltest.c'
--- a/client/mysqltest.c	2008-05-06 13:37:36 +0000
+++ b/client/mysqltest.c	2008-06-03 15:55:53 +0000
@@ -67,7 +67,8 @@
 enum {
   OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
   OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
-  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES
+  OPT_MAX_CONNECT_RETRIES, OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
+  OPT_RESULT_FORMAT_VERSION
 };
 
 static int record= 0, opt_sleep= -1;
@@ -77,6 +78,7 @@
 const char *opt_include= 0, *opt_charsets_dir;
 static int opt_port= 0;
 static int opt_max_connect_retries;
+static int opt_result_format_version;
 static my_bool opt_compress= 0, silent= 0, verbose= 0;
 static my_bool debug_info_flag= 0, debug_check_flag= 0;
 static my_bool tty_password= 0;
@@ -268,10 +270,12 @@
   Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP,
   Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
   Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
+  Q_RESULT_FORMAT_VERSION,
 
   Q_UNKNOWN,			       /* Unknown command.   */
   Q_COMMENT,			       /* Comments, ignored. */
-  Q_COMMENT_WITH_COMMAND
+  Q_COMMENT_WITH_COMMAND,
+  Q_EMPTY_LINE
 };
 
 
@@ -359,6 +363,7 @@
   "change_user",
   "mkdir",
   "rmdir",
+  "result_format",
 
   0
 };
@@ -1994,6 +1999,59 @@
 }
 
 
+static void
+set_result_format_version(ulong new_version)
+{
+  switch (new_version){
+  case 1:
+    /* The first format */
+    break;
+  case 2:
+    /* New format that also writes comments and empty lines
+       from test file to result */
+    break;
+  default:
+    die("Version format %lu has not yet been implemented", new_version);
+    break;
+  }
+  opt_result_format_version= new_version;
+}
+
+
+/*
+  Set the result format version to use when generating
+  the .result file
+*/
+
+static void
+do_result_format_version(struct st_command *command)
+{
+  long version;
+  static DYNAMIC_STRING ds_version;
+  const struct command_arg result_format_args[] = {
+    "version", ARG_STRING, TRUE, &ds_version, "Version to use",
+  };
+
+  DBUG_ENTER("do_result_format_version");
+
+  check_command_args(command, command->first_argument,
+                     result_format_args,
+                     sizeof(result_format_args)/sizeof(struct command_arg),
+                     ',');
+
+  /* Convert version  number to int */
+  if (!str2int(ds_version.str, 10, (long) 0, (long) INT_MAX, &version))
+    die("Invalid version number: '%s'", ds_version.str);
+
+  set_result_format_version(version);
+
+  dynstr_append(&ds_res, "result_format: ");
+  dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
+  dynstr_append(&ds_res, "\n");
+  dynstr_free(&ds_version);
+}
+
+
 /*
   Set variable from the result of a field in a query
 
@@ -4654,7 +4712,7 @@
 
 int read_line(char *buf, int size)
 {
-  char c, last_quote;
+  char c, last_quote, last_char= 0;
   char *p= buf, *buf_end= buf + size - 1;
   int skip_char= 0;
   enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
@@ -4753,14 +4811,24 @@
       }
       else if (my_isspace(charset_info, c))
       {
-        /* Skip all space at begining of line */
 	if (c == '\n')
         {
+          if (last_char == '\n')
+          {
+            /* Two new lines in a row, return empty line */
+            DBUG_PRINT("info", ("Found two new lines in a row"));
+            *p++= c;
+            *p= 0;
+            DBUG_RETURN(0);
+          }
+
           /* Query hasn't started yet */
 	  start_lineno= cur_file->lineno;
           DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
                               start_lineno));
         }
+
+        /* Skip all space at begining of line */
 	skip_char= 1;
       }
       else if (end_of_query(c))
@@ -4801,6 +4869,8 @@
 
     }
 
+    last_char= c;
+
     if (!skip_char)
     {
       /* Could be a multibyte character */
@@ -5046,9 +5116,10 @@
     DBUG_RETURN(1);
   }
 
-  convert_to_format_v1(read_command_buf);
+  if (opt_result_format_version == 1)
+    convert_to_format_v1(read_command_buf);
 
-  DBUG_PRINT("info", ("query: %s", read_command_buf));
+  DBUG_PRINT("info", ("query: '%s'", read_command_buf));
   if (*p == '#')
   {
     command->type= Q_COMMENT;
@@ -5058,6 +5129,10 @@
     command->type= Q_COMMENT_WITH_COMMAND;
     p+= 2; /* Skip past -- */
   }
+  else if (*p == '\n')
+  {
+    command->type= Q_EMPTY_LINE;
+  }
 
   /* Skip leading spaces */
   while (*p && my_isspace(charset_info, *p))
@@ -5150,6 +5225,11 @@
   {"result-file", 'R', "Read/Store result from/in this file.",
    (uchar**) &result_file_name, (uchar**) &result_file_name, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"result-format-version", OPT_RESULT_FORMAT_VERSION,
+   "Version of the result file format to use",
+   (uchar**) &opt_result_format_version,
+   (uchar**) &opt_result_format_version, 0,
+   GET_INT, REQUIRED_ARG, 1, 1, 2, 0, 0, 0},
   {"server-arg", 'A', "Send option value to embedded server as a parameter.",
    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"server-file", 'F', "Read embedded server arguments from file.",
@@ -5341,6 +5421,9 @@
     sf_malloc_quick=1;
 #endif
     break;
+  case OPT_RESULT_FORMAT_VERSION:
+    set_result_format_version(opt_result_format_version);
+    break;
   case 'V':
     print_version();
     exit(0);
@@ -7047,6 +7130,7 @@
       case Q_COPY_FILE: do_copy_file(command); break;
       case Q_CHMOD_FILE: do_chmod_file(command); break;
       case Q_PERL: do_perl(command); break;
+      case Q_RESULT_FORMAT_VERSION: do_result_format_version(command); break;
       case Q_DELIMITER:
         do_delimiter(command);
 	break;
@@ -7163,9 +7247,38 @@
 	do_sync_with_master2(0);
 	break;
       }
-      case Q_COMMENT:				/* Ignore row */
+      case Q_COMMENT:
+      {
+        const char* p= command->query;
         command->last_argument= command->end;
+
+        /* Don't output comments in v1 */
+        if (opt_result_format_version == 1)
+          break;
+
+        /* Don't output comments if query logging is off */
+        if (disable_query_log)
+          break;
+
+        /* Write comment's with two starting #'s to result file */
+        if (p && *p == '#' && *(p+1) == '#')
+        {
+          dynstr_append_mem(&ds_res, command->query, command->query_len);
+          dynstr_append(&ds_res, "\n");
+        }
 	break;
+      }
+      case Q_EMPTY_LINE:
+        /* Don't output newline in v1 */
+        if (opt_result_format_version == 1)
+          break;
+
+        /* Don't output newline if query logging is off */
+        if (disable_query_log)
+          break;
+
+        dynstr_append(&ds_res, "\n");
+        break;
       case Q_PING:
 	(void) mysql_ping(&cur_con->mysql);
 	break;

=== added file 'mysql-test/include/show_qc_status.inc'
--- a/mysql-test/include/show_qc_status.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/show_qc_status.inc	2008-05-28 14:26:26 +0000
@@ -0,0 +1,10 @@
+#
+# Retrieve the value of  'show status like "Qcache_[inserts, hits, queries]"'
+#  and display it in a minimal fashion on one line
+#
+let $_qcache_inserts= query_get_value(SHOW STATUS LIKE "Qcache_inserts", Value, 1);
+let $_qcache_hits= query_get_value(SHOW STATUS LIKE "Qcache_hits", Value, 1);
+let $_qcache_queries= query_get_value(SHOW STATUS LIKE "Qcache_queries_in_cache", Value, 1);
+echo Qcache_queries          $_qcache_queries;
+echo Qcache_inserts          $_qcache_inserts;
+echo Qcache_hits             $_qcache_hits;

=== modified file 'mysql-test/suite/ndb/r/ndb_blob.result'
--- a/mysql-test/suite/ndb/r/ndb_blob.result	2008-05-21 16:39:51 +0000
+++ b/mysql-test/suite/ndb/r/ndb_blob.result	2008-06-03 10:00:31 +0000
@@ -620,3 +620,19 @@
 Level	Code	Message
 drop table t1;
 drop table t2;
+create table t1 (
+a    int primary key,
+giga longblob) 
+engine=ndb;
+set @stuff = '1234567890';
+insert into t1 values (0, repeat(@stuff, 2000));
+select sha1(repeat(@stuff, 2000));
+sha1(repeat(@stuff, 2000))
+c8d94eb4127361ac22cf1c8a8f1178a37fb25e41
+select sha1(giga) from t1;
+sha1(giga)
+c8d94eb4127361ac22cf1c8a8f1178a37fb25e41
+select (giga = repeat(@stuff, 2000)) from t1 where a=0;
+(giga = repeat(@stuff, 2000))
+1
+drop table t1;

=== added file 'mysql-test/suite/ndb/r/ndb_cache_trans.result'
--- a/mysql-test/suite/ndb/r/ndb_cache_trans.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_cache_trans.result	2008-05-30 15:46:02 +0000
@@ -0,0 +1,317 @@
+result_format: 2
+drop table if exists t1;
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+## Turn off autocommit, instead use COMMIT after each statement
+set AUTOCOMMIT=off;
+
+## Create test table in NDB
+CREATE TABLE t1 (
+  pk int not null primary key,
+  a int,
+  b int not null,
+  c varchar(20)
+) ENGINE=ndbcluster;
+
+## Add first row
+insert into t1 value (1, 2, 3, 'First row');
+COMMIT;
+
+## Query should be inserted in qcache
+Qcache_queries          0
+Qcache_inserts          0
+Qcache_hits             0
+select * from t1;
+pk	a	b	c
+1	2	3	First row
+Qcache_queries          1
+Qcache_inserts          1
+Qcache_hits             0
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          1
+Qcache_hits             0
+
+## Perform the same query and make sure the query cache is hit
+Qcache_queries          1
+Qcache_inserts          1
+Qcache_hits             0
+select * from t1;
+pk	a	b	c
+1	2	3	First row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          1
+Qcache_hits             1
+
+## Update the table, should be no queries in cache afterwards
+update t1 set a=3 where pk=1;
+COMMIT;
+Qcache_queries          0
+Qcache_inserts          1
+Qcache_hits             1
+
+## Read row after update, should not hit the cache, but get inserted
+select * from t1;
+pk	a	b	c
+1	3	3	First row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          2
+Qcache_hits             1
+
+## Read row from cache
+select * from t1;
+pk	a	b	c
+1	3	3	First row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          2
+Qcache_hits             2
+
+## Insert two new rows, queries in cache should be zero
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+COMMIT;
+Qcache_queries          0
+Qcache_inserts          2
+Qcache_hits             2
+
+## Read the three rows, should not hit the cache
+select * from t1 order by pk;
+pk	a	b	c
+1	3	3	First row
+2	7	8	Second row
+4	5	6	Fourth row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          3
+Qcache_hits             2
+
+## Read the three rows, should now hit the cache!
+select * from t1 order by pk;
+pk	a	b	c
+1	3	3	First row
+2	7	8	Second row
+4	5	6	Fourth row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          3
+Qcache_hits             3
+
+## Two selects in the same transaction should hit cache
+select * from t1 order by pk;
+pk	a	b	c
+1	3	3	First row
+2	7	8	Second row
+4	5	6	Fourth row
+select * from t1 order by pk;
+pk	a	b	c
+1	3	3	First row
+2	7	8	Second row
+4	5	6	Fourth row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          3
+Qcache_hits             5
+
+## Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b=3;
+pk	a	b	c
+1	3	3	First row
+COMMIT;
+Qcache_queries          2
+Qcache_inserts          4
+Qcache_hits             5
+
+## Same query again...
+select * from t1 where b=3;
+pk	a	b	c
+1	3	3	First row
+COMMIT;
+Qcache_queries          2
+Qcache_inserts          4
+Qcache_hits             6
+
+## Delete from the table, should clear the cache
+delete from t1 where c='Fourth row';
+COMMIT;
+Qcache_queries          0
+Qcache_inserts          4
+Qcache_hits             6
+select * from t1 where b=3;
+pk	a	b	c
+1	3	3	First row
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          5
+Qcache_hits             6
+
+## Start another connection and check that the query cache is hit
+set AUTOCOMMIT=off;
+use test;
+select * from t1 order by pk;
+pk	a	b	c
+1	3	3	First row
+2	7	8	Second row
+select * from t1 where b=3;
+pk	a	b	c
+1	3	3	First row
+Qcache_queries          2
+Qcache_inserts          6
+Qcache_hits             7
+
+## Update the table and switch to other connection
+update t1 set a=4 where b=3;
+COMMIT;
+
+## Connection 2
+set AUTOCOMMIT=off;
+use test;
+
+## Should not hit cache, table updated
+Qcache_queries          0
+Qcache_inserts          6
+Qcache_hits             7
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	4	3	First row
+Qcache_queries          1
+Qcache_inserts          7
+Qcache_hits             7
+## Should hit cache
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	4	3	First row
+Qcache_queries          1
+Qcache_inserts          7
+Qcache_hits             8
+
+## Connection 1, should hit the cache
+Qcache_queries          1
+Qcache_inserts          7
+Qcache_hits             8
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	4	3	First row
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	4	3	First row
+Qcache_queries          1
+Qcache_inserts          7
+Qcache_hits             10
+
+## Starting transaction and update t1
+begin;
+update t1 set a=5 where pk=1;
+Qcache_queries          0
+Qcache_inserts          7
+Qcache_hits             10
+
+## Connection 2
+## Update has flushed the qc for t1, should not hit qc
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	4	3	First row
+Qcache_queries          1
+Qcache_inserts          8
+Qcache_hits             10
+
+## Connection 1
+commit;
+Qcache_queries          1
+Qcache_inserts          8
+Qcache_hits             10
+
+## Connection 2
+## Update is now committed, should not hit the cache
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	5	3	First row
+Qcache_queries          1
+Qcache_inserts          9
+Qcache_hits             10
+COMMIT;
+Qcache_queries          1
+Qcache_inserts          9
+Qcache_hits             10
+
+## Connection 1
+## Should hit the cache
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	5	3	First row
+Qcache_queries          1
+Qcache_inserts          9
+Qcache_hits             11
+
+update t1 set a=6 where pk=1;
+
+## Following query should not be taken from cache, trans is ongoing
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	6	3	First row
+Qcache_queries          0
+Qcache_inserts          9
+Qcache_hits             11
+
+## Connection 2 should still see old data and not hit cache
+Qcache_queries          0
+Qcache_inserts          9
+Qcache_hits             11
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	5	3	First row
+Qcache_queries          1
+Qcache_inserts          10
+Qcache_hits             11
+
+## Connection 1
+COMMIT;
+
+## Update has just been committed, should not hit cache
+Qcache_queries          1
+Qcache_inserts          10
+Qcache_hits             11
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	6	3	First row
+Qcache_queries          1
+Qcache_inserts          11
+Qcache_hits             11
+
+## Connection 2
+
+## Should hit cache
+Qcache_queries          1
+Qcache_inserts          11
+Qcache_hits             11
+select * from t1 order by pk desc;
+pk	a	b	c
+2	7	8	Second row
+1	6	3	First row
+Qcache_queries          1
+Qcache_inserts          11
+Qcache_hits             12
+
+drop table t1;
+
+## Finally, there should be no queries in cache
+Qcache_queries          0
+Qcache_inserts          11
+Qcache_hits             12
+
+SET GLOBAL query_cache_size=0;

=== modified file 'mysql-test/suite/ndb/t/ndb_blob.test'
--- a/mysql-test/suite/ndb/t/ndb_blob.test	2008-05-21 16:39:51 +0000
+++ b/mysql-test/suite/ndb/t/ndb_blob.test	2008-06-03 10:00:31 +0000
@@ -565,3 +565,27 @@
 
 drop table t1;
 drop table t2;
+
+# bug # 31284
+#   Long Blob (8000 byte parts) with Blob v2 (+2 bytes length)
+#   exposed buffer overrun for old Api setValue() call used for
+#   writing parts.
+#   Check that data written into long Blob can be retrieved
+#   correctly
+create table t1 (
+  a    int primary key,
+  giga longblob) 
+engine=ndb;
+
+# length 10
+set @stuff = '1234567890';
+
+# 20,000 bytes = 3 parts
+insert into t1 values (0, repeat(@stuff, 2000));
+
+# Check that we get the same data back that we put in
+select sha1(repeat(@stuff, 2000));
+select sha1(giga) from t1;
+select (giga = repeat(@stuff, 2000)) from t1 where a=0;
+
+drop table t1;

=== added file 'mysql-test/suite/ndb/t/ndb_cache_trans.test'
--- a/mysql-test/suite/ndb/t/ndb_cache_trans.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_cache_trans.test	2008-05-28 14:26:26 +0000
@@ -0,0 +1,200 @@
+-- source include/have_query_cache.inc
+-- source include/have_ndb.inc
+-- source include/not_embedded.inc
+
+--result_format 2
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+# Turn on and reset query cache
+set GLOBAL query_cache_type=on;
+set GLOBAL query_cache_size=1355776;
+reset query cache;
+flush status;
+
+## Turn off autocommit, instead use COMMIT after each statement
+set AUTOCOMMIT=off;
+
+## Create test table in NDB
+CREATE TABLE t1 (
+  pk int not null primary key,
+  a int,
+  b int not null,
+  c varchar(20)
+) ENGINE=ndbcluster;
+
+## Add first row
+insert into t1 value (1, 2, 3, 'First row');
+COMMIT;
+
+## Query should be inserted in qcache
+--source include/show_qc_status.inc
+select * from t1;
+--source include/show_qc_status.inc
+COMMIT;
+--source include/show_qc_status.inc
+
+## Perform the same query and make sure the query cache is hit
+--source include/show_qc_status.inc
+select * from t1;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Update the table, should be no queries in cache afterwards
+update t1 set a=3 where pk=1;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Read row after update, should not hit the cache, but get inserted
+select * from t1;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Read row from cache
+select * from t1;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Insert two new rows, queries in cache should be zero
+insert into t1 value (2, 7, 8, 'Second row');
+insert into t1 value (4, 5, 6, 'Fourth row');
+COMMIT;
+--source include/show_qc_status.inc
+
+## Read the three rows, should not hit the cache
+select * from t1 order by pk;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Read the three rows, should now hit the cache!
+select * from t1 order by pk;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Two selects in the same transaction should hit cache
+select * from t1 order by pk;
+select * from t1 order by pk;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Perform a "new" query and make sure the query cache is not hit
+select * from t1 where b=3;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Same query again...
+select * from t1 where b=3;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Delete from the table, should clear the cache
+delete from t1 where c='Fourth row';
+COMMIT;
+--source include/show_qc_status.inc
+select * from t1 where b=3;
+COMMIT;
+--source include/show_qc_status.inc
+
+## Start another connection and check that the query cache is hit
+connect (con1,localhost,root,,);
+connection con1;
+set AUTOCOMMIT=off;
+use test;
+select * from t1 order by pk;
+select * from t1 where b=3;
+--source include/show_qc_status.inc
+
+## Update the table and switch to other connection
+update t1 set a=4 where b=3;
+COMMIT;
+
+## Connection 2
+connect (con2,localhost,root,,);
+connection con2;
+set AUTOCOMMIT=off;
+use test;
+
+## Should not hit cache, table updated
+--source include/show_qc_status.inc
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+## Should hit cache
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+## Connection 1, should hit the cache
+connection con1;
+--source include/show_qc_status.inc
+select * from t1 order by pk desc;
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+
+## Starting transaction and update t1
+begin;
+update t1 set a=5 where pk=1;
+--source include/show_qc_status.inc
+
+## Connection 2
+connection con2;
+## Update has flushed the qc for t1, should not hit qc
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+## Connection 1
+connection con1;
+commit;
+--source include/show_qc_status.inc
+
+## Connection 2
+connection con2;
+## Update is now committed, should not hit the cache
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+COMMIT;
+--source include/show_qc_status.inc
+
+## Connection 1
+connection con1;
+## Should hit the cache
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+update t1 set a=6 where pk=1;
+
+## Following query should not be taken from cache, trans is ongoing
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+
+## Connection 2 should still see old data and not hit cache
+connection con2;
+--source include/show_qc_status.inc
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+## Connection 1
+connection con1;
+COMMIT;
+
+## Update has just been committed, should not hit cache
+--source include/show_qc_status.inc
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+## Connection 2
+connection con2;
+
+## Should hit cache
+--source include/show_qc_status.inc
+select * from t1 order by pk desc;
+--source include/show_qc_status.inc
+
+drop table t1;
+
+## Finally, there should be no queries in cache
+--source include/show_qc_status.inc
+
+SET GLOBAL query_cache_size=0;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2008-05-27 14:12:38 +0000
+++ b/sql/ha_ndbcluster.cc	2008-05-30 11:12:38 +0000
@@ -4614,21 +4614,26 @@
   {
     DBUG_PRINT("info", ("lock_type == F_UNLCK"));
 
-    if (ndb_cache_check_time && m_rows_changed)
+    if (m_rows_changed)
     {
-      DBUG_PRINT("info", ("Rows has changed and util thread is running"));
+      DBUG_PRINT("info", ("Rows has changed"));
+
       if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
       {
-        DBUG_PRINT("info", ("Add share to list of tables to be invalidated"));
+        DBUG_PRINT("info", ("Add share to list of changed tables"));
         /* NOTE push_back allocates memory using transactions mem_root! */
-        thd_ndb->changed_tables.push_back(m_share, &thd->transaction.mem_root);
+        thd_ndb->changed_tables.push_back(m_share,
+                                          &thd->transaction.mem_root);
       }
 
-      pthread_mutex_lock(&m_share->mutex);
-      DBUG_PRINT("info", ("Invalidating commit_count"));
-      m_share->commit_count= 0;
-      m_share->commit_count_lock++;
-      pthread_mutex_unlock(&m_share->mutex);
+      if (ndb_cache_check_time)
+      {
+        pthread_mutex_lock(&m_share->mutex);
+        DBUG_PRINT("info", ("Invalidating commit_count"));
+        m_share->commit_count= 0;
+        m_share->commit_count_lock++;
+        pthread_mutex_unlock(&m_share->mutex);
+      }
     }
 
     if (!--thd_ndb->lock_count)
@@ -8080,20 +8085,34 @@
                                    ulonglong *engine_data)
 {
   Uint64 commit_count;
-  bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
   char *dbname= full_name;
   char *tabname= dbname+strlen(dbname)+1;
 #ifndef DBUG_OFF
   char buff[22], buff2[22];
 #endif
   DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
-  DBUG_PRINT("enter", ("dbname: %s, tabname: %s, is_autocommit: %d",
-                       dbname, tabname, is_autocommit));
+  DBUG_PRINT("enter", ("dbname: %s, tabname: %s",
+                       dbname, tabname));
 
-  if (!is_autocommit)
+  if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
   {
-    DBUG_PRINT("exit", ("No, don't use cache in transaction"));
-    DBUG_RETURN(FALSE);
+    /* Don't allow qc to be used if table has been previously
+       modified in transaction */
+    Thd_ndb *thd_ndb= get_thd_ndb(thd);
+    if (!thd_ndb->changed_tables.is_empty())
+    {
+      NDB_SHARE* share;
+      List_iterator_fast<NDB_SHARE> it(thd_ndb->changed_tables);
+      while ((share= it++))
+      {
+        if (strcmp(share->table_name, tabname) == 0 &&
+            strcmp(share->db, dbname) == 0)
+        {
+          DBUG_PRINT("exit", ("No, transaction has changed table"));
+          DBUG_RETURN(FALSE);
+        }
+      }
+    }
   }
 
   if (ndb_get_commitcount(thd, dbname, tabname, &commit_count))
@@ -8155,15 +8174,29 @@
 #ifndef DBUG_OFF
   char buff[22];
 #endif
-  bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
   DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
-  DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d",
-		      m_dbname, m_tabname, is_autocommit));
+  DBUG_PRINT("enter",("dbname: %s, tabname: %s",
+		      m_dbname, m_tabname));
 
-  if (!is_autocommit)
+  if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
   {
-    DBUG_PRINT("exit", ("Can't register table during transaction"));
-    DBUG_RETURN(FALSE);
+    /* Don't allow qc to be used if table has been previously
+       modified in transaction */
+    Thd_ndb *thd_ndb= get_thd_ndb(thd);
+    if (!thd_ndb->changed_tables.is_empty())
+    {
+      DBUG_ASSERT(m_share);
+      NDB_SHARE* share;
+      List_iterator_fast<NDB_SHARE> it(thd_ndb->changed_tables);
+      while ((share= it++))
+      {
+        if (m_share == share)
+        {
+          DBUG_PRINT("exit", ("No, transaction has changed table"));
+          DBUG_RETURN(FALSE);
+        }
+      }
+    }
   }
 
   if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count))

=== modified file 'storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp'
--- a/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp	2007-05-21 09:03:20 +0000
+++ b/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp	2008-05-29 15:58:58 +0000
@@ -156,7 +156,10 @@
     
     DumpTsman = 9800, 
     DumpLgman = 10000,
-    DumpPgman = 11000
+    DumpPgman = 11000,
+
+    SchemaResourceSnapshot = 4000, // Save resource consumption
+    SchemaResourceCheckLeak = 4001 // check same as snapshot
   };
 public:
   

=== modified file 'storage/ndb/include/kernel/signaldata/KeyInfo.hpp'
--- a/storage/ndb/include/kernel/signaldata/KeyInfo.hpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/include/kernel/signaldata/KeyInfo.hpp	2008-06-03 10:00:31 +0000
@@ -37,6 +37,16 @@
   STATIC_CONST( HeaderLength = 3 );
   STATIC_CONST( DataLength = 20 );
   STATIC_CONST( MaxSignalLength = HeaderLength + DataLength );
+  
+  /* IndexBound constants */
+  STATIC_CONST( PerBoundColumnOverhead = 2 );
+  /* Max number of key columns with max total key size */
+  STATIC_CONST( MaxWordsPerBoundRow =   \
+                (PerBoundColumnOverhead * MAX_ATTRIBUTES_IN_INDEX)    \
+                + MAX_KEY_SIZE_IN_WORDS );
+  /* Single key column with max total key size */
+  STATIC_CONST( MaxWordsPerBoundColumn =     \
+                PerBoundColumnOverhead + MAX_KEY_SIZE_IN_WORDS );
 
 private:
   Uint32 connectPtr;

=== modified file 'storage/ndb/include/mgmapi/mgmapi_config_parameters.h'
--- a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2008-05-21 09:16:35 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2008-05-29 13:09:49 +0000
@@ -26,6 +26,7 @@
 #define CFG_NODE_HOST                 5
 #define CFG_NODE_SYSTEM               6
 #define CFG_NODE_DATADIR              7
+#define CFG_9                         9         /* used in later version */
 
 /**
  * DB config parameters
@@ -136,6 +137,7 @@
 
 #define CFG_NODE_ARBIT_RANK           200
 #define CFG_NODE_ARBIT_DELAY          201
+#define CFG_202                       202       /* used in later version */
 
 #define CFG_MIN_LOGLEVEL          250
 #define CFG_LOGLEVEL_STARTUP      250
@@ -165,6 +167,7 @@
 #define CFG_CONNECTION_HOSTNAME_2     408
 #define CFG_CONNECTION_GROUP          409
 #define CFG_CONNECTION_NODE_ID_SERVER 410
+#define CFG_411                       411       /* used in later version */
 
 #define CFG_TCP_SERVER                452
 #define CFG_TCP_SEND_BUFFER_SIZE      454

=== modified file 'storage/ndb/src/kernel/blocks/ERROR_codes.txt'
--- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2008-04-25 07:14:29 +0000
+++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt	2008-05-30 08:03:55 +0000
@@ -551,6 +551,11 @@
 6005 Crash in participant @ CreateTabReq::CreateDrop
 6007 Fail on readTableFile for READ_TAB_FILE1 (28770)
 
+6200 Set error code after handleTabInfoInit in master
+6201 Set error code after handleTabInfoInit in master (index)
+6202 Set error code before CREATE_FRAGMENTATION in master
+6203 Set error code before CREATE_FRAGMENTATION in master (index)
+
 Dbtup:
 4014 - handleInsert - Out of undo buffer
 4015 - handleInsert - Out of log space

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2007-03-16 10:16:48 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp	2008-05-29 15:58:58 +0000
@@ -881,6 +881,10 @@
   FragmentrecPtr fragrecptr;
   Uint32 cfirstfreefrag;
   Uint32 cfragmentsize;
+  RSS_OP_COUNTER(cnoOfFreeFragrec);
+  RSS_OP_SNAPSHOT(cnoOfFreeFragrec);
+
+
 /* --------------------------------------------------------------------------------- */
 /* FS_CONNECTREC                                                                     */
 /* --------------------------------------------------------------------------------- */

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp	2007-02-14 05:37:40 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp	2008-05-29 15:58:58 +0000
@@ -43,6 +43,9 @@
 
   cnoOfAllocatedPages = cpagesize = 0;
   // Records with constant sizes
+
+  RSS_OP_COUNTER_INIT(cnoOfFreeFragrec);
+
 }//Dbacc::initData()
 
 void Dbacc::initRecords() 

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2008-05-26 08:30:47 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2008-05-29 15:58:58 +0000
@@ -858,6 +858,7 @@
   regFragPtr.p->nextfreefrag = cfirstfreefrag;
   cfirstfreefrag = regFragPtr.i;
   initFragGeneral(regFragPtr);
+  RSS_OP_FREE(cnoOfFreeFragrec);
 }//Dbacc::releaseFragRecord()
 
 /* -------------------------------------------------------------------------- */
@@ -8074,6 +8075,7 @@
 /* --------------------------------------------------------------------------------- */
 void Dbacc::seizeFragrec(Signal* signal) 
 {
+  RSS_OP_ALLOC(cnoOfFreeFragrec);
   fragrecptr.i = cfirstfreefrag;
   ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
   cfirstfreefrag = fragrecptr.p->nextfreefrag;
@@ -8520,6 +8522,18 @@
     return;
   }//if
 #endif
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
+  {
+    RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
+    return;
+  }
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
+  {
+    RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
+    return;
+  }
 }//Dbacc::execDUMP_STATE_ORD()
 
 void

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2008-05-16 13:08:36 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2008-05-30 08:03:55 +0000
@@ -87,6 +87,8 @@
 #include <signaldata/CreateObj.hpp>
 #include <SLList.hpp>
 
+#include <signaldata/DumpStateOrd.hpp>
+
 #include <EventLogger.hpp>
 extern EventLogger * g_eventLogger;
 
@@ -309,8 +311,28 @@
               c_counterMgr.getNoOfFree());
     c_counterMgr.printNODE_FAILREP();
   }
-    
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
+  {
+    RSS_AP_SNAPSHOT_SAVE(c_rope_pool);
+    RSS_AP_SNAPSHOT_SAVE(c_attributeRecordPool);
+    RSS_AP_SNAPSHOT_SAVE(c_tableRecordPool);
+    RSS_AP_SNAPSHOT_SAVE(c_triggerRecordPool);
+    RSS_AP_SNAPSHOT_SAVE(c_obj_pool);
+  }
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
+  {
+    RSS_AP_SNAPSHOT_CHECK(c_rope_pool);
+    RSS_AP_SNAPSHOT_CHECK(c_attributeRecordPool);
+    RSS_AP_SNAPSHOT_CHECK(c_tableRecordPool);
+    RSS_AP_SNAPSHOT_CHECK(c_triggerRecordPool);
+    RSS_AP_SNAPSHOT_CHECK(c_obj_pool);
+  }
+
   return;
+
+
 }//Dbdict::execDUMP_STATE_ORD()
 
 /* ---------------------------------------------------------------- */
@@ -2039,7 +2061,6 @@
   c_tableRecordPool.getPtr(tablePtr, i);
   ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
   initialiseTableRecord(tablePtr);
-  tablePtr.p->tabState = TableRecord::DEFINING;
   return i;
 }
 
@@ -3937,10 +3958,26 @@
     
     handleTabInfoInit(r, &parseRecord);
     releaseSections(signal);
+
+    if (parseRecord.errorCode == 0)
+    {
+      if (ERROR_INSERTED(6200) ||
+          (ERROR_INSERTED(6201) && 
+           DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
+      {
+        CLEAR_ERROR_INSERT_VALUE;
+        parseRecord.errorCode = 1;
+      }
+    }
     
     if(parseRecord.errorCode != 0){
       jam();
       c_opCreateTable.release(createTabPtr);
+      if (!parseRecord.tablePtr.isNull())
+      {
+        jam();
+        releaseTableObject(parseRecord.tablePtr.i, true);
+      }
       break;
     }
     
@@ -3990,9 +4027,20 @@
       */
       parseRecord.tablePtr.p->primaryTableId = RNIL;
     }
-    EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
-		   CreateFragmentationReq::SignalLength);
-    jamEntry();
+    if (ERROR_INSERTED(6202) || 
+        (ERROR_INSERTED(6203) && 
+         DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
+    {
+      CLEAR_ERROR_INSERT_VALUE;
+      signal->theData[0] = 1;
+    }
+    else
+    {
+      EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
+                     CreateFragmentationReq::SignalLength);
+      jamEntry();
+    }
+    
     if (signal->theData[0] != 0)
     {
       jam();
@@ -6263,7 +6311,7 @@
     jam();    \
     parseP->errorCode = error; parseP->errorLine = __LINE__; \
     parseP->errorKey = it.getKey(); \
-    return;   \
+    return;                         \
   }//if
 
 // handleAddTableFailure(signal, __LINE__, allocatedTable);
@@ -6349,10 +6397,11 @@
 
   if(checkExist){
     jam();
-    tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0, 
-	       CreateTableRef::TableAlreadyExist);
+    
+    tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0,
+               CreateTableRef::TableAlreadyExist;);
   }
-  
+
   TableRecordPtr tablePtr;
   switch (parseP->requestType) {
   case DictTabInfo::CreateTableFromAPI: {
@@ -6365,7 +6414,6 @@
     // Check if no free tables existed.
     /* ---------------------------------------------------------------- */
     tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
-    
     c_tableRecordPool.getPtr(tablePtr);
     break;
   }
@@ -6400,21 +6448,20 @@
 /* ---------------------------------------------------------------- */
     Uint32 tableVersion = c_tableDesc.TableVersion;
     tablePtr.p->tableVersion = tableVersion;
-    
+ 
     break;
   }
   default:
     ndbrequire(false);
     break;
   }//switch
-  parseP->tablePtr = tablePtr;
   
   { 
     Rope name(c_rope_pool, tablePtr.p->tableName);
     tabRequire(name.assign(c_tableDesc.TableName, tableNameLength, name_hash),
-	       CreateTableRef::OutOfStringBuffer);
+               CreateTableRef::OutOfStringBuffer);
   }
-
+  
   Ptr<DictObject> obj_ptr;
   if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
     jam();
@@ -6431,7 +6478,9 @@
 	     c_tableDesc.TableName, tablePtr.i, tablePtr.p->m_obj_ptr_i);
 #endif
   }
-  
+  parseP->tablePtr = tablePtr;
+  tablePtr.p->tabState = TableRecord::DEFINING;
+
   // Disallow logging of a temporary table.
   tabRequire(!(c_tableDesc.TableTemporaryFlag && c_tableDesc.TableLoggedFlag),
              CreateTableRef::NoLoggingTemporaryTable);
@@ -6511,6 +6560,7 @@
      * Release table
      */
     releaseTableObject(tablePtr.i, checkExist);
+    parseP->tablePtr.setNull();
     return;
   }
 

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2008-05-16 13:08:36 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2008-05-30 08:03:55 +0000
@@ -198,6 +198,7 @@
   typedef Ptr<AttributeRecord> AttributeRecordPtr;
   ArrayPool<AttributeRecord> c_attributeRecordPool;
   DLHashTable<AttributeRecord> c_attributeRecordHash;
+  RSS_AP_SNAPSHOT(c_attributeRecordPool);
 
   /**
    * Shared table / index record.  Most of this is permanent data stored
@@ -384,6 +385,7 @@
 
   typedef Ptr<TableRecord> TableRecordPtr;
   ArrayPool<TableRecord> c_tableRecordPool;
+  RSS_AP_SNAPSHOT(c_tableRecordPool);
 
   /**  Node Group and Tablespace id+version + range or list data.
     *  This is only stored temporarily in DBDICT during an ongoing
@@ -463,6 +465,7 @@
   Uint32 c_maxNoOfTriggers;
   typedef Ptr<TriggerRecord> TriggerRecordPtr;
   ArrayPool<TriggerRecord> c_triggerRecordPool;
+  RSS_AP_SNAPSHOT(c_triggerRecordPool);
 
   /**
    * Information for each FS connection.
@@ -612,6 +615,7 @@
   Filegroup_hash c_filegroup_hash;
   
   RopePool c_rope_pool;
+  RSS_AP_SNAPSHOT(c_rope_pool);
 
   struct DictObject {
     DictObject() {}
@@ -643,6 +647,7 @@
   
   DLHashTable<DictObject> c_obj_hash; // Name
   ArrayPool<DictObject> c_obj_pool;
+  RSS_AP_SNAPSHOT(c_obj_pool);
   
   DictObject * get_object(const char * name){
     return get_object(name, strlen(name) + 1);
@@ -1120,6 +1125,7 @@
    * Temporary structure used when parsing table info
    */
   struct ParseDictTabInfoRecord {
+    ParseDictTabInfoRecord() { tablePtr.setNull();}
     DictTabInfo::RequestType requestType;
     Uint32 errorCode;
     Uint32 errorLine;

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2007-11-19 10:04:24 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	2008-05-30 06:33:46 +0000
@@ -2647,6 +2647,7 @@
 // Configurable
   FragrecordPtr fragptr;
   ArrayPool<Fragrecord> c_fragment_pool;
+  RSS_AP_SNAPSHOT(c_fragment_pool);
 
 #define ZGCPREC_FILE_SIZE 1
   GcpRecord *gcpRecord;

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-04-23 14:29:01 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2008-05-30 06:33:46 +0000
@@ -19725,6 +19725,18 @@
       infoEvent(buf);
     }
   }
+  
+  if (arg == DumpStateOrd::SchemaResourceSnapshot)
+  {
+    RSS_AP_SNAPSHOT_SAVE(c_fragment_pool);
+    return;
+  }
+
+  if (arg == DumpStateOrd::SchemaResourceCheckLeak)
+  {
+    RSS_AP_SNAPSHOT_CHECK(c_fragment_pool);
+    return;
+  }
 }//Dblqh::execDUMP_STATE_ORD()
 
 /* **************************************************************** */

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-04-03 12:46:03 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-05-29 15:58:58 +0000
@@ -2967,10 +2967,14 @@
   Fragoperrec *fragoperrec;
   Uint32 cfirstfreeFragopr;
   Uint32 cnoOfFragoprec;
+  RSS_OP_COUNTER(cnoOfFreeFragoprec);
+  RSS_OP_SNAPSHOT(cnoOfFreeFragoprec);
 
   Fragrecord *fragrecord;
   Uint32 cfirstfreefrag;
   Uint32 cnoOfFragrec;
+  RSS_OP_COUNTER(cnoOfFreeFragrec);
+  RSS_OP_SNAPSHOT(cnoOfFreeFragrec);
 
   AlterTabOperation *alterTabOperRec;
   Uint32 cfirstfreeAlterTabOp;
@@ -2993,6 +2997,8 @@
 
   TableDescriptor *tableDescriptor;
   Uint32 cnoOfTabDescrRec;
+  RSS_OP_COUNTER(cnoOfFreeTabDescrRec);
+  RSS_OP_SNAPSHOT(cnoOfFreeTabDescrRec);
   
   Uint32 cdata[32];
   Uint32 cdataPages[16];

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2007-06-12 07:39:23 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2008-05-29 15:58:58 +0000
@@ -259,6 +259,22 @@
              max_loop);
   }
 #endif
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
+  {
+    RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragoprec);
+    RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
+    RSS_OP_SNAPSHOT_SAVE(cnoOfFreeTabDescrRec);
+    return;
+  }
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
+  {
+    RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragoprec);
+    RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
+    RSS_OP_SNAPSHOT_CHECK(cnoOfFreeTabDescrRec);
+    return;
+  }
 }//Dbtup::execDUMP_STATE_ORD()
 
 /* ---------------------------------------------------------------- */

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2007-06-14 17:09:19 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2008-05-29 15:58:58 +0000
@@ -117,6 +117,10 @@
   
   initData();
   CLEAR_ERROR_INSERT_VALUE;
+
+  RSS_OP_COUNTER_INIT(cnoOfFreeFragoprec);
+  RSS_OP_COUNTER_INIT(cnoOfFreeFragrec);
+  RSS_OP_COUNTER_INIT(cnoOfFreeTabDescrRec);
 }//Dbtup::Dbtup()
 
 Dbtup::~Dbtup() 
@@ -762,6 +766,7 @@
 {
   regFragPtr.p->nextfreefrag = cfirstfreefrag;
   cfirstfreefrag = regFragPtr.i;
+  RSS_OP_FREE(cnoOfFreeFragrec);
 }//Dbtup::releaseFragrec()
 
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2008-03-19 12:57:01 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2008-05-29 15:58:58 +0000
@@ -266,6 +266,7 @@
   ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
   cfirstfreefrag= regFragPtr.p->nextfreefrag;
   regFragPtr.p->nextfreefrag= RNIL;
+  RSS_OP_ALLOC(cnoOfFreeFragrec);
 }
 
 void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr) 
@@ -275,6 +276,7 @@
   cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
   fragOperPtr.p->nextFragoprec = RNIL;
   fragOperPtr.p->inUse = true;
+  RSS_OP_ALLOC(cnoOfFreeFragoprec);
 }//Dbtup::seizeFragoperrec()
 
 void Dbtup::seizeAlterTabOperation(AlterTabOperationPtr& alterTabOpPtr)
@@ -314,6 +316,17 @@
   fragOperPtr.p->attributeCount--;
   const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
 
+  if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0||
+      ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
+      ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0||
+      ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
+    jam();
+    terrorCode = 1;
+    addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+    CLEAR_ERROR_INSERT_VALUE;
+    return;
+  }
+
   if (regTabPtr.p->tableStatus != DEFINING)
   {
     ndbrequire(regTabPtr.p->tableStatus == DEFINED);
@@ -455,17 +468,6 @@
                    fragOperPtr.p->charsetIndex, attrDes2);
   setTabDescrWord(firstTabDesIndex + 1, attrDes2);
 
-  if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0||
-      ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
-      ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0||
-      ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
-    jam();
-    terrorCode = 1;
-    addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
-    CLEAR_ERROR_INSERT_VALUE;
-    return;
-  }
-
 /* **************************************************************** */
 /* **************          TUP_ADD_ATTCONF       ****************** */
 /* **************************************************************** */
@@ -1359,7 +1361,6 @@
   deleteFragTab(regTabPtr, fragId);
   releaseFragrec(regFragPtr);
   releaseTabDescr(regTabPtr);
-  initTab(regTabPtr);
 
   signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
   signal->theData[1]= terrorCode;
@@ -1372,10 +1373,24 @@
                            FragoperrecPtr fragOperPtr,
                            FragrecordPtr regFragPtr,
                            Tablerec* const regTabPtr,
-                           Uint32 fragId) 
+                           Uint32 fragId)
 {
+  bool found = false;
+  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) 
+  {
+    jam();
+    if (regTabPtr->fragid[i] == fragId) 
+    {
+      jam();
+      ndbrequire(regTabPtr->fragrec[i] == regFragPtr.i);
+      regTabPtr->fragid[i] = RNIL;
+      regTabPtr->fragrec[i] = RNIL;
+      found = true;
+      break;
+    }
+  }
+  ndbrequire(found);
   fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr, fragId);
-  initTab(regTabPtr);
 }
 
 void Dbtup::fragrefuse3Lab(Signal* signal,
@@ -1413,6 +1428,7 @@
   fragOperPtr.p->inUse = false;
   fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
   cfirstfreeFragopr = fragOperPtr.i;
+  RSS_OP_FREE(cnoOfFreeFragoprec);
 }//Dbtup::releaseFragoperrec()
 
 void Dbtup::releaseAlterTabOpRec(AlterTabOperationPtr regAlterTabOpPtr)
@@ -1466,6 +1482,19 @@
   
   tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
   tabPtr.p->m_dropTable.tabUserPtr = req->senderData;
+
+  if (tabPtr.p->tableStatus == NOT_DEFINED) 
+  {
+    jam();
+    DropTabConf * const dropConf= (DropTabConf *)signal->getDataPtrSend();
+    dropConf->senderRef= reference();
+    dropConf->senderData= tabPtr.p->m_dropTable.tabUserPtr;
+    dropConf->tableId= tabPtr.i;
+    sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_TAB_CONF,
+               signal, DropTabConf::SignalLength, JBB);
+    return;
+  }
+
   tabPtr.p->tableStatus = DROPPING;
 
   signal->theData[0]= ZREL_FRAG;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2008-02-03 11:32:08 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp	2008-05-29 15:58:58 +0000
@@ -144,6 +144,7 @@
 void Dbtup::insertTdArea(Uint32 tabDesRef, Uint32 list) 
 {
   ndbrequire(list < 16);
+  RSS_OP_FREE_X(cnoOfFreeTabDescrRec, 1 << list);
   setTabDescrWord(tabDesRef + ZTD_FL_HEADER, ZTD_TYPE_FREE);
   setTabDescrWord(tabDesRef + ZTD_FL_NEXT, cfreeTdList[list]);
   if (cfreeTdList[list] != RNIL) {
@@ -217,6 +218,8 @@
 void Dbtup::removeTdArea(Uint32 tabDesRef, Uint32 list) 
 {
   ndbrequire(list < 16);
+  RSS_OP_ALLOC_X(cnoOfFreeTabDescrRec, 1 << list);
+
   Uint32 tabDescrNextPtr = getTabDescrWord(tabDesRef + ZTD_FL_NEXT);
   Uint32 tabDescrPrevPtr = getTabDescrWord(tabDesRef + ZTD_FL_PREV);
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp	2006-12-23 19:20:40 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp	2008-05-30 06:33:46 +0000
@@ -451,6 +451,7 @@
   };
   typedef Ptr<Index> IndexPtr;
   ArrayPool<Index> c_indexPool;
+  RSS_AP_SNAPSHOT(c_indexPool);
 
   /*
    * Fragment of an index, as known to DIH/TC.  Represents the two
@@ -481,6 +482,7 @@
   };
   typedef Ptr<Frag> FragPtr;
   ArrayPool<Frag> c_fragPool;
+  RSS_AP_SNAPSHOT(c_fragPool);
 
   /*
    * Fragment metadata operation.
@@ -500,6 +502,7 @@
   };
   typedef Ptr<FragOp> FragOpPtr;
   ArrayPool<FragOp> c_fragOpPool;
+  RSS_AP_SNAPSHOT(c_fragOpPool);
 
   // node handles
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp	2006-12-23 19:20:40 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp	2008-05-30 06:33:46 +0000
@@ -55,6 +55,20 @@
     abort();
   }
 #endif
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
+  {
+    RSS_AP_SNAPSHOT_SAVE(c_indexPool);
+    RSS_AP_SNAPSHOT_SAVE(c_fragPool);
+    RSS_AP_SNAPSHOT_SAVE(c_fragOpPool);
+  }
+
+  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
+  {
+    RSS_AP_SNAPSHOT_CHECK(c_indexPool);
+    RSS_AP_SNAPSHOT_CHECK(c_fragPool);
+    RSS_AP_SNAPSHOT_CHECK(c_fragOpPool);
+  }
 }
 
 #ifdef VM_TRACE

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2008-02-20 09:04:29 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2008-05-29 15:58:58 +0000
@@ -822,5 +822,38 @@
 
 #include "Mutex.hpp"
 
+#ifdef ERROR_INSERT
+#define RSS_AP_SNAPSHOT(x) Uint32 rss_##x
+#define RSS_AP_SNAPSHOT_SAVE(x) rss_##x = x.getNoOfFree()
+#define RSS_AP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x.getNoOfFree())
+
+#define RSS_OP_COUNTER(x) Uint32 x
+#define RSS_OP_COUNTER_INIT(x) x = 0
+#define RSS_OP_ALLOC(x) x ++
+#define RSS_OP_FREE(x) x --
+#define RSS_OP_ALLOC_X(x,n) x += n
+#define RSS_OP_FREE_X(x,n) x -= n
+
+#define RSS_OP_SNAPSHOT(x) Uint32 rss_##x
+#define RSS_OP_SNAPSHOT_SAVE(x) rss_##x = x
+#define RSS_OP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x)
+#else
+#define RSS_AP_SNAPSHOT(x)
+#define RSS_AP_SNAPSHOT_SAVE(x)
+#define RSS_AP_SNAPSHOT_CHECK(x)
+
+#define RSS_OP_COUNTER(x)
+#define RSS_OP_COUNTER_INIT(x)
+#define RSS_OP_ALLOC(x)
+#define RSS_OP_FREE(x)
+#define RSS_OP_ALLOC_X(x,n)
+#define RSS_OP_FREE_X(x,n)
+
+#define RSS_OP_SNAPSHOT(x)
+#define RSS_OP_SNAPSHOT_SAVE(x)
+#define RSS_OP_SNAPSHOT_CHECK(x)
+
+#endif
+
 #endif
 

=== modified file 'storage/ndb/src/ndbapi/Ndb.cpp'
--- a/storage/ndb/src/ndbapi/Ndb.cpp	2008-02-20 09:04:29 +0000
+++ b/storage/ndb/src/ndbapi/Ndb.cpp	2008-06-03 10:00:31 +0000
@@ -550,7 +550,8 @@
       Uint32 hashValue;
       {
 	Uint32 buf[4];
-        Uint64 tmp[1000];
+        const Uint32 MaxKeySizeInLongWords= (NDB_MAX_KEY_SIZE + 7) / 8;
+        Uint64 tmp[ MaxKeySizeInLongWords ];
 
         if (keyLen >= sizeof(tmp))
         {

=== modified file 'storage/ndb/src/ndbapi/NdbBlob.cpp'
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp	2008-05-23 10:20:10 +0000
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp	2008-06-03 10:00:31 +0000
@@ -621,7 +621,7 @@
 NdbBlob::copyKeyFromRow(const NdbRecord *record, const char *row,
                         Buf& packedBuf, Buf& unpackedBuf)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   DBUG_ENTER("NdbBlob::copyKeyFromRow");
 
   assert(record->flags & NdbRecord::RecHasAllKeys);

=== modified file 'storage/ndb/src/ndbapi/NdbIndexStat.cpp'
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp	2008-02-19 15:00:29 +0000
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp	2008-06-03 10:00:31 +0000
@@ -398,7 +398,7 @@
                              Uint32* keyStatData,
                              Uint32& keyLength)
 {
-  char buf[256]; // For shrinking MySQLD varchars
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
 
   Uint32 key_index= record->key_indexes[ keyPartNum ];
   const NdbRecord::Attr *column= &record->columns[ key_index ];

=== modified file 'storage/ndb/src/ndbapi/NdbOperationDefine.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2008-04-08 08:31:46 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp	2008-06-03 10:00:31 +0000
@@ -481,7 +481,7 @@
   int tReturnCode;
   Uint32 tAttrId;
   Uint32 tData;
-  Uint32 tempData[2000];
+  Uint32 tempData[ NDB_MAX_TUPLE_SIZE_IN_WORDS ];
   OperationType tOpType = theOperationType;
   OperationStatus tStatus = theStatus;
 
@@ -884,7 +884,9 @@
   DBUG_PRINT("info", ("aLen=%u", (Uint32)aLen));
 
   // wl3717_todo not optimal..
-  Uint64 buf[2048];
+  const Uint32 MaxTupleSizeInLongWords= (NDB_MAX_TUPLE_SIZE + 7)/ 8;
+  Uint64 buf[ MaxTupleSizeInLongWords ];
+  assert( aLen < (NDB_MAX_TUPLE_SIZE - 2) );
   unsigned char* p = (unsigned char*)buf;
   p[0] = (aLen & 0xff);
   p[1] = (aLen >> 8);

=== modified file 'storage/ndb/src/ndbapi/NdbOperationExec.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-04-01 15:37:28 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp	2008-06-03 10:00:31 +0000
@@ -606,7 +606,7 @@
 NdbOperation::buildSignalsNdbRecord(Uint32 aTC_ConnectPtr, 
                                     Uint64 aTransId)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   Uint32 *keyInfoPtr, *attrInfoPtr;
   Uint32 remain;
   int res;

=== modified file 'storage/ndb/src/ndbapi/NdbOperationInt.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationInt.cpp	2008-05-27 19:12:32 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationInt.cpp	2008-06-03 10:00:31 +0000
@@ -1115,7 +1115,7 @@
 
   m_no_disk_flag &= (col->m_storageType == NDB_STORAGETYPE_DISK ? 0:1);
 
-  Uint32 tempData[2000];
+  Uint32 tempData[ NDB_MAX_TUPLE_SIZE_IN_WORDS ];
   if (((UintPtr)val & 3) != 0) {
     memcpy(tempData, val, len);
     val = tempData;

=== modified file 'storage/ndb/src/ndbapi/NdbOperationSearch.cpp'
--- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2008-04-08 08:31:46 +0000
+++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp	2008-06-03 10:00:31 +0000
@@ -62,7 +62,8 @@
                        (long) aValuePassed));
   
   const char* aValue = aValuePassed;
-  Uint64 tempData[512];
+  const Uint32 MaxKeyLenInLongWords= (NDB_MAX_KEY_SIZE + 7)/8;
+  Uint64 tempData[ MaxKeyLenInLongWords ];
 
   if ((theStatus == OperationDefined) &&
       (aValue != NULL) &&
@@ -465,8 +466,8 @@
 void
 NdbOperation::reorderKEYINFO()
 {
-  Uint32 data[4000];
-  Uint32 size = 4000;
+  Uint32 data[ NDB_MAX_KEYSIZE_IN_WORDS ];
+  Uint32 size = NDB_MAX_KEYSIZE_IN_WORDS;
   getKeyFromTCREQ(data, size);
   Uint32 pos = 1;
   Uint32 k;
@@ -480,7 +481,8 @@
           if (theTupleKeyDefined[j][0] == i) {
             Uint32 off = theTupleKeyDefined[j][1] - 1;
             Uint32 len = theTupleKeyDefined[j][2];
-            assert(off < 4000 && off + len <= 4000);
+            assert(off < NDB_MAX_KEYSIZE_IN_WORDS && 
+                   off + len <= NDB_MAX_KEYSIZE_IN_WORDS);
             int ret = insertKEYINFO((char*)&data[off], pos, len);
             assert(ret == 0);
             pos += len;
@@ -508,11 +510,12 @@
   NdbApiSignal* tSignal = theTCREQ->next();
   unsigned n = 0;
   while (pos < size) {
-    if (n == 20) {
+    if (n == KeyInfo::DataLength) {
       tSignal = tSignal->next();
       n = 0;
     }
-    data[pos++] = tSignal->getDataPtrSend()[3 + n++];
+    data[pos++] = 
+      tSignal->getDataPtrSend()[KeyInfo::HeaderLength + n++];
   }
   return 0;
 }
@@ -538,7 +541,8 @@
     ptrs[0].len = len;
     ptrs[1].ptr = 0;
     
-    Uint64 tmp[1000];
+    const Uint32 MaxKeyLenInLongWords= (NDB_MAX_KEY_SIZE + 7)/ 8; 
+    Uint64 tmp[ MaxKeyLenInLongWords ]; 
     Uint32 hashValue;
     int ret = Ndb::computeHash(&hashValue, 
                                m_currentTable,

=== modified file 'storage/ndb/src/ndbapi/NdbRecord.hpp'
--- a/storage/ndb/src/ndbapi/NdbRecord.hpp	2008-04-01 15:37:28 +0000
+++ b/storage/ndb/src/ndbapi/NdbRecord.hpp	2008-06-03 10:00:31 +0000
@@ -133,6 +133,9 @@
       return (flags & IsNullable) &&
              (row[nullbit_byte_offset] & (1 << nullbit_bit_in_byte));
     }
+
+    /* 255 bytes of data and 1 byte of length */
+    STATIC_CONST( SHRINK_VARCHAR_BUFFSIZE= 256 );
     /*
       Mysqld uses a slightly different format for storing varchar in
       index keys; the length is always two bytes little endian, even
@@ -143,7 +146,7 @@
     {
       const char *p= row + offset;
       Uint32 len= uint2korr(p);
-      if (len >= 256 || len >= maxSize)
+      if (len >= SHRINK_VARCHAR_BUFFSIZE || len >= maxSize)
         return false;
       buf[0]= (unsigned char)len;
       memcpy(buf+1, p+2, len);

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-05-27 11:48:47 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2008-06-03 10:00:31 +0000
@@ -515,7 +515,8 @@
                                            const char *row,
                                            Uint32 distkeyMax)
 {
-  Uint64 tmp[1000];
+  const Uint32 MaxKeySizeInLongWords= (NDB_MAX_KEY_SIZE + 7) / 8; 
+  Uint64 tmp[ MaxKeySizeInLongWords ];
   char* tmpshrink = (char*)tmp;
   size_t tmplen = sizeof(tmp);
   
@@ -2854,7 +2855,7 @@
                                               const char *row,
                                               Uint32 bound_type)
 {
-  char buf[256];
+  char buf[NdbRecord::Attr::SHRINK_VARCHAR_BUFFSIZE];
   Uint32 currLen= theTotalNrOfKeyWordInSignal;
   Uint32 remaining= KeyInfo::DataLength - currLen;
   const NdbRecord::Attr *column= &key_record->columns[column_index];
@@ -2904,7 +2905,10 @@
     theTotalNrOfKeyWordInSignal= currLen + totalLen;
   } else {
     if(!aligned || !nobytes){
-      Uint32 tempData[2000];
+      /* Space for Bound type, Attr header and (possibly max-sized)
+       * key column
+       */
+      Uint32 tempData[ KeyInfo::MaxWordsPerBoundColumn ];
       if (len > sizeof(tempData))
         len= sizeof(tempData);
       tempData[0] = bound_type;

=== modified file 'storage/ndb/test/ndbapi/testDict.cpp'
--- a/storage/ndb/test/ndbapi/testDict.cpp	2008-01-24 15:39:38 +0000
+++ b/storage/ndb/test/ndbapi/testDict.cpp	2008-05-30 08:03:55 +0000
@@ -24,6 +24,8 @@
 #include <random.h>
 #include <NdbAutoPtr.hpp>
 #include <NdbMixRestarter.hpp>
+#include <NdbSqlUtil.hpp>
+#include <NdbEnv.h>
 
 char f_tablename[256];
  
@@ -1967,10 +1969,13 @@
   return NDBT_OK;
 }
 
+#include <NDBT_Tables.hpp>
+
 int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
-  static int acclst[] = { 3001 };
+  static int acclst[] = { 3001, 6200, 6202 };
   static int tuplst[] = { 4007, 4008, 4009, 4010, 4011, 4012 };
-  static int tuxlst[] = { 12001, 12002, 12003, 12004, 12005, 12006 };
+  static int tuxlst[] = { 12001, 12002, 12003, 12004, 12005, 12006, 
+                          6201, 6203 };
   static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
   static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
   static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
@@ -1982,31 +1987,64 @@
   NdbDictionary::Table tab(*ctx->getTab());
   tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
 
+  int errNo = 0;
+  char buf[100];
+  if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
+  {
+    errNo = atoi(buf);
+    ndbout_c("Using errno: %u", errNo);
+  }
+  
   // ordered index on first few columns
   NdbDictionary::Index idx("X");
   idx.setTable(tab.getName());
   idx.setType(NdbDictionary::Index::OrderedIndex);
   idx.setLogging(false);
-  for (int i_hate_broken_compilers = 0;
-       i_hate_broken_compilers < 3 &&
+  for (int cnt = 0, i_hate_broken_compilers = 0;
+       cnt < 3 &&
        i_hate_broken_compilers < tab.getNoOfColumns();
        i_hate_broken_compilers++) {
-    idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
+    if (NdbSqlUtil::check_column_for_ordered_index
+        (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
+        tab.getColumn(i_hate_broken_compilers)->getStorageType() != 
+        NdbDictionary::Column::StorageTypeDisk)
+    {
+      idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
+      cnt++;
+    }
+  }
+
+  for (Uint32 i = 0; i<tab.getNoOfColumns(); i++)
+  {
+    if (tab.getColumn(i)->getStorageType() == 
+        NdbDictionary::Column::StorageTypeDisk)
+    {
+      NDBT_Tables::create_default_tablespace(pNdb);
+      break;
+    }
   }
 
   const int loops = ctx->getNumLoops();
   int result = NDBT_OK;
   (void)pDic->dropTable(tab.getName());
 
+  int dump1 = DumpStateOrd::SchemaResourceSnapshot;
+  int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
+
   for (int l = 0; l < loops; l++) {
     for (unsigned i0 = 0; i0 < acccnt; i0++) {
       unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
       int errval = acclst[j];
+      if (errNo != 0 && errNo != errval)
+        continue;
       g_info << "insert error node=" << nodeId << " value=" << errval << endl;
       CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
              "failed to set error insert");
+      CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
+
       CHECK2(pDic->createTable(tab) != 0,
              "failed to fail after error insert " << errval);
+      CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
       CHECK2(pDic->createTable(tab) == 0,
              pDic->getNdbError());
       CHECK2(pDic->dropTable(tab.getName()) == 0,
@@ -2015,11 +2053,15 @@
     for (unsigned i1 = 0; i1 < tupcnt; i1++) {
       unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
       int errval = tuplst[j];
+      if (errNo != 0 && errNo != errval)
+        continue;
       g_info << "insert error node=" << nodeId << " value=" << errval << endl;
       CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
              "failed to set error insert");
+      CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
       CHECK2(pDic->createTable(tab) != 0,
              "failed to fail after error insert " << errval);
+      CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
       CHECK2(pDic->createTable(tab) == 0,
              pDic->getNdbError());
       CHECK2(pDic->dropTable(tab.getName()) == 0,
@@ -2028,13 +2070,17 @@
     for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
       unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
       int errval = tuxlst[j];
+      if (errNo != 0 && errNo != errval)
+        continue;
       g_info << "insert error node=" << nodeId << " value=" << errval << endl;
       CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
              "failed to set error insert");
       CHECK2(pDic->createTable(tab) == 0,
              pDic->getNdbError());
+      CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
       CHECK2(pDic->createIndex(idx) != 0,
              "failed to fail after error insert " << errval);
+      CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
       CHECK2(pDic->createIndex(idx) == 0,
              pDic->getNdbError());
       CHECK2(pDic->dropTable(tab.getName()) == 0,

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2008-05-21 16:39:51 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2008-05-29 15:58:58 +0000
@@ -1129,3 +1129,9 @@
 args: -n Bug34853 T1
 
 # EOF 2008-04-25
+# 2008-05-29
+max-time: 1200
+cmd: testDict
+args: -l 1 -n FailAddFragment
+
+# EOF 2008-05-29



