~dingqi-lxb/percona-server/5.5_log_queries_in_memory

« back to all changes in this revision

Viewing changes to patches/query_cache_enhance.patch

  • Committer: dingqi.lxb at taobao
  • Date: 2012-01-01 03:46:09 UTC
  • mfrom: (198.3.2 percona-server)
  • Revision ID: dingqi.lxb@taobao.com-20120101034609-gohh9k05kvkqjzz8
mergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# name       : query_cache_with_comments.patch
 
1
# name       : query_cache_enhance.patch
2
2
# introduced : 11 or before
3
3
# maintainer : Oleg
4
4
#
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;
46
 
--- /dev/null
47
 
+++ b/sql/query_strip_comments.h
48
 
@@ -0,0 +1,37 @@
49
 
+#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_
50
 
+#define _SQL_QUERY_STRIPC_COMMENTS_H_
51
 
+#ifdef HAVE_QUERY_CACHE
52
 
+
53
 
+// implemented in sql_cache.cc
54
 
+class QueryStripComments
55
 
+{
56
 
+private:
57
 
+  QueryStripComments(const QueryStripComments&);
58
 
+  QueryStripComments& operator=(const QueryStripComments&);
59
 
+public:
60
 
+  QueryStripComments();
61
 
+  ~QueryStripComments();
62
 
+  void set(const char* a_query, uint a_query_length, uint a_additional_length);
63
 
+  
64
 
+  char* query()        { return buffer; }
65
 
+  uint  query_length() { return length; }
66
 
+private:
67
 
+  void cleanup();
68
 
+private:
69
 
+  char* buffer;
70
 
+  uint  length /*query length, not buffer length*/;
71
 
+  uint  buffer_length;
72
 
+};
73
 
+class QueryStripComments_Backup
74
 
+{
75
 
+public:
76
 
+  QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc);
77
 
+  ~QueryStripComments_Backup();
78
 
+private:
79
 
+  THD*  thd;
80
 
+  char* query;
81
 
+  uint  length;
82
 
+};
83
 
+
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
88
 
@@ -344,6 +344,181 @@
 
48
@@ -344,6 +344,496 @@
89
49
 #include "probes_mysql.h"
90
50
 #include "transaction.h"
91
51
 
92
 
+#include "query_strip_comments.h"
93
 
+
94
 
+QueryStripComments::QueryStripComments()
95
 
+{
96
 
+  buffer = 0;
97
 
+  length = 0;
98
 
+  buffer_length = 0;
99
 
+}
100
 
+QueryStripComments::~QueryStripComments()
101
 
+{
102
 
+  cleanup();
103
 
+}
104
 
+
105
 
+inline bool query_strip_comments_is_white_space(char c)
106
 
+{
107
 
+  return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c ));
108
 
+}
109
 
+void QueryStripComments::set(const char* query, uint query_length, uint additional_length)
110
 
+{
111
 
+  uint new_buffer_length = query_length + additional_length;
112
 
+  if(new_buffer_length > buffer_length)
113
 
+  {
114
 
+    cleanup();
115
 
+    buffer = (char*)my_malloc(new_buffer_length,MYF(0));
116
 
+  }
117
 
+  uint query_position = 0;
118
 
+  uint position = 0;
119
 
+  // Skip whitespaces from begin
120
 
+  while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position]))
121
 
+  {
122
 
+    ++query_position;
123
 
+  }
124
 
+  long int last_space = -1;
125
 
+  while(query_position < query_length)
126
 
