]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- up to 5.5.21 auto/th/mysql-5_5_21-1
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Sat, 14 Apr 2012 08:51:52 +0000 (08:51 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    bug54330.patch -> 1.1
    bug933969.patch -> 1.1
    bug966844_page_size_error_on_5520_upgrade.patch -> 1.1
    innodb_io_patches.patch -> 1.12
    innodb_pass_corrupt_table.patch -> 1.14
    mysql.spec -> 1.570
    mysql_dump_ignore_ct.patch -> 1.6
    query_cache_enhance.patch -> 1.14
    utf8_general50_ci.patch -> 1.2
    warning_fixes.patch -> 1.3

bug54330.patch [new file with mode: 0644]
bug933969.patch [new file with mode: 0644]
bug966844_page_size_error_on_5520_upgrade.patch [new file with mode: 0644]
innodb_io_patches.patch
innodb_pass_corrupt_table.patch
mysql.spec
mysql_dump_ignore_ct.patch
query_cache_enhance.patch
utf8_general50_ci.patch
warning_fixes.patch

diff --git a/bug54330.patch b/bug54330.patch
new file mode 100644 (file)
index 0000000..850f838
--- /dev/null
@@ -0,0 +1,236 @@
+--- a/storage/innobase/row/row0merge.c
++++ b/storage/innobase/row/row0merge.c
+@@ -1607,22 +1607,28 @@
+       const dict_index_t*     index,  /*!< in: index being created */
+       merge_file_t*           file,   /*!< in/out: file containing
+                                       index entries */
+-      ulint*                  half,   /*!< in/out: half the file */
+       row_merge_block_t*      block,  /*!< in/out: 3 buffers */
+       int*                    tmpfd,  /*!< in/out: temporary file handle */
+-      struct TABLE*           table)  /*!< in/out: MySQL table, for
++      struct TABLE*           table,  /*!< in/out: MySQL table, for
+                                       reporting erroneous key value
+                                       if applicable */
++      ulint*                  num_run,/*!< in/out: Number of runs remain
++                                      to be merged */
++      ulint*                  run_offset) /*!< in/out: Array contains the
++                                      first offset number for each merge
++                                      run */
+ {
+       ulint           foffs0; /*!< first input offset */
+       ulint           foffs1; /*!< second input offset */
+       ulint           error;  /*!< error code */
+       merge_file_t    of;     /*!< output file */
+-      const ulint     ihalf   = *half;
++      const ulint     ihalf   = run_offset[*num_run / 2];
+                               /*!< half the input file */
+-      ulint           ohalf;  /*!< half the output file */
++      ulint           n_run   = 0;
++                              /*!< num of runs generated from this merge */
+       UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
++
+       ut_ad(ihalf < file->offset);
+       of.fd = *tmpfd;
+@@ -1638,17 +1644,20 @@
+ #endif /* POSIX_FADV_SEQUENTIAL */
+       /* Merge blocks to the output file. */
+-      ohalf = 0;
+       foffs0 = 0;
+       foffs1 = ihalf;
++      UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
++
+       for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
+-              ulint   ahalf;  /*!< arithmetic half the input file */
+               if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
+                       return(DB_INTERRUPTED);
+               }
++              /* Remember the offset number for this run */
++              run_offset[n_run++] = of.offset;
++
+               error = row_merge_blocks(index, file, block,
+                                        &foffs0, &foffs1, &of, table);
+@@ -1656,21 +1665,6 @@
+                       return(error);
+               }
+-              /* Record the offset of the output file when
+-              approximately half the output has been generated.  In
+-              this way, the next invocation of row_merge() will
+-              spend most of the time in this loop.  The initial
+-              estimate is ohalf==0. */
+-              ahalf = file->offset / 2;
+-              ut_ad(ohalf <= of.offset);
+-
+-              /* Improve the estimate until reaching half the input
+-              file size, or we can not get any closer to it.  All
+-              comparands should be non-negative when !(ohalf < ahalf)
+-              because ohalf <= of.offset. */
+-              if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
+-                      ohalf = of.offset;
+-              }
+       }
+       /* Copy the last blocks, if there are any. */
+@@ -1680,6 +1674,9 @@
+                       return(DB_INTERRUPTED);
+               }
++              /* Remember the offset number for this run */
++              run_offset[n_run++] = of.offset;
++
+               if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
+                       return(DB_CORRUPTION);
+               }
+@@ -1692,6 +1689,9 @@
+                       return(DB_INTERRUPTED);
+               }
++              /* Remember the offset number for this run */
++              run_offset[n_run++] = of.offset;
++
+               if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
+                       return(DB_CORRUPTION);
+               }
+@@ -1703,10 +1703,23 @@
+               return(DB_CORRUPTION);
+       }
++      ut_ad(n_run <= *num_run);
++
++      *num_run = n_run;
++
++      /* Each run can contain one or more offsets. As merge goes on,
++      the number of runs (to merge) will reduce until we have one
++      single run. So the number of runs will always be smaller than
++      the number of offsets in file */
++      ut_ad((*num_run) <= file->offset);
++
++      /* The number of offsets in output file is always equal or
++      smaller than input file */
++      ut_ad(of.offset <= file->offset);
++
+       /* Swap file descriptors for the next pass. */
+       *tmpfd = file->fd;
+       *file = of;
+-      *half = ohalf;
+       UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
+@@ -1731,27 +1744,44 @@
+                                       if applicable */
+ {
+       ulint   half = file->offset / 2;
++      ulint   num_runs;
++      ulint*  run_offset;
++      ulint   error = DB_SUCCESS;
++
++      /* Record the number of merge runs we need to perform */
++      num_runs = file->offset;
++
++      /* If num_runs are less than 1, nothing to merge */
++      if (num_runs <= 1) {
++              return(error);
++      }
++
++      /* "run_offset" records each run's first offset number */
++      run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
++
++      /* This tells row_merge() where to start for the first round
++      of merge. */
++      run_offset[half] = half;
+       /* The file should always contain at least one byte (the end
+       of file marker).  Thus, it must be at least one block. */
+       ut_ad(file->offset > 0);
++      /* Merge the runs until we have one big run */
+       do {
+-              ulint   error;
++              error = row_merge(trx, index, file, block, tmpfd,
++                                table, &num_runs, run_offset);
+-              error = row_merge(trx, index, file, &half,
+-                                block, tmpfd, table);
++              UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
+               if (error != DB_SUCCESS) {
+-                      return(error);
++                      break;
+               }
++      } while (num_runs > 1);
+-              /* half > 0 should hold except when the file consists
+-              of one block.  No need to merge further then. */
+-              ut_ad(half > 0 || file->offset == 1);
+-      } while (half < file->offset && half > 0);
++      mem_free(run_offset);
+-      return(DB_SUCCESS);
++      return(error);
+ }
+ /*************************************************************//**
+--- /dev/null
++++ b/mysql-test/suite/innodb/r/bug54330.result
+@@ -0,0 +1,13 @@
++DROP TABLE IF EXISTS t1;
++CREATE TABLE t1 (
++id BIGINT(20) AUTO_INCREMENT PRIMARY KEY,
++bar BIGINT(20)
++) ENGINE=InnoDB;
++SELECT COUNT(*) FROM t1;
++COUNT(*)
++517672
++ALTER TABLE t1 ADD INDEX baz (bar);
++SELECT COUNT(*) FROM t1 FORCE INDEX (baz);
++COUNT(*)
++517672
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/suite/innodb/t/bug54330.test
+@@ -0,0 +1,38 @@
++# Testcase for MySQL bug #54330 - broken fast index creation
++
++--disable_warnings
++DROP TABLE IF EXISTS t1;
++--enable_warnings
++
++CREATE TABLE t1 (
++       id BIGINT(20) AUTO_INCREMENT PRIMARY KEY,
++       bar BIGINT(20)
++) ENGINE=InnoDB;
++
++--disable_query_log
++SET @old_autocommit=@@AUTOCOMMIT;
++SET AUTOCOMMIT=0;
++let $1= 515641;
++while ($1)
++{
++  eval INSERT INTO t1 (bar) VALUES (NULL);
++  dec $1;
++}
++let $1= 2031;
++while ($1)
++{
++  eval INSERT INTO t1 (bar) VALUES ($1);
++  dec $1;
++}
++COMMIT;
++SET AUTOCOMMIT=@old_autocommit;
++--enable_query_log
++
++SELECT COUNT(*) FROM t1;
++
++ALTER TABLE t1 ADD INDEX baz (bar);
++
++# With the bug present this will differ from the SELECT above!
++SELECT COUNT(*) FROM t1 FORCE INDEX (baz);
++
++DROP TABLE t1;
diff --git a/bug933969.patch b/bug933969.patch
new file mode 100644 (file)
index 0000000..2590716
--- /dev/null
@@ -0,0 +1,92 @@
+--- /dev/null
++++ b/mysql-test/r/percona_bug933969.result
+@@ -0,0 +1,16 @@
++RESET MASTER;
++DROP TABLE IF EXISTS t1;
++CREATE TABLE t1 (word VARCHAR(20));
++INSERT INTO t1 VALUES ("hamite");
++INSERT INTO t1 VALUES ("hoho");
++INSERT INTO t1 VALUES ("znamenito");
++INSERT INTO t1 VALUES ("mrachny");
++INSERT INTO t1 VALUES ("mrak");
++INSERT INTO t1 VALUES ("zhut");
++INSERT INTO t1 VALUES ("parnisha");
++INSERT INTO t1 VALUES ("krrasota!");
++INSERT INTO t1 VALUES ("podumayesh");
++INSERT INTO t1 VALUES ("ogo!");
++FLUSH LOGS;
++DROP TABLE t1;
++RESET MASTER;
+--- /dev/null
++++ b/mysql-test/t/percona_bug933969.test
+@@ -0,0 +1,42 @@
++###################### percona_bug933969.test ########################
++# Bug #933969: mysqlbinlog doesn't accept stdin                      #
++#                                                                    #
++# The goal of this testcase is to test that mysqlbinlog handle       #
++# stdin correctly when stdin is pipe.                                #
++# i.e. "cat log | mysqlbinlog -" don't cause mysqlbinlog failure     #
++######################################################################
++-- source include/have_log_bin.inc
++-- source include/not_windows.inc
++-- source include/not_embedded.inc
++
++# deletes all the binary logs
++RESET MASTER;
++
++--disable_warnings
++DROP TABLE IF EXISTS t1;
++--enable_warnings
++
++# produce some statements for binlog
++
++CREATE TABLE t1 (word VARCHAR(20));
++
++INSERT INTO t1 VALUES ("hamite");
++INSERT INTO t1 VALUES ("hoho");
++INSERT INTO t1 VALUES ("znamenito");
++INSERT INTO t1 VALUES ("mrachny");
++INSERT INTO t1 VALUES ("mrak");
++INSERT INTO t1 VALUES ("zhut");
++INSERT INTO t1 VALUES ("parnisha");
++INSERT INTO t1 VALUES ("krrasota!");
++INSERT INTO t1 VALUES ("podumayesh");
++INSERT INTO t1 VALUES ("ogo!");
++
++FLUSH LOGS;
++
++# run mysqlbinlog and make sure it ends normally
++
++let $MYSQLD_DATADIR= `SELECT @@datadir`;
++--system cat $MYSQLD_DATADIR/master-bin.000001 | $MYSQL_BINLOG - >/dev/null
++
++DROP TABLE t1;
++RESET MASTER;
+--- a/client/mysqlbinlog.cc
++++ b/client/mysqlbinlog.cc
+@@ -1760,7 +1760,7 @@
+   }
+   pos= my_b_tell(file);
+-  my_b_seek(file, (my_off_t)0);
++  DBUG_ASSERT(pos == 0);
+   if (my_b_read(file, header, sizeof(header)))
+   {
+     error("Failed reading header; probably an empty file.");
+@@ -1920,7 +1920,7 @@
+     /* read from normal file */
+     if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
+       return ERROR_STOP;
+-    if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
++    if (init_io_cache(file, fd, 0, READ_CACHE, (my_off_t) 0, 0,
+                     MYF(MY_WME | MY_NABP)))
+     {
+       my_close(fd, MYF(MY_WME));
+@@ -1928,6 +1928,7 @@
+     }
+     if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
+       goto end;
++    my_b_seek(file, start_position_mot);
+   }
+   else
+   {
diff --git a/bug966844_page_size_error_on_5520_upgrade.patch b/bug966844_page_size_error_on_5520_upgrade.patch
new file mode 100644 (file)
index 0000000..826ad4c
--- /dev/null
@@ -0,0 +1,22 @@
+Bug#966844 "page size 1024 but the only supported page size in this release is=16384" error on upgrade to 5.5.2[01]
+
+Patch is from http://bugs.mysql.com/bug.php?id=64160
+http://bugs.mysql.com/file.php?id=18031&text=1
+By Kevin Lewis
+
+Adapted to Percona Server by Stewart Smith
+
+--- a/storage/innobase/srv/srv0start.c
++++ b/storage/innobase/srv/srv0start.c
+@@ -925,8 +925,9 @@
+ #endif /* UNIV_LOG_ARCHIVE */
+                               min_flushed_lsn, max_flushed_lsn);
+-                      if (UNIV_PAGE_SIZE
+-                          != fsp_flags_get_page_size(flags)) {
++                      if (!one_opened
++                          && UNIV_PAGE_SIZE
++                             != fsp_flags_get_page_size(flags)) {
+                               ut_print_timestamp(stderr);
+                               fprintf(stderr,
index 43511318a634e0c420cb85677f9de9e29cf70e9f..97e546bfd9f52f1ffaf17be9be97f24f8759fea0 100644 (file)
        }
  
        return(count);
-@@ -1940,6 +1988,22 @@
-               buf_pool = buf_pool_from_array(i);
-+              if (lsn_limit != IB_ULONGLONG_MAX) {
-+                      buf_page_t*     bpage;
-+
-+                      buf_flush_list_mutex_enter(buf_pool);
-+                      bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
-+                      if (!bpage
-+                          || bpage->oldest_modification >= lsn_limit) {
-+
-+                              buf_flush_list_mutex_exit(buf_pool);
-+                              continue;
-+                      } else {
-+
-+                              buf_flush_list_mutex_exit(buf_pool);
-+                      }
-+              }
-+
-               if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) {
-                       /* We have two choices here. If lsn_limit was
-                       specified then skipping an instance of buffer
 --- a/storage/innobase/buf/buf0rea.c
 +++ b/storage/innobase/buf/buf0rea.c
 @@ -427,6 +427,10 @@
  
  static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
    PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
-@@ -11450,6 +11476,135 @@
+@@ -11442,6 +11468,127 @@
    "trigger a readahead.",
    NULL, NULL, 56, 0, 64, 0);
  
 +  PLUGIN_VAR_RQCMDARG,
 +  "Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)",
 +  NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib);
-+
-+#ifdef UNIV_DEBUG
-+static MYSQL_SYSVAR_ULONG(flush_checkpoint_debug, srv_flush_checkpoint_debug,
-+  PLUGIN_VAR_RQCMDARG,
-+  "Debug flags for InnoDB flushing and checkpointing (0=none,"
-+  "1=stop preflush and checkpointing)",
-+  NULL, NULL, 0, 0, 1, 0);
-+#endif
 +
  static struct st_mysql_sys_var* innobase_system_variables[]= {
    MYSQL_SYSVAR(additional_mem_pool_size),
    MYSQL_SYSVAR(autoextend_increment),
-@@ -11470,6 +11625,7 @@
+@@ -11462,6 +11609,7 @@
    MYSQL_SYSVAR(file_format_check),
    MYSQL_SYSVAR(file_format_max),
    MYSQL_SYSVAR(flush_log_at_trx_commit),
    MYSQL_SYSVAR(flush_method),
    MYSQL_SYSVAR(force_recovery),
    MYSQL_SYSVAR(large_prefix),
-@@ -11509,6 +11665,13 @@
+@@ -11501,6 +11649,13 @@
    MYSQL_SYSVAR(show_verbose_locks),
    MYSQL_SYSVAR(show_locks_held),
    MYSQL_SYSVAR(version),
    MYSQL_SYSVAR(use_sys_malloc),
    MYSQL_SYSVAR(use_native_aio),
    MYSQL_SYSVAR(change_buffering),
-@@ -11521,6 +11684,9 @@
-   MYSQL_SYSVAR(purge_threads),
-   MYSQL_SYSVAR(purge_batch_size),
-   MYSQL_SYSVAR(rollback_segments),
-+#ifdef UNIV_DEBUG
-+  MYSQL_SYSVAR(flush_checkpoint_debug),
-+#endif
-   NULL
- };
 --- a/storage/innobase/ibuf/ibuf0ibuf.c
 +++ b/storage/innobase/ibuf/ibuf0ibuf.c
 @@ -523,8 +523,10 @@
  /*-------------------------------------------*/
  
  extern ulint  srv_n_rows_inserted;
-@@ -255,6 +266,9 @@
- extern        ibool   srv_print_buf_io;
- extern        ibool   srv_print_log_io;
- extern        ibool   srv_print_latch_waits;
-+
-+extern        ulint   srv_flush_checkpoint_debug;
-+
- #else /* UNIV_DEBUG */
- # define srv_print_thread_releases    FALSE
- # define srv_print_lock_waits         FALSE
-@@ -399,8 +413,9 @@
+@@ -399,8 +410,9 @@
                                when writing data files, but do flush
                                after writing to log files */
        SRV_UNIX_NOSYNC,        /*!< do not flush after writing */
                log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
        }
  
-@@ -1655,10 +1686,13 @@
-               recv_apply_hashed_log_recs(TRUE);
-       }
-+ retry:
-       n_pages = buf_flush_list(ULINT_MAX, new_oldest);
--      if (sync) {
--              buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
-+      if (sync && n_pages != 0) {
-+              //buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
-+              os_thread_sleep(100000);
-+              goto retry;
-       }
-       if (n_pages == ULINT_UNDEFINED) {
-@@ -1979,6 +2013,13 @@
- {
-       ib_uint64_t     oldest_lsn;
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug == 1) {
-+
-+              return TRUE;
-+      }
-+#endif
-+
-       if (recv_recovery_is_on()) {
-               recv_apply_hashed_log_recs(TRUE);
-       }
-@@ -2070,7 +2111,11 @@
-                                       physical write will always be made to
-                                       log files */
- {
--      /* Preflush pages synchronously */
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug == 1)
-+              return;
-+#endif
-+/* Preflush pages synchronously */
-       while (!log_preflush_pool_modified_pages(lsn, TRUE));
-@@ -2096,7 +2141,13 @@
-       ibool           checkpoint_sync;
-       ibool           do_checkpoint;
-       ibool           success;
--loop:
-+
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug == 1)
-+              return;
-+#endif
-+
-+ loop:
-       sync = FALSE;
-       checkpoint_sync = FALSE;
-       do_checkpoint = FALSE;
-@@ -2119,13 +2170,15 @@
-               /* A flush is urgent: we have to do a synchronous preflush */
+@@ -2120,10 +2151,10 @@
  
                sync = TRUE;
--              advance = 2 * (age - log->max_modified_age_sync);
+               advance = 2 * (age - log->max_modified_age_sync);
 -      } else if (age > log->max_modified_age_async) {
-+              advance = age - log->max_modified_age_sync;
 +      } else if (age > log_max_modified_age_async()) {
  
                /* A flush is not urgent: we do an asynchronous preflush */
 -              advance = age - log->max_modified_age_async;
 +              advance = age - log_max_modified_age_async();
-+              log->check_flush_or_checkpoint = FALSE;
        } else {
                advance = 0;
-+              log->check_flush_or_checkpoint = FALSE;
        }
