--- /dev/null
+--- 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;
--- /dev/null
+--- /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
+ {
--- /dev/null
+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,
}
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 @@
# 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);
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);
#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);
#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);
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
# 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
%patch161 -p1
%patch162 -p1
%patch163 -p1
+%patch164 -p1
+%patch165 -p1
+%patch166 -p1
# </percona>
# to get these files rebuild
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;
-# name : query_cache_enhance.patch
+# name : query_cache_with_comments.patch
# introduced : 11 or before
# maintainer : Oleg
#
+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 char* old_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,
#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
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 */