+  {
127
 
+    char current = query[query_position];
128
 
+    bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position
129
 
+    switch(current)
 
52
+
 
53
+namespace query_comments_parser
 
54
+{
 
55
+
 
56
+
 
57
+enum Kind
 
58
+{
 
59
+  /* 'Empty' symbol - epsilon in classic parsers */
 
60
+  Empty,
 
61
+  /*
 
62
+    Special symbols:
 
63
+      * exclamation comment: slash-star-exclamation comment-body star-slash
 
64
+      * single-line and multi-line comments
 
65
+  */
 
66
+  Special,
 
67
+  /* Whitespaces: ' ' \t \r \n */
 
68
+  WhiteSpace,
 
69
+  /*
 
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)
 
74
+  */
 
75
+  Comment,
 
76
+  /* Not a special symbols (this symbols can't be before SELECT ). */
 
77
+  Another,
 
78
+  /* Error: not-closed quotes, not-closed C-style comment, end-of-query */
 
79
+  Error
 
80
+};
 
81
+
 
82
+
 
83
+/**
 
84
+  Analyze kind of prefix of input string.
 
85
+
 
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.
 
89
+
 
90
+  @return kind of analyzed prefix.
 
91
+*/
 
92
+static Kind analyze(const char **where, const char *const end)
 
93
+{
 
94
+  DBUG_ASSERT(where != NULL);
 
95
+  DBUG_ASSERT(*where != NULL);
 
96
+  const char*&to= *where;
 
97
+  /* if empty */
 
98
+  if (*to == '\0')
 
99
+  {
 
100
+    return Empty;
 
101
+  }
 
102
+
 
103
+  /* current symbol */
 
104
+  char current= *to;
 
105
+
 
106
+  switch (current)
 
107
+  {
 
108
+  case '\'':
 
109
+  case '"':
 
110
+    /* skip quote */
 
111
+    to++;
 
112
+    /* search pair */
 
113
+    while (true)
130
114
+    {
131
 
+    case '\'':
132
 
+    case '"':
133
 
+      {
134
 
+        buffer[position++] = query[query_position++]; // copy current symbol
135
 
+        while(query_position < query_length)
136
 
+        {
137
 
+          if(current == query[query_position]) // found pair quote
138
 
+          {
139
 
+            break;
140
 
+          }
141
 
+          buffer[position++] = query[query_position++]; // copy current symbol
142
 
+        }
143
 
+        break;
144
 
+      }
145
 
+    case '/':
146
 
+      {
147
 
+        if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
148
 
+        {
149
 
+          query_position += 2; // skip "/*"
150
 
+          do
151
 
+          {
152
 
+            if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/"
153
 
+            {
154
 
+              query_position += 2; // skip "*/"
155
 
+              insert_space = true;
156
 
+              break;
157
 
+            }
158
 
+            else
159
 
+            {
160
 
+              ++query_position;
161
 
+            }
162
 
+          }
163
 
+          while(query_position < query_length);
164
 
+          if(!insert_space)
165
 
+          {
 
115
+      /* check for pair of quote */
 
116
+      if (*to == current)
 
117
+      {
 
118
+        /* skip second quote */
 
119
+        to++;
 
120
+        /* check for same symbol after second quote */
 
121
+        if (to < end && *to == current)
 
122
+        {
 
123
+          /* same symbol, skip it */
 
124
+          to++;
 
125
+          /* check for end-of-line */
 
126
+          if (to == end)
 
127
+          {
 
128
+            /* not found - not closed quote */
 
129
+            return Error;
 
130
+          }
 
131
+          else
 
132
+          {
 
133
+            /* continue search of pair */
166
134
+            continue;
167
135
+          }
168
136
+        }
169
 
+        break;
170
 
+      }
171
 
+    case '-':
172
 
+      {
173
 
+        if(query[query_position+1] == '-')
174
 
+        {
175
 
+          ++query_position; // skip "-", and go to search of "\n"
176
 
+        }
177
 
+        else
178
 
+        {
179
 
+          break;
180
 
+        }
181
 
+      }
182
 
+    case '#':
183
 
+      {
184
 
+        do
185
 
+        {
186
 
+          ++query_position; // skip current symbol (# or -)
187
 
+          if('\n' == query[query_position])  // check for '\n'
188
 
+          {
189
 
+            ++query_position; // skip '\n'
190
 
+            insert_space = true;
191
 
+            break;
192
 
+          }
193
 
+        }
194
 
+        while(query_position < query_length);
195
 
+        if(insert_space)
196
 
+        {
197
 
+          break;
198
 
+        }
199
 
+        else
200
 
+        {
201
 
+          continue;
202
 
+        }
203
 
+      }
204
 
+    default:
205
 
+      if(query_strip_comments_is_white_space(current))
206
 
+      {
207
 
+        insert_space = true;
208
 
+        ++query_position;
209
 
+      }
210
 
+      break; // make gcc happy
211
 
+    }
212
 
+    if(insert_space)
213
 
+    {
214
 
+      if((last_space + 1) != position)
215
 
+      {
216
 
+        last_space = position;
217
 
+        buffer[position++] = ' ';
218
 
+      }
219
 
+    }
220
 
+    else
221
 
+    {
222
 
+      buffer[position++] = query[query_position++];
223
 
+    }
224
 
+  }
225
 
+  while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1]))
226
 
+  {
227
 
+    --position;
228
 
+  }
229
 
+  buffer[position] = 0;
230
 
+  length = position;
231
 
+}
232
 
+void QueryStripComments::cleanup()
233
 
+{
234
 
+  if(buffer)
235
 
+  {
236
 
+    my_free(buffer);
237
 
+  }
238
 
+  buffer        = 0;
239
 
+  length        = 0;
240
 
+  buffer_length = 0;
241
 
+}
242
 
+QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc)
243
 
+{
244
 
+  if(opt_query_cache_strip_comments)
245
 
+  {
246
 
+    thd = a_thd;
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());
251
 
+  }
252
 
+  else
253
 
+  {
254
 
+    thd = 0;
255
 
+    query = 0;
256
 
+    length = 0;
257
 
+  }
258
 
+}
259
 
+QueryStripComments_Backup::~QueryStripComments_Backup()
260
 
+{
261
 
+  if(thd)
262
 
+  {
263
 
+    thd->set_query(query,length);
264
 
+  }
265
 
+}
 
137
+        else
 
138
+        {
 
139
+          return Another;
 
140
+        }
 
141
+      }
 
142
+      /* check for escaped symbols */
 
143
+      if (*to == '\\')
 
144
+      {
 
145
+        /* backslash, skip it */
 
146
+        to++;
 
147
+      }
 
148
+      /* check for end-of-line */
 
149
+      if (to == end)
 
150
+      {
 
151
+        /* not found - not closed quote */
 
152
+        return Error;
 
153
+      }
 
154
+      /* skip current symbol */
 
155
+      to++;
 
156
+    }
 
157
+  case '-':
 
158
+    /* Skip minus */
 
159
+    to++;
 
160
+    /* Check for second minus */
 
161
+    if (*to != '-')
 
162
+    {
 
163
+      /* Just minus */
 
164
+      return Another;
 
165
+    }
 
166
+    else
 
167
+    {
 
168
+      /*
 
169
+        Prefix is  minus-minus, next case-branch is processing
 
170
+        single line comments.
 
171
+      */
 
172
+    }
 
173
+  case '#':
 
174
+    /*
 
175
+      This is single-line comment, it started by "#" or "--".
 
176
+      Skip first symbol.
 
177
+    */
 
178
+    to++;
 
179
+    /* search new-line */
 
180
+    to= strchr(to, '\n');
 
181
+    if (NULL == to)
 
182
+    {
 
183
+      /* not found, end of the comment is the end of the query */
 
184
+      to= end;
 
185
+    }
 