-       checkpoint_age = log->lsn - log->last_checkpoint_lsn;
-@@ -2137,14 +2190,14 @@
+@@ -2137,7 +2168,7 @@
  
                do_checkpoint = TRUE;
  
                /* A checkpoint is not urgent: do it asynchronously */
  
                do_checkpoint = TRUE;
--              log->check_flush_or_checkpoint = FALSE;
-+              //log->check_flush_or_checkpoint = FALSE;
-       } else {
--              log->check_flush_or_checkpoint = FALSE;
-+              //log->check_flush_or_checkpoint = FALSE;
-       }
-       mutex_exit(&(log->mutex));
-@@ -2152,6 +2205,7 @@
-       if (advance) {
-               ib_uint64_t     new_oldest = oldest_lsn + advance;
-+retry:
-               success = log_preflush_pool_modified_pages(new_oldest, sync);
-               /* If the flush succeeded, this thread has done its part
-@@ -2166,7 +2220,7 @@
-                       log->check_flush_or_checkpoint = TRUE;
-                       mutex_exit(&(log->mutex));
--                      goto loop;
-+                      goto retry;
-               }
-       }
-@@ -2607,7 +2661,7 @@
+@@ -2607,7 +2638,7 @@
  
        mutex_exit(&(log_sys->mutex));
  
  
        mutex_enter(&(log_sys->mutex));
  
-@@ -3044,7 +3098,11 @@
- log_check_margins(void)
- /*===================*/
- {
--loop:
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug == 1)
-+              return;
-+#endif
-+ loop:
-       log_flush_margin();
-       log_checkpoint_margin();
-@@ -3349,6 +3407,17 @@
+@@ -3349,6 +3380,17 @@
                log_sys->flushed_to_disk_lsn,
                log_sys->last_checkpoint_lsn);
  
  /*-------------------------------------------*/
  UNIV_INTERN ulong     srv_n_spin_wait_rounds  = 30;
  UNIV_INTERN ulong     srv_n_free_tickets_to_enter = 500;
-@@ -417,6 +429,9 @@
- UNIV_INTERN ibool     srv_print_buf_io                = FALSE;
- UNIV_INTERN ibool     srv_print_log_io                = FALSE;
- UNIV_INTERN ibool     srv_print_latch_waits           = FALSE;
-+
-+UNIV_INTERN ulong     srv_flush_checkpoint_debug = 0;
-+
- #endif /* UNIV_DEBUG */
- UNIV_INTERN ulint             srv_n_rows_inserted             = 0;
-@@ -2713,7 +2728,7 @@
+@@ -2713,7 +2725,7 @@
  
        ut_ad(!mutex_own(&kernel_mutex));
  
  
        do {
                /* Check for shutdown and change in purge config. */
-@@ -2746,6 +2761,7 @@
+@@ -2746,6 +2758,7 @@
        ulint           n_pages_purged  = 0;
        ulint           n_bytes_merged;
        ulint           n_pages_flushed;
        ulint           n_bytes_archived;
        ulint           n_tables_to_drop;
        ulint           n_ios;
-@@ -2753,7 +2769,20 @@
+@@ -2753,7 +2766,20 @@
        ulint           n_ios_very_old;
        ulint           n_pend_ios;
        ulint           next_itr_time;
  
  #ifdef UNIV_DEBUG_THREAD_CREATION
        fprintf(stderr, "Master thread starts, id %lu\n",
-@@ -2775,6 +2804,9 @@
+@@ -2775,6 +2801,9 @@
  
        mutex_exit(&kernel_mutex);
  
  loop:
        /*****************************************************************/
        /* ---- When there is database activity by users, we cycle in this
-@@ -2805,9 +2837,13 @@
+@@ -2805,9 +2834,13 @@
        /* Sleep for 1 second on entrying the for loop below the first time. */
        next_itr_time = ut_time_ms() + 1000;
  
                /* ALTER TABLE in MySQL requires on Unix that the table handler
                can drop tables lazily after there no longer are SELECT
                queries to them. */
-@@ -2831,6 +2867,7 @@
+@@ -2831,6 +2864,7 @@
                srv_main_thread_op_info = "sleeping";
                srv_main_1_second_loops++;
  
                if (next_itr_time > cur_time
                    && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
  
-@@ -2841,10 +2878,26 @@
+@@ -2841,10 +2875,26 @@
                                        (next_itr_time - cur_time)
                                         * 1000));
                        srv_main_sleeps++;
  
                /* Flush logs if needed */
                srv_sync_log_buffer_in_background();
-@@ -2864,7 +2917,7 @@
+@@ -2864,7 +2914,7 @@
                if (n_pend_ios < SRV_PEND_IO_THRESHOLD
                    && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
                        srv_main_thread_op_info = "doing insert buffer merge";
  
                        /* Flush logs if needed */
                        srv_sync_log_buffer_in_background();
-@@ -2881,7 +2934,11 @@
+@@ -2881,7 +2931,11 @@
                        n_pages_flushed = buf_flush_list(
                                PCT_IO(100), IB_ULONGLONG_MAX);
  
  
                        /* Try to keep the rate of flushing of dirty
                        pages such that redo log generation does not
-@@ -2897,6 +2954,224 @@
+@@ -2897,6 +2951,224 @@
                                                n_flush,
                                                IB_ULONGLONG_MAX);
                        }
                }
  
                if (srv_activity_count == old_activity_count) {
-@@ -2945,12 +3220,12 @@
+@@ -2945,12 +3217,12 @@
        even if the server were active */
  
        srv_main_thread_op_info = "doing insert buffer merge";
                srv_main_thread_op_info = "master purging";
  
                srv_master_do_purge();
-@@ -2982,11 +3257,18 @@
-                         PCT_IO(10), IB_ULONGLONG_MAX);
-       }
--      srv_main_thread_op_info = "making checkpoint";
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug != 1) {
-+#endif
--      /* Make a new checkpoint about once in 10 seconds */
-+              srv_main_thread_op_info = "making checkpoint";
--      log_checkpoint(TRUE, FALSE);
-+              /* Make a new checkpoint about once in 10 seconds */
-+
-+              log_checkpoint(TRUE, FALSE);
-+#ifdef UNIV_DEBUG
-+      }
-+#endif
-       srv_main_thread_op_info = "reserving kernel mutex";
-@@ -3028,7 +3310,7 @@
+@@ -3028,7 +3300,7 @@
                }
        }
  
                srv_main_thread_op_info = "master purging";
  
                srv_master_do_purge();
