]> git.pld-linux.org Git - packages/mysql.git/blob - query_cache_enhance.patch
- up to 5.5.15
[packages/mysql.git] / query_cache_enhance.patch
1 # name       : query_cache_with_comments.patch
2 # introduced : 11 or before
3 # maintainer : Oleg
4 #
5 #!!! notice !!!
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 --- /dev/null
9 +++ b/patch_info/query_cache_enhance.patch
10 @@ -0,0 +1,15 @@
11 +File=query_cache_enhance.patch
12 +Name= query cache Percona's cumulative patch
13 +Version=1.0
14 +Author=Percona <info@percona.com>
15 +License=GPL
16 +Comment= 1) Add new status - Waiting on query cache mutex (status_wait_query_cache_mutex.patch)
17 +         2) Remove comments from query (need for cache hit) (query_cache_with_comments.patch)
18 +         3) Totally disable query cache (query_cache_totally_disable.info)
19 +2010-05 - First version avaliable (query_cache_with_comments.patch)
20 +2010-07 - First version avaliable (status_wait_query_cache_mutex.patch
21 +2010-07 - First version avaliable (query_cache_totally_disable.info)
22 +2010-07 - Fix crash (query_cache_with_comments.patch)
23 +2010-07 - Fix incorrect behavior diff (query_cache_with_comments.patch)
24 +2010-09 - Merge patches to one
25 +2010-11 - Ported to 5.5
26 --- a/sql/mysqld.cc
27 +++ b/sql/mysqld.cc
28 @@ -904,6 +904,7 @@
29  #endif
30  #ifdef HAVE_QUERY_CACHE
31  ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
32 +my_bool opt_query_cache_strip_comments= FALSE;
33  Query_cache query_cache;
34  #endif
35  #ifdef HAVE_SMEM
36 --- a/sql/mysqld.h
37 +++ b/sql/mysqld.h
38 @@ -91,6 +91,7 @@
39  extern my_bool opt_log, opt_slow_log;
40  extern my_bool opt_backup_history_log;
41  extern my_bool opt_backup_progress_log;
42 +extern my_bool opt_query_cache_strip_comments;
43  extern ulonglong log_output_options;
44  extern ulong log_backup_output_options;
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 --- a/sql/sql_cache.cc
87 +++ b/sql/sql_cache.cc
88 @@ -344,6 +344,181 @@
89  #include "probes_mysql.h"
90  #include "transaction.h"
91  
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)
130 +    {
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 +          {
166 +            continue;
167 +          }
168 +        }
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 +}
266 +
267  #ifdef EMBEDDED_LIBRARY
268  #include "emb_qcache.h"
269  #endif
270 @@ -454,7 +629,14 @@
271    Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
272    DBUG_ENTER("Query_cache::try_lock");
273  
274 +  const char* old_proc_info= thd->proc_info;
275 +  thd_proc_info(thd,"Waiting on query cache mutex");
276    mysql_mutex_lock(&structure_guard_mutex);
277 +  DEBUG_SYNC(thd, "status_waiting_on_query_cache_mutex");
278 +  DBUG_EXECUTE_IF("status_waiting_on_query_cache_mutex_sleep", {
279 +      sleep(1);
280 +    });
281 +  thd->proc_info = old_proc_info;
282    while (1)
283    {
284      if (m_cache_lock_status == Query_cache::UNLOCKED)
285 @@ -1274,6 +1456,8 @@
286        unlock();
287        DBUG_VOID_RETURN;
288      }
289 +    QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
290 +    QueryStripComments_Backup backup(thd,query_strip_comments);
291  
292      /* Key is query + database + flag */
293      if (thd->db_length)
294 @@ -1451,6 +1635,9 @@
295    Query_cache_block_table *block_table, *block_table_end;
296    ulong tot_length;
297    Query_cache_query_flags flags;
298 +  QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
299 +  char *sql_backup          = sql;
300 +  uint  query_length_backup = query_length;
301    DBUG_ENTER("Query_cache::send_result_to_client");
302  
303    /*
304 @@ -1472,21 +1659,103 @@
305  
306    {
307      uint i= 0;
308 -    /*
309 -      Skip '(' characters in queries like following:
310 -      (select a from t1) union (select a from t1);
311 -    */
312 -    while (sql[i]=='(')
313 -      i++;
314 +    if(opt_query_cache_strip_comments)
315 +    {
316 +      /* Skip all comments and non-letter symbols */
317 +      uint& query_position = i;
318 +      char* query = sql;
319 +      while(query_position < query_length)
320 +      {
321 +        bool check = false;
322 +        char current = query[query_position];
323 +        switch(current)
324 +        {
325 +        case '/':
326 +          if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
327 +          {
328 +            query_position += 2; // skip "/*"
329 +            do
330 +            {
331 +              if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
332 +              {
333 +                query_position += 2; // skip "*/" (without space)
334 +                break;
335 +              }
336 +              else
337 +              {
338 +                ++query_position;
339 +              }
340 +            }
341 +            while(query_position < query_length);
342 +            continue; // analyze current symbol
343 +          }
344 +          break;
345 +        case '-':
346 +          if(query[query_position+1] == '-')
347 +          {
348 +            ++query_position; // skip "-"
349 +          }
350 +          else
351 +          {
352 +            break;
353 +          }
354 +        case '#':
355 +          do
356 +          {
357 +            ++query_position; // skip current symbol
358 +            if('\n' == query[query_position])  // check for '\n'
359 +            {
360 +              ++query_position; // skip '\n'
361 +              break;
362 +            }
363 +          }
364 +          while(query_position < query_length);
365 +          continue; // analyze current symbol
366 +        case '\r':
367 +        case '\n':
368 +        case '\t':
369 +        case ' ':
370 +        case '(':
371 +        case ')':
372 +          break;
373 +        default:
374 +          check = true;
375 +          break; // make gcc happy
376 +        } // switch(current)
377 +        if(check)
378 +        {
379 +          if(query_position + 2 < query_length)
380 +          {
381 +            // cacheable
382 +            break;
383 +          }
384 +          else
385 +          {
386 +            DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
387 +            goto err;
388 +          }
389 +        } // if(check)
390 +        ++query_position;
391 +      } // while(query_position < query_length)
392 +    }
393 +    else // if(opt_query_cache_strip_comments)
394 +    {
395 +      /*
396 +        Skip '(' characters in queries like following:
397 +        (select a from t1) union (select a from t1);
398 +      */
399 +      while (sql[i]=='(')
400 +        i++;
401  
402 -    /*
403 -      Test if the query is a SELECT
404 -      (pre-space is removed in dispatch_command).
405 +    } // if(opt_query_cache_strip_comments)    
406 +      /*
407 +        Test if the query is a SELECT
408 +        (pre-space is removed in dispatch_command).
409  
410 -      First '/' looks like comment before command it is not
411 -      frequently appeared in real life, consequently we can
412 -      check all such queries, too.
413 -    */
414 +        First '/' looks like comment before command it is not
415 +        frequently appeared in real life, consequently we can
416 +        check all such queries, too.
417 +      */
418      if ((my_toupper(system_charset_info, sql[i])     != 'S' ||
419           my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
420           my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
421 @@ -1521,6 +1790,12 @@
422      goto err_unlock;
423  
424    Query_cache_block *query_block;
425 +  if(opt_query_cache_strip_comments)
426 +  {
427 +    query_strip_comments->set(sql, query_length, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
428 +    sql          = query_strip_comments->query();
429 +    query_length = query_strip_comments->query_length();
430 +  }
431  
432    tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
433    if (thd->db_length)
434 @@ -1587,6 +1862,8 @@
435          (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
436    query_block = (Query_cache_block *)  my_hash_search(&queries, (uchar*) sql,
437                                                        tot_length);
438 +  sql          = sql_backup;
439 +  query_length = query_length_backup;
440    /* Quick abort on unlocked data */
441    if (query_block == 0 ||
442        query_block->query()->result() == 0 ||
443 --- a/sql/sql_class.h
444 +++ b/sql/sql_class.h
445 @@ -40,6 +40,9 @@
446  #include "thr_lock.h"             /* thr_lock_type, THR_LOCK_DATA,
447                                       THR_LOCK_INFO */
448  
449 +#ifdef HAVE_QUERY_CACHE
450 +#include "query_strip_comments.h"
451 +#endif // HAVE_QUERY_CACHE
452  
453  class Reprepare_observer;
454  class Relay_log_info;
455 @@ -760,6 +763,9 @@
456      statement lifetime. FIXME: must be const
457    */
458     ulong id;
459 +#ifdef HAVE_QUERY_CACHE
460 +  QueryStripComments query_strip_comments; // see sql_cache.cc
461 +#endif //HAVE_QUERY_CACHE
462  
463    /*
464      MARK_COLUMNS_NONE:  Means mark_used_colums is not set and no indicator to
465 --- a/sql/sys_vars.cc
466 +++ b/sql/sys_vars.cc
467 @@ -1786,6 +1786,11 @@
468         NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
469         ON_UPDATE(fix_query_cache_size));
470  
471 +static Sys_var_mybool Sys_query_cache_strip_comments(
472 +       "query_cache_strip_comments", "Enable and disable optimisation \"strip comment for query cache\" - optimisation strip all comments from query while search query result in query cache",
473 +       GLOBAL_VAR(opt_query_cache_strip_comments), CMD_LINE(OPT_ARG),
474 +       DEFAULT(FALSE));
475 +
476  static Sys_var_ulong Sys_query_cache_limit(
477         "query_cache_limit",
478         "Don't cache results that are bigger than this",
This page took 1.476857 seconds and 3 git commands to generate.