186
+    else
 
187
+    {
 
188
+      /* skip end-of-line */
 
189
+      to++;
 
190
+    }
 
191
+    return Comment;
 
192
+  case '/':
 
193
+    /* skip slash */
 
194
+    to++;
 
195
+    /* check for star */
 
196
+    if (*to == '*')
 
197
+    {
 
198
+      /* skip star */
 
199
+      to++;
 
200
+      /* check for exclamation */
 
201
+      bool exclamation= (*to == '!');
 
202
+      /* search star-slash */
 
203
+      to= strstr(to, "*/");
 
204
+      if (NULL == to)
 
205
+      {
 
206
+        /* not found - not closed comment */
 
207
+        return Error;
 
208
+      }
 
209
+      else
 
210
+      {
 
211
+        /* found */
 
212
+        DBUG_ASSERT(to + 1 < end);
 
213
+        DBUG_ASSERT(0 == strncmp(to, "*/", 2));
 
214
+        /* skip star-slash */
 
215
+        to++;
 
216
+        to++;
 
217
+        return (exclamation ? Special : Comment);
 
218
+      }
 
219
+    }
 
220
+    else
 
221
+    {
 
222
+      /* just slash */
 
223
+      return Another;
 
224
+    }
 
225
+  case ' ':
 
226
+  case '\t':
 
227
+  case '\r':
 
228
+  case '\n':
 
229
+    {
 
230
+      /* skip space */
 
231
+      to++;
 
232
+      return WhiteSpace;
 
233
+    }
 
234
+  case '\\':
 
235
+    {
 
236
+      /* skip backslash */
 
237
+      to++;
 
238
+      if (to == end)
 
239
+      {
 
240
+        /*
 
241
+          query complete by backslash
 
242
+          probable error?
 
243
+        */
 
244
+        return Another;
 
245
+      }
 
246
+      else
 
247
+      {
 
248
+        /* skip after backslash symbol */
 
249
+        to++;
 
250
+        return Another;
 
251
+      }
 
252
+    }
 
253
+  case '(':
 
254
+  case ')':
 
255
+    {
 
256
+      /* skip parenthese */
 
257
+      to++;
 
258
+      return Special;
 
259
+    }
 
260
+  default:
 
261
+    {
 
262
+      /* skip symbol */
 
263
+      to++;
 
264
+      return Another;
 
265
+    }
 
266
+  };
 
267
+}
 
268
+
 
269
+
 
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)
 
274
+{
 
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;
 
284
+  while (true)
 
285
+  {
 
286
+    from= to;
 
287
+    switch (analyze(&to, end))
 
288
+    {
 
289
+    case Empty:
 
290
+      {
 
291
+        /*
 
292
+          parse completed
 
293
+          check for whitespace in the end
 
294
+        */
 
295
+        if (current == space)
 
296
+        {
 
297
+          /* drop whitespace in the end of query */
 
298
+          --current;
 
299
+        }
 
300
+        /* result is null-terminated string */
 
301
+        *current= 0;
 
302
+        /* set result length */
 
303
+        *result_length= current - result;
 
304
+        /* all right */
 
305
+        return true;
 
306
+      }
 
307
+    case Comment:
 
308
+      /* should just insert space instead of comment */
 
309
+    case WhiteSpace:
 
310
+      if (space == current || from == query)
 
311
+      {
 
312
+        /* previous symbol was space */
 
313
+      }
 
314
+      else
 
315
+      {
 
316
+        /* insert space to result buffer */
 
317
+        *current= ' ';
 
318
+        /* switch after inserted space */
 
319
+        current++;
 
320
+      }
 
321
+      /* remember last-after-space position */
 
322
+      space= current;
 
323
+      /* parse again */
 
324
+      continue;
 
325
+    case Special:
 
326
+    case Another:
 
327
+      {
 
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 */
 
335
+        from= to;
 
336
+        /* parse again */
 
337
+        continue;
 
338
+      }
 
339
+    case Error:
 
340
+    default:
 
341
+      {
 
342
+        /* bad source query */
 
343
+        return false;
 
344
+      }
 
345
+    }
 
346
+  }
 
347
+}
 
348
+
 
349
+
 
350
+static size_t skip_not_another(const char *const query, size_t query_length)
 
351
+{
 
352
+  const char *from= query;
 
353
+  const char *to=   query;
 
354
+  const char *const end= query + query_length;
 
355
+  while (true)
 
356
+  {
 
357
+    switch (analyze(&to, end))
 
358
+    {
 
359
+    case Error:
 
360
+      return 0;
 
361
+    case Empty:
 
362
+    case Another:
 
363
+      return (from - query);
 
364
+    default:
 
365
+      from= to;
 
366
+      continue;
 
367
+    };
 
368
+  }
 
369
+}
 
370
+
 
371
+
 
372
+static size_t skip_default(const char *const query, size_t /* query_length */)
 
373
+{
 
374
+  size_t query_position= 0;
 
375
+  /*
 
376
+    Skip '(' characters in queries like following:
 
377
+    (select a from t1) union (select a from t1);
 
378
+  */
 
379
+  while (query[query_position]=='(')
 
380
+    query_position++;
 
381
+  return query_position;
 
382
+}
 
383
+
 
384
+
 
385
+} /* namespace query_comments_parser */
 
386
+
 
387
+class Query_Switcher
 
388
+{
 
389
+private:
 
390
+  Query_Switcher(const Query_Switcher&);
 
391
+  Query_Switcher& operator=(const Query_Switcher&);
 
392
+
 
393
+
 
394
+public:
 
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())
 
400
+  {
 
401
+  }
 