-@@ -3053,7 +3335,7 @@
+@@ -3053,7 +3325,7 @@
                buf_flush_list below. Otherwise, the system favors
                clean pages over cleanup throughput. */
                n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
        }
  
        srv_main_thread_op_info = "reserving kernel mutex";
-@@ -3065,6 +3347,10 @@
-       }
-       mutex_exit(&kernel_mutex);
-+#ifdef UNIV_DEBUG
-+      if (srv_flush_checkpoint_debug == 1)
-+              goto skip_flush;
-+#endif
- flush_loop:
-       srv_main_thread_op_info = "flushing buffer pool pages";
-       srv_main_flush_loops++;
-@@ -3105,6 +3391,9 @@
-               goto flush_loop;
-       }
-+#ifdef UNIV_DEBUG
-+skip_flush:
-+#endif
-       srv_main_thread_op_info = "reserving kernel mutex";
-       mutex_enter(&kernel_mutex);
-@@ -3193,6 +3482,7 @@
+@@ -3193,6 +3465,7 @@
        srv_slot_t*     slot;
        ulint           retries = 0;
        ulint           n_total_purged = ULINT_UNDEFINED;
  
        ut_a(srv_n_purge_threads == 1);
  
-@@ -3213,9 +3503,12 @@
+@@ -3213,9 +3486,12 @@
  
        mutex_exit(&kernel_mutex);
  
  
                /* If there are very few records to purge or the last
                purge didn't purge any records then wait for activity.
-@@ -3262,6 +3555,16 @@
+@@ -3262,6 +3538,16 @@
                } while (n_pages_purged > 0 && !srv_fast_shutdown);
  
                srv_sync_log_buffer_in_background();
 +# SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_flushed';
 +
 +DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/innodb/r/percona_sync_flush.result
-@@ -0,0 +1,35 @@
-+DROP TABLE IF EXISTS t1;
-+CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
-+SET @@global.innodb_flush_checkpoint_debug=1;
-+INSERT INTO t1(foo) VALUES ('a'), ('b');
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+INSERT INTO t1(foo) SELECT foo FROM t1;
-+UPDATE t1 SET foo='c';
-+SET @@global.innodb_flush_checkpoint_debug=0;
-+UPDATE t1 SET foo='d' WHERE foo='c';
-+DROP TABLE t1;
---- /dev/null
-+++ b/mysql-test/suite/innodb/t/percona_sync_flush.test
-@@ -0,0 +1,33 @@
-+# Test for InnoDB sync state flushing.
-+
-+--source include/have_innodb.inc
-+--source include/have_debug.inc
-+
-+--disable_warnings
-+DROP TABLE IF EXISTS t1;
-+--enable_warnings
-+
-+CREATE TABLE t1 (id INT AUTO_INCREMENT, foo CHAR(255), PRIMARY KEY (id)) ENGINE=InnoDB;
-+
-+# It is hard to get to InnoDB sync state flushing in MTR with regular workload.  Perhaps
-+# it is possible with many parallel connections, but that would be brittle anyway.
-+# So, just disable preflushing and checkpointing and issue simple workload.
-+SET @@global.innodb_flush_checkpoint_debug=1;
-+
-+INSERT INTO t1(foo) VALUES ('a'), ('b');
-+
-+let $rep=0;
-+while ($rep < 14)
-+{
-+        INSERT INTO t1(foo) SELECT foo FROM t1;
-+        UPDATE t1 SET foo='c';
-+        inc $rep;
-+}
-+
-+# By now checkpoint age should be well past sync flush point.  Allow
-+# preflushing/checkpointing again and do some work in order to do the sync flush.
-+SET @@global.innodb_flush_checkpoint_debug=0;
-+
-+UPDATE t1 SET foo='d' WHERE foo='c';
-+
-+DROP TABLE t1;
---- a/mysql-test/suite/sys_vars/r/all_vars.result
-+++ b/mysql-test/suite/sys_vars/r/all_vars.result
-@@ -4,6 +4,7 @@
- insert into t2 select variable_name from information_schema.global_variables;
- insert into t2 select variable_name from information_schema.session_variables;
- delete from t2 where variable_name='innodb_change_buffering_debug';
-+delete from t2 where variable_name='innodb_flush_checkpoint_debug';
- update t2 set variable_name= replace(variable_name, "PERFORMANCE_SCHEMA_", "PFS_");
- select variable_name as `There should be *no* long test name listed below:` from t2
- where length(variable_name) > 50;
---- a/mysql-test/suite/sys_vars/t/all_vars.test
-+++ b/mysql-test/suite/sys_vars/t/all_vars.test
-@@ -47,8 +47,9 @@
- insert into t2 select variable_name from information_schema.global_variables;
- insert into t2 select variable_name from information_schema.session_variables;
--# This is only present in debug builds.
-+# These are only present in debug builds.
- delete from t2 where variable_name='innodb_change_buffering_debug';
-+delete from t2 where variable_name='innodb_flush_checkpoint_debug';
- # Performance schema variables are too long for files named
- # 'mysql-test/suite/sys_vars/t/' ...
 --- a/mysql-test/suite/innodb/t/innodb_cmp_drop_table-master.opt
 +++ b/mysql-test/suite/innodb/t/innodb_cmp_drop_table-master.opt
 @@ -1 +1 @@
index fcd4909eb6706c49d091d5672498756d6c85e504..63b1c657585242136a287549965e350780df46f3 100644 (file)
@@ -7,7 +7,7 @@
 # should be done or reviewed by the maintainer!
 --- a/storage/innobase/btr/btr0btr.c
 +++ b/storage/innobase/btr/btr0btr.c
-@@ -692,6 +692,12 @@
+@@ -713,6 +713,12 @@
  
        block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
                              index, mtr);
 +      }
 +      ut_a(block);
 +
-       ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
-            == dict_table_is_comp(index->table));
+       btr_assert_not_corrupted(block, index);
  #ifdef UNIV_BTR_DEBUG
-@@ -978,6 +984,12 @@
+       if (!dict_index_is_ibuf(index)) {
+@@ -998,6 +1004,12 @@
  
        root = btr_root_get(index, &mtr);
  
@@ -33,7 +33,7 @@
        if (flag == BTR_N_LEAF_PAGES) {
                seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
  
-@@ -1437,6 +1449,13 @@
+@@ -1457,6 +1469,13 @@
  
        root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
                            NULL, &mtr);
@@ -47,7 +47,7 @@
  #ifdef UNIV_BTR_DEBUG
        ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
                                    + root, space));
-@@ -1460,6 +1479,12 @@
+@@ -1480,6 +1499,12 @@
  
        root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
                            NULL, &mtr);
@@ -60,7 +60,7 @@
  #ifdef UNIV_BTR_DEBUG
        ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
                                    + root, space));
-@@ -1493,6 +1518,11 @@
+@@ -1513,6 +1538,11 @@
        block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
                              NULL, mtr);
  
  #ifdef UNIV_BTR_DEBUG
                ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
  #endif /* UNIV_BTR_DEBUG */
-@@ -590,6 +620,19 @@
+@@ -595,6 +625,19 @@
                file, line, mtr);
  
        if (block == NULL) {
                /* This must be a search to perform an insert/delete
                mark/ delete; try using the insert/delete buffer */
  
-@@ -664,6 +707,16 @@
+@@ -669,6 +712,16 @@
        block->check_index_page_at_flush = TRUE;
        page = buf_block_get_frame(block);
  
        if (rw_latch != RW_NO_LATCH) {
  #ifdef UNIV_ZIP_DEBUG
                const page_zip_des_t*   page_zip
-@@ -857,6 +910,17 @@
+@@ -862,6 +915,17 @@
                                         RW_NO_LATCH, NULL, BUF_GET,
                                         file, line, mtr);
                page = buf_block_get_frame(block);
                ut_ad(index->id == btr_page_get_index_id(page));
  
                block->check_index_page_at_flush = TRUE;
-@@ -977,6 +1041,14 @@
+@@ -982,6 +1046,14 @@
                                         RW_NO_LATCH, NULL, BUF_GET,
                                         file, line, mtr);
                page = buf_block_get_frame(block);
                ut_ad(index->id == btr_page_get_index_id(page));
  
                if (height == ULINT_UNDEFINED) {
-@@ -1190,6 +1262,12 @@
+@@ -1195,6 +1267,12 @@
        *big_rec = NULL;
  
        block = btr_cur_get_block(cursor);
        page = buf_block_get_frame(block);
        index = cursor->index;
        zip_size = buf_block_get_zip_size(block);
-@@ -2922,6 +3000,11 @@
+@@ -2927,6 +3005,11 @@
  
        block = btr_cur_get_block(cursor);
  
        ut_ad(page_is_leaf(buf_block_get_frame(block)));
  
        rec = btr_cur_get_rec(cursor);
-@@ -3630,6 +3713,11 @@
+@@ -3635,6 +3718,11 @@
  
                page = btr_cur_get_page(&cursor);
  
  /**************************************************************//**
  Allocates memory for a persistent cursor object and initializes the cursor.
  @return       own: persistent cursor */
-@@ -102,6 +102,12 @@
+@@ -114,6 +114,12 @@
        ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
  
        block = btr_pcur_get_block(cursor);
        index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
  
        page_cursor = btr_pcur_get_page_cur(cursor);
-@@ -397,6 +403,15 @@
+@@ -409,6 +415,15 @@
                                   cursor->latch_mode,
                                   btr_pcur_get_btr_cur(cursor)->index, mtr);
        next_page = buf_block_get_frame(next_block);
  
  /* prototypes for new functions added to ha_innodb.cc */
  trx_t* innobase_get_trx();
-@@ -1151,6 +1152,11 @@
+@@ -1150,6 +1151,11 @@
                        ready = buf_flush_ready_for_replace(&block->page);
                        mutex_exit(&block->mutex);
  
                        if (!ready) {
  
                                return(block);
-@@ -1947,6 +1953,13 @@
+@@ -1946,6 +1952,13 @@
                return(NULL);
        }
  
        block_mutex = buf_page_get_mutex_enter(bpage);
  
        rw_lock_s_unlock(&buf_pool->page_hash_latch);
-@@ -2526,6 +2539,13 @@
+@@ -2525,6 +2538,13 @@
                return(NULL);
        }
  
        switch (buf_block_get_state(block)) {
                buf_page_t*     bpage;
                ibool           success;
-@@ -3200,6 +3220,7 @@
+@@ -3199,6 +3219,7 @@
        bpage->newest_modification = 0;
        bpage->oldest_modification = 0;
        HASH_INVALIDATE(bpage, hash);
  #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
        bpage->file_page_was_freed = FALSE;
  #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
-@@ -3838,6 +3859,7 @@
+@@ -3837,6 +3858,7 @@
                                (ulong) bpage->offset);
                }
  
                /* From version 3.23.38 up we store the page checksum
                to the 4 first bytes of the page end lsn field */
  
-@@ -3879,6 +3901,23 @@
+@@ -3878,6 +3900,23 @@
                              REFMAN "forcing-innodb-recovery.html\n"
                              "InnoDB: about forcing recovery.\n", stderr);
  
                        if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
                                /* If page space id is larger than TRX_SYS_SPACE
                                (0), we will attempt to mark the corresponding
-@@ -3895,6 +3934,7 @@
+@@ -3894,6 +3933,7 @@
                                }
                        }
                }
  
                if (recv_recovery_is_on()) {
                        /* Pages must be uncompressed for crash recovery. */
