List:Commits« Previous MessageNext Message »
From:Monty Taylor Date:June 2 2008 7:17am
Subject:bzr commit into mysql-5.1-telco-6.2 branch (monty:2612)
View as plain text  
#At file:///home/mtaylor/src/mysql/mysql-5.1-telco-6.2/

 2612 Monty Taylor	2008-06-02 [merge]
      Merged.
added:
  mysql-test/include/show_qc_status.inc
  mysql-test/suite/ndb/r/ndb_cache_trans.result
  mysql-test/suite/ndb/t/ndb_cache_trans.test
modified:
  client/mysqltest.c
  sql/ha_ndbcluster.cc
  storage/ndb/src/kernel/blocks/ERROR_codes.txt
  storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
  storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
  storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
  storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
  storage/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
  storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
  storage/ndb/test/ndbapi/testDict.cpp

=== modified file 'client/mysqltest.c'
--- a/client/mysqltest.c	2008-03-30 11:12:27 +0000
+++ b/client/mysqltest.c	2008-05-30 15:39:09 +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_logdir= "";
 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 @@ enum enum_commands {
   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 @@ const char *command_names[]=
   "change_user",
   "mkdir",
   "rmdir",
+  "result_format",
 
   0
 };
@@ -1994,6 +1999,59 @@ void var_query_set(VAR *var, const char 
 }
 
 
+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 @@ my_bool end_of_query(int c)
 
 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 @@ int read_line(char *buf, int size)
       }
       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 @@ int read_line(char *buf, int size)
 
     }
 
+    last_char= c;
+
     if (!skip_char)
     {
       /* Could be a multibyte character */
@@ -5046,9 +5116,10 @@ int read_command(struct st_command** com
     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 @@ int read_command(struct st_command** com
     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 @@ static struct my_option my_long_options[
   {"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 @@ get_one_option(int optid, const struct m
     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);
@@ -7035,6 +7118,7 @@ int main(int argc, char **argv)
       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;
@@ -7151,9 +7235,38 @@ int main(int argc, char **argv)
 	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;

=== 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;

=== 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 @@ int ha_ndbcluster::external_lock(THD *th
   {
     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 @@ ndbcluster_cache_retrieval_allowed(THD *
                                    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 @@ ha_ndbcluster::register_query_cache_tabl
 #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/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 @@ Dbdict:
 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/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2008-05-29 15:58:58 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2008-05-30 08:03:55 +0000
@@ -2061,7 +2061,6 @@ Uint32 Dbdict::getFreeTableRecord(Uint32
   c_tableRecordPool.getPtr(tablePtr, i);
   ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
   initialiseTableRecord(tablePtr);
-  tablePtr.p->tabState = TableRecord::DEFINING;
   return i;
 }
 
@@ -3959,10 +3958,26 @@ Dbdict::execCREATE_TABLE_REQ(Signal* sig
     
     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;
     }
     
@@ -4012,9 +4027,20 @@ Dbdict::execCREATE_TABLE_REQ(Signal* sig
       */
       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();
@@ -6285,7 +6311,7 @@ Dbdict::execTC_SCHVERCONF(Signal* signal
     jam();    \
     parseP->errorCode = error; parseP->errorLine = __LINE__; \
     parseP->errorKey = it.getKey(); \
-    return;   \
+    return;                         \
   }//if
 
 // handleAddTableFailure(signal, __LINE__, allocatedTable);
@@ -6371,10 +6397,11 @@ void Dbdict::handleTabInfoInit(SimplePro
 
   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: {
@@ -6387,7 +6414,6 @@ void Dbdict::handleTabInfoInit(SimplePro
     // Check if no free tables existed.
     /* ---------------------------------------------------------------- */
     tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
-    
     c_tableRecordPool.getPtr(tablePtr);
     break;
   }
@@ -6422,21 +6448,20 @@ void Dbdict::handleTabInfoInit(SimplePro
 /* ---------------------------------------------------------------- */
     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();
@@ -6453,7 +6478,9 @@ void Dbdict::handleTabInfoInit(SimplePro
 	     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);
@@ -6533,6 +6560,7 @@ void Dbdict::handleTabInfoInit(SimplePro
      * 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-29 15:58:58 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2008-05-30 08:03:55 +0000
@@ -1125,6 +1125,7 @@ private:
    * 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 @@ private:
 // 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 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal
       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/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 @@ private:
   };
   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 @@ private:
   };
   typedef Ptr<Frag> FragPtr;
   ArrayPool<Frag> c_fragPool;
+  RSS_AP_SNAPSHOT(c_fragPool);
 
   /*
    * Fragment metadata operation.
@@ -500,6 +502,7 @@ private:
   };
   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 @@ Dbtux::execDUMP_STATE_ORD(Signal* signal
     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/test/ndbapi/testDict.cpp'
--- a/storage/ndb/test/ndbapi/testDict.cpp	2008-05-29 15:58:58 +0000
+++ b/storage/ndb/test/ndbapi/testDict.cpp	2008-05-30 08:03:55 +0000
@@ -1972,9 +1972,10 @@ runCreateDiskTable(NDBT_Context* ctx, ND
 #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]);

Thread
bzr commit into mysql-5.1-telco-6.2 branch (monty:2612) Monty Taylor2 Jun