402
+
 
403
+  Query_Switcher(char   **query,
 
404
+                 size_t  *length) :
 
405
+    target_query(query),
 
406
+    target_length(length),
 
407
+    backup_query(*query),
 
408
+    backup_length(*length)
 
409
+  {
 
410
+  }
 
411
+public:
 
412
+  void replace(Query_Without_Comments *query_without_comments)
 
413
+  {
 
414
+    *target_query=  query_without_comments->query();
 
415
+    *target_length= query_without_comments->length();
 
416
+  }
 
417
+  void restore()
 
418
+  {
 
419
+    *target_query=  backup_query;
 
420
+    *target_length= backup_length;
 
421
+  }
 
422
+private:
 
423
+  char*  *target_query;
 
424
+  size_t *target_length;
 
425
+public:
 
426
+  char *const  backup_query;
 
427
+  size_t const backup_length;
 
428
+};
 
429
+
 
430
+class Comments_Processor
 
431
+{
 
432
+private:
 
433
+  Comments_Processor(const Comments_Processor&);
 
434
+  Comments_Processor& operator=(const Comments_Processor&);
 
435
+
 
436
+
 
437
+public:
 
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),
 
443
+    restore               (false)
 
444
+  {
 
445
+  }
 
446
+
 
447
+
 
448
+  Comments_Processor(Query_Without_Comments *current_query_without_comments,
 
449
+                     char                  **query,
 
450
+                     size_t                 *length,
 
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),
 
456
+    restore               (false)
 
457
+  {
 
458
+  }
 
459
+
 
460
+
 
461
+  ~Comments_Processor()
 
462
+  {
 
463
+    restore_comments();
 
464
+  }
 
465
+
 
466
+
 
467
+  size_t prefix_length()
 
468
+  {
 
469
+    using query_comments_parser::skip_not_another;
 
470
+    using query_comments_parser::skip_default;
 
471
+    if (enabled)
 
472
+    {
 
473
+      return skip_not_another(query_switcher.backup_query,
 
474
+                              query_switcher.backup_length);
 
475
+    }
 
476
+    else
 
477
+    {
 
478
+      return skip_default(query_switcher.backup_query,
 
479
+                          query_switcher.backup_length);
 
480
+    }
 
481
+  }
 
482
+
 
483
+
 
484
+  bool remove_comments()
 
485
+  {
 
486
+    if (!enabled || restore)
 
487
+    {
 
488
+      return true;
 
489
+    }
 
490
+    /* Allocate memory for query rewrite */
 
491
+    if (!query_without_comments->allocate(query_switcher.backup_length,
 
492
+                                          db_length))
 
493
+    {
 
494
+      return false;
 
495
+    }
 
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(),
 
502
+                                              &result_length)))
 
503
+    {
 
504
+      return false;
 
505
+    }
 
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);
 
514
+    return restore;
 
515
+  }
 
516
+
 
517
+
 
518
+  void restore_comments()
 
519
+  {
 
520
+    if (enabled && restore)
 
521
+    {
 
522
+      /* Replace striped query by original */
 
523
+      query_switcher.restore();
 
524
+
 
525
+      /* Clean query_without_comments */
 
526
+      query_without_comments->set_length(0);
 
527
+
 
528
+      /* Mark as restored */
 
529
+      restore= false;
 
530
+    }
 
531
+  }
 
532
+private:
 
533
+  Query_Switcher query_switcher;
 
534
+private:
 
535
+  const size_t db_length;
 
536
+private:
 
537
+  Query_Without_Comments *query_without_comments;
 
538
+  bool                    enabled;
 
539
+  bool                    restore;
 
540
+};
266
541
+
267
542
 #ifdef EMBEDDED_LIBRARY
268
543
 #include "emb_qcache.h"
269
544
 #endif
270
 
@@ -454,7 +629,12 @@
 
545
@@ -454,7 +939,12 @@
271
546
   Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
272
547
   DBUG_ENTER("Query_cache::try_lock");
273
548
 
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);
280
555
   while (1)
281
556
   {
282
557
     if (m_cache_lock_status == Query_cache::UNLOCKED)
283
 
@@ -1274,6 +1454,8 @@
 
558
@@ -1274,6 +1764,8 @@
284
559
       unlock();
285
560
       DBUG_VOID_RETURN;
286
561
     }
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();
289
564
 
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 @@
 
568
 */
 
569
 
 
570
 int
 
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)
 
573
 {
 
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),
 
582
+                                        &sql,
 
583
+                                        &query_length,
 
584
+                                        thd->db_length);
300
585
 
301
586
   /*
302
 
@@ -1472,21 +1657,103 @@
 
587
     Testing 'query_cache_size' without a lock here is safe: the thing
 
588
@@ -1471,13 +1968,7 @@
 
589
   }
303
590
 
304
591
   {
305
 
     uint i= 0;
 
592
-    uint i= 0;
306
593
-    /*
307
594
-      Skip '(' characters in queries like following:
308
595
-      (select a from t1) union (select a from t1);
309
596
-    */
310
597
-    while (sql[i]=='(')
311
598
-      i++;
312
 
+    if(opt_query_cache_strip_comments)
313
 