-@@ -3904,8 +3944,11 @@
+@@ -3903,8 +3943,11 @@
  
                if (uncompressed && !recv_no_ibuf_operations) {
                        ibuf_merge_or_delete_for_page(
        if (descr != NULL) {
 --- a/storage/innobase/handler/ha_innodb.cc
 +++ b/storage/innobase/handler/ha_innodb.cc
-@@ -4011,6 +4011,12 @@
+@@ -4024,6 +4024,12 @@
                DBUG_RETURN(1);
        }
  
 +              DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 +      }
 +
-       /* Create buffers for packing the fields of a record. Why
-       table->reclength did not work here? Obviously, because char
-       fields when packed actually became 1 byte longer, when we also
-@@ -4038,6 +4044,19 @@
+       /* Will be allocated if it is needed in ::update_row() */
+       upd_buf = NULL;
+       upd_buf_size = 0;
+@@ -4043,6 +4049,17 @@
        /* Get pointer to a table object in InnoDB dictionary cache */
        ib_table = dict_table_get(norm_name, TRUE);
-       
 +      if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
 +              free_share(share);
-+              my_free(upd_buff);
++              my_free(upd_buf);
++              upd_buf = NULL;
++              upd_buf_size = 0;
 +
 +              DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 +      }
 +
 +      share->ib_table = ib_table;
-+
-+
-+
-+
 +
        if (NULL == ib_table) {
                if (is_part && retries < 10) {
-                       ++retries;
-@@ -5187,6 +5206,10 @@
+                       /* MySQL partition engine hard codes the file name
+@@ -5263,6 +5280,10 @@
  
        ha_statistic_increment(&SSV::ha_write_count);
  
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
                table->timestamp_field->set_time();
  
-@@ -5403,6 +5426,10 @@
+@@ -5479,6 +5500,10 @@
  func_exit:
        innobase_active_small();
  
        DBUG_RETURN(error_result);
  }
  
-@@ -5580,6 +5607,10 @@
+@@ -5673,6 +5698,10 @@
  
        ha_statistic_increment(&SSV::ha_update_count);
  
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
                table->timestamp_field->set_time();
  
-@@ -5668,6 +5699,10 @@
+@@ -5760,6 +5789,10 @@
  
        innobase_active_small();
  
        DBUG_RETURN(error);
  }
  
-@@ -5689,6 +5724,10 @@
+@@ -5781,6 +5814,10 @@
  
        ha_statistic_increment(&SSV::ha_delete_count);
  
        if (!prebuilt->upd_node) {
                row_get_prebuilt_update_vector(prebuilt);
        }
-@@ -5715,6 +5754,10 @@
+@@ -5807,6 +5844,10 @@
  
        innobase_active_small();
  
        DBUG_RETURN(error);
  }
  
-@@ -5954,6 +5997,10 @@
+@@ -6046,6 +6087,10 @@
  
        ha_statistic_increment(&SSV::ha_read_key_count);
  
        index = prebuilt->index;
  
        if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
-@@ -6022,6 +6069,10 @@
+@@ -6113,6 +6158,10 @@
                ret = DB_UNSUPPORTED;
        }
  
        switch (ret) {
        case DB_SUCCESS:
                error = 0;
-@@ -6136,6 +6187,10 @@
+@@ -6227,6 +6276,10 @@
  {
        DBUG_ENTER("change_active_index");
  
        ut_ad(user_thd == ha_thd());
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
  
-@@ -6249,6 +6304,10 @@
+@@ -6340,6 +6393,10 @@
  
        DBUG_ENTER("general_fetch");
  
        ut_a(prebuilt->trx == thd_to_trx(user_thd));
  
        innodb_srv_conc_enter_innodb(prebuilt->trx);
-@@ -6258,6 +6317,10 @@
+@@ -6349,6 +6406,10 @@
  
        innodb_srv_conc_exit_innodb(prebuilt->trx);
  
        switch (ret) {
        case DB_SUCCESS:
                error = 0;
-@@ -7524,10 +7587,18 @@
+@@ -7615,10 +7676,18 @@
  
        update_thd(ha_thd());
  
        error = convert_error_code_to_mysql(error, prebuilt->table->flags,
                                            NULL);
  
-@@ -8039,6 +8110,16 @@
+@@ -8124,6 +8193,16 @@
        return(ranges + (double) rows / (double) total_rows * time_for_scan);
  }
  
  /*********************************************************************//**
  Calculates the key number used inside MySQL for an Innobase index. We will
  first check the "index translation table" for a match of the index to get
-@@ -8216,7 +8297,7 @@
+@@ -8301,7 +8380,7 @@
        ib_table = prebuilt->table;
  
        if (flag & HA_STATUS_TIME) {
                        /* In sql_show we call with this flag: update
                        then statistics so that they are up-to-date */
  
-@@ -8516,10 +8597,18 @@
+@@ -8601,10 +8680,18 @@
        THD*            thd,            /*!< in: connection thread handle */
        HA_CHECK_OPT*   check_opt)      /*!< in: currently ignored */
  {
        return(0);
  }
  
-@@ -8755,6 +8844,10 @@
+@@ -8840,6 +8927,10 @@
                my_error(ER_QUERY_INTERRUPTED, MYF(0));
        }
  
        DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
  }
  
-@@ -9525,6 +9618,10 @@
+@@ -9610,6 +9701,10 @@
  
        update_thd(thd);
  
        if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
                ut_print_timestamp(stderr);
                fprintf(stderr,
-@@ -11989,6 +12086,26 @@
+@@ -12073,6 +12168,26 @@
    "dump file (if present). Disabled by default.",
    NULL, NULL, FALSE);
  
  static struct st_mysql_sys_var* innobase_system_variables[]= {
    MYSQL_SYSVAR(additional_mem_pool_size),
    MYSQL_SYSVAR(autoextend_increment),
-@@ -12082,6 +12199,7 @@
+@@ -12166,6 +12281,7 @@
  #ifdef UNIV_DEBUG
-   MYSQL_SYSVAR(flush_checkpoint_debug),
- #endif
+   MYSQL_SYSVAR(trx_rseg_n_slots_debug),
+ #endif /* UNIV_DEBUG */
 +  MYSQL_SYSVAR(corrupt_table_action),
    NULL
  };
  } INNOBASE_SHARE;
  
  
-@@ -135,6 +136,7 @@
+@@ -136,6 +137,7 @@
        int close(void);
        double scan_time();
        double read_time(uint index, uint ranges, ha_rows rows);
  
 --- a/storage/innobase/row/row0sel.c
 +++ b/storage/innobase/row/row0sel.c
-@@ -3912,6 +3912,13 @@
+@@ -3919,6 +3919,13 @@
        /* PHASE 4: Look for matching records in a loop */
  
        rec = btr_pcur_get_rec(pcur);
        ut_ad(!!page_rec_is_comp(rec) == comp);
  #ifdef UNIV_SEARCH_DEBUG
        /*
-@@ -3989,7 +3996,13 @@
+@@ -3996,7 +4003,13 @@
        if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
  
  wrong_offs:
                        ut_print_timestamp(stderr);
                        buf_page_print(page_align(rec), 0);
                        fprintf(stderr,
-@@ -4040,7 +4053,8 @@
+@@ -4047,7 +4060,8 @@
  
        offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
  
index 8b0bbe97ca311c67aa440a5b9fbb6e66ffee13db..059a91387b02c074ca688b7215821844d137433a 100644 (file)
@@ -35,13 +35,13 @@ Summary(ru.UTF-8):  MySQL - быстрый SQL-сервер
 Summary(uk.UTF-8):     MySQL - швидкий SQL-сервер
 Summary(zh_CN.UTF-8):  MySQL数据库服务器
 Name:          mysql
-Version:       5.5.20
-Release:       2
+Version:       5.5.21
+Release:       1
 License:       GPL + MySQL FLOSS Exception
 Group:         Applications/Databases
 # Source0Download: http://dev.mysql.com/downloads/mysql/5.5.html#downloads
 Source0:       http://vesta.informatik.rwth-aachen.de/mysql/Downloads/MySQL-5.5/%{name}-%{version}.tar.gz
-# Source0-md5: 375794ebf84b4c7b63f1676bc7416cd0
+# Source0-md5: 86d6bd335054a0aed1756ed60574c16d
 Source100:     http://sphinxsearch.com/files/sphinx-2.0.3-release.tar.gz
 # Source100-md5:       a1293aecd5034aa797811610beb7ba89
 Source1:       %{name}.init
@@ -75,70 +75,73 @@ Patch19:    %{name}-chain-certs.patch
 # from fedora
 Patch20:       %{name}-dubious-exports.patch
 # <percona patches, updated with percona.sh>
-Patch100:      microsec_process.patch
-Patch101:      optimizer_fix.patch
-Patch102:      mysql_dump_ignore_ct.patch
-Patch103:      control_online_alter_index.patch
-Patch104:      show_temp.patch
-Patch105:      innodb_show_status.patch
-Patch106:      innodb_io_patches.patch
-Patch107:      innodb_opt_lru_count.patch
-Patch108:      innodb_extra_rseg.patch
-Patch109:      innodb_overwrite_relay_log_info.patch
-Patch110:      innodb_thread_concurrency_timer_based.patch
-Patch111:      innodb_dict_size_limit.patch
-Patch112:      innodb_split_buf_pool_mutex.patch
-Patch113:      innodb_expand_import.patch
-Patch114:      innodb_show_sys_tables.patch
-Patch115:      innodb_stats.patch
-Patch116:      innodb_recovery_patches.patch
-Patch117:      innodb_admin_command_base.patch
-Patch118:      innodb_show_lock_name.patch
-Patch119:      innodb_extend_slow.patch
-Patch120:      innodb_lru_dump_restore.patch
-Patch121:      innodb_separate_doublewrite.patch
-Patch122:      innodb_pass_corrupt_table.patch
-Patch123:      innodb_fast_checksum.patch
-Patch124:      innodb_files_extend.patch
-Patch125:      innodb_fix_misc.patch
-Patch126:      innodb_deadlock_count.patch
-Patch127:      innodb_adaptive_hash_index_partitions.patch
-Patch128:      innodb_buffer_pool_pages_i_s.patch
-Patch129:      innodb_buffer_pool_shm.patch
-Patch130:      innodb_show_status_extend.patch
-Patch131:      innodb_kill_idle_transaction.patch
-Patch132:      innodb_fake_changes.patch
-Patch133:      slow_extended.patch
-Patch134:      percona_support.patch
-Patch135:      query_cache_enhance.patch
-Patch136:      log_connection_error.patch
-Patch137:      mysql_syslog.patch
-Patch138:      error_pad.patch
-Patch139:      response_time_distribution.patch
-Patch140:      remove_fcntl_excessive_calls.patch
-Patch141:      sql_no_fcache.patch
-Patch142:      show_slave_status_nolock.patch
-Patch143:      log_warnings_suppress.patch
-Patch144:      userstat.patch
-Patch145:      bug580324.patch
-Patch146:      mysql_remove_eol_carret.patch
-Patch147:      processlist_row_stats.patch
-Patch148:      innodb_expand_fast_index_creation.patch
-Patch149:      innodb_bug60788.patch
-Patch150:      start-stop-messages.patch
-Patch151:      file-contents.patch
-Patch152:      slave_timeout_fix.patch
-Patch153:      utf8_general50_ci.patch
-Patch154:      bug813587.patch
-Patch155:      valgrind_zlib_suppression.patch
-Patch156:      memory_dynamic_rows.patch
-Patch157:      xtradb_bug317074.patch
-Patch158:      subunit.patch
-Patch159:      bug860910.patch
-Patch160:      bug45702.patch
-Patch161:      group_commit.patch
-Patch162:      warning_fixes.patch
-Patch163:      bug917246.patch
+Patch100:      bug933969.patch
+Patch101:      microsec_process.patch
+Patch102:      optimizer_fix.patch
+Patch103:      mysql_dump_ignore_ct.patch
+Patch104:      control_online_alter_index.patch
+Patch105:      show_temp.patch
+Patch106:      innodb_show_status.patch
+Patch107:      innodb_io_patches.patch
+Patch108:      innodb_opt_lru_count.patch
+Patch109:      innodb_extra_rseg.patch
+Patch110:      innodb_overwrite_relay_log_info.patch
+Patch111:      innodb_thread_concurrency_timer_based.patch
+Patch112:      innodb_dict_size_limit.patch
+Patch113:      innodb_split_buf_pool_mutex.patch
+Patch114:      innodb_expand_import.patch
+Patch115:      innodb_show_sys_tables.patch
+Patch116:      innodb_stats.patch
+Patch117:      innodb_recovery_patches.patch
+Patch118:      innodb_admin_command_base.patch
+Patch119:      innodb_show_lock_name.patch
+Patch120:      innodb_extend_slow.patch
+Patch121:      innodb_lru_dump_restore.patch
+Patch122:      innodb_separate_doublewrite.patch
+Patch123:      innodb_pass_corrupt_table.patch
+Patch124:      innodb_fast_checksum.patch
+Patch125:      innodb_files_extend.patch
+Patch126:      innodb_fix_misc.patch
+Patch127:      innodb_deadlock_count.patch
+Patch128:      innodb_adaptive_hash_index_partitions.patch
+Patch129:      innodb_buffer_pool_pages_i_s.patch
+Patch130:      innodb_buffer_pool_shm.patch
+Patch131:      innodb_show_status_extend.patch
+Patch132:      innodb_kill_idle_transaction.patch
+Patch133:      innodb_fake_changes.patch
+Patch134:      slow_extended.patch
+Patch135:      percona_support.patch
+Patch136:      query_cache_enhance.patch
+Patch137:      log_connection_error.patch
+Patch138:      mysql_syslog.patch
+Patch139:      error_pad.patch
+Patch140:      response_time_distribution.patch
+Patch141:      remove_fcntl_excessive_calls.patch
+Patch142:      sql_no_fcache.patch
+Patch143:      show_slave_status_nolock.patch
+Patch144:      log_warnings_suppress.patch
+Patch145:      userstat.patch
+Patch146:      bug580324.patch
+Patch147:      mysql_remove_eol_carret.patch
+Patch148:      processlist_row_stats.patch
+Patch149:      innodb_expand_fast_index_creation.patch
+Patch150:      innodb_bug60788.patch
+Patch151:      start-stop-messages.patch
+Patch152:      file-contents.patch
+Patch153:      slave_timeout_fix.patch
+Patch154:      utf8_general50_ci.patch
+Patch155:      bug813587.patch
+Patch156:      valgrind_zlib_suppression.patch
+Patch157:      memory_dynamic_rows.patch
+Patch158:      xtradb_bug317074.patch
+Patch159:      subunit.patch
+Patch160:      bug860910.patch
+Patch161:      bug45702.patch
+Patch162:      group_commit.patch
+Patch163:      warning_fixes.patch
+Patch164:      bug917246.patch
+Patch165:      bug54330.patch
+Patch166:      bug966844_page_size_error_on_5520_upgrade.patch
 # </percona>
 URL:           http://www.mysql.com/products/community/
 BuildRequires: bison
@@ -635,6 +638,9 @@ mv sphinx-*/mysqlse storage/sphinx
 %patch161 -p1
 %patch162 -p1
 %patch163 -p1
