]> git.pld-linux.org Git - packages/mysql.git/blame - query_cache_enhance.patch
- disable response-time-distribution patch on arch which has no atomic builtins even...
[packages/mysql.git] / query_cache_enhance.patch
CommitLineData
b4e1fa2c
AM
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!
11822e22
AM
8diff -ruN /dev/null b/patch_info/query_cache_enhance.patch
9--- /dev/null 1970-01-01 00:00:00.000000000 +0000
10+++ b/patch_info/query_cache_enhance.patch 2011-04-09 18:48:53.000000000 +0400
b4e1fa2c
AM
11@@ -0,0 +1,15 @@
12+File=query_cache_enhance.patch
13+Name= query cache Percona's cumulative patch
14+Version=1.0
15+Author=Percona <info@percona.com>
16+License=GPL
17+Comment= 1) Add new status - Waiting on query cache mutex (status_wait_query_cache_mutex.patch)
18+ 2) Remove comments from query (need for cache hit) (query_cache_with_comments.patch)
19+ 3) Totally disable query cache (query_cache_totally_disable.info)
20+2010-05 - First version avaliable (query_cache_with_comments.patch)
21+2010-07 - First version avaliable (status_wait_query_cache_mutex.patch
22+2010-07 - First version avaliable (query_cache_totally_disable.info)
23+2010-07 - Fix crash (query_cache_with_comments.patch)
24+2010-07 - Fix incorrect behavior diff (query_cache_with_comments.patch)
25+2010-09 - Merge patches to one
26+2010-11 - Ported to 5.5
27diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
11822e22
AM
28--- a/sql/mysqld.cc 2011-04-09 18:48:50.000000000 +0400
29+++ b/sql/mysqld.cc 2011-04-09 18:48:53.000000000 +0400
30@@ -903,6 +903,7 @@
b4e1fa2c
AM
31 #endif
32 #ifdef HAVE_QUERY_CACHE
33 ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
34+my_bool opt_query_cache_strip_comments= FALSE;
35 Query_cache query_cache;
36 #endif
37 #ifdef HAVE_SMEM
38diff -ruN a/sql/mysqld.h b/sql/mysqld.h
11822e22
AM
39--- a/sql/mysqld.h 2011-04-09 18:48:50.000000000 +0400
40+++ b/sql/mysqld.h 2011-04-09 18:48:53.000000000 +0400
b4e1fa2c
AM
41@@ -91,6 +91,7 @@
42 extern my_bool opt_log, opt_slow_log;
43 extern my_bool opt_backup_history_log;
44 extern my_bool opt_backup_progress_log;
45+extern my_bool opt_query_cache_strip_comments;
46 extern ulonglong log_output_options;
47 extern ulong log_backup_output_options;
48 extern my_bool opt_log_queries_not_using_indexes;
11822e22
AM
49diff -ruN /dev/null b/sql/query_strip_comments.h
50--- /dev/null 1970-01-01 00:00:00.000000000 +0000
51+++ b/sql/query_strip_comments.h 2011-04-09 18:48:53.000000000 +0400
b4e1fa2c
AM
52@@ -0,0 +1,37 @@
53+#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_
54+#define _SQL_QUERY_STRIPC_COMMENTS_H_
55+#ifdef HAVE_QUERY_CACHE
56+
57+// implemented in sql_cache.cc
58+class QueryStripComments
59+{
60+private:
61+ QueryStripComments(const QueryStripComments&);
62+ QueryStripComments& operator=(const QueryStripComments&);
63+public:
64+ QueryStripComments();
65+ ~QueryStripComments();
66+ void set(const char* a_query, uint a_query_length, uint a_additional_length);
67+
68+ char* query() { return buffer; }
69+ uint query_length() { return length; }
70+private:
71+ void cleanup();
72+private:
73+ char* buffer;
74+ uint length /*query length, not buffer length*/;
75+ uint buffer_length;
76+};
77+class QueryStripComments_Backup
78+{
79+public:
80+ QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc);
81+ ~QueryStripComments_Backup();
82+private:
83+ THD* thd;
84+ char* query;
85+ uint length;
86+};
87+
88+#endif // HAVE_QUERY_CACHE
89+#endif // _SQL_QUERY_STRIPC_COMMENTS_H_
90diff -ruN a/sql/sql_cache.cc b/sql/sql_cache.cc
11822e22
AM
91--- a/sql/sql_cache.cc 2011-04-09 18:48:50.000000000 +0400
92+++ b/sql/sql_cache.cc 2011-04-09 18:48:53.000000000 +0400
b4e1fa2c
AM
93@@ -344,6 +344,181 @@
94 #include "probes_mysql.h"
95 #include "transaction.h"
96
97+#include "query_strip_comments.h"
98+
99+QueryStripComments::QueryStripComments()
100+{
101+ buffer = 0;
102+ length = 0;
103+ buffer_length = 0;
104+}
105+QueryStripComments::~QueryStripComments()
106+{
107+ cleanup();
108+}
109+
110+inline bool query_strip_comments_is_white_space(char c)
111+{
112+ return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c ));
113+}
114+void QueryStripComments::set(const char* query, uint query_length, uint additional_length)
115+{
116+ uint new_buffer_length = query_length + additional_length;
117+ if(new_buffer_length > buffer_length)
118+ {
119+ cleanup();
120+ buffer = (char*)my_malloc(new_buffer_length,MYF(0));
121+ }
122+ uint query_position = 0;
123+ uint position = 0;
124+ // Skip whitespaces from begin
125+ while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position]))
126+ {
127+ ++query_position;
128+ }
129+ long int last_space = -1;
130+ while(query_position < query_length)
131+ {
132+ char current = query[query_position];
133+ bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position
134+ switch(current)
135+ {
136+ case '\'':
137+ case '"':
138+ {
139+ buffer[position++] = query[query_position++]; // copy current symbol
140+ while(query_position < query_length)
141+ {
142+ if(current == query[query_position]) // found pair quote
143+ {
144+ break;
145+ }
146+ buffer[position++] = query[query_position++]; // copy current symbol
147+ }
148+ break;
149+ }
150+ case '/':
151+ {
152+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
153+ {
154+ query_position += 2; // skip "/*"
155+ do
156+ {
157+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/"
158+ {
159+ query_position += 2; // skip "*/"
160+ insert_space = true;
161+ break;
162+ }
163+ else
164+ {
165+ ++query_position;
166+ }
167+ }
168+ while(query_position < query_length);
169+ if(!insert_space)
170+ {
171+ continue;
172+ }
173+ }
174+ break;
175+ }
176+ case '-':
177+ {
178+ if(query[query_position+1] == '-')
179+ {
180+ ++query_position; // skip "-", and go to search of "\n"
181+ }
182+ else
183+ {
184+ break;
185+ }
186+ }
187+ case '#':
188+ {
189+ do
190+ {
191+ ++query_position; // skip current symbol (# or -)
192+ if('\n' == query[query_position]) // check for '\n'
193+ {
194+ ++query_position; // skip '\n'
195+ insert_space = true;
196+ break;
197+ }
198+ }
199+ while(query_position < query_length);
200+ if(insert_space)
201+ {
202+ break;
203+ }
204+ else
205+ {
206+ continue;
207+ }
208+ }
209+ default:
210+ if(query_strip_comments_is_white_space(current))
211+ {
212+ insert_space = true;
213+ ++query_position;
214+ }
215+ break; // make gcc happy
216+ }
217+ if(insert_space)
218+ {
219+ if((last_space + 1) != position)
220+ {
221+ last_space = position;
222+ buffer[position++] = ' ';
223+ }
224+ }
225+ else
226+ {
227+ buffer[position++] = query[query_position++];
228+ }
229+ }
230+ while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1]))
231+ {
232+ --position;
233+ }
234+ buffer[position] = 0;
235+ length = position;
236+}
237+void QueryStripComments::cleanup()
238+{
239+ if(buffer)
240+ {
241+ my_free(buffer);
242+ }
243+ buffer = 0;
244+ length = 0;
245+ buffer_length = 0;
246+}
247+QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc)
248+{
249+ if(opt_query_cache_strip_comments)
250+ {
251+ thd = a_thd;
252+ query = thd->query();
253+ length = thd->query_length();
254+ qsc->set(query,length,thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
255+ thd->set_query(qsc->query(),qsc->query_length());
256+ }
257+ else
258+ {
259+ thd = 0;
260+ query = 0;
261+ length = 0;
262+ }
263+}
264+QueryStripComments_Backup::~QueryStripComments_Backup()
265+{
266+ if(thd)
267+ {
268+ thd->set_query(query,length);
269+ }
270+}
271+
272 #ifdef EMBEDDED_LIBRARY
273 #include "emb_qcache.h"
274 #endif
275@@ -454,7 +629,12 @@
276 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
277 DBUG_ENTER("Query_cache::try_lock");
278
279+ const char* old_proc_info= thd->proc_info;
280+ thd_proc_info(thd,"Waiting on query cache mutex");
281 mysql_mutex_lock(&structure_guard_mutex);
282+ DBUG_EXECUTE_IF("status_wait_query_cache_mutex_sleep", {
283+ sleep(5);
284+ });
285 while (1)
286 {
287 if (m_cache_lock_status == Query_cache::UNLOCKED)
288@@ -501,6 +681,7 @@
289 }
290 }
291 mysql_mutex_unlock(&structure_guard_mutex);
292+ thd->proc_info = old_proc_info;
293
294 DBUG_RETURN(interrupt);
295 }
296@@ -1274,6 +1455,8 @@
297 unlock();
298 DBUG_VOID_RETURN;
299 }
300+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
301+ QueryStripComments_Backup backup(thd,query_strip_comments);
302
303 /* Key is query + database + flag */
304 if (thd->db_length)
305@@ -1451,6 +1634,9 @@
306 Query_cache_block_table *block_table, *block_table_end;
307 ulong tot_length;
308 Query_cache_query_flags flags;
309+ QueryStripComments *query_strip_comments = &(thd->query_strip_comments);
310+ char *sql_backup = sql;
311+ uint query_length_backup = query_length;
312 DBUG_ENTER("Query_cache::send_result_to_client");
313
314 /*
315@@ -1472,21 +1658,103 @@
316
317 {
318 uint i= 0;
319- /*
320- Skip '(' characters in queries like following:
321- (select a from t1) union (select a from t1);
322- */
323- while (sql[i]=='(')
324- i++;
325+ if(opt_query_cache_strip_comments)
326+ {
327+ /* Skip all comments and non-letter symbols */
328+ uint& query_position = i;
329+ char* query = sql;
330+ while(query_position < query_length)
331+ {
332+ bool check = false;
333+ char current = query[query_position];
334+ switch(current)
335+ {
336+ case '/':
337+ if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2]))
338+ {
339+ query_position += 2; // skip "/*"
340+ do
341+ {
342+ if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space)
343+ {
344+ query_position += 2; // skip "*/" (without space)
345+ break;
346+ }
347+ else
348+ {
349+ ++query_position;
350+ }
351+ }
352+ while(query_position < query_length);
353+ continue; // analyze current symbol
354+ }
355+ break;
356+ case '-':
357+ if(query[query_position+1] == '-')
358+ {
359+ ++query_position; // skip "-"
360+ }
361+ else
362+ {
363+ break;
364+ }
365+ case '#':
366+ do
367+ {
368+ ++query_position; // skip current symbol
369+ if('\n' == query[query_position]) // check for '\n'
370+ {
371+ ++query_position; // skip '\n'
372+ break;
373+ }
374+ }
375+ while(query_position < query_length);
376+ continue; // analyze current symbol
377+ case '\r':
378+ case '\n':
379+ case '\t':
380+ case ' ':
381+ case '(':
382+ case ')':
383+ break;
384+ default:
385+ check = true;
386+ break; // make gcc happy
387+ } // switch(current)
388+ if(check)
389+ {
390+ if(query_position + 2 < query_length)
391+ {
392+ // cacheable
393+ break;
394+ }
395+ else
396+ {
397+ DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
398+ goto err;
399+ }
400+ } // if(check)
401+ ++query_position;
402+ } // while(query_position < query_length)
403+ }
404+ else // if(opt_query_cache_strip_comments)
405+ {
406+ /*
407+ Skip '(' characters in queries like following:
408+ (select a from t1) union (select a from t1);
409+ */
410+ while (sql[i]=='(')
411+ i++;
412
413- /*
414- Test if the query is a SELECT
415- (pre-space is removed in dispatch_command).
416+ } // if(opt_query_cache_strip_comments)
417+ /*
418+ Test if the query is a SELECT
419+ (pre-space is removed in dispatch_command).
420
421- First '/' looks like comment before command it is not
422- frequently appeared in real life, consequently we can
423- check all such queries, too.
424- */
425+ First '/' looks like comment before command it is not
426+ frequently appeared in real life, consequently we can
427+ check all such queries, too.
428+ */
429 if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
430 my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
431 my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
432@@ -1521,6 +1789,12 @@
433 goto err_unlock;
434
435 Query_cache_block *query_block;
436+ if(opt_query_cache_strip_comments)
437+ {
438+ query_strip_comments->set(sql, query_length, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
439+ sql = query_strip_comments->query();
440+ query_length = query_strip_comments->query_length();
441+ }
442
443 tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
444 if (thd->db_length)
445@@ -1587,6 +1861,8 @@
446 (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
447 query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql,
448 tot_length);
449+ sql = sql_backup;
450+ query_length = query_length_backup;
451 /* Quick abort on unlocked data */
452 if (query_block == 0 ||
453 query_block->query()->result() == 0 ||
454diff -ruN a/sql/sql_class.h b/sql/sql_class.h
11822e22
AM
455--- a/sql/sql_class.h 2011-04-09 18:48:50.000000000 +0400
456+++ b/sql/sql_class.h 2011-04-09 18:48:53.000000000 +0400
b4e1fa2c
AM
457@@ -40,6 +40,9 @@
458 #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
459 THR_LOCK_INFO */
460
461+#ifdef HAVE_QUERY_CACHE
462+#include "query_strip_comments.h"
463+#endif // HAVE_QUERY_CACHE
464
465 class Reprepare_observer;
466 class Relay_log_info;
a9ee80b9 467@@ -765,6 +768,9 @@
b4e1fa2c
AM
468 statement lifetime. FIXME: must be const
469 */
470 ulong id;
471+#ifdef HAVE_QUERY_CACHE
472+ QueryStripComments query_strip_comments; // see sql_cache.cc
473+#endif //HAVE_QUERY_CACHE
474
475 /*
476 MARK_COLUMNS_NONE: Means mark_used_colums is not set and no indicator to
477diff -ruN a/sql/sys_vars.cc b/sql/sys_vars.cc
11822e22
AM
478--- a/sql/sys_vars.cc 2011-04-09 18:48:50.000000000 +0400
479+++ b/sql/sys_vars.cc 2011-04-09 18:48:53.000000000 +0400
480@@ -1750,6 +1750,11 @@
b4e1fa2c
AM
481 NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
482 ON_UPDATE(fix_query_cache_size));
483
484+static Sys_var_mybool Sys_query_cache_strip_comments(
485+ "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",
486+ GLOBAL_VAR(opt_query_cache_strip_comments), CMD_LINE(OPT_ARG),
487+ DEFAULT(FALSE));
488+
489 static Sys_var_ulong Sys_query_cache_limit(
490 "query_cache_limit",
491 "Don't cache results that are bigger than this",
This page took 1.578967 seconds and 4 git commands to generate.