+    {
314
 
+      /* Skip all comments and non-letter symbols */
315
 
+      uint& query_position = i;
316
 
+      char* query = sql;
317
 
+      while(query_position < query_length)
318
 
+      {
319
 
+        bool check = false;
320
 
+        char current = query[query_position];
321
 
+        switch(current)
322
 
+        {
323
 
+        case '/':
324
 
+          if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
325
 
+          {
326
 
+            query_position += 2; // skip "/*"
327
 
+            do
328
 
+            {
329
 
+              if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
330
 
+              {
331
 
+                query_position += 2; // skip "*/" (without space)
332
 
+                break;
333
 
+              }
334
 
+              else
335
 
+              {
336
 
+                ++query_position;
337
 
+              }
338
 
+            }
339
 
+            while(query_position < query_length);
340
 
+            continue; // analyze current symbol
341
 
+          }
342
 
+          break;
343
 
+        case '-':
344
 
+          if(query[query_position+1] == '-')
345
 
+          {
346
 
+            ++query_position; // skip "-"
347
 
+          }
348
 
+          else
349
 
+          {
350
 
+            break;
351
 
+          }
352
 
+        case '#':
353
 
+          do
354
 
+          {
355
 
+            ++query_position; // skip current symbol
356
 
+            if('\n' == query[query_position])  // check for '\n'
357
 
+            {
358
 
+              ++query_position; // skip '\n'
359
 
+              break;
360
 
+            }
361
 
+          }
362
 
+          while(query_position < query_length);
363
 
+          continue; // analyze current symbol
364
 
+        case '\r':
365
 
+        case '\n':
366
 
+        case '\t':
367
 
+        case ' ':
368
 
+        case '(':
369
 
+        case ')':
370
 
+          break;
371
 
+        default:
372
 
+          check = true;
373
 
+          break; // make gcc happy
374
 
+        } // switch(current)
375
 
+        if(check)
376
 
+        {
377
 
+          if(query_position + 2 < query_length)
378
 
+          {
379
 
+            // cacheable
380
 
+            break;
381
 
+          }
382
 
+          else
383
 
+          {
384
 
+            DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
385
 
+            goto err;
386
 
+          }
387
 
+        } // if(check)
388
 
+        ++query_position;
389
 
+      } // while(query_position < query_length)
390
 
+    }
391
 
+    else // if(opt_query_cache_strip_comments)
392
 
+    {
393
 
+      /*
394
 
+        Skip '(' characters in queries like following:
395
 
+        (select a from t1) union (select a from t1);
396
 
+      */
397
 
+      while (sql[i]=='(')
398
 
+        i++;
399
 
 
400
 
-    /*
401
 
-      Test if the query is a SELECT
402
 
-      (pre-space is removed in dispatch_command).
403
 
+    } // if(opt_query_cache_strip_comments)    
404
 
+      /*
405
 
+        Test if the query is a SELECT
406
 
+        (pre-space is removed in dispatch_command).
407
 
 
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.
411
 
-    */
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.
415
 
+      */
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();
 
600
 
 
601
     /*
 
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.
 
606
     */
 
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') &&
 
610
-        sql[i] != '/')
 
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') ||
 
615
+           sql[i] == '/')))
 
616
     {
 
617
       DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
 
618
       goto err;
 
619
@@ -1543,6 +2035,7 @@
420
620
     goto err_unlock;
421
621
 
422
622
   Query_cache_block *query_block;
423
 
+  if(opt_query_cache_strip_comments)
424
 
+  {
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();
428
 
+  }
 
623
+  comments_processor.remove_comments();
429
624
 
430
 
   tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
431
 
   if (thd->db_length)
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,
435
630
                                                       tot_length);
436
 
+  sql          = sql_backup;
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
443
 
@@ -40,6 +40,9 @@
444
 
 #include "thr_lock.h"             /* thr_lock_type, THR_LOCK_DATA,
445
 
                                      THR_LOCK_INFO */
446
 
 
447
 
+#ifdef HAVE_QUERY_CACHE
448
 
+#include "query_strip_comments.h"
449
 
+#endif // HAVE_QUERY_CACHE
450
 
 
451
 
 class Reprepare_observer;
452
 
 class Relay_log_info;
453
 
@@ -764,6 +767,9 @@
454
 
     statement lifetime. FIXME: must be const
455
 
   */
456
 
    ulong id;
457
 
+#ifdef HAVE_QUERY_CACHE
458
 
+  QueryStripComments query_strip_comments; // see sql_cache.cc
459
 
+#endif //HAVE_QUERY_CACHE
460
 
 
461
 
   /*
462
 
     MARK_COLUMNS_NONE:  Means mark_used_colums is not set and no indicator to
 
637
@@ -1487,6 +1487,74 @@
 
638
 
 
639
 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
 
640
 
 
641
+
 
642
+#ifdef HAVE_QUERY_CACHE
 
643
+
 
644
+
 
645
+/*
 
646
+  @class Query_Without_Comments
 
647
+  This class provides way for safety (re)allocation
 
648
+  a memory for a query without comments.
 
649
+*/
 
650
+class Query_Without_Comments
 
651
+{
 
652
+private:
 
653
+  /*
 
654
+    Denied copy and assigment for object of this class.
 
655
+  */
 
656
+  Query_Without_Comments(const Query_Without_Comments&);
 
657
+  Query_Without_Comments& operator=(const Query_Without_Comments&);
 
658
+
 
659
+
 
660
+public:
 
661
+  /*
 
662
+    Constructor is filling fields by zero (no allocation).
 
663
+  */
 
664
+  Query_Without_Comments();
 
665
+
 
666
+
 
667
+  /*
 
668
+    Destructor clean allocated memory
 
669
+  */
 
670
+  ~Query_Without_Comments();
 
671
+public:
 
672
+
 
673
+
 
674
+/*
 
675
+    (Re)allocate memory for query. Query length after that is 0.
 
676
+  */
 
677
+  bool allocate(size_t query_length, size_t db_length);
 
678
+
 
679
+
 
680
+  /*
 
681
+    Set result query length, when query
 
682
+    without comments is copied to buffer.
 
683
+  */
 
684
+  void set_length(size_t query_length);
 
685
+
 
686
+
 
687
+public:
 
688
+  /*
 
689
+    Result query.
 
690
+  */
 
691
+  char*  query();
 
692
+
 
693
+
 
694
+  /*
 
695
+    Result query length
 
696
+  */
 
697
+  size_t length();
 
698
+
 
699
+
 
700
+private:
 
701
+  char* buffer;
 
702
+  size_t q_length;
 
703
+  size_t b_length;
 
704
+};
 