+%patch164 -p1
+%patch165 -p1
+%patch166 -p1
 # </percona>
 
 # to get these files rebuild
index ae58526f5bf1a86e00c3c54c6c94b7938f9ddc68..8cbdb14fbe3976122a761835683e0e06e8096489 100644 (file)
@@ -22,8 +22,8 @@ diff -ruN a/client/client_priv.h b/client/client_priv.h
                  opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
                  opt_slave_apply= 0, 
                  opt_include_master_host_port= 0,
--                opt_events= 0,
-+                opt_events= 0, opt_ignore_show_create_table_error=0,
+-                opt_events= 0, opt_comments_used= 0,
++                opt_events= 0, opt_comments_used= 0, opt_ignore_show_create_table_error=0,
                  opt_alltspcs=0, opt_notspcs= 0;
  static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
  static ulong opt_max_allowed_packet, opt_net_buffer_length;
index 305783f32016f3a167c3011dd5d96aeaa739fb32..eb1754c19fd4b2a345f3d55a04dd9754d6e7b04e 100644 (file)
@@ -1,4 +1,4 @@
-# name       : query_cache_enhance.patch
+# name       : query_cache_with_comments.patch
 # introduced : 11 or before
 # maintainer : Oleg
 #
@@ -25,7 +25,7 @@
 +2010-11 - Ported to 5.5
 --- a/sql/mysqld.cc
 +++ b/sql/mysqld.cc
-@@ -909,6 +909,7 @@
+@@ -915,6 +915,7 @@
  #endif
  #ifdef HAVE_QUERY_CACHE
  ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
  extern ulonglong log_output_options;
  extern ulong log_backup_output_options;
  extern my_bool opt_log_queries_not_using_indexes;
+--- /dev/null
++++ b/sql/query_strip_comments.h
+@@ -0,0 +1,37 @@
++#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_
++#define _SQL_QUERY_STRIPC_COMMENTS_H_
++#ifdef HAVE_QUERY_CACHE
++
++// implemented in sql_cache.cc
++class QueryStripComments
++{
++private:
++  QueryStripComments(const QueryStripComments&);
++  QueryStripComments& operator=(const QueryStripComments&);
++public:
++  QueryStripComments();
++  ~QueryStripComments();
++  void set(const char* a_query, uint a_query_length, uint a_additional_length);
++  
++  char* query()        { return buffer; }
++  uint  query_length() { return length; }
++private:
++  void cleanup();
++private:
++  char* buffer;
++  uint  length /*query length, not buffer length*/;
++  uint  buffer_length;
++};
++class QueryStripComments_Backup
++{
++public:
++  QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc);
++  ~QueryStripComments_Backup();
++private:
++  THD*  thd;
++  char* query;
++  uint  length;
++};
++
++#endif // HAVE_QUERY_CACHE
++#endif // _SQL_QUERY_STRIPC_COMMENTS_H_
 --- a/sql/sql_cache.cc
 +++ b/sql/sql_cache.cc
-@@ -344,6 +344,496 @@
+@@ -344,6 +344,198 @@
  #include "probes_mysql.h"
  #include "transaction.h"
  
++#include "query_strip_comments.h"
 +
-+namespace query_comments_parser
-+{
-+
-+
-+enum Kind
-+{
-+  /* 'Empty' symbol - epsilon in classic parsers */
-+  Empty,
-+  /*
-+    Special symbols:
-+      * exclamation comment: slash-star-exclamation comment-body star-slash
-+      * single-line and multi-line comments
-+  */
-+  Special,
-+  /* Whitespaces: ' ' \t \r \n */
-+  WhiteSpace,
-+  /*
-+    1) C-style comment (slash-star comment-body star-slash)
-+    2) signle-line comment:
-+      * sharp comment (sharp comment-body new-line)
-+      * minus-minus comment (minus-minus comment-body new-line)
-+  */
-+  Comment,
-+  /* Not a special symbols (this symbols can't be before SELECT ). */
-+  Another,
-+  /* Error: not-closed quotes, not-closed C-style comment, end-of-query */
-+  Error
-+};
++/*
++  Number of bytes to be allocated in a query cache buffer in addition to the
++  query string length.
 +
++  The query buffer layout is:
 +
-+/**
-+  Analyze kind of prefix of input string.
++  buffer :==
++    <statement>   The input statement(s)
++    '\0'          Terminating null char
++    <db_length>   Length of following current database name (size_t)
++    <db_name>     Name of current database
++    <flags>       Flags struct
++*/
++#define QUERY_BUFFER_ADDITIONAL_LENGTH(db_length)               \
++  (1 + sizeof(size_t) + db_length + QUERY_CACHE_FLAGS_SIZE)
 +
-+  @param where pointer to pointer to begin of string. After analyzing input
-+  string function skip analyzed prefix and return pointer to the next part
-+  of string in the @param where.
++QueryStripComments::QueryStripComments()
++{
++  buffer = 0;
++  length = 0;
++  buffer_length = 0;
++}
++QueryStripComments::~QueryStripComments()
++{
++  cleanup();
++}
 +
-+  @return kind of analyzed prefix.
-+*/
-+static Kind analyze(const char **where, const char *const end)
++inline bool query_strip_comments_is_white_space(char c)
++{
++  return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c ));
++}
++void QueryStripComments::set(const char* query, uint query_length, uint additional_length)
 +{
-+  DBUG_ASSERT(where != NULL);
-+  DBUG_ASSERT(*where != NULL);
-+  const char*&to= *where;
-+  /* if empty */
-+  if (*to == '\0')
++  uint new_buffer_length = query_length + additional_length;
++  if(new_buffer_length > buffer_length)
 +  {
-+    return Empty;
++    cleanup();
++    buffer = (char*)my_malloc(new_buffer_length,MYF(0));
 +  }
-+
-+  /* current symbol */
-+  char current= *to;
-+
-+  switch (current)
++  uint query_position = 0;
++  uint position = 0;
++  // Skip whitespaces from begin
++  while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position]))
++  {
++    ++query_position;
++  }
++  long int last_space = -1;
++  while(query_position < query_length)
 +  {
-+  case '\'':
-+  case '"':
-+    /* skip quote */
-+    to++;
-+    /* search pair */
-+    while (true)
++    char current = query[query_position];
++    bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position
++    switch(current)
 +    {
-+      /* check for pair of quote */
-+      if (*to == current)
++    case '\'':
++    case '"':
 +      {
-+        /* skip second quote */
-+        to++;
-+        /* check for same symbol after second quote */
-+        if (to < end && *to == current)
++        buffer[position++] = query[query_position++]; // copy current symbol
++        while(query_position < query_length)
 +        {
-+          /* same symbol, skip it */
-+          to++;
-+          /* check for end-of-line */
-+          if (to == end)
++          if(current == query[query_position]) // found pair quote
 +          {
-+            /* not found - not closed quote */
-+            return Error;
++            break;
 +          }
-+          else
++          buffer[position++] = query[query_position++]; // copy current symbol
++        }
++        break;
++      }
++    case '/':
++      {
++        if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
++        {
++          query_position += 2; // skip "/*"
++          do
++          {
++            if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/"
++            {
++              query_position += 2; // skip "*/"
++              insert_space = true;
++              break;
++            }
++            else
++            {
++              ++query_position;
++            }
++          }
++          while(query_position < query_length);
++          if(!insert_space)
 +          {
-+            /* continue search of pair */
 +            continue;
 +          }
 +        }
++        break;
++      }
++    case '-':
++      {
++        if(query[query_position+1] == '-')
++        {
++          ++query_position; // skip "-", and go to search of "\n"
++        }
 +        else
 +        {
-+          return Another;
++          break;
 +        }
 +      }
-+      /* check for escaped symbols */
-+      if (*to == '\\')
-+      {
-+        /* backslash, skip it */
-+        to++;
-+      }
-+      /* check for end-of-line */
-+      if (to == end)
-+      {
-+        /* not found - not closed quote */
-+        return Error;
-+      }
-+      /* skip current symbol */
-+      to++;
-+    }
-+  case '-':
-+    /* Skip minus */
-+    to++;
-+    /* Check for second minus */
-+    if (*to != '-')
-+    {
-+      /* Just minus */
-+      return Another;
-+    }
-+    else
-+    {
-+      /*
-+        Prefix is  minus-minus, next case-branch is processing
-+        single line comments.
-+      */
-+    }
-+  case '#':
-+    /*
-+      This is single-line comment, it started by "#" or "--".
-+      Skip first symbol.
-+    */
-+    to++;
-+    /* search new-line */
-+    to= strchr(to, '\n');
-+    if (NULL == to)
-+    {
-+      /* not found, end of the comment is the end of the query */
-+      to= end;
-+    }
-+    else
-+    {
-+      /* skip end-of-line */
-+      to++;
-+    }
-+    return Comment;
-+  case '/':
-+    /* skip slash */
-+    to++;
-+    /* check for star */
-+    if (*to == '*')
-+    {
-+      /* skip star */
-+      to++;
-+      /* check for exclamation */
-+      bool exclamation= (*to == '!');
-+      /* search star-slash */
-+      to= strstr(to, "*/");
-+      if (NULL == to)
++    case '#':
 +      {
-+        /* not found - not closed comment */
-+        return Error;
++        do
++        {
++          ++query_position; // skip current symbol (# or -)
++          if('\n' == query[query_position])  // check for '\n'
++          {
++            ++query_position; // skip '\n'
++            insert_space = true;
++            break;
++          }
++        }
++        while(query_position < query_length);
++        if(insert_space)
++        {
++          break;
++        }
++        else
++        {
++          continue;
++        }
 +      }
-+      else
++    default:
++      if(query_strip_comments_is_white_space(current))
 +      {
-+        /* found */
-+        DBUG_ASSERT(to + 1 < end);
-+        DBUG_ASSERT(0 == strncmp(to, "*/", 2));
-+        /* skip star-slash */
-+        to++;
-+        to++;
-+        return (exclamation ? Special : Comment);
++        insert_space = true;
++        ++query_position;
 +      }
++      break; // make gcc happy
 +    }
-+    else
-+    {
-+      /* just slash */
-+      return Another;
-+    }
-+  case ' ':
-+  case '\t':
-+  case '\r':
-+  case '\n':
-+    {
-+      /* skip space */
-+      to++;
-+      return WhiteSpace;
-+    }
-+  case '\\':
++    if(insert_space)
 +    {
-+      /* skip backslash */
-+      to++;
-+      if (to == end)
++      if((uint) (last_space + 1) != position)
 +      {
-+        /*
-+          query complete by backslash
-+          probable error?
-+        */
-+        return Another;
++        last_space = position;
++        buffer[position++] = ' ';
 +      }
-+      else
-+      {
-+        /* skip after backslash symbol */
-+        to++;
-+        return Another;
-+      }
-+    }
-+  case '(':
-+  case ')':
-+    {
-+      /* skip parenthese */
-+      to++;
-+      return Special;
 +    }
-+  default:
++    else if (query_position < query_length)
 +    {
-+      /* skip symbol */
-+      to++;
-+      return Another;
++      buffer[position++] = query[query_position++];
 +    }
-+  };
-+}
-+
-+
-+static bool remove_comments_from_query(const char *const query,
-+                                       const size_t       query_length,
-+                                       char       *const result,
-+                                       size_t            *result_length)
-+{
-+  /* pointer to begin of parsed block */
-+  const char *from=  query;
-+  const char *to=    query;
-+  /* pointer to end of the query */
-+  const char *const end= query + query_length;
-+  /* pointer to last space */
-+  const char *space= NULL;
-+  /* current position in result buffer */
-+  char *current= result;
-+  while (true)
++  }
++  while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1]))
 +  {
-+    from= to;
-+    switch (analyze(&to, end))
-+    {
-+    case Empty:
-+      {
-+        /*
-+          parse completed
-+          check for whitespace in the end
-+        */
-+        if (current == space)
-+        {
-+          /* drop whitespace in the end of query */
-+          --current;
-+        }
-+        /* result is null-terminated string */
-+        *current= 0;
-+        /* set result length */
-+        *result_length= current - result;
-+        /* all right */
-+        return true;
-+      }
-+    case Comment:
-+      /* should just insert space instead of comment */
-+    case WhiteSpace:
-+      if (space == current || from == query)
-+      {
-+        /* previous symbol was space */
-+      }
-+      else
-+      {
-+        /* insert space to result buffer */
-+        *current= ' ';
-+        /* switch after inserted space */
-+        current++;
-+      }
-+      /* remember last-after-space position */
-+      space= current;
-+      /* parse again */
-+      continue;
-+    case Special:
-+    case Another:
-+      {
-+        /* calculate parsed block size */
-+        size_t block_size= to - from;
-+        /* copy parsed block to result */
-+        memcpy(current, from, block_size);
-+        /* switch result after copied block */
-+        current+= block_size;
-+        /* switch after parsed block */
-+        from= to;
-+        /* parse again */
-+        continue;
-+      }
-+    case Error:
-+    default:
-+      {
-+        /* bad source query */
-+        return false;
-+      }
-+    }
++    --position;
 +  }
