43
43
extern ulonglong log_output_options;
44
44
extern ulong log_backup_output_options;
45
45
extern my_bool opt_log_queries_not_using_indexes;
47
+++ b/sql/query_strip_comments.h
49
+#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_
50
+#define _SQL_QUERY_STRIPC_COMMENTS_H_
51
+#ifdef HAVE_QUERY_CACHE
53
+// implemented in sql_cache.cc
54
+class QueryStripComments
57
+ QueryStripComments(const QueryStripComments&);
58
+ QueryStripComments& operator=(const QueryStripComments&);
60
+ QueryStripComments();
61
+ ~QueryStripComments();
62
+ void set(const char* a_query, uint a_query_length, uint a_additional_length);
64
+ char* query() { return buffer; }
65
+ uint query_length() { return length; }
70
+ uint length /*query length, not buffer length*/;
73
+class QueryStripComments_Backup
76
+ QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc);
77
+ ~QueryStripComments_Backup();
84
+#endif // HAVE_QUERY_CACHE
85
+#endif // _SQL_QUERY_STRIPC_COMMENTS_H_
86
46
--- a/sql/sql_cache.cc
87
47
+++ b/sql/sql_cache.cc
89
49
#include "probes_mysql.h"
90
50
#include "transaction.h"
92
+#include "query_strip_comments.h"
94
+QueryStripComments::QueryStripComments()
100
+QueryStripComments::~QueryStripComments()
105
+inline bool query_strip_comments_is_white_space(char c)
107
+ return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c ));
109
+void QueryStripComments::set(const char* query, uint query_length, uint additional_length)
111
+ uint new_buffer_length = query_length + additional_length;
112
+ if(new_buffer_length > buffer_length)
115
+ buffer = (char*)my_malloc(new_buffer_length,MYF(0));
117
+ uint query_position = 0;
119
+ // Skip whitespaces from begin
120
+ while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position]))
124
+ long int last_space = -1;
125
+ while(query_position < query_length)
127
+ char current = query[query_position];
128
+ bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position
53
+namespace query_comments_parser
59
+ /* 'Empty' symbol - epsilon in classic parsers */
63
+ * exclamation comment: slash-star-exclamation comment-body star-slash
64
+ * single-line and multi-line comments
67
+ /* Whitespaces: ' ' \t \r \n */
70
+ 1) C-style comment (slash-star comment-body star-slash)
71
+ 2) signle-line comment:
72
+ * sharp comment (sharp comment-body new-line)
73
+ * minus-minus comment (minus-minus comment-body new-line)
76
+ /* Not a special symbols (this symbols can't be before SELECT ). */
78
+ /* Error: not-closed quotes, not-closed C-style comment, end-of-query */
84
+ Analyze kind of prefix of input string.
86
+ @param where pointer to pointer to begin of string. After analyzing input
87
+ string function skip analyzed prefix and return pointer to the next part
88
+ of string in the @param where.
90
+ @return kind of analyzed prefix.
92
+static Kind analyze(const char **where, const char *const end)
94
+ DBUG_ASSERT(where != NULL);
95
+ DBUG_ASSERT(*where != NULL);
96
+ const char*&to= *where;
103
+ /* current symbol */
134
+ buffer[position++] = query[query_position++]; // copy current symbol
135
+ while(query_position < query_length)
137
+ if(current == query[query_position]) // found pair quote
141
+ buffer[position++] = query[query_position++]; // copy current symbol
147
+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
149
+ query_position += 2; // skip "/*"
152
+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/"
154
+ query_position += 2; // skip "*/"
155
+ insert_space = true;
163
+ while(query_position < query_length);
115
+ /* check for pair of quote */
116
+ if (*to == current)
118
+ /* skip second quote */
120
+ /* check for same symbol after second quote */
121
+ if (to < end && *to == current)
123
+ /* same symbol, skip it */
125
+ /* check for end-of-line */
128
+ /* not found - not closed quote */
133
+ /* continue search of pair */
173
+ if(query[query_position+1] == '-')
175
+ ++query_position; // skip "-", and go to search of "\n"
186
+ ++query_position; // skip current symbol (# or -)
187
+ if('\n' == query[query_position]) // check for '\n'
189
+ ++query_position; // skip '\n'
190
+ insert_space = true;
194
+ while(query_position < query_length);
205
+ if(query_strip_comments_is_white_space(current))
207
+ insert_space = true;
210
+ break; // make gcc happy
214
+ if((last_space + 1) != position)
216
+ last_space = position;
217
+ buffer[position++] = ' ';
222
+ buffer[position++] = query[query_position++];
225
+ while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1]))
229
+ buffer[position] = 0;
232
+void QueryStripComments::cleanup()
242
+QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc)
244
+ if(opt_query_cache_strip_comments)
247
+ query = thd->query();
248
+ length = thd->query_length();
249
+ qsc->set(query,length,thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
250
+ thd->set_query(qsc->query(),qsc->query_length());
259
+QueryStripComments_Backup::~QueryStripComments_Backup()
263
+ thd->set_query(query,length);
142
+ /* check for escaped symbols */
145
+ /* backslash, skip it */
148
+ /* check for end-of-line */
151
+ /* not found - not closed quote */
154
+ /* skip current symbol */
160
+ /* Check for second minus */
169
+ Prefix is minus-minus, next case-branch is processing
170
+ single line comments.
175
+ This is single-line comment, it started by "#" or "--".
179
+ /* search new-line */
180
+ to= strchr(to, '\n');
183
+ /* not found, end of the comment is the end of the query */
188
+ /* skip end-of-line */
195
+ /* check for star */
200
+ /* check for exclamation */
201
+ bool exclamation= (*to == '!');
202
+ /* search star-slash */
203
+ to= strstr(to, "*/");
206
+ /* not found - not closed comment */
212
+ DBUG_ASSERT(to + 1 < end);
213
+ DBUG_ASSERT(0 == strncmp(to, "*/", 2));
214
+ /* skip star-slash */
217
+ return (exclamation ? Special : Comment);
236
+ /* skip backslash */
241
+ query complete by backslash
248
+ /* skip after backslash symbol */
256
+ /* skip parenthese */
270
+static bool remove_comments_from_query(const char *const query,
271
+ const size_t query_length,
272
+ char *const result,
273
+ size_t *result_length)
275
+ /* pointer to begin of parsed block */
276
+ const char *from= query;
277
+ const char *to= query;
278
+ /* pointer to end of the query */
279
+ const char *const end= query + query_length;
280
+ /* pointer to last space */
281
+ const char *space= NULL;
282
+ /* current position in result buffer */
283
+ char *current= result;
287
+ switch (analyze(&to, end))
293
+ check for whitespace in the end
295
+ if (current == space)
297
+ /* drop whitespace in the end of query */
300
+ /* result is null-terminated string */
302
+ /* set result length */
303
+ *result_length= current - result;
308
+ /* should just insert space instead of comment */
310
+ if (space == current || from == query)
312
+ /* previous symbol was space */
316
+ /* insert space to result buffer */
318
+ /* switch after inserted space */
321
+ /* remember last-after-space position */
328
+ /* calculate parsed block size */
329
+ size_t block_size= to - from;
330
+ /* copy parsed block to result */
331
+ memcpy(current, from, block_size);
332
+ /* switch result after copied block */
333
+ current+= block_size;
334
+ /* switch after parsed block */
342
+ /* bad source query */
350
+static size_t skip_not_another(const char *const query, size_t query_length)
352
+ const char *from= query;
353
+ const char *to= query;
354
+ const char *const end= query + query_length;
357
+ switch (analyze(&to, end))
363
+ return (from - query);
372
+static size_t skip_default(const char *const query, size_t /* query_length */)
374
+ size_t query_position= 0;
376
+ Skip '(' characters in queries like following:
377
+ (select a from t1) union (select a from t1);
379
+ while (query[query_position]=='(')
381
+ return query_position;
385
+} /* namespace query_comments_parser */
387
+class Query_Switcher
390
+ Query_Switcher(const Query_Switcher&);
391
+ Query_Switcher& operator=(const Query_Switcher&);
395
+ Query_Switcher(THD *thd) :
396
+ target_query(&(thd_query_string(thd)->str)),
397
+ target_length(&(thd_query_string(thd)->length)),
398
+ backup_query(thd->query()),
399
+ backup_length(thd->query_length())
403
+ Query_Switcher(char **query,
405
+ target_query(query),
406
+ target_length(length),
407
+ backup_query(*query),
408
+ backup_length(*length)
412
+ void replace(Query_Without_Comments *query_without_comments)
414
+ *target_query= query_without_comments->query();
415
+ *target_length= query_without_comments->length();
419
+ *target_query= backup_query;
420
+ *target_length= backup_length;
423
+ char* *target_query;
424
+ size_t *target_length;
426
+ char *const backup_query;
427
+ size_t const backup_length;
430
+class Comments_Processor
433
+ Comments_Processor(const Comments_Processor&);
434
+ Comments_Processor& operator=(const Comments_Processor&);
438
+ Comments_Processor(THD *thd) :
439
+ query_switcher (thd),
440
+ db_length (thd->db_length),
441
+ query_without_comments(&(thd->query_without_comments)),
442
+ enabled (opt_query_cache_strip_comments),
448
+ Comments_Processor(Query_Without_Comments *current_query_without_comments,
451
+ const size_t current_db_length) :
452
+ query_switcher (query, length),
453
+ db_length (current_db_length),
454
+ query_without_comments(current_query_without_comments),
455
+ enabled (opt_query_cache_strip_comments),
461
+ ~Comments_Processor()
463
+ restore_comments();
467
+ size_t prefix_length()
469
+ using query_comments_parser::skip_not_another;
470
+ using query_comments_parser::skip_default;
473
+ return skip_not_another(query_switcher.backup_query,
474
+ query_switcher.backup_length);
478
+ return skip_default(query_switcher.backup_query,
479
+ query_switcher.backup_length);
484
+ bool remove_comments()
486
+ if (!enabled || restore)
490
+ /* Allocate memory for query rewrite */
491
+ if (!query_without_comments->allocate(query_switcher.backup_length,
496
+ /* Remove comment from query */
497
+ size_t result_length;
498
+ using query_comments_parser::remove_comments_from_query;
499
+ if (!(restore= remove_comments_from_query(query_switcher.backup_query,
500
+ query_switcher.backup_length,
501
+ query_without_comments->query(),
506
+ query_without_comments->set_length(result_length);
507
+ size_t db_length_from_query=
508
+ *((size_t*)(query_switcher.backup_query +
509
+ query_switcher.backup_length + 1));
510
+ *((size_t*)(query_without_comments->query() +
511
+ result_length + 1))= db_length_from_query;
512
+ /* Replace original query by striped */
513
+ query_switcher.replace(query_without_comments);
518
+ void restore_comments()
520
+ if (enabled && restore)
522
+ /* Replace striped query by original */
523
+ query_switcher.restore();
525
+ /* Clean query_without_comments */
526
+ query_without_comments->set_length(0);
528
+ /* Mark as restored */
533
+ Query_Switcher query_switcher;
535
+ const size_t db_length;
537
+ Query_Without_Comments *query_without_comments;
267
542
#ifdef EMBEDDED_LIBRARY
268
543
#include "emb_qcache.h"
271
546
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
272
547
DBUG_ENTER("Query_cache::try_lock");
274
+ const char* old_proc_info= thd->proc_info;
549
+ const char *old_proc_info= thd->proc_info;
275
550
+ thd_proc_info(thd,"Waiting on query cache mutex");
276
551
+ DEBUG_SYNC(thd, "before_query_cache_mutex");
277
552
mysql_mutex_lock(&structure_guard_mutex);
282
557
if (m_cache_lock_status == Query_cache::UNLOCKED)
283
@@ -1274,6 +1454,8 @@
558
@@ -1274,6 +1764,8 @@
285
560
DBUG_VOID_RETURN;
287
+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
288
+ QueryStripComments_Backup backup(thd,query_strip_comments);
562
+ Comments_Processor comments_processor(thd);
563
+ comments_processor.remove_comments();
290
565
/* Key is query + database + flag */
291
566
if (thd->db_length)
292
@@ -1451,6 +1633,9 @@
293
Query_cache_block_table *block_table, *block_table_end;
567
@@ -1440,7 +1932,7 @@
571
-Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
572
+Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length_uint)
574
ulonglong engine_data;
575
Query_cache_query *query;
576
@@ -1452,6 +1944,11 @@
294
577
ulong tot_length;
295
578
Query_cache_query_flags flags;
296
+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
297
+ char *sql_backup = sql;
298
+ uint query_length_backup = query_length;
299
579
DBUG_ENTER("Query_cache::send_result_to_client");
580
+ size_t query_length= query_length_uint;
581
+ Comments_Processor comments_processor(&(thd->query_without_comments),
302
@@ -1472,21 +1657,103 @@
587
Testing 'query_cache_size' without a lock here is safe: the thing
588
@@ -1471,13 +1968,7 @@
307
594
- Skip '(' characters in queries like following:
308
595
- (select a from t1) union (select a from t1);
310
597
- while (sql[i]=='(')
312
+ if(opt_query_cache_strip_comments)
314
+ /* Skip all comments and non-letter symbols */
315
+ uint& query_position = i;
317
+ while(query_position < query_length)
319
+ bool check = false;
320
+ char current = query[query_position];
324
+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
326
+ query_position += 2; // skip "/*"
329
+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
331
+ query_position += 2; // skip "*/" (without space)
339
+ while(query_position < query_length);
340
+ continue; // analyze current symbol
344
+ if(query[query_position+1] == '-')
346
+ ++query_position; // skip "-"
355
+ ++query_position; // skip current symbol
356
+ if('\n' == query[query_position]) // check for '\n'
358
+ ++query_position; // skip '\n'
362
+ while(query_position < query_length);
363
+ continue; // analyze current symbol
373
+ break; // make gcc happy
374
+ } // switch(current)
377
+ if(query_position + 2 < query_length)
384
+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
389
+ } // while(query_position < query_length)
391
+ else // if(opt_query_cache_strip_comments)
394
+ Skip '(' characters in queries like following:
395
+ (select a from t1) union (select a from t1);
397
+ while (sql[i]=='(')
401
- Test if the query is a SELECT
402
- (pre-space is removed in dispatch_command).
403
+ } // if(opt_query_cache_strip_comments)
405
+ Test if the query is a SELECT
406
+ (pre-space is removed in dispatch_command).
408
- First '/' looks like comment before command it is not
409
- frequently appeared in real life, consequently we can
410
- check all such queries, too.
412
+ First '/' looks like comment before command it is not
413
+ frequently appeared in real life, consequently we can
414
+ check all such queries, too.
416
if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
417
my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
418
my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
419
@@ -1521,6 +1788,12 @@
599
+ size_t i= comments_processor.prefix_length();
602
Test if the query is a SELECT
603
@@ -1487,10 +1978,11 @@
604
frequently appeared in real life, consequently we can
605
check all such queries, too.
607
- if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
608
- my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
609
- my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
611
+ if (!((i + 2 < query_length) &&
612
+ ((my_toupper(system_charset_info, sql[i]) == 'S' &&
613
+ my_toupper(system_charset_info, sql[i + 1]) == 'E' &&
614
+ my_toupper(system_charset_info, sql[i + 2]) == 'L') ||
617
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
619
@@ -1543,6 +2035,7 @@
422
622
Query_cache_block *query_block;
423
+ if(opt_query_cache_strip_comments)
425
+ query_strip_comments->set(sql, query_length, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
426
+ sql = query_strip_comments->query();
427
+ query_length = query_strip_comments->query_length();
623
+ comments_processor.remove_comments();
430
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
432
@@ -1587,6 +1860,8 @@
625
tot_length= query_length + 1 + sizeof(size_t) +
626
thd->db_length + QUERY_CACHE_FLAGS_SIZE;
627
@@ -1611,6 +2104,7 @@
433
628
(uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
434
629
query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql,
437
+ query_length = query_length_backup;
631
+ comments_processor.restore_comments();
438
632
/* Quick abort on unlocked data */
439
633
if (query_block == 0 ||
440
634
query_block->query()->result() == 0 ||
441
635
--- a/sql/sql_class.h
442
636
+++ b/sql/sql_class.h
444
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
447
+#ifdef HAVE_QUERY_CACHE
448
+#include "query_strip_comments.h"
449
+#endif // HAVE_QUERY_CACHE
451
class Reprepare_observer;
452
class Relay_log_info;
454
statement lifetime. FIXME: must be const
457
+#ifdef HAVE_QUERY_CACHE
458
+ QueryStripComments query_strip_comments; // see sql_cache.cc
459
+#endif //HAVE_QUERY_CACHE
462
MARK_COLUMNS_NONE: Means mark_used_colums is not set and no indicator to
637
@@ -1487,6 +1487,74 @@
639
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
642
+#ifdef HAVE_QUERY_CACHE
646
+ @class Query_Without_Comments
647
+ This class provides way for safety (re)allocation
648
+ a memory for a query without comments.
650
+class Query_Without_Comments
654
+ Denied copy and assigment for object of this class.
656
+ Query_Without_Comments(const Query_Without_Comments&);
657
+ Query_Without_Comments& operator=(const Query_Without_Comments&);
662
+ Constructor is filling fields by zero (no allocation).
664
+ Query_Without_Comments();
668
+ Destructor clean allocated memory
670
+ ~Query_Without_Comments();
675
+ (Re)allocate memory for query. Query length after that is 0.
677
+ bool allocate(size_t query_length, size_t db_length);
681
+ Set result query length, when query
682
+ without comments is copied to buffer.
684
+ void set_length(size_t query_length);
695
+ Result query length
707
+#endif /* HAVE_QUERY_CACHE */
711
For each client connection we create a separate thread with THD serving as
712
@@ -1544,6 +1612,7 @@
713
struct st_mysql_stmt *current_stmt;
715
#ifdef HAVE_QUERY_CACHE
716
+ Query_Without_Comments query_without_comments;
717
Query_cache_tls query_cache_tls;
719
NET net; // client connection descriptor
463
720
--- a/sql/sys_vars.cc
464
721
+++ b/sql/sys_vars.cc
465
722
@@ -1809,6 +1809,11 @@
1458
1737
+Variable_name Value
1459
1738
+Qcache_hits 50
1460
1739
+-----------------------------------------------------
1740
+select */* a comment \*/from t1
1741
+-----------------------------------------------------
1742
+show status like "Qcache_queries_in_cache";
1743
+Variable_name Value
1744
+Qcache_queries_in_cache 1
1745
+show status like "Qcache_inserts";
1746
+Variable_name Value
1748
+show status like "Qcache_hits";
1749
+Variable_name Value
1751
+select */* a comment \*/from t1;
1756
+select */* a comment \*/from t1;
1761
+show status like "Qcache_queries_in_cache";
1762
+Variable_name Value
1763
+Qcache_queries_in_cache 1
1764
+show status like "Qcache_inserts";
1765
+Variable_name Value
1767
+show status like "Qcache_hits";
1768
+Variable_name Value
1770
+-----------------------------------------------------
1771
+select *# a comment \
1773
+-----------------------------------------------------
1774
+show status like "Qcache_queries_in_cache";
1775
+Variable_name Value
1776
+Qcache_queries_in_cache 1
1777
+show status like "Qcache_inserts";
1778
+Variable_name Value
1780
+show status like "Qcache_hits";
1781
+Variable_name Value
1783
+select *# a comment \
1789
+select *# a comment \
1795
+show status like "Qcache_queries_in_cache";
1796
+Variable_name Value
1797
+Qcache_queries_in_cache 1
1798
+show status like "Qcache_inserts";
1799
+Variable_name Value
1801
+show status like "Qcache_hits";
1802
+Variable_name Value
1804
+-----------------------------------------------------
1805
+select *-- a comment \
1807
+-----------------------------------------------------
1808
+show status like "Qcache_queries_in_cache";
1809
+Variable_name Value
1810
+Qcache_queries_in_cache 1
1811
+show status like "Qcache_inserts";
1812
+Variable_name Value
1814
+show status like "Qcache_hits";
1815
+Variable_name Value
1817
+select *-- a comment \
1823
+select *-- a comment \
1829
+show status like "Qcache_queries_in_cache";
1830
+Variable_name Value
1831
+Qcache_queries_in_cache 1
1832
+show status like "Qcache_inserts";
1833
+Variable_name Value
1835
+show status like "Qcache_hits";
1836
+Variable_name Value
1838
+-----------------------------------------------------
1839
+select "\\"" /* not a comment */" from t1
1840
+-----------------------------------------------------
1841
+show status like "Qcache_queries_in_cache";
1842
+Variable_name Value
1843
+Qcache_queries_in_cache 1
1844
+show status like "Qcache_inserts";
1845
+Variable_name Value
1847
+show status like "Qcache_hits";
1848
+Variable_name Value
1850
+select "\\"" /* not a comment */" from t1;
1851
+\" /* not a comment */
1852
+\" /* not a comment */
1853
+\" /* not a comment */
1854
+\" /* not a comment */
1855
+select "\\"" /* not a comment */" from t1;
1856
+\" /* not a comment */
1857
+\" /* not a comment */
1858
+\" /* not a comment */
1859
+\" /* not a comment */
1860
+show status like "Qcache_queries_in_cache";
1861
+Variable_name Value
1862
+Qcache_queries_in_cache 2
1863
+show status like "Qcache_inserts";
1864
+Variable_name Value
1866
+show status like "Qcache_hits";
1867
+Variable_name Value
1869
+-----------------------------------------------------
1870
+select "\\"" /*! not a comment */" from t1
1871
+-----------------------------------------------------
1872
+show status like "Qcache_queries_in_cache";
1873
+Variable_name Value
1874
+Qcache_queries_in_cache 2
1875
+show status like "Qcache_inserts";
1876
+Variable_name Value
1878
+show status like "Qcache_hits";
1879
+Variable_name Value
1881
+select "\\"" /*! not a comment */" from t1;
1882
+\" /*! not a comment */
1883
+\" /*! not a comment */
1884
+\" /*! not a comment */
1885
+\" /*! not a comment */
1886
+select "\\"" /*! not a comment */" from t1;
1887
+\" /*! not a comment */
1888
+\" /*! not a comment */
1889
+\" /*! not a comment */
1890
+\" /*! not a comment */
1891
+show status like "Qcache_queries_in_cache";
1892
+Variable_name Value
1893
+Qcache_queries_in_cache 3
1894
+show status like "Qcache_inserts";
1895
+Variable_name Value
1897
+show status like "Qcache_hits";
1898
+Variable_name Value
1900
+-----------------------------------------------------
1461
1901
+select ' \' ' from t1
1462
1902
+-----------------------------------------------------
1463
1903
+show status like "Qcache_queries_in_cache";
1464
1904
+Variable_name Value
1465
+Qcache_queries_in_cache 1
1466
+show status like "Qcache_inserts";
1467
+Variable_name Value
1469
+show status like "Qcache_hits";
1470
+Variable_name Value
1472
+select ' \' ' from t1;
1477
+select ' \' ' from t1;
1482
+show status like "Qcache_queries_in_cache";
1483
+Variable_name Value
1484
+Qcache_queries_in_cache 2
1485
+show status like "Qcache_inserts";
1486
+Variable_name Value
1488
+show status like "Qcache_hits";
1489
+Variable_name Value
1905
+Qcache_queries_in_cache 3
1906
+show status like "Qcache_inserts";
1907
+Variable_name Value
1909
+show status like "Qcache_hits";
1910
+Variable_name Value
1912
+select ' \' ' from t1;
1917
+select ' \' ' from t1;
1922
+show status like "Qcache_queries_in_cache";
1923
+Variable_name Value
1924
+Qcache_queries_in_cache 4
1925
+show status like "Qcache_inserts";
1926
+Variable_name Value
1928
+show status like "Qcache_hits";
1929
+Variable_name Value
1931
+-----------------------------------------------------
1932
+select ' \' /* comment inside quotes with internal backslash quote */' from t1
1933
+-----------------------------------------------------
1934
+show status like "Qcache_queries_in_cache";
1935
+Variable_name Value
1936
+Qcache_queries_in_cache 4
1937
+show status like "Qcache_inserts";
1938
+Variable_name Value
1940
+show status like "Qcache_hits";
1941
+Variable_name Value
1943
+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
1944
+' /* comment inside quotes with internal backslash quote */
1945
+ ' /* comment inside quotes with internal backslash quote */
1946
+ ' /* comment inside quotes with internal backslash quote */
1947
+ ' /* comment inside quotes with internal backslash quote */
1948
+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
1949
+' /* comment inside quotes with internal backslash quote */
1950
+ ' /* comment inside quotes with internal backslash quote */
1951
+ ' /* comment inside quotes with internal backslash quote */
1952
+ ' /* comment inside quotes with internal backslash quote */
1953
+show status like "Qcache_queries_in_cache";
1954
+Variable_name Value
1955
+Qcache_queries_in_cache 5
1956
+show status like "Qcache_inserts";
1957
+Variable_name Value
1959
+show status like "Qcache_hits";
1960
+Variable_name Value
1491
1962
+DROP TABLE t1;
1492
1963
+SET GLOBAL query_cache_size=default;
1493
1964
+set global query_cache_strip_comments=OFF;
2350
2821
+Variable_name Value
2351
2822
+Qcache_hits 25
2352
2823
+-----------------------------------------------------
2824
+select */* a comment \*/from t1
2825
+-----------------------------------------------------
2826
+show status like "Qcache_queries_in_cache";
2827
+Variable_name Value
2828
+Qcache_queries_in_cache 20
2829
+show status like "Qcache_inserts";
2830
+Variable_name Value
2832
+show status like "Qcache_hits";
2833
+Variable_name Value
2835
+select */* a comment \*/from t1;
2840
+select */* a comment \*/from t1;
2845
+show status like "Qcache_queries_in_cache";
2846
+Variable_name Value
2847
+Qcache_queries_in_cache 21
2848
+show status like "Qcache_inserts";
2849
+Variable_name Value
2851
+show status like "Qcache_hits";
2852
+Variable_name Value
2854
+-----------------------------------------------------
2855
+select *# a comment \
2857
+-----------------------------------------------------
2858
+show status like "Qcache_queries_in_cache";
2859
+Variable_name Value
2860
+Qcache_queries_in_cache 21
2861
+show status like "Qcache_inserts";
2862
+Variable_name Value
2864
+show status like "Qcache_hits";
2865
+Variable_name Value
2867
+select *# a comment \
2873
+select *# a comment \
2879
+show status like "Qcache_queries_in_cache";
2880
+Variable_name Value
2881
+Qcache_queries_in_cache 22
2882
+show status like "Qcache_inserts";
2883
+Variable_name Value
2885
+show status like "Qcache_hits";
2886
+Variable_name Value
2888
+-----------------------------------------------------
2889
+select *-- a comment \
2891
+-----------------------------------------------------
2892
+show status like "Qcache_queries_in_cache";
2893
+Variable_name Value
2894
+Qcache_queries_in_cache 22
2895
+show status like "Qcache_inserts";
2896
+Variable_name Value
2898
+show status like "Qcache_hits";
2899
+Variable_name Value
2901
+select *-- a comment \
2907
+select *-- a comment \
2913
+show status like "Qcache_queries_in_cache";
2914
+Variable_name Value
2915
+Qcache_queries_in_cache 23
2916
+show status like "Qcache_inserts";
2917
+Variable_name Value
2919
+show status like "Qcache_hits";
2920
+Variable_name Value
2922
+-----------------------------------------------------
2923
+select "\\"" /* not a comment */" from t1
2924
+-----------------------------------------------------
2925
+show status like "Qcache_queries_in_cache";
2926
+Variable_name Value
2927
+Qcache_queries_in_cache 23
2928
+show status like "Qcache_inserts";
2929
+Variable_name Value
2931
+show status like "Qcache_hits";
2932
+Variable_name Value
2934
+select "\\"" /* not a comment */" from t1;
2935
+\" /* not a comment */
2936
+\" /* not a comment */
2937
+\" /* not a comment */
2938
+\" /* not a comment */
2939
+select "\\"" /* not a comment */" from t1;
2940
+\" /* not a comment */
2941
+\" /* not a comment */
2942
+\" /* not a comment */
2943
+\" /* not a comment */
2944
+show status like "Qcache_queries_in_cache";
2945
+Variable_name Value
2946
+Qcache_queries_in_cache 24
2947
+show status like "Qcache_inserts";
2948
+Variable_name Value
2950
+show status like "Qcache_hits";
2951
+Variable_name Value
2953
+-----------------------------------------------------
2954
+select "\\"" /*! not a comment */" from t1
2955
+-----------------------------------------------------
2956
+show status like "Qcache_queries_in_cache";
2957
+Variable_name Value
2958
+Qcache_queries_in_cache 24
2959
+show status like "Qcache_inserts";
2960
+Variable_name Value
2962
+show status like "Qcache_hits";
2963
+Variable_name Value
2965
+select "\\"" /*! not a comment */" from t1;
2966
+\" /*! not a comment */
2967
+\" /*! not a comment */
2968
+\" /*! not a comment */
2969
+\" /*! not a comment */
2970
+select "\\"" /*! not a comment */" from t1;
2971
+\" /*! not a comment */
2972
+\" /*! not a comment */
2973
+\" /*! not a comment */
2974
+\" /*! not a comment */
2975
+show status like "Qcache_queries_in_cache";
2976
+Variable_name Value
2977
+Qcache_queries_in_cache 25
2978
+show status like "Qcache_inserts";
2979
+Variable_name Value
2981
+show status like "Qcache_hits";
2982
+Variable_name Value
2984
+-----------------------------------------------------
2353
2985
+select ' \' ' from t1
2354
2986
+-----------------------------------------------------
2355
2987
+show status like "Qcache_queries_in_cache";
2356
2988
+Variable_name Value
2357
+Qcache_queries_in_cache 20
2358
+show status like "Qcache_inserts";
2359
+Variable_name Value
2361
+show status like "Qcache_hits";
2362
+Variable_name Value
2364
+select ' \' ' from t1;
2369
+select ' \' ' from t1;
2374
+show status like "Qcache_queries_in_cache";
2375
+Variable_name Value
2376
+Qcache_queries_in_cache 21
2377
+show status like "Qcache_inserts";
2378
+Variable_name Value
2380
+show status like "Qcache_hits";
2381
+Variable_name Value
2989
+Qcache_queries_in_cache 25
2990
+show status like "Qcache_inserts";
2991
+Variable_name Value
2993
+show status like "Qcache_hits";
2994
+Variable_name Value
2996
+select ' \' ' from t1;
3001
+select ' \' ' from t1;
3006
+show status like "Qcache_queries_in_cache";
3007
+Variable_name Value
3008
+Qcache_queries_in_cache 26
3009
+show status like "Qcache_inserts";
3010
+Variable_name Value
3012
+show status like "Qcache_hits";
3013
+Variable_name Value
3015
+-----------------------------------------------------
3016
+select ' \' /* comment inside quotes with internal backslash quote */' from t1
3017
+-----------------------------------------------------
3018
+show status like "Qcache_queries_in_cache";
3019
+Variable_name Value
3020
+Qcache_queries_in_cache 26
3021
+show status like "Qcache_inserts";
3022
+Variable_name Value
3024
+show status like "Qcache_hits";
3025
+Variable_name Value
3027
+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
3028
+' /* comment inside quotes with internal backslash quote */
3029
+ ' /* comment inside quotes with internal backslash quote */
3030
+ ' /* comment inside quotes with internal backslash quote */
3031
+ ' /* comment inside quotes with internal backslash quote */
3032
+select ' \' /* comment inside quotes with internal backslash quote */' from t1;
3033
+' /* comment inside quotes with internal backslash quote */
3034
+ ' /* comment inside quotes with internal backslash quote */
3035
+ ' /* comment inside quotes with internal backslash quote */
3036
+ ' /* comment inside quotes with internal backslash quote */
3037
+show status like "Qcache_queries_in_cache";
3038
+Variable_name Value
3039
+Qcache_queries_in_cache 27
3040
+show status like "Qcache_inserts";
3041
+Variable_name Value
3043
+show status like "Qcache_hits";
3044
+Variable_name Value
2383
3046
+DROP TABLE t1;
2384
3047
+SET GLOBAL query_cache_size=default;
2385
3048
+set global query_cache_strip_comments=OFF;
3115
3778
+try_lock_mutex_query
3116
3779
+SET GLOBAL query_cache_size=0;
3781
+++ b/mysql-test/r/percona_query_cache_with_comments_crash_2.result
3783
+DROP TABLE IF EXISTS table17_int;
3784
+DROP TABLE IF EXISTS table30_int;
3785
+CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int);
3786
+CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int);
3787
+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*/;
3789
+DROP TABLE table17_int;
3790
+DROP TABLE table30_int;
3792
+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2-master.opt
3794
+--query-cache-size=10M --query-cache-strip-comments
3796
+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2.test
3799
+DROP TABLE IF EXISTS table17_int;
3800
+DROP TABLE IF EXISTS table30_int;
3802
+CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int);
3803
+CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int);
3804
+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*/;
3805
+DROP TABLE table17_int;
3806
+DROP TABLE table30_int;
3807
--- a/sql/sql_class.cc
3808
+++ b/sql/sql_class.cc
3809
@@ -807,6 +807,99 @@
3810
sql_errno == ER_TRG_NO_DEFINER);
3813
+#ifdef HAVE_QUERY_CACHE
3816
+Query_Without_Comments::Query_Without_Comments() :
3824
+Query_Without_Comments::~Query_Without_Comments()
3833
+bool Query_Without_Comments::allocate(size_t query_length, size_t db_length)
3835
+ DBUG_ENTER("Query_Without_Comments::allocate");
3836
+ DBUG_PRINT("info", ("old buffer: %p "
3837
+ "old query: '%-.4096s' "
3838
+ "old buffer length: %u "
3839
+ "old query length: %u",
3843
+ (uint) q_length));
3844
+ /* save maximum query length for check in the set_length */
3845
+ q_length= query_length;
3846
+ /* according to sql_parse.cc memory allocation */
3847
+ size_t new_b_length= (query_length + 1) + sizeof(size_t) + db_length +
3848
+ QUERY_CACHE_FLAGS_SIZE;
3849
+ if (b_length < new_b_length)
3851
+ b_length= new_b_length;
3854
+ buffer= (char*) my_realloc(buffer, b_length, MYF(0));
3858
+ buffer= (char *) my_malloc(b_length, MYF(0));
3862
+ DBUG_PRINT("info", ("buffer: %p "
3863
+ "buffer length: %u "
3864
+ "query maximum length: %u",
3867
+ (uint) q_length));
3868
+ DBUG_RETURN(buffer);
3872
+void Query_Without_Comments::set_length(size_t query_length)
3874
+ DBUG_ENTER("Query_Without_Comments::set_length");
3875
+ DBUG_ASSERT(query_length <= q_length);
3876
+ buffer[query_length]= 0;
3877
+ DBUG_PRINT("info", ("buffer: %p "
3878
+ "query: '%-.4096s' "
3879
+ "buffer length: %u "
3880
+ "query maximum length: %u "
3881
+ "query length: %u",
3886
+ (uint) query_length));
3887
+ q_length= query_length;
3892
+char* Query_Without_Comments::query()
3898
+size_t Query_Without_Comments::length()
3904
+#endif // HAVE_QUERY_CACHE
3908
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,