705
+
 
706
+
 
707
+#endif /* HAVE_QUERY_CACHE */
 
708
+
 
709
 /**
 
710
   @class THD
 
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;
 
714
 #endif
 
715
 #ifdef HAVE_QUERY_CACHE
 
716
+  Query_Without_Comments query_without_comments;
 
717
   Query_cache_tls query_cache_tls;
 
718
 #endif
 
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 @@
476
733
        "Don't cache results that are bigger than this",
477
734
--- /dev/null
478
735
+++ b/mysql-test/include/percona_query_cache_with_comments.inc
479
 
@@ -0,0 +1,95 @@
 
736
@@ -0,0 +1,117 @@
480
737
+--source include/percona_query_cache_with_comments_clear.inc
481
738
+let $query=/* with comment first */select * from t1;
482
739
+eval $query;
570
827
+;
571
828
+--source include/percona_query_cache_with_comments_eval.inc
572
829
+
 
830
+let $query=select */* a comment \*/from t1;
 
831
+--source include/percona_query_cache_with_comments_eval.inc
 
832
+
 
833
+let $query=select *# a comment \\
 
834
+from t1;
 
835
+--source include/percona_query_cache_with_comments_eval.inc
 
836
+
 
837
+let $query=select *-- a comment \\
 
838
+from t1;
 
839
+--source include/percona_query_cache_with_comments_eval.inc
 
840
+
 
841
+let $query=select "\\\\"" /* not a comment */" from t1;
 
842
+--source include/percona_query_cache_with_comments_eval.inc
 
843
+
 
844
+let $query=select "\\\\"" /*! not a comment */" from t1;
 
845
+--source include/percona_query_cache_with_comments_eval.inc
 
846
+
 
847
+# following two queries related to bug #856404.
 
848
+# There are different queries, but opt_query_cache_strip_comments thinks that they are equal.
573
849
+let $query=select ' \'  ' from t1;
574
850
+--source include/percona_query_cache_with_comments_eval.inc
 
851
+
 
852
+let $query=select ' \' /* comment inside quotes with internal backslash quote */' from t1;
 
853
+--source include/percona_query_cache_with_comments_eval.inc
575
854
--- /dev/null
576
855
+++ b/mysql-test/include/percona_query_cache_with_comments_begin.inc
577
856
@@ -0,0 +1,12 @@
624
903
+
625
904
--- /dev/null
626
905
+++ b/mysql-test/r/percona_query_cache_with_comments.result
627
 
@@ -0,0 +1,866 @@
 
906
@@ -0,0 +1,1058 @@
628
907
+set global query_cache_strip_comments=ON;
629
908
+set GLOBAL query_cache_size=1355776;
630
909
+drop table if exists t1;
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
 
1747
+Qcache_inserts 1
 
1748
+show status like "Qcache_hits";
 
1749
+Variable_name  Value
 
1750
+Qcache_hits    50
 
1751
+select */* a comment \*/from t1;
 
1752
+a
 
1753
+1
 
1754
+2
 
1755
+3
 
1756
+select */* a comment \*/from t1;
 
1757
+a
 
1758
+1
 
1759
+2
 
1760
+3
 
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
 
1766
+Qcache_inserts 1
 
1767
+show status like "Qcache_hits";
 
1768
+Variable_name  Value
 
1769
+Qcache_hits    52
 
1770
+-----------------------------------------------------
 
1771
+select *# a comment \
 
1772
+from t1
 
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
 
1779
+Qcache_inserts 1
 
1780
+show status like "Qcache_hits";
 
1781
+Variable_name  Value
 
1782
+Qcache_hits    52
 
1783
+select *# a comment \
 
1784
+from t1;
 
1785
+a
 
1786
+1
 
1787
+2
 
1788
+3
 
1789
+select *# a comment \
 
1790
+from t1;
 
1791
+a
 
1792
+1
 
1793
+2
 
1794
+3
 
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
 
1800
+Qcache_inserts 1
 
1801
+show status like "Qcache_hits";
 
1802
+Variable_name  Value
 
1803
+Qcache_hits    54
 
1804
+-----------------------------------------------------
 
1805
+select *-- a comment \
 
1806
+from t1
 
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
 
1813
+Qcache_inserts 1
 
1814
+show status like "Qcache_hits";
 
1815
+Variable_name  Value
 
1816
+Qcache_hits    54
 
1817
+select *-- a comment \
 
1818
+from t1;
 
1819
+a
 
1820
+1
 
1821
+2
 
1822
+3
 
1823
+select *-- a comment \
 
1824
+from t1;
 
1825
+a
 
1826
+1
 
1827
+2
 
1828
+3
 
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
 
1834
+Qcache_inserts 1
 
1835
+show status like "Qcache_hits";
 
1836
+Variable_name  Value
 
1837
+Qcache_hits    56
 
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
 
1846
+Qcache_inserts 1
 
1847
+show status like "Qcache_hits";
 
1848
+Variable_name  Value
 
1849
+Qcache_hits    56
 
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
 
1865
+Qcache_inserts 2
 
1866
+show status like "Qcache_hits";
 