++  buffer[position] = 0;
++  length = position;
 +}
-+
-+
-+static size_t skip_not_another(const char *const query, size_t query_length)
++void QueryStripComments::cleanup()
 +{
-+  const char *from= query;
-+  const char *to=   query;
-+  const char *const end= query + query_length;
-+  while (true)
++  if(buffer)
 +  {
-+    switch (analyze(&to, end))
-+    {
-+    case Error:
-+      return 0;
-+    case Empty:
-+    case Another:
-+      return (from - query);
-+    default:
-+      from= to;
-+      continue;
-+    };
++    my_free(buffer);
 +  }
++  buffer        = 0;
++  length        = 0;
++  buffer_length = 0;
 +}
-+
-+
-+static size_t skip_default(const char *const query, size_t /* query_length */)
-+{
-+  size_t query_position= 0;
-+  /*
-+    Skip '(' characters in queries like following:
-+    (select a from t1) union (select a from t1);
-+  */
-+  while (query[query_position]=='(')
-+    query_position++;
-+  return query_position;
-+}
-+
-+
-+} /* namespace query_comments_parser */
-+
-+class Query_Switcher
++QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc)
 +{
-+private:
-+  Query_Switcher(const Query_Switcher&);
-+  Query_Switcher& operator=(const Query_Switcher&);
-+
-+
-+public:
-+  Query_Switcher(THD *thd) :
-+    target_query(&(thd_query_string(thd)->str)),
-+    target_length(&(thd_query_string(thd)->length)),
-+    backup_query(thd->query()),
-+    backup_length(thd->query_length())
-+  {
-+  }
-+
-+  Query_Switcher(char   **query,
-+                 size_t  *length) :
-+    target_query(query),
-+    target_length(length),
-+    backup_query(*query),
-+    backup_length(*length)
-+  {
-+  }
-+public:
-+  void replace(Query_Without_Comments *query_without_comments)
++  if(opt_query_cache_strip_comments)
 +  {
-+    *target_query=  query_without_comments->query();
-+    *target_length= query_without_comments->length();
++    thd = a_thd;
++    query = thd->query();
++    length = thd->query_length();
++    qsc->set(query, length, QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length));
++    *(size_t *) (qsc->query() + qsc->query_length() + 1)= thd->db_length;
++    thd->set_query(qsc->query(),qsc->query_length());
 +  }
-+  void restore()
++  else
 +  {
-+    *target_query=  backup_query;
-+    *target_length= backup_length;
++    thd = 0;
++    query = 0;
++    length = 0;
 +  }
-+private:
-+  char*  *target_query;
-+  size_t *target_length;
-+public:
-+  char *const  backup_query;
-+  size_t const backup_length;
-+};
-+
-+class Comments_Processor
++}
++QueryStripComments_Backup::~QueryStripComments_Backup()
 +{
-+private:
-+  Comments_Processor(const Comments_Processor&);
-+  Comments_Processor& operator=(const Comments_Processor&);
-+
-+
-+public:
-+  Comments_Processor(THD *thd) :
-+    query_switcher        (thd),
-+    db_length             (thd->db_length),
-+    query_without_comments(&(thd->query_without_comments)),
-+    enabled               (opt_query_cache_strip_comments),
-+    restore               (false)
-+  {
-+  }
-+
-+
-+  Comments_Processor(Query_Without_Comments *current_query_without_comments,
-+                     char                  **query,
-+                     size_t                 *length,
-+                     const size_t            current_db_length) :
-+    query_switcher        (query, length),
-+    db_length             (current_db_length),
-+    query_without_comments(current_query_without_comments),
-+    enabled               (opt_query_cache_strip_comments),
-+    restore               (false)
-+  {
-+  }
-+
-+
-+  ~Comments_Processor()
++  if(thd)
 +  {
-+    restore_comments();
++    thd->set_query(query,length);
 +  }
-+
-+
-+  size_t prefix_length()
-+  {
-+    using query_comments_parser::skip_not_another;
-+    using query_comments_parser::skip_default;
-+    if (enabled)
-+    {
-+      return skip_not_another(query_switcher.backup_query,
-+                              query_switcher.backup_length);
-+    }
-+    else
-+    {
-+      return skip_default(query_switcher.backup_query,
-+                          query_switcher.backup_length);
-+    }
-+  }
-+
-+
-+  bool remove_comments()
-+  {
-+    if (!enabled || restore)
-+    {
-+      return true;
-+    }
-+    /* Allocate memory for query rewrite */
-+    if (!query_without_comments->allocate(query_switcher.backup_length,
-+                                          db_length))
-+    {
-+      return false;
-+    }
-+    /* Remove comment from query */
-+    size_t result_length;
-+    using query_comments_parser::remove_comments_from_query;
-+    if (!(restore= remove_comments_from_query(query_switcher.backup_query,
-+                                              query_switcher.backup_length,
-+                                              query_without_comments->query(),
-+                                              &result_length)))
-+    {
-+      return false;
-+    }
-+    query_without_comments->set_length(result_length);
-+    size_t db_length_from_query=
-+        *((size_t*)(query_switcher.backup_query +
-+                    query_switcher.backup_length + 1));
-+    *((size_t*)(query_without_comments->query() +
-+                result_length + 1))= db_length_from_query;
-+    /* Replace original query by striped */
-+    query_switcher.replace(query_without_comments);
-+    return restore;
-+  }
-+
-+
-+  void restore_comments()
-+  {
-+    if (enabled && restore)
-+    {
-+      /* Replace striped query by original */
-+      query_switcher.restore();
-+
-+      /* Clean query_without_comments */
-+      query_without_comments->set_length(0);
-+
-+      /* Mark as restored */
-+      restore= false;
-+    }
-+  }
-+private:
-+  Query_Switcher query_switcher;
-+private:
-+  const size_t db_length;
-+private:
-+  Query_Without_Comments *query_without_comments;
-+  bool                    enabled;
-+  bool                    restore;
-+};
++}
 +
  #ifdef EMBEDDED_LIBRARY
  #include "emb_qcache.h"
  #endif
-@@ -454,7 +944,12 @@
+@@ -454,7 +646,12 @@
    Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
    DBUG_ENTER("Query_cache::try_lock");
  
-+  const char *old_proc_info= thd->proc_info;
++  const charold_proc_info= thd->proc_info;
 +  thd_proc_info(thd,"Waiting on query cache mutex");
 +  DEBUG_SYNC(thd, "before_query_cache_mutex");
    mysql_mutex_lock(&structure_guard_mutex);
    while (1)
    {
      if (m_cache_lock_status == Query_cache::UNLOCKED)
-@@ -1274,6 +1769,8 @@
+@@ -1274,6 +1471,8 @@
        unlock();
        DBUG_VOID_RETURN;
      }
-+    Comments_Processor comments_processor(thd);
-+    comments_processor.remove_comments();
++    QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
++    QueryStripComments_Backup backup(thd,query_strip_comments);
  
      /* Key is query + database + flag */
      if (thd->db_length)
-@@ -1440,7 +1937,7 @@
- */
- int
--Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
-+Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length_uint)
- {
-   ulonglong engine_data;
-   Query_cache_query *query;
-@@ -1452,6 +1949,11 @@
+@@ -1451,6 +1650,9 @@
+   Query_cache_block_table *block_table, *block_table_end;
    ulong tot_length;
    Query_cache_query_flags flags;
++  QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
++  char *sql_backup          = sql;
++  uint  query_length_backup = query_length;
    DBUG_ENTER("Query_cache::send_result_to_client");
-+  size_t query_length= query_length_uint;
-+  Comments_Processor comments_processor(&(thd->query_without_comments),
-+                                        &sql,
-+                                        &query_length,
-+                                        thd->db_length);
  
    /*
-     Testing 'query_cache_size' without a lock here is safe: the thing
-@@ -1471,13 +1973,7 @@
-   }
+@@ -1472,21 +1674,103 @@
  
    {
--    uint i= 0;
+     uint i= 0;
 -    /*
 -      Skip '(' characters in queries like following:
 -      (select a from t1) union (select a from t1);
 -    */
 -    while (sql[i]=='(')
 -      i++;
-+    size_t i= comments_processor.prefix_length();
++    if(opt_query_cache_strip_comments)
++    {
++      /* Skip all comments and non-letter symbols */
++      uint& query_position = i;
++      char* query = sql;
++      while(query_position < query_length)
++      {
++        bool check = false;
++        char current = query[query_position];
++        switch(current)
++        {
++        case '/':
++          if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
++          {
++            query_position += 2; // skip "/*"
++            do
++            {
++              if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
++              {
++                query_position += 2; // skip "*/" (without space)
++                break;
++              }
++              else
++              {
++                ++query_position;
++              }
++            }
++            while(query_position < query_length);
++            continue; // analyze current symbol
++          }
++          break;
++        case '-':
++          if(query[query_position+1] == '-')
++          {
++            ++query_position; // skip "-"
++          }
++          else
++          {
++            break;
++          }
++        case '#':
++          do
++          {
++            ++query_position; // skip current symbol
++            if('\n' == query[query_position])  // check for '\n'
++            {
++              ++query_position; // skip '\n'
++              break;
++            }
++          }
++          while(query_position < query_length);
++          continue; // analyze current symbol
++        case '\r':
++        case '\n':
++        case '\t':
++        case ' ':
++        case '(':
++        case ')':
++          break;
++        default:
++          check = true;
++          break; // make gcc happy
++        } // switch(current)
++        if(check)
++        {
++          if(query_position + 2 < query_length)
++          {
++            // cacheable
++            break;
++          }
++          else
++          {
++            DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
++            goto err;
++          }
++        } // if(check)
++        ++query_position;
++      } // while(query_position < query_length)
++    }
++    else // if(opt_query_cache_strip_comments)
++    {
++      /*
++        Skip '(' characters in queries like following:
++        (select a from t1) union (select a from t1);
++      */
++      while (sql[i]=='(')
++        i++;
+-    /*
+-      Test if the query is a SELECT
+-      (pre-space is removed in dispatch_command).
++    } // if(opt_query_cache_strip_comments)    
++      /*
++        Test if the query is a SELECT
++        (pre-space is removed in dispatch_command).
  
-     /*
-       Test if the query is a SELECT
-@@ -1487,10 +1983,11 @@
-       frequently appeared in real life, consequently we can
-       check all such queries, too.
-     */
--    if ((my_toupper(system_charset_info, sql[i])     != 'S' ||
--         my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
--         my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
--        sql[i] != '/')
-+    if (!((i + 2 < query_length) &&
-+          ((my_toupper(system_charset_info, sql[i])     == 'S' &&
-+            my_toupper(system_charset_info, sql[i + 1]) == 'E' &&
-+            my_toupper(system_charset_info, sql[i + 2]) == 'L') ||
-+           sql[i] == '/')))
-     {
-       DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
-       goto err;
-@@ -1543,6 +2040,7 @@
+-      First '/' looks like comment before command it is not
+-      frequently appeared in real life, consequently we can
+-      check all such queries, too.
+-    */
++        First '/' looks like comment before command it is not
++        frequently appeared in real life, consequently we can
++        check all such queries, too.
++      */
+     if ((my_toupper(system_charset_info, sql[i])     != 'S' ||
+          my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
+          my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
+@@ -1543,6 +1827,14 @@
      goto err_unlock;
  
    Query_cache_block *query_block;
-+  comments_processor.remove_comments();
++  if(opt_query_cache_strip_comments)
++  {
++    query_strip_comments->set(sql, query_length,
++                              QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length));
++    sql          = query_strip_comments->query();
++    query_length = query_strip_comments->query_length();
++    *(size_t *) (sql + query_length + 1)= thd->db_length;
++  }
  
    tot_length= query_length + 1 + sizeof(size_t) + 
                thd->db_length + QUERY_CACHE_FLAGS_SIZE;
-@@ -1611,6 +2109,7 @@
+@@ -1611,6 +1903,8 @@
         (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
    query_block = (Query_cache_block *)  my_hash_search(&queries, (uchar*) sql,
                                                        tot_length);
-+  comments_processor.restore_comments();
++  sql          = sql_backup;
++  query_length = query_length_backup;
    /* Quick abort on unlocked data */
    if (query_block == 0 ||
        query_block->query()->result() == 0 ||
 --- a/sql/sql_class.h
 +++ b/sql/sql_class.h
-@@ -1485,6 +1485,74 @@
+@@ -40,6 +40,9 @@
+ #include "thr_lock.h"             /* thr_lock_type, THR_LOCK_DATA,
+                                      THR_LOCK_INFO */
  
- extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
++#ifdef HAVE_QUERY_CACHE
++#include "query_strip_comments.h"
++#endif // HAVE_QUERY_CACHE
  
-+
+ class Reprepare_observer;
+ class Relay_log_info;
+@@ -766,6 +769,9 @@
+     statement lifetime. FIXME: must be const
+   */
+    ulong id;
 +#ifdef HAVE_QUERY_CACHE
-+
-+
-+/*
-+  @class Query_Without_Comments
-+  This class provides way for safety (re)allocation
-+  a memory for a query without comments.
-+*/
-+class Query_Without_Comments
-+{
-+private:
-+  /*
-+    Denied copy and assigment for object of this class.
-+  */
-+  Query_Without_Comments(const Query_Without_Comments&);
-+  Query_Without_Comments& operator=(const Query_Without_Comments&);
-+
-+
-+public:
-+  /*
-+    Constructor is filling fields by zero (no allocation).
-+  */
-+  Query_Without_Comments();
-+
-+
-+  /*
-+    Destructor clean allocated memory
-+  */
-+  ~Query_Without_Comments();
-+public:
-+
-+
-+/*
-+    (Re)allocate memory for query. Query length after that is 0.
-+  */
-+  bool allocate(size_t query_length, size_t db_length);
-+
-+
-+  /*
-+    Set result query length, when query
-+    without comments is copied to buffer.
-+  */
-+  void set_length(size_t query_length);
-+
-+
-+public:
-+  /*
-+    Result query.
-+  */
-+  char*  query();
-+
-+
-+  /*
-+    Result query length
-+  */
-+  size_t length();
-+
-+
-+private:
-+  char* buffer;
-+  size_t q_length;
-+  size_t b_length;
-+};
-+
-+
-+#endif /* HAVE_QUERY_CACHE */
-+
- /**
-   @class THD
-   For each client connection we create a separate thread with THD serving as
-@@ -1542,6 +1610,7 @@
-   struct st_mysql_stmt *current_stmt;
- #endif
- #ifdef HAVE_QUERY_CACHE
-+  Query_Without_Comments query_without_comments;
-   Query_cache_tls query_cache_tls;
- #endif
-   NET   net;                          // client connection descriptor
++  QueryStripComments query_strip_comments; // see sql_cache.cc
++#endif //HAVE_QUERY_CACHE
+   /*
+     MARK_COLUMNS_NONE:  Means mark_used_colums is not set and no indicator to
 --- a/sql/sys_vars.cc
 +++ b/sql/sys_vars.cc
-@@ -1888,6 +1888,11 @@
+@@ -1895,6 +1895,11 @@
         NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
         ON_UPDATE(fix_query_cache_size));
  
         "Don't cache results that are bigger than this",
 --- /dev/null
 +++ b/mysql-test/include/percona_query_cache_with_comments.inc
-@@ -0,0 +1,117 @@
+@@ -0,0 +1,95 @@
 +--source include/percona_query_cache_with_comments_clear.inc
 +let $query=/* with comment first */select * from t1;
 +eval $query;
 +;
 +--source include/percona_query_cache_with_comments_eval.inc
 +
-+let $query=select */* a comment \*/from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select *# a comment \\
-+from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select *-- a comment \\
-+from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select "\\\\"" /* not a comment */" from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select "\\\\"" /*! not a comment */" from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
-+
-+# following two queries related to bug #856404.
-+# There are different queries, but opt_query_cache_strip_comments thinks that they are equal.
 +let $query=select ' \'  ' from t1;
 +--source include/percona_query_cache_with_comments_eval.inc
-+
-+let $query=select ' \' /* comment inside quotes with internal backslash quote */' from t1;
-+--source include/percona_query_cache_with_comments_eval.inc
 --- /dev/null
 +++ b/mysql-test/include/percona_query_cache_with_comments_begin.inc
 @@ -0,0 +1,12 @@
 +
 --- /dev/null
 +++ b/mysql-test/r/percona_query_cache_with_comments.result
-@@ -0,0 +1,1058 @@
+@@ -0,0 +1,866 @@
 +set global query_cache_strip_comments=ON;
 +set GLOBAL query_cache_size=1355776;
 +drop table if exists t1;
 +2
 +3
 +select * from t1
-+/* comment in the end */
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   42
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   42
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   44
-+-----------------------------------------------------
-+select * from t1 #comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   44
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 #comment in the end
-+;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   46
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   46
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   48
-+-----------------------------------------------------
-+select * from t1 -- comment in the end
-+
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       1
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        1
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   48
-+select * from t1 -- comment in the end
-+;
-+a
-+1
-+2
-+3
-+select * from t1 -- comment in the end
++/* comment in the end */
 +;
 +a
 +1
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   50
++Qcache_hits   42
 +-----------------------------------------------------
-+select */* a comment \*/from t1
++select * from t1 #comment in the end
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   50
-+select */* a comment \*/from t1;
++Qcache_hits   42
++select * from t1 #comment in the end;
 +a
 +1
 +2
 +3
-+select */* a comment \*/from t1;
++select * from t1 #comment in the end;
 +a
 +1
 +2
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   52
++Qcache_hits   44
 +-----------------------------------------------------
-+select *# a comment \
-+from t1
++select * from t1 #comment in the end
++
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   52
-+select *# a comment \
-+from t1;
++Qcache_hits   44
++select * from t1 #comment in the end
++;
 +a
 +1
 +2
 +3
-+select *# a comment \
-+from t1;
++select * from t1 #comment in the end
++;
 +a
 +1
 +2
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   54
++Qcache_hits   46
 +-----------------------------------------------------
-+select *-- a comment \
-+from t1
++select * from t1 -- comment in the end
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   54
-+select *-- a comment \
-+from t1;
++Qcache_hits   46
++select * from t1 -- comment in the end;
 +a
 +1
 +2
 +3
-+select *-- a comment \
-+from t1;
++select * from t1 -- comment in the end;
 +a
 +1
 +2
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   56
++Qcache_hits   48
 +-----------------------------------------------------
-+select "\\"" /* not a comment */" from t1
++select * from t1 -- comment in the end
++
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
 +Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   56
-+select "\\"" /* not a comment */" from t1;
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+select "\\"" /* not a comment */" from t1;
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   57
-+-----------------------------------------------------
-+select "\\"" /*! not a comment */" from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       2
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        2
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   57
-+select "\\"" /*! not a comment */" from t1;
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+select "\\"" /*! not a comment */" from t1;
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
++Qcache_hits   48
++select * from t1 -- comment in the end
++;
++a
++1
++2
++3
++select * from t1 -- comment in the end
++;
++a
++1
++2
++3
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
-+Qcache_queries_in_cache       3
++Qcache_queries_in_cache       1
 +show status like "Qcache_inserts";
 +Variable_name Value
-+Qcache_inserts        3
++Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   58
++Qcache_hits   50
 +-----------------------------------------------------
 +select ' \'  ' from t1
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
-+Qcache_queries_in_cache       3
++Qcache_queries_in_cache       1
 +show status like "Qcache_inserts";
 +Variable_name Value
-+Qcache_inserts        3
++Qcache_inserts        1
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   58
++Qcache_hits   50
 +select ' \'  ' from t1;
 +'  
 + '  
 + '  
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
-+Qcache_queries_in_cache       4
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        4
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   59
-+-----------------------------------------------------
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       4
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        4
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   59
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
-+' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
-+' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       5
++Qcache_queries_in_cache       2
 +show status like "Qcache_inserts";
 +Variable_name Value
-+Qcache_inserts        5
++Qcache_inserts        2
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   60
++Qcache_hits   51
 +DROP TABLE t1;
 +SET GLOBAL query_cache_size=default;
 +set global query_cache_strip_comments=OFF;
 +SET GLOBAL query_cache_size= default;
 --- /dev/null
 +++ b/mysql-test/r/percona_query_cache_with_comments_disable.result
-@@ -0,0 +1,1057 @@
+@@ -0,0 +1,865 @@
 +set GLOBAL query_cache_size=1355776;
 +drop table if exists t1;
 +create table t1 (a int not null);
 +Variable_name Value
 +Qcache_hits   25
 +-----------------------------------------------------
-+select */* a comment \*/from t1
++select ' \'  ' from t1
 +-----------------------------------------------------
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
 +show status like "Qcache_hits";
 +Variable_name Value
 +Qcache_hits   25
-+select */* a comment \*/from t1;
-+a
-+1
-+2
-+3
-+select */* a comment \*/from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       21
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        21
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   26
-+-----------------------------------------------------
-+select *# a comment \
-+from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       21
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        21
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   26
-+select *# a comment \
-+from t1;
-+a
-+1
-+2
-+3
-+select *# a comment \
-+from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       22
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        22
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   27
-+-----------------------------------------------------
-+select *-- a comment \
-+from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       22
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        22
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   27
-+select *-- a comment \
-+from t1;
-+a
-+1
-+2
-+3
-+select *-- a comment \
-+from t1;
-+a
-+1
-+2
-+3
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       23
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        23
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   28
-+-----------------------------------------------------
-+select "\\"" /* not a comment */" from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       23
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        23
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   28
-+select "\\"" /* not a comment */" from t1;
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+select "\\"" /* not a comment */" from t1;
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+\" /* not a comment */
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       24
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        24
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   29
-+-----------------------------------------------------
-+select "\\"" /*! not a comment */" from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       24
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        24
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   29
-+select "\\"" /*! not a comment */" from t1;
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+select "\\"" /*! not a comment */" from t1;
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+\" /*! not a comment */
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       25
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        25
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   30
-+-----------------------------------------------------
-+select ' \'  ' from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       25
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        25
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   30
 +select ' \'  ' from t1;
 +'  
 + '  
 + '  
 +show status like "Qcache_queries_in_cache";
 +Variable_name Value
-+Qcache_queries_in_cache       26
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        26
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   31
-+-----------------------------------------------------
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1
-+-----------------------------------------------------
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       26
-+show status like "Qcache_inserts";
-+Variable_name Value
-+Qcache_inserts        26
-+show status like "Qcache_hits";
-+Variable_name Value
-+Qcache_hits   31
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
-+' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
-+' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+ ' /* comment inside quotes with internal backslash quote */
-+show status like "Qcache_queries_in_cache";
-+Variable_name Value
-+Qcache_queries_in_cache       27
++Qcache_queries_in_cache       21
 +show status like "Qcache_inserts";
 +Variable_name Value
-+Qcache_inserts        27
++Qcache_inserts        21
 +show status like "Qcache_hits";
 +Variable_name Value
-+Qcache_hits   32
++Qcache_hits   26
 +DROP TABLE t1;
 +SET GLOBAL query_cache_size=default;
 +set global query_cache_strip_comments=OFF;
 +SET GLOBAL query_cache_size=0;
 --- a/mysql-test/r/mysqld--help-notwin.result
 +++ b/mysql-test/r/mysqld--help-notwin.result
-@@ -493,6 +493,10 @@
+@@ -500,6 +500,10 @@
   The minimum size for blocks allocated by the query cache
   --query-cache-size=# 
   The memory allocated to store results from old queries
   --query-cache-type=name 
   OFF = Don't cache or retrieve results. ON = Cache all
   results except SELECT SQL_NO_CACHE ... queries. DEMAND =
-@@ -931,6 +935,7 @@
+@@ -942,6 +946,7 @@
  query-cache-limit 1048576
  query-cache-min-res-unit 4096
  query-cache-size 0
 +try_lock_mutex_query
 +SET GLOBAL query_cache_size=0;
 --- /dev/null
-+++ b/mysql-test/r/percona_query_cache_with_comments_crash_2.result
++++ b/mysql-test/r/percona_bug856404.result
 @@ -0,0 +1,8 @@
 +DROP TABLE IF EXISTS table17_int;
 +DROP TABLE IF EXISTS table30_int;
 +DROP TABLE table17_int;
 +DROP TABLE table30_int;
 --- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2-master.opt
++++ b/mysql-test/t/percona_bug856404-master.opt
 @@ -0,0 +1 @@
 +--query-cache-size=10M --query-cache-strip-comments
 --- /dev/null
-+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2.test
-@@ -0,0 +1,9 @@
++++ b/mysql-test/t/percona_bug856404.test
+@@ -0,0 +1,15 @@
++########################################################################
++# Bug #856404: Crash when query_cache_strip_comments enabled
++########################################################################
++
 +--disable_warnings
 +DROP TABLE IF EXISTS table17_int;
 +DROP TABLE IF EXISTS table30_int;
 +--enable_warnings
++
 +CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int);
 +CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int);
 +SELECT X . `pk` FROM `table17_int` AS X LEFT JOIN `table30_int` AS Y USING ( `col_enum_not_null_key` ) WHERE X . `col_char_10_not_null_key` != '   you need to translate Views labels into other languages, consider installing the <a href=\" !path\">Internationalization</a> package\'s Views translation module.' LIMIT 7  /*Generated by THREAD_ID 1*/;
++
 +DROP TABLE table17_int;
 +DROP TABLE table30_int;
---- a/sql/sql_class.cc
-+++ b/sql/sql_class.cc
-@@ -807,6 +807,99 @@
-           sql_errno == ER_TRG_NO_DEFINER);
- }
-+#ifdef HAVE_QUERY_CACHE
-+
-+
-+Query_Without_Comments::Query_Without_Comments() :
-+  buffer(0),
-+  q_length(0),
-+  b_length(0)
-+{
-+}
-+
-+
-+Query_Without_Comments::~Query_Without_Comments()
-+{
-+  if(buffer)
-+  {
-+    my_free(buffer);
-+  }
-+}
-+
-+
-+bool Query_Without_Comments::allocate(size_t query_length, size_t db_length)
-+{
-+  DBUG_ENTER("Query_Without_Comments::allocate");
-+  DBUG_PRINT("info", ("old buffer: %p "
-+                      "old query: '%-.4096s' "
-+                      "old buffer length: %u "
-+                      "old query length: %u",
-+                      buffer,
-+                      buffer,
-+                      (uint) b_length,
-+                      (uint) q_length));
-+  /* save maximum query length for check in the set_length */
-+  q_length= query_length;
-+  /* according to sql_parse.cc memory allocation */
-+  size_t new_b_length= (query_length + 1) + sizeof(size_t) + db_length +
-+    QUERY_CACHE_FLAGS_SIZE;
-+  if (b_length < new_b_length)
-+  {
-+    b_length= new_b_length;
-+    if (buffer)
-+    {
-+      buffer= (char*) my_realloc(buffer, b_length, MYF(0));
-+    }
-+    else
-+    {
-+      buffer= (char *) my_malloc(b_length, MYF(0));
-+    }
-+  }
-+  buffer[0]= 0;
-+  DBUG_PRINT("info", ("buffer: %p "
-+                      "buffer length: %u "
-+                      "query maximum length: %u",
-+                      buffer,
-+                      (uint) b_length,
-+                      (uint) q_length));
-+  DBUG_RETURN(buffer);
-+}
-+
-+
-+void Query_Without_Comments::set_length(size_t query_length)
-+{
-+  DBUG_ENTER("Query_Without_Comments::set_length");
-+  DBUG_ASSERT(query_length <= q_length);
-+  buffer[query_length]= 0;
-+  DBUG_PRINT("info", ("buffer: %p "
-+                      "query: '%-.4096s' "
-+                      "buffer length: %u "
-+                      "query maximum length: %u "
-+                      "query length: %u",
-+                      buffer,
-+                      buffer,
-+                      (uint) b_length,
-+                      (uint) q_length,
-+                      (uint) query_length));
-+  q_length= query_length;
-+  DBUG_VOID_RETURN;
-+}
-+
-+
-+char* Query_Without_Comments::query()
-+{
-+  return buffer;
-+}
-+
-+
-+size_t Query_Without_Comments::length()
-+{
-+  return q_length;
-+}
-+
-+
-+#endif // HAVE_QUERY_CACHE
-+
- THD::THD()
-    :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
index 02a38dc0686f865e21dc2f5e9017fce298898f6f..3f100e7864a1be8f342e97a4d7f8a6011f706a15 100644 (file)
  #ifdef HAVE_UCA_COLLATIONS
  
  #ifdef HAVE_CHARSET_ucs2
-@@ -204,6 +207,7 @@
- #ifdef HAVE_CHARSET_ucs2
+@@ -205,6 +208,7 @@
    add_compiled_collation(&my_charset_ucs2_general_ci);
    add_compiled_collation(&my_charset_ucs2_bin);
+   add_compiled_collation(&my_charset_ucs2_general_mysql500_ci);
 +  add_compiled_collation(&my_charset_ucs2_general50_ci);
  #ifdef HAVE_UCA_COLLATIONS
    add_compiled_collation(&my_charset_ucs2_unicode_ci);
    add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci);
-@@ -236,6 +240,7 @@
- #ifdef HAVE_CHARSET_utf8
+@@ -238,6 +242,7 @@
    add_compiled_collation(&my_charset_utf8_general_ci);
    add_compiled_collation(&my_charset_utf8_bin);
+   add_compiled_collation(&my_charset_utf8_general_mysql500_ci);
 +  add_compiled_collation(&my_charset_utf8_general50_ci);
  #ifdef HAVE_UTF8_GENERAL_CS
    add_compiled_collation(&my_charset_utf8_general_cs);
  #endif
 --- a/strings/ctype-ucs2.c
 +++ b/strings/ctype-ucs2.c
-@@ -3154,6 +3154,42 @@
-     &my_collation_ucs2_general_ci_handler
+@@ -3188,6 +3188,42 @@
  };
  
 +
 +extern MY_UNICASE_INFO *my_unicase_general50[256];
 +
      90,0,0,           /* number       */
 --- a/strings/ctype-utf8.c
 +++ b/strings/ctype-utf8.c
-@@ -193,6 +193,138 @@
+@@ -192,6 +192,138 @@
+   {0x00DE,0x00FE,0x00DE},  {0x0178,0x00FF,0x0059}
  };
  
 +static MY_UNICASE_INFO plane00_general50[]={
 +  {0x0000,0x0000,0x0000},  {0x0001,0x0001,0x0001},
 +  {0x0002,0x0002,0x0002},  {0x0003,0x0003,0x0003},
 +
 +
  
- static MY_UNICASE_INFO plane01[]={
-   {0x0100,0x0101,0x0041},  {0x0100,0x0101,0x0041},
-@@ -1542,6 +1674,48 @@
+ /*
+   Almost similar to plane00, but maps sorting order
+@@ -1718,6 +1850,48 @@
  
  
  /*
    Turkish lower/upper mapping:
    1. LOWER(0x0049 LATIN CAPITAL LETTER I) -> 
             0x0131 LATIN SMALL   LETTER DOTLESS I
-@@ -2814,6 +2988,39 @@
+@@ -3023,6 +3197,39 @@
  };
  
  
 +ue
 +ß
 +drop table t1;
---- /dev/null
-+++ b/mysql-test/r/percona_ucs2_general50_ci.result
-@@ -0,0 +1,38 @@
-+SET NAMES latin1;
-+SET collation_connection='ucs2_general50_ci';
-+drop table if exists t1;
-+create table t1 as select repeat(' ', 64) as s1;
-+select collation(s1) from t1;
-+collation(s1)
-+ucs2_general50_ci
-+delete from t1;
-+insert into t1 values ('a'),('ae'),(_latin1 0xE4);
-+insert into t1 values ('o'),('oe'),(_latin1 0xF6);
-+insert into t1 values ('s'),('ss'),(_latin1 0xDF);
-+insert into t1 values ('u'),('ue'),(_latin1 0xFC);
-+select s1, hex(s1) from t1 order by s1, binary s1;
-+s1    hex(s1)
-+\0     00
-+\0     00
-+\0     00
-+\0     00
-+\0     00
-+\0     00
-+\0     00
-+\0     00
-+a     61
-+o     6F
-+s     73
-+u     75
-+select group_concat(s1 order by binary s1) from t1 group by s1;
-+group_concat(s1 order by binary s1)
-+\0a
-+\0o
-+\0
-+\0u
-+\0
-+a
-+o
-+s
-+u
-+drop table t1;
+Binary files /dev/null and b/mysql-test/r/percona_ucs2_general50_ci.result differ
index 1045e9b1bc70ab947a922649334b0210f65eb1a9..c9eab678aa938e6f3f33f1f372d9ae721b89b3a3 100644 (file)
@@ -9,3 +9,23 @@
        int             error= 0;
        struct timespec abstime;
  
+--- a/storage/innobase/ibuf/ibuf0ibuf.c
++++ b/storage/innobase/ibuf/ibuf0ibuf.c
+@@ -1523,7 +1523,7 @@
+       for (i = 0; i < IBUF_OP_COUNT; i++) {
+ #ifdef HAVE_ATOMIC_BUILTINS
+-              os_atomic_increment_ulint(&arr[i], ops[i]);
++              (void) os_atomic_increment_ulint(&arr[i], ops[i]);
+ #else /* HAVE_ATOMIC_BUILTINS */
+               arr[i] += ops[i];
+ #endif /* HAVE_ATOMIC_BUILTINS */
+@@ -4785,7 +4785,7 @@
+       mem_heap_free(heap);
+ #ifdef HAVE_ATOMIC_BUILTINS
+-      os_atomic_increment_ulint(&ibuf->n_merges, 1);
++      (void) os_atomic_increment_ulint(&ibuf->n_merges, 1);
+       ibuf_add_ops(ibuf->n_merged_ops, mops);
+       ibuf_add_ops(ibuf->n_discarded_ops, dops);
+ #else /* HAVE_ATOMIC_BUILTINS */
This page took 0.371358 seconds and 4 git commands to generate.