1867
+Variable_name  Value
 
1868
+Qcache_hits    57
 
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
 
1877
+Qcache_inserts 2
 
1878
+show status like "Qcache_hits";
 
1879
+Variable_name  Value
 
1880
+Qcache_hits    57
 
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
 
1896
+Qcache_inserts 3
 
1897
+show status like "Qcache_hits";
 
1898
+Variable_name  Value
 
1899
+Qcache_hits    58
 
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
1468
 
+Qcache_inserts 1
1469
 
+show status like "Qcache_hits";
1470
 
+Variable_name  Value
1471
 
+Qcache_hits    50
1472
 
+select ' \'  ' from t1;
1473
 
+'  
1474
 
+ '  
1475
 
+ '  
1476
 
+ '  
1477
 
+select ' \'  ' from t1;
1478
 
+'  
1479
 
+ '  
1480
 
+ '  
1481
 
+ '  
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
1487
 
+Qcache_inserts 2
1488
 
+show status like "Qcache_hits";
1489
 
+Variable_name  Value
1490
 
+Qcache_hits    51
 
1905
+Qcache_queries_in_cache        3
 
1906
+show status like "Qcache_inserts";
 
1907
+Variable_name  Value
 
1908
+Qcache_inserts 3
 
1909
+show status like "Qcache_hits";
 
1910
+Variable_name  Value
 
1911
+Qcache_hits    58
 
1912
+select ' \'  ' from t1;
 
1913
+'  
 
1914
+ '  
 
1915
+ '  
 
1916
+ '  
 
1917
+select ' \'  ' from t1;
 
1918
+'  
 
1919
+ '  
 
1920
+ '  
 
1921
+ '  
 
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
 
1927
+Qcache_inserts 4
 
1928
+show status like "Qcache_hits";
 
1929
+Variable_name  Value
 
1930
+Qcache_hits    59
 
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
 
1939
+Qcache_inserts 4
 
1940
+show status like "Qcache_hits";
 
1941
+Variable_name  Value
 
1942
+Qcache_hits    59
 
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
 
1958
+Qcache_inserts 5
 
1959
+show status like "Qcache_hits";
 
1960
+Variable_name  Value
 
1961
+Qcache_hits    60
1491
1962
+DROP TABLE t1;
1492
1963
+SET GLOBAL query_cache_size=default;
1493
1964
+set global query_cache_strip_comments=OFF;
1517
1988
+SET GLOBAL query_cache_size= default;
1518
1989
--- /dev/null
1519
1990
+++ b/mysql-test/r/percona_query_cache_with_comments_disable.result
1520
 
@@ -0,0 +1,865 @@
 
1991
@@ -0,0 +1,1057 @@
1521
1992
+set GLOBAL query_cache_size=1355776;
1522
1993
+drop table if exists t1;
1523
1994
+create table t1 (a int not null);
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
 
2831
+Qcache_inserts 20
 
2832
+show status like "Qcache_hits";
 
2833
+Variable_name  Value
 
2834
+Qcache_hits    25
 
2835
+select */* a comment \*/from t1;
 
2836
+a
 
2837
+1
 
2838
+2
 
2839
+3
 
2840
+select */* a comment \*/from t1;
 
2841
+a
 
2842
+1
 
2843
+2
 
2844
+3
 
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
 
2850
+Qcache_inserts 21
 
2851
+show status like "Qcache_hits";
 
2852
+Variable_name  Value
 
2853
+Qcache_hits    26
 
2854
+-----------------------------------------------------
 
2855
+select *# a comment \
 
2856
+from t1
 
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
 
2863
+Qcache_inserts 21
 
2864
+show status like "Qcache_hits";
 
2865
+Variable_name  Value
 
2866
+Qcache_hits    26
 
2867
+select *# a comment \
 
2868
+from t1;
 
2869
+a
 
2870
+1
 
2871
+2
 
2872
+3
 
2873
+select *# a comment \
 
2874
+from t1;
 
2875
+a
 
2876
+1
 
2877
+2
 
2878
+3
 
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
 
2884
+Qcache_inserts 22
 
2885
+show status like "Qcache_hits";
 
2886
+Variable_name  Value
 
2887
+Qcache_hits    27
 
2888
+-----------------------------------------------------
 
2889
+select *-- a comment \
 
2890
+from t1
 
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
 
2897
+Qcache_inserts 22
 
2898
+show status like "Qcache_hits";
 
2899
+Variable_name  Value
 
2900
+Qcache_hits    27
 
2901
+select *-- a comment \
 
2902
+from t1;
 
2903
+a
 
2904
+1
 
2905
+2
 
2906
+3
 
2907
+select *-- a comment \
 
2908
+from t1;
 
2909
+a
 
2910
+1
 
2911
+2
 
2912
+3
 
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
 
2918
+Qcache_inserts 23
 
2919
+show status like "Qcache_hits";
 
2920
+Variable_name  Value
 
2921
+Qcache_hits    28
 
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
 
2930
+Qcache_inserts 23
 
2931
+show status like "Qcache_hits";
 
2932
+Variable_name  Value
 
2933
+Qcache_hits    28
 
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
 
2949
+Qcache_inserts 24
 
2950
+show status like "Qcache_hits";
 
2951
+Variable_name  Value
 
2952
+Qcache_hits    29
 
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
 
2961
+Qcache_inserts 24
 
2962
+show status like "Qcache_hits";
 
2963
+Variable_name  Value
 
2964
+Qcache_hits    29
 
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
 
2980
+Qcache_inserts 25
 
2981
+show status like "Qcache_hits";
 
2982
+Variable_name  Value
 
2983
+Qcache_hits    30
 
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
2360
 
+Qcache_inserts 20
2361
 
+show status like "Qcache_hits";
2362
 
+Variable_name  Value
2363
 
+Qcache_hits    25
2364
 
+select ' \'  ' from t1;
2365
 
+'  
2366
 
+ '  
2367
 
+ '  
2368
 
+ '  
2369
 
+select ' \'  ' from t1;
2370
 
+'  
2371
 
+ '  
2372
 
+ '  
2373
 
+ '  
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
2379
 
+Qcache_inserts 21
2380
 
+show status like "Qcache_hits";
2381
 
+Variable_name  Value
2382
 
+Qcache_hits    26
 
2989
+Qcache_queries_in_cache        25
 
2990
+show status like "Qcache_inserts";
 
2991
+Variable_name  Value
 
2992
+Qcache_inserts 25
 
2993
+show status like "Qcache_hits";
 
2994
+Variable_name  Value
 
2995
+Qcache_hits    30
 
2996
+select ' \'  ' from t1;
 
2997
+'  
 
2998
+ '  
 
2999
+ '  
 
3000
+ '  
 
3001
+select ' \'  ' from t1;
 
3002
+'  
 
3003
+ '  
 
3004
+ '  
 
3005
+ '  
 
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
 
3011
+Qcache_inserts 26
 
3012
+show status like "Qcache_hits";
 
3013
+Variable_name  Value
 
3014
+Qcache_hits    31
 
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
 
3023
+Qcache_inserts 26
 
3024
+show status like "Qcache_hits";
 
3025
+Variable_name  Value
 
3026
+Qcache_hits    31
 
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
 
3042
+Qcache_inserts 27
 
3043
+show status like "Qcache_hits";
 
3044
+Variable_name  Value
 
3045
+Qcache_hits    32
2383
3046
+DROP TABLE t1;
2384
3047
+SET GLOBAL query_cache_size=default;
2385
3048
+set global query_cache_strip_comments=OFF;
3114
3777
+action
3115
3778
+try_lock_mutex_query
3116
3779
+SET GLOBAL query_cache_size=0;
 
3780
--- /dev/null
 
3781
+++ b/mysql-test/r/percona_query_cache_with_comments_crash_2.result
 
3782
@@ -0,0 +1,8 @@
 
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*/;
 
3788
+pk
 
3789
+DROP TABLE table17_int;
 
3790
+DROP TABLE table30_int;
 
3791
--- /dev/null
 
3792
+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2-master.opt
 
3793
@@ -0,0 +1 @@
 
3794
+--query-cache-size=10M --query-cache-strip-comments
 
3795
--- /dev/null
 
3796
+++ b/mysql-test/t/percona_query_cache_with_comments_crash_2.test
 
3797
@@ -0,0 +1,9 @@
 
3798
+--disable_warnings
 
3799
+DROP TABLE IF EXISTS table17_int;
 
3800
+DROP TABLE IF EXISTS table30_int;
 
3801
+--enable_warnings
 
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);
 
3811
 }
 
3812
 
 
3813
+#ifdef HAVE_QUERY_CACHE
 
3814
+
 
3815
+
 
3816
+Query_Without_Comments::Query_Without_Comments() :
 
3817
+  buffer(0),
 
3818
+  q_length(0),
 
3819
+  b_length(0)
 
3820
+{
 
3821
+}
 
3822
+
 
3823
+
 
3824
+Query_Without_Comments::~Query_Without_Comments()
 
3825
+{
 
3826
+  if(buffer)
 
3827
+  {
 
3828
+    my_free(buffer);
 
3829
+  }
 
3830
+}
 
3831
+
 
3832
+
 
3833
+bool Query_Without_Comments::allocate(size_t query_length, size_t db_length)
 
3834
+{
 
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",
 
3840
+                      buffer,
 
3841
+                      buffer,
 
3842
+                      (uint) b_length,
 
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)
 
3850
+  {
 
3851
+    b_length= new_b_length;
 
3852
+    if (buffer)
 
3853
+    {
 
3854
+      buffer= (char*) my_realloc(buffer, b_length, MYF(0));
 
3855
+    }
 
3856
+    else
 
3857
+    {
 
3858
+      buffer= (char *) my_malloc(b_length, MYF(0));
 
3859
+    }
 
3860
+  }
 
3861
+  buffer[0]= 0;
 
3862
+  DBUG_PRINT("info", ("buffer: %p "
 
3863
+                      "buffer length: %u "
 
3864
+                      "query maximum length: %u",
 
3865
+                      buffer,
 
3866
+                      (uint) b_length,
 
3867
+                      (uint) q_length));
 
3868
+  DBUG_RETURN(buffer);
 
3869
+}
 
3870
+
 
3871
+
 
3872
+void Query_Without_Comments::set_length(size_t query_length)
 
3873
+{
 
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",
 
3882
+                      buffer,
 
3883
+                      buffer,
 
3884
+                      (uint) b_length,
 
3885
+                      (uint) q_length,
 
3886
+                      (uint) query_length));
 
3887
+  q_length= query_length;
 
3888
+  DBUG_VOID_RETURN;
 
3889
+}
 
3890
+
 
3891
+
 
3892
+char* Query_Without_Comments::query()
 
3893
+{
 
3894
+  return buffer;
 
3895
+}
 
3896
+
 
3897
+
 
3898
+size_t Query_Without_Comments::length()
 
3899
+{
 
3900
+  return q_length;
 
3901
+}
 
3902
+
 
3903
+
 
3904
+#endif // HAVE_QUERY_CACHE
 
3905
+
 
3906
 
 
3907
 THD::THD()
 
3908
    :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,