Merge lp:~akopytov/percona-server/bug915814-5.5 into lp:percona-server/5.5
- bug915814-5.5
- Merge into 5.5
Proposed by
Alexey Kopytov
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Laurynas Biveinis | ||||||||
Approved revision: | no longer in the source branch. | ||||||||
Merged at revision: | 230 | ||||||||
Proposed branch: | lp:~akopytov/percona-server/bug915814-5.5 | ||||||||
Merge into: | lp:percona-server/5.5 | ||||||||
Diff against target: |
1805 lines (+448/-1188) 1 file modified
patches/query_cache_enhance.patch (+448/-1188) |
||||||||
To merge this branch: | bzr merge lp:~akopytov/percona-server/bug915814-5.5 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+98997@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : | # |
Revision history for this message
Alexey Kopytov (akopytov) wrote : | # |
There was another problem with the old patch that was caught by Jenkins. Link for the fixed version: http://
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
I'd prefer to have a #define or enum constant for the query buffer length, together with the layout-explaining comment, instead of two separate copies at around diff lines 348 and 942.
review:
Needs Fixing
Revision history for this message
Alexey Kopytov (akopytov) wrote : | # |
On 25.03.12 14:16, Laurynas Biveinis wrote:
> I'd prefer to have a #define or enum constant for the query buffer length
Done.
http://
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'patches/query_cache_enhance.patch' | |||
2 | --- patches/query_cache_enhance.patch 2012-02-02 07:11:59 +0000 | |||
3 | +++ patches/query_cache_enhance.patch 2012-03-25 11:37:19 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # name : query_cache_enhance.patch | 1 | # name : query_cache_with_comments.patch |
7 | 2 | # introduced : 11 or before | 2 | # introduced : 11 or before |
8 | 3 | # maintainer : Oleg | 3 | # maintainer : Oleg |
9 | 4 | # | 4 | # |
10 | @@ -25,7 +25,7 @@ | |||
11 | 25 | +2010-11 - Ported to 5.5 | 25 | +2010-11 - Ported to 5.5 |
12 | 26 | --- a/sql/mysqld.cc | 26 | --- a/sql/mysqld.cc |
13 | 27 | +++ b/sql/mysqld.cc | 27 | +++ b/sql/mysqld.cc |
15 | 28 | @@ -909,6 +909,7 @@ | 28 | @@ -915,6 +915,7 @@ |
16 | 29 | #endif | 29 | #endif |
17 | 30 | #ifdef HAVE_QUERY_CACHE | 30 | #ifdef HAVE_QUERY_CACHE |
18 | 31 | ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; | 31 | ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; |
19 | @@ -43,510 +43,252 @@ | |||
20 | 43 | extern ulonglong log_output_options; | 43 | extern ulonglong log_output_options; |
21 | 44 | extern ulong log_backup_output_options; | 44 | extern ulong log_backup_output_options; |
22 | 45 | extern my_bool opt_log_queries_not_using_indexes; | 45 | extern my_bool opt_log_queries_not_using_indexes; |
23 | 46 | --- /dev/null | ||
24 | 47 | +++ b/sql/query_strip_comments.h | ||
25 | 48 | @@ -0,0 +1,37 @@ | ||
26 | 49 | +#ifndef _SQL_QUERY_STRIPC_COMMENTS_H_ | ||
27 | 50 | +#define _SQL_QUERY_STRIPC_COMMENTS_H_ | ||
28 | 51 | +#ifdef HAVE_QUERY_CACHE | ||
29 | 52 | + | ||
30 | 53 | +// implemented in sql_cache.cc | ||
31 | 54 | +class QueryStripComments | ||
32 | 55 | +{ | ||
33 | 56 | +private: | ||
34 | 57 | + QueryStripComments(const QueryStripComments&); | ||
35 | 58 | + QueryStripComments& operator=(const QueryStripComments&); | ||
36 | 59 | +public: | ||
37 | 60 | + QueryStripComments(); | ||
38 | 61 | + ~QueryStripComments(); | ||
39 | 62 | + void set(const char* a_query, uint a_query_length, uint a_additional_length); | ||
40 | 63 | + | ||
41 | 64 | + char* query() { return buffer; } | ||
42 | 65 | + uint query_length() { return length; } | ||
43 | 66 | +private: | ||
44 | 67 | + void cleanup(); | ||
45 | 68 | +private: | ||
46 | 69 | + char* buffer; | ||
47 | 70 | + uint length /*query length, not buffer length*/; | ||
48 | 71 | + uint buffer_length; | ||
49 | 72 | +}; | ||
50 | 73 | +class QueryStripComments_Backup | ||
51 | 74 | +{ | ||
52 | 75 | +public: | ||
53 | 76 | + QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc); | ||
54 | 77 | + ~QueryStripComments_Backup(); | ||
55 | 78 | +private: | ||
56 | 79 | + THD* thd; | ||
57 | 80 | + char* query; | ||
58 | 81 | + uint length; | ||
59 | 82 | +}; | ||
60 | 83 | + | ||
61 | 84 | +#endif // HAVE_QUERY_CACHE | ||
62 | 85 | +#endif // _SQL_QUERY_STRIPC_COMMENTS_H_ | ||
63 | 46 | --- a/sql/sql_cache.cc | 86 | --- a/sql/sql_cache.cc |
64 | 47 | +++ b/sql/sql_cache.cc | 87 | +++ b/sql/sql_cache.cc |
66 | 48 | @@ -344,6 +344,496 @@ | 88 | @@ -344,6 +344,198 @@ |
67 | 49 | #include "probes_mysql.h" | 89 | #include "probes_mysql.h" |
68 | 50 | #include "transaction.h" | 90 | #include "transaction.h" |
69 | 51 | 91 | ||
109 | 52 | + | 92 | +#include "query_strip_comments.h" |
110 | 53 | +namespace query_comments_parser | 93 | + |
111 | 54 | +{ | 94 | +/* |
112 | 55 | + | 95 | + Number of bytes to be allocated in a query cache buffer in addition to the |
113 | 56 | + | 96 | + query string length. |
114 | 57 | +enum Kind | 97 | + |
115 | 58 | +{ | 98 | + The query buffer layout is: |
116 | 59 | + /* 'Empty' symbol - epsilon in classic parsers */ | 99 | + |
117 | 60 | + Empty, | 100 | + buffer :== |
118 | 61 | + /* | 101 | + <statement> The input statement(s) |
119 | 62 | + Special symbols: | 102 | + '\0' Terminating null char |
120 | 63 | + * exclamation comment: slash-star-exclamation comment-body star-slash | 103 | + <db_length> Length of following current database name (size_t) |
121 | 64 | + * single-line and multi-line comments | 104 | + <db_name> Name of current database |
122 | 65 | + */ | 105 | + <flags> Flags struct |
84 | 66 | + Special, | ||
85 | 67 | + /* Whitespaces: ' ' \t \r \n */ | ||
86 | 68 | + WhiteSpace, | ||
87 | 69 | + /* | ||
88 | 70 | + 1) C-style comment (slash-star comment-body star-slash) | ||
89 | 71 | + 2) signle-line comment: | ||
90 | 72 | + * sharp comment (sharp comment-body new-line) | ||
91 | 73 | + * minus-minus comment (minus-minus comment-body new-line) | ||
92 | 74 | + */ | ||
93 | 75 | + Comment, | ||
94 | 76 | + /* Not a special symbols (this symbols can't be before SELECT ). */ | ||
95 | 77 | + Another, | ||
96 | 78 | + /* Error: not-closed quotes, not-closed C-style comment, end-of-query */ | ||
97 | 79 | + Error | ||
98 | 80 | +}; | ||
99 | 81 | + | ||
100 | 82 | + | ||
101 | 83 | +/** | ||
102 | 84 | + Analyze kind of prefix of input string. | ||
103 | 85 | + | ||
104 | 86 | + @param where pointer to pointer to begin of string. After analyzing input | ||
105 | 87 | + string function skip analyzed prefix and return pointer to the next part | ||
106 | 88 | + of string in the @param where. | ||
107 | 89 | + | ||
108 | 90 | + @return kind of analyzed prefix. | ||
123 | 91 | +*/ | 106 | +*/ |
146 | 92 | +static Kind analyze(const char **where, const char *const end) | 107 | +#define QUERY_BUFFER_ADDITIONAL_LENGTH(db_length) \ |
147 | 93 | +{ | 108 | + (1 + sizeof(size_t) + db_length + QUERY_CACHE_FLAGS_SIZE) |
148 | 94 | + DBUG_ASSERT(where != NULL); | 109 | + |
149 | 95 | + DBUG_ASSERT(*where != NULL); | 110 | +QueryStripComments::QueryStripComments() |
150 | 96 | + const char*&to= *where; | 111 | +{ |
151 | 97 | + /* if empty */ | 112 | + buffer = 0; |
152 | 98 | + if (*to == '\0') | 113 | + length = 0; |
153 | 99 | + { | 114 | + buffer_length = 0; |
154 | 100 | + return Empty; | 115 | +} |
155 | 101 | + } | 116 | +QueryStripComments::~QueryStripComments() |
156 | 102 | + | 117 | +{ |
157 | 103 | + /* current symbol */ | 118 | + cleanup(); |
158 | 104 | + char current= *to; | 119 | +} |
159 | 105 | + | 120 | + |
160 | 106 | + switch (current) | 121 | +inline bool query_strip_comments_is_white_space(char c) |
161 | 107 | + { | 122 | +{ |
162 | 108 | + case '\'': | 123 | + return ((' ' == c) || ('\t' == c) || ('\r' == c) || ('\n' ==c )); |
163 | 109 | + case '"': | 124 | +} |
164 | 110 | + /* skip quote */ | 125 | +void QueryStripComments::set(const char* query, uint query_length, uint additional_length) |
165 | 111 | + to++; | 126 | +{ |
166 | 112 | + /* search pair */ | 127 | + uint new_buffer_length = query_length + additional_length; |
167 | 113 | + while (true) | 128 | + if(new_buffer_length > buffer_length) |
168 | 129 | + { | ||
169 | 130 | + cleanup(); | ||
170 | 131 | + buffer = (char*)my_malloc(new_buffer_length,MYF(0)); | ||
171 | 132 | + } | ||
172 | 133 | + uint query_position = 0; | ||
173 | 134 | + uint position = 0; | ||
174 | 135 | + // Skip whitespaces from begin | ||
175 | 136 | + while((query_position < query_length) && query_strip_comments_is_white_space(query[query_position])) | ||
176 | 137 | + { | ||
177 | 138 | + ++query_position; | ||
178 | 139 | + } | ||
179 | 140 | + long int last_space = -1; | ||
180 | 141 | + while(query_position < query_length) | ||
181 | 142 | + { | ||
182 | 143 | + char current = query[query_position]; | ||
183 | 144 | + bool insert_space = false; // insert space to buffer, (IMPORTANT) don't update query_position | ||
184 | 145 | + switch(current) | ||
185 | 114 | + { | 146 | + { |
205 | 115 | + /* check for pair of quote */ | 147 | + case '\'': |
206 | 116 | + if (*to == current) | 148 | + case '"': |
207 | 117 | + { | 149 | + { |
208 | 118 | + /* skip second quote */ | 150 | + buffer[position++] = query[query_position++]; // copy current symbol |
209 | 119 | + to++; | 151 | + while(query_position < query_length) |
210 | 120 | + /* check for same symbol after second quote */ | 152 | + { |
211 | 121 | + if (to < end && *to == current) | 153 | + if(current == query[query_position]) // found pair quote |
212 | 122 | + { | 154 | + { |
213 | 123 | + /* same symbol, skip it */ | 155 | + break; |
214 | 124 | + to++; | 156 | + } |
215 | 125 | + /* check for end-of-line */ | 157 | + buffer[position++] = query[query_position++]; // copy current symbol |
216 | 126 | + if (to == end) | 158 | + } |
217 | 127 | + { | 159 | + break; |
218 | 128 | + /* not found - not closed quote */ | 160 | + } |
219 | 129 | + return Error; | 161 | + case '/': |
220 | 130 | + } | 162 | + { |
221 | 131 | + else | 163 | + if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2])) |
222 | 132 | + { | 164 | + { |
223 | 133 | + /* continue search of pair */ | 165 | + query_position += 2; // skip "/*" |
224 | 166 | + do | ||
225 | 167 | + { | ||
226 | 168 | + if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" | ||
227 | 169 | + { | ||
228 | 170 | + query_position += 2; // skip "*/" | ||
229 | 171 | + insert_space = true; | ||
230 | 172 | + break; | ||
231 | 173 | + } | ||
232 | 174 | + else | ||
233 | 175 | + { | ||
234 | 176 | + ++query_position; | ||
235 | 177 | + } | ||
236 | 178 | + } | ||
237 | 179 | + while(query_position < query_length); | ||
238 | 180 | + if(!insert_space) | ||
239 | 181 | + { | ||
240 | 134 | + continue; | 182 | + continue; |
241 | 135 | + } | 183 | + } |
242 | 136 | + } | 184 | + } |
647 | 137 | + else | 185 | + break; |
648 | 138 | + { | 186 | + } |
649 | 139 | + return Another; | 187 | + case '-': |
650 | 140 | + } | 188 | + { |
651 | 141 | + } | 189 | + if(query[query_position+1] == '-') |
652 | 142 | + /* check for escaped symbols */ | 190 | + { |
653 | 143 | + if (*to == '\\') | 191 | + ++query_position; // skip "-", and go to search of "\n" |
654 | 144 | + { | 192 | + } |
655 | 145 | + /* backslash, skip it */ | 193 | + else |
656 | 146 | + to++; | 194 | + { |
657 | 147 | + } | 195 | + break; |
658 | 148 | + /* check for end-of-line */ | 196 | + } |
659 | 149 | + if (to == end) | 197 | + } |
660 | 150 | + { | 198 | + case '#': |
661 | 151 | + /* not found - not closed quote */ | 199 | + { |
662 | 152 | + return Error; | 200 | + do |
663 | 153 | + } | 201 | + { |
664 | 154 | + /* skip current symbol */ | 202 | + ++query_position; // skip current symbol (# or -) |
665 | 155 | + to++; | 203 | + if('\n' == query[query_position]) // check for '\n' |
666 | 156 | + } | 204 | + { |
667 | 157 | + case '-': | 205 | + ++query_position; // skip '\n' |
668 | 158 | + /* Skip minus */ | 206 | + insert_space = true; |
669 | 159 | + to++; | 207 | + break; |
670 | 160 | + /* Check for second minus */ | 208 | + } |
671 | 161 | + if (*to != '-') | 209 | + } |
672 | 162 | + { | 210 | + while(query_position < query_length); |
673 | 163 | + /* Just minus */ | 211 | + if(insert_space) |
674 | 164 | + return Another; | 212 | + { |
675 | 165 | + } | 213 | + break; |
676 | 166 | + else | 214 | + } |
677 | 167 | + { | 215 | + else |
678 | 168 | + /* | 216 | + { |
679 | 169 | + Prefix is minus-minus, next case-branch is processing | 217 | + continue; |
680 | 170 | + single line comments. | 218 | + } |
681 | 171 | + */ | 219 | + } |
682 | 172 | + } | 220 | + default: |
683 | 173 | + case '#': | 221 | + if(query_strip_comments_is_white_space(current)) |
684 | 174 | + /* | 222 | + { |
685 | 175 | + This is single-line comment, it started by "#" or "--". | 223 | + insert_space = true; |
686 | 176 | + Skip first symbol. | 224 | + ++query_position; |
687 | 177 | + */ | 225 | + } |
688 | 178 | + to++; | 226 | + break; // make gcc happy |
689 | 179 | + /* search new-line */ | 227 | + } |
690 | 180 | + to= strchr(to, '\n'); | 228 | + if(insert_space) |
691 | 181 | + if (NULL == to) | 229 | + { |
692 | 182 | + { | 230 | + if((uint) (last_space + 1) != position) |
693 | 183 | + /* not found, end of the comment is the end of the query */ | 231 | + { |
694 | 184 | + to= end; | 232 | + last_space = position; |
695 | 185 | + } | 233 | + buffer[position++] = ' '; |
696 | 186 | + else | 234 | + } |
697 | 187 | + { | 235 | + } |
698 | 188 | + /* skip end-of-line */ | 236 | + else if (query_position < query_length) |
699 | 189 | + to++; | 237 | + { |
700 | 190 | + } | 238 | + buffer[position++] = query[query_position++]; |
701 | 191 | + return Comment; | 239 | + } |
702 | 192 | + case '/': | 240 | + } |
703 | 193 | + /* skip slash */ | 241 | + while((0 < position) && query_strip_comments_is_white_space(buffer[position - 1])) |
704 | 194 | + to++; | 242 | + { |
705 | 195 | + /* check for star */ | 243 | + --position; |
706 | 196 | + if (*to == '*') | 244 | + } |
707 | 197 | + { | 245 | + buffer[position] = 0; |
708 | 198 | + /* skip star */ | 246 | + length = position; |
709 | 199 | + to++; | 247 | +} |
710 | 200 | + /* check for exclamation */ | 248 | +void QueryStripComments::cleanup() |
711 | 201 | + bool exclamation= (*to == '!'); | 249 | +{ |
712 | 202 | + /* search star-slash */ | 250 | + if(buffer) |
713 | 203 | + to= strstr(to, "*/"); | 251 | + { |
714 | 204 | + if (NULL == to) | 252 | + my_free(buffer); |
715 | 205 | + { | 253 | + } |
716 | 206 | + /* not found - not closed comment */ | 254 | + buffer = 0; |
717 | 207 | + return Error; | 255 | + length = 0; |
718 | 208 | + } | 256 | + buffer_length = 0; |
719 | 209 | + else | 257 | +} |
720 | 210 | + { | 258 | +QueryStripComments_Backup::QueryStripComments_Backup(THD* a_thd,QueryStripComments* qsc) |
721 | 211 | + /* found */ | 259 | +{ |
722 | 212 | + DBUG_ASSERT(to + 1 < end); | 260 | + if(opt_query_cache_strip_comments) |
723 | 213 | + DBUG_ASSERT(0 == strncmp(to, "*/", 2)); | 261 | + { |
724 | 214 | + /* skip star-slash */ | 262 | + thd = a_thd; |
725 | 215 | + to++; | 263 | + query = thd->query(); |
726 | 216 | + to++; | 264 | + length = thd->query_length(); |
727 | 217 | + return (exclamation ? Special : Comment); | 265 | + qsc->set(query, length, QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length)); |
728 | 218 | + } | 266 | + *(size_t *) (qsc->query() + qsc->query_length() + 1)= thd->db_length; |
729 | 219 | + } | 267 | + thd->set_query(qsc->query(),qsc->query_length()); |
730 | 220 | + else | 268 | + } |
731 | 221 | + { | 269 | + else |
732 | 222 | + /* just slash */ | 270 | + { |
733 | 223 | + return Another; | 271 | + thd = 0; |
734 | 224 | + } | 272 | + query = 0; |
735 | 225 | + case ' ': | 273 | + length = 0; |
736 | 226 | + case '\t': | 274 | + } |
737 | 227 | + case '\r': | 275 | +} |
738 | 228 | + case '\n': | 276 | +QueryStripComments_Backup::~QueryStripComments_Backup() |
739 | 229 | + { | 277 | +{ |
740 | 230 | + /* skip space */ | 278 | + if(thd) |
741 | 231 | + to++; | 279 | + { |
742 | 232 | + return WhiteSpace; | 280 | + thd->set_query(query,length); |
743 | 233 | + } | 281 | + } |
744 | 234 | + case '\\': | 282 | +} |
341 | 235 | + { | ||
342 | 236 | + /* skip backslash */ | ||
343 | 237 | + to++; | ||
344 | 238 | + if (to == end) | ||
345 | 239 | + { | ||
346 | 240 | + /* | ||
347 | 241 | + query complete by backslash | ||
348 | 242 | + probable error? | ||
349 | 243 | + */ | ||
350 | 244 | + return Another; | ||
351 | 245 | + } | ||
352 | 246 | + else | ||
353 | 247 | + { | ||
354 | 248 | + /* skip after backslash symbol */ | ||
355 | 249 | + to++; | ||
356 | 250 | + return Another; | ||
357 | 251 | + } | ||
358 | 252 | + } | ||
359 | 253 | + case '(': | ||
360 | 254 | + case ')': | ||
361 | 255 | + { | ||
362 | 256 | + /* skip parenthese */ | ||
363 | 257 | + to++; | ||
364 | 258 | + return Special; | ||
365 | 259 | + } | ||
366 | 260 | + default: | ||
367 | 261 | + { | ||
368 | 262 | + /* skip symbol */ | ||
369 | 263 | + to++; | ||
370 | 264 | + return Another; | ||
371 | 265 | + } | ||
372 | 266 | + }; | ||
373 | 267 | +} | ||
374 | 268 | + | ||
375 | 269 | + | ||
376 | 270 | +static bool remove_comments_from_query(const char *const query, | ||
377 | 271 | + const size_t query_length, | ||
378 | 272 | + char *const result, | ||
379 | 273 | + size_t *result_length) | ||
380 | 274 | +{ | ||
381 | 275 | + /* pointer to begin of parsed block */ | ||
382 | 276 | + const char *from= query; | ||
383 | 277 | + const char *to= query; | ||
384 | 278 | + /* pointer to end of the query */ | ||
385 | 279 | + const char *const end= query + query_length; | ||
386 | 280 | + /* pointer to last space */ | ||
387 | 281 | + const char *space= NULL; | ||
388 | 282 | + /* current position in result buffer */ | ||
389 | 283 | + char *current= result; | ||
390 | 284 | + while (true) | ||
391 | 285 | + { | ||
392 | 286 | + from= to; | ||
393 | 287 | + switch (analyze(&to, end)) | ||
394 | 288 | + { | ||
395 | 289 | + case Empty: | ||
396 | 290 | + { | ||
397 | 291 | + /* | ||
398 | 292 | + parse completed | ||
399 | 293 | + check for whitespace in the end | ||
400 | 294 | + */ | ||
401 | 295 | + if (current == space) | ||
402 | 296 | + { | ||
403 | 297 | + /* drop whitespace in the end of query */ | ||
404 | 298 | + --current; | ||
405 | 299 | + } | ||
406 | 300 | + /* result is null-terminated string */ | ||
407 | 301 | + *current= 0; | ||
408 | 302 | + /* set result length */ | ||
409 | 303 | + *result_length= current - result; | ||
410 | 304 | + /* all right */ | ||
411 | 305 | + return true; | ||
412 | 306 | + } | ||
413 | 307 | + case Comment: | ||
414 | 308 | + /* should just insert space instead of comment */ | ||
415 | 309 | + case WhiteSpace: | ||
416 | 310 | + if (space == current || from == query) | ||
417 | 311 | + { | ||
418 | 312 | + /* previous symbol was space */ | ||
419 | 313 | + } | ||
420 | 314 | + else | ||
421 | 315 | + { | ||
422 | 316 | + /* insert space to result buffer */ | ||
423 | 317 | + *current= ' '; | ||
424 | 318 | + /* switch after inserted space */ | ||
425 | 319 | + current++; | ||
426 | 320 | + } | ||
427 | 321 | + /* remember last-after-space position */ | ||
428 | 322 | + space= current; | ||
429 | 323 | + /* parse again */ | ||
430 | 324 | + continue; | ||
431 | 325 | + case Special: | ||
432 | 326 | + case Another: | ||
433 | 327 | + { | ||
434 | 328 | + /* calculate parsed block size */ | ||
435 | 329 | + size_t block_size= to - from; | ||
436 | 330 | + /* copy parsed block to result */ | ||
437 | 331 | + memcpy(current, from, block_size); | ||
438 | 332 | + /* switch result after copied block */ | ||
439 | 333 | + current+= block_size; | ||
440 | 334 | + /* switch after parsed block */ | ||
441 | 335 | + from= to; | ||
442 | 336 | + /* parse again */ | ||
443 | 337 | + continue; | ||
444 | 338 | + } | ||
445 | 339 | + case Error: | ||
446 | 340 | + default: | ||
447 | 341 | + { | ||
448 | 342 | + /* bad source query */ | ||
449 | 343 | + return false; | ||
450 | 344 | + } | ||
451 | 345 | + } | ||
452 | 346 | + } | ||
453 | 347 | +} | ||
454 | 348 | + | ||
455 | 349 | + | ||
456 | 350 | +static size_t skip_not_another(const char *const query, size_t query_length) | ||
457 | 351 | +{ | ||
458 | 352 | + const char *from= query; | ||
459 | 353 | + const char *to= query; | ||
460 | 354 | + const char *const end= query + query_length; | ||
461 | 355 | + while (true) | ||
462 | 356 | + { | ||
463 | 357 | + switch (analyze(&to, end)) | ||
464 | 358 | + { | ||
465 | 359 | + case Error: | ||
466 | 360 | + return 0; | ||
467 | 361 | + case Empty: | ||
468 | 362 | + case Another: | ||
469 | 363 | + return (from - query); | ||
470 | 364 | + default: | ||
471 | 365 | + from= to; | ||
472 | 366 | + continue; | ||
473 | 367 | + }; | ||
474 | 368 | + } | ||
475 | 369 | +} | ||
476 | 370 | + | ||
477 | 371 | + | ||
478 | 372 | +static size_t skip_default(const char *const query, size_t /* query_length */) | ||
479 | 373 | +{ | ||
480 | 374 | + size_t query_position= 0; | ||
481 | 375 | + /* | ||
482 | 376 | + Skip '(' characters in queries like following: | ||
483 | 377 | + (select a from t1) union (select a from t1); | ||
484 | 378 | + */ | ||
485 | 379 | + while (query[query_position]=='(') | ||
486 | 380 | + query_position++; | ||
487 | 381 | + return query_position; | ||
488 | 382 | +} | ||
489 | 383 | + | ||
490 | 384 | + | ||
491 | 385 | +} /* namespace query_comments_parser */ | ||
492 | 386 | + | ||
493 | 387 | +class Query_Switcher | ||
494 | 388 | +{ | ||
495 | 389 | +private: | ||
496 | 390 | + Query_Switcher(const Query_Switcher&); | ||
497 | 391 | + Query_Switcher& operator=(const Query_Switcher&); | ||
498 | 392 | + | ||
499 | 393 | + | ||
500 | 394 | +public: | ||
501 | 395 | + Query_Switcher(THD *thd) : | ||
502 | 396 | + target_query(&(thd_query_string(thd)->str)), | ||
503 | 397 | + target_length(&(thd_query_string(thd)->length)), | ||
504 | 398 | + backup_query(thd->query()), | ||
505 | 399 | + backup_length(thd->query_length()) | ||
506 | 400 | + { | ||
507 | 401 | + } | ||
508 | 402 | + | ||
509 | 403 | + Query_Switcher(char **query, | ||
510 | 404 | + size_t *length) : | ||
511 | 405 | + target_query(query), | ||
512 | 406 | + target_length(length), | ||
513 | 407 | + backup_query(*query), | ||
514 | 408 | + backup_length(*length) | ||
515 | 409 | + { | ||
516 | 410 | + } | ||
517 | 411 | +public: | ||
518 | 412 | + void replace(Query_Without_Comments *query_without_comments) | ||
519 | 413 | + { | ||
520 | 414 | + *target_query= query_without_comments->query(); | ||
521 | 415 | + *target_length= query_without_comments->length(); | ||
522 | 416 | + } | ||
523 | 417 | + void restore() | ||
524 | 418 | + { | ||
525 | 419 | + *target_query= backup_query; | ||
526 | 420 | + *target_length= backup_length; | ||
527 | 421 | + } | ||
528 | 422 | +private: | ||
529 | 423 | + char* *target_query; | ||
530 | 424 | + size_t *target_length; | ||
531 | 425 | +public: | ||
532 | 426 | + char *const backup_query; | ||
533 | 427 | + size_t const backup_length; | ||
534 | 428 | +}; | ||
535 | 429 | + | ||
536 | 430 | +class Comments_Processor | ||
537 | 431 | +{ | ||
538 | 432 | +private: | ||
539 | 433 | + Comments_Processor(const Comments_Processor&); | ||
540 | 434 | + Comments_Processor& operator=(const Comments_Processor&); | ||
541 | 435 | + | ||
542 | 436 | + | ||
543 | 437 | +public: | ||
544 | 438 | + Comments_Processor(THD *thd) : | ||
545 | 439 | + query_switcher (thd), | ||
546 | 440 | + db_length (thd->db_length), | ||
547 | 441 | + query_without_comments(&(thd->query_without_comments)), | ||
548 | 442 | + enabled (opt_query_cache_strip_comments), | ||
549 | 443 | + restore (false) | ||
550 | 444 | + { | ||
551 | 445 | + } | ||
552 | 446 | + | ||
553 | 447 | + | ||
554 | 448 | + Comments_Processor(Query_Without_Comments *current_query_without_comments, | ||
555 | 449 | + char **query, | ||
556 | 450 | + size_t *length, | ||
557 | 451 | + const size_t current_db_length) : | ||
558 | 452 | + query_switcher (query, length), | ||
559 | 453 | + db_length (current_db_length), | ||
560 | 454 | + query_without_comments(current_query_without_comments), | ||
561 | 455 | + enabled (opt_query_cache_strip_comments), | ||
562 | 456 | + restore (false) | ||
563 | 457 | + { | ||
564 | 458 | + } | ||
565 | 459 | + | ||
566 | 460 | + | ||
567 | 461 | + ~Comments_Processor() | ||
568 | 462 | + { | ||
569 | 463 | + restore_comments(); | ||
570 | 464 | + } | ||
571 | 465 | + | ||
572 | 466 | + | ||
573 | 467 | + size_t prefix_length() | ||
574 | 468 | + { | ||
575 | 469 | + using query_comments_parser::skip_not_another; | ||
576 | 470 | + using query_comments_parser::skip_default; | ||
577 | 471 | + if (enabled) | ||
578 | 472 | + { | ||
579 | 473 | + return skip_not_another(query_switcher.backup_query, | ||
580 | 474 | + query_switcher.backup_length); | ||
581 | 475 | + } | ||
582 | 476 | + else | ||
583 | 477 | + { | ||
584 | 478 | + return skip_default(query_switcher.backup_query, | ||
585 | 479 | + query_switcher.backup_length); | ||
586 | 480 | + } | ||
587 | 481 | + } | ||
588 | 482 | + | ||
589 | 483 | + | ||
590 | 484 | + bool remove_comments() | ||
591 | 485 | + { | ||
592 | 486 | + if (!enabled || restore) | ||
593 | 487 | + { | ||
594 | 488 | + return true; | ||
595 | 489 | + } | ||
596 | 490 | + /* Allocate memory for query rewrite */ | ||
597 | 491 | + if (!query_without_comments->allocate(query_switcher.backup_length, | ||
598 | 492 | + db_length)) | ||
599 | 493 | + { | ||
600 | 494 | + return false; | ||
601 | 495 | + } | ||
602 | 496 | + /* Remove comment from query */ | ||
603 | 497 | + size_t result_length; | ||
604 | 498 | + using query_comments_parser::remove_comments_from_query; | ||
605 | 499 | + if (!(restore= remove_comments_from_query(query_switcher.backup_query, | ||
606 | 500 | + query_switcher.backup_length, | ||
607 | 501 | + query_without_comments->query(), | ||
608 | 502 | + &result_length))) | ||
609 | 503 | + { | ||
610 | 504 | + return false; | ||
611 | 505 | + } | ||
612 | 506 | + query_without_comments->set_length(result_length); | ||
613 | 507 | + size_t db_length_from_query= | ||
614 | 508 | + *((size_t*)(query_switcher.backup_query + | ||
615 | 509 | + query_switcher.backup_length + 1)); | ||
616 | 510 | + *((size_t*)(query_without_comments->query() + | ||
617 | 511 | + result_length + 1))= db_length_from_query; | ||
618 | 512 | + /* Replace original query by striped */ | ||
619 | 513 | + query_switcher.replace(query_without_comments); | ||
620 | 514 | + return restore; | ||
621 | 515 | + } | ||
622 | 516 | + | ||
623 | 517 | + | ||
624 | 518 | + void restore_comments() | ||
625 | 519 | + { | ||
626 | 520 | + if (enabled && restore) | ||
627 | 521 | + { | ||
628 | 522 | + /* Replace striped query by original */ | ||
629 | 523 | + query_switcher.restore(); | ||
630 | 524 | + | ||
631 | 525 | + /* Clean query_without_comments */ | ||
632 | 526 | + query_without_comments->set_length(0); | ||
633 | 527 | + | ||
634 | 528 | + /* Mark as restored */ | ||
635 | 529 | + restore= false; | ||
636 | 530 | + } | ||
637 | 531 | + } | ||
638 | 532 | +private: | ||
639 | 533 | + Query_Switcher query_switcher; | ||
640 | 534 | +private: | ||
641 | 535 | + const size_t db_length; | ||
642 | 536 | +private: | ||
643 | 537 | + Query_Without_Comments *query_without_comments; | ||
644 | 538 | + bool enabled; | ||
645 | 539 | + bool restore; | ||
646 | 540 | +}; | ||
745 | 541 | + | 283 | + |
746 | 542 | #ifdef EMBEDDED_LIBRARY | 284 | #ifdef EMBEDDED_LIBRARY |
747 | 543 | #include "emb_qcache.h" | 285 | #include "emb_qcache.h" |
748 | 544 | #endif | 286 | #endif |
750 | 545 | @@ -454,7 +944,12 @@ | 287 | @@ -454,7 +646,12 @@ |
751 | 546 | Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__); | 288 | Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__); |
752 | 547 | DBUG_ENTER("Query_cache::try_lock"); | 289 | DBUG_ENTER("Query_cache::try_lock"); |
753 | 548 | 290 | ||
755 | 549 | + const char *old_proc_info= thd->proc_info; | 291 | + const char* old_proc_info= thd->proc_info; |
756 | 550 | + thd_proc_info(thd,"Waiting on query cache mutex"); | 292 | + thd_proc_info(thd,"Waiting on query cache mutex"); |
757 | 551 | + DEBUG_SYNC(thd, "before_query_cache_mutex"); | 293 | + DEBUG_SYNC(thd, "before_query_cache_mutex"); |
758 | 552 | mysql_mutex_lock(&structure_guard_mutex); | 294 | mysql_mutex_lock(&structure_guard_mutex); |
759 | @@ -555,171 +297,191 @@ | |||
760 | 555 | while (1) | 297 | while (1) |
761 | 556 | { | 298 | { |
762 | 557 | if (m_cache_lock_status == Query_cache::UNLOCKED) | 299 | if (m_cache_lock_status == Query_cache::UNLOCKED) |
764 | 558 | @@ -1274,6 +1769,8 @@ | 300 | @@ -1274,6 +1471,8 @@ |
765 | 559 | unlock(); | 301 | unlock(); |
766 | 560 | DBUG_VOID_RETURN; | 302 | DBUG_VOID_RETURN; |
767 | 561 | } | 303 | } |
770 | 562 | + Comments_Processor comments_processor(thd); | 304 | + QueryStripComments *query_strip_comments = &(thd->query_strip_comments); |
771 | 563 | + comments_processor.remove_comments(); | 305 | + QueryStripComments_Backup backup(thd,query_strip_comments); |
772 | 564 | 306 | ||
773 | 565 | /* Key is query + database + flag */ | 307 | /* Key is query + database + flag */ |
774 | 566 | if (thd->db_length) | 308 | if (thd->db_length) |
785 | 567 | @@ -1440,7 +1937,7 @@ | 309 | @@ -1451,6 +1650,9 @@ |
786 | 568 | */ | 310 | Query_cache_block_table *block_table, *block_table_end; |
777 | 569 | |||
778 | 570 | int | ||
779 | 571 | -Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) | ||
780 | 572 | +Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length_uint) | ||
781 | 573 | { | ||
782 | 574 | ulonglong engine_data; | ||
783 | 575 | Query_cache_query *query; | ||
784 | 576 | @@ -1452,6 +1949,11 @@ | ||
787 | 577 | ulong tot_length; | 311 | ulong tot_length; |
788 | 578 | Query_cache_query_flags flags; | 312 | Query_cache_query_flags flags; |
789 | 313 | + QueryStripComments *query_strip_comments = &(thd->query_strip_comments); | ||
790 | 314 | + char *sql_backup = sql; | ||
791 | 315 | + uint query_length_backup = query_length; | ||
792 | 579 | DBUG_ENTER("Query_cache::send_result_to_client"); | 316 | DBUG_ENTER("Query_cache::send_result_to_client"); |
793 | 580 | + size_t query_length= query_length_uint; | ||
794 | 581 | + Comments_Processor comments_processor(&(thd->query_without_comments), | ||
795 | 582 | + &sql, | ||
796 | 583 | + &query_length, | ||
797 | 584 | + thd->db_length); | ||
798 | 585 | 317 | ||
799 | 586 | /* | 318 | /* |
803 | 587 | Testing 'query_cache_size' without a lock here is safe: the thing | 319 | @@ -1472,21 +1674,103 @@ |
801 | 588 | @@ -1471,13 +1973,7 @@ | ||
802 | 589 | } | ||
804 | 590 | 320 | ||
805 | 591 | { | 321 | { |
807 | 592 | - uint i= 0; | 322 | uint i= 0; |
808 | 593 | - /* | 323 | - /* |
809 | 594 | - Skip '(' characters in queries like following: | 324 | - Skip '(' characters in queries like following: |
810 | 595 | - (select a from t1) union (select a from t1); | 325 | - (select a from t1) union (select a from t1); |
811 | 596 | - */ | 326 | - */ |
812 | 597 | - while (sql[i]=='(') | 327 | - while (sql[i]=='(') |
813 | 598 | - i++; | 328 | - i++; |
835 | 599 | + size_t i= comments_processor.prefix_length(); | 329 | + if(opt_query_cache_strip_comments) |
836 | 600 | 330 | + { | |
837 | 601 | /* | 331 | + /* Skip all comments and non-letter symbols */ |
838 | 602 | Test if the query is a SELECT | 332 | + uint& query_position = i; |
839 | 603 | @@ -1487,10 +1983,11 @@ | 333 | + char* query = sql; |
840 | 604 | frequently appeared in real life, consequently we can | 334 | + while(query_position < query_length) |
841 | 605 | check all such queries, too. | 335 | + { |
842 | 606 | */ | 336 | + bool check = false; |
843 | 607 | - if ((my_toupper(system_charset_info, sql[i]) != 'S' || | 337 | + char current = query[query_position]; |
844 | 608 | - my_toupper(system_charset_info, sql[i + 1]) != 'E' || | 338 | + switch(current) |
845 | 609 | - my_toupper(system_charset_info, sql[i + 2]) != 'L') && | 339 | + { |
846 | 610 | - sql[i] != '/') | 340 | + case '/': |
847 | 611 | + if (!((i + 2 < query_length) && | 341 | + if(((query_position + 2) < query_length) && ('*' == query[query_position+1]) && ('!' != query[query_position+2])) |
848 | 612 | + ((my_toupper(system_charset_info, sql[i]) == 'S' && | 342 | + { |
849 | 613 | + my_toupper(system_charset_info, sql[i + 1]) == 'E' && | 343 | + query_position += 2; // skip "/*" |
850 | 614 | + my_toupper(system_charset_info, sql[i + 2]) == 'L') || | 344 | + do |
851 | 615 | + sql[i] == '/'))) | 345 | + { |
852 | 616 | { | 346 | + if('*' == query[query_position] && '/' == query[query_position+1]) // check for "*/" (without space) |
853 | 617 | DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); | 347 | + { |
854 | 618 | goto err; | 348 | + query_position += 2; // skip "*/" (without space) |
855 | 619 | @@ -1543,6 +2040,7 @@ | 349 | + break; |
856 | 350 | + } | ||
857 | 351 | + else | ||
858 | 352 | + { | ||
859 | 353 | + ++query_position; | ||
860 | 354 | + } | ||
861 | 355 | + } | ||
862 | 356 | + while(query_position < query_length); | ||
863 | 357 | + continue; // analyze current symbol | ||
864 | 358 | + } | ||
865 | 359 | + break; | ||
866 | 360 | + case '-': | ||
867 | 361 | + if(query[query_position+1] == '-') | ||
868 | 362 | + { | ||
869 | 363 | + ++query_position; // skip "-" | ||
870 | 364 | + } | ||
871 | 365 | + else | ||
872 | 366 | + { | ||
873 | 367 | + break; | ||
874 | 368 | + } | ||
875 | 369 | + case '#': | ||
876 | 370 | + do | ||
877 | 371 | + { | ||
878 | 372 | + ++query_position; // skip current symbol | ||
879 | 373 | + if('\n' == query[query_position]) // check for '\n' | ||
880 | 374 | + { | ||
881 | 375 | + ++query_position; // skip '\n' | ||
882 | 376 | + break; | ||
883 | 377 | + } | ||
884 | 378 | + } | ||
885 | 379 | + while(query_position < query_length); | ||
886 | 380 | + continue; // analyze current symbol | ||
887 | 381 | + case '\r': | ||
888 | 382 | + case '\n': | ||
889 | 383 | + case '\t': | ||
890 | 384 | + case ' ': | ||
891 | 385 | + case '(': | ||
892 | 386 | + case ')': | ||
893 | 387 | + break; | ||
894 | 388 | + default: | ||
895 | 389 | + check = true; | ||
896 | 390 | + break; // make gcc happy | ||
897 | 391 | + } // switch(current) | ||
898 | 392 | + if(check) | ||
899 | 393 | + { | ||
900 | 394 | + if(query_position + 2 < query_length) | ||
901 | 395 | + { | ||
902 | 396 | + // cacheable | ||
903 | 397 | + break; | ||
904 | 398 | + } | ||
905 | 399 | + else | ||
906 | 400 | + { | ||
907 | 401 | + DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); | ||
908 | 402 | + goto err; | ||
909 | 403 | + } | ||
910 | 404 | + } // if(check) | ||
911 | 405 | + ++query_position; | ||
912 | 406 | + } // while(query_position < query_length) | ||
913 | 407 | + } | ||
914 | 408 | + else // if(opt_query_cache_strip_comments) | ||
915 | 409 | + { | ||
916 | 410 | + /* | ||
917 | 411 | + Skip '(' characters in queries like following: | ||
918 | 412 | + (select a from t1) union (select a from t1); | ||
919 | 413 | + */ | ||
920 | 414 | + while (sql[i]=='(') | ||
921 | 415 | + i++; | ||
922 | 416 | |||
923 | 417 | - /* | ||
924 | 418 | - Test if the query is a SELECT | ||
925 | 419 | - (pre-space is removed in dispatch_command). | ||
926 | 420 | + } // if(opt_query_cache_strip_comments) | ||
927 | 421 | + /* | ||
928 | 422 | + Test if the query is a SELECT | ||
929 | 423 | + (pre-space is removed in dispatch_command). | ||
930 | 424 | |||
931 | 425 | - First '/' looks like comment before command it is not | ||
932 | 426 | - frequently appeared in real life, consequently we can | ||
933 | 427 | - check all such queries, too. | ||
934 | 428 | - */ | ||
935 | 429 | + First '/' looks like comment before command it is not | ||
936 | 430 | + frequently appeared in real life, consequently we can | ||
937 | 431 | + check all such queries, too. | ||
938 | 432 | + */ | ||
939 | 433 | if ((my_toupper(system_charset_info, sql[i]) != 'S' || | ||
940 | 434 | my_toupper(system_charset_info, sql[i + 1]) != 'E' || | ||
941 | 435 | my_toupper(system_charset_info, sql[i + 2]) != 'L') && | ||
942 | 436 | @@ -1543,6 +1827,14 @@ | ||
943 | 620 | goto err_unlock; | 437 | goto err_unlock; |
944 | 621 | 438 | ||
945 | 622 | Query_cache_block *query_block; | 439 | Query_cache_block *query_block; |
947 | 623 | + comments_processor.remove_comments(); | 440 | + if(opt_query_cache_strip_comments) |
948 | 441 | + { | ||
949 | 442 | + query_strip_comments->set(sql, query_length, | ||
950 | 443 | + QUERY_BUFFER_ADDITIONAL_LENGTH(thd->db_length)); | ||
951 | 444 | + sql = query_strip_comments->query(); | ||
952 | 445 | + query_length = query_strip_comments->query_length(); | ||
953 | 446 | + *(size_t *) (sql + query_length + 1)= thd->db_length; | ||
954 | 447 | + } | ||
955 | 624 | 448 | ||
956 | 625 | tot_length= query_length + 1 + sizeof(size_t) + | 449 | tot_length= query_length + 1 + sizeof(size_t) + |
957 | 626 | thd->db_length + QUERY_CACHE_FLAGS_SIZE; | 450 | thd->db_length + QUERY_CACHE_FLAGS_SIZE; |
959 | 627 | @@ -1611,6 +2109,7 @@ | 451 | @@ -1611,6 +1903,8 @@ |
960 | 628 | (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); | 452 | (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); |
961 | 629 | query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql, | 453 | query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql, |
962 | 630 | tot_length); | 454 | tot_length); |
964 | 631 | + comments_processor.restore_comments(); | 455 | + sql = sql_backup; |
965 | 456 | + query_length = query_length_backup; | ||
966 | 632 | /* Quick abort on unlocked data */ | 457 | /* Quick abort on unlocked data */ |
967 | 633 | if (query_block == 0 || | 458 | if (query_block == 0 || |
968 | 634 | query_block->query()->result() == 0 || | 459 | query_block->query()->result() == 0 || |
969 | 635 | --- a/sql/sql_class.h | 460 | --- a/sql/sql_class.h |
970 | 636 | +++ b/sql/sql_class.h | 461 | +++ b/sql/sql_class.h |
1054 | 637 | @@ -1485,6 +1485,74 @@ | 462 | @@ -40,6 +40,9 @@ |
1055 | 638 | 463 | #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA, | |
1056 | 639 | extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); | 464 | THR_LOCK_INFO */ |
1057 | 640 | 465 | ||
1058 | 641 | + | 466 | +#ifdef HAVE_QUERY_CACHE |
1059 | 642 | +#ifdef HAVE_QUERY_CACHE | 467 | +#include "query_strip_comments.h" |
1060 | 643 | + | 468 | +#endif // HAVE_QUERY_CACHE |
1061 | 644 | + | 469 | |
1062 | 645 | +/* | 470 | class Reprepare_observer; |
1063 | 646 | + @class Query_Without_Comments | 471 | class Relay_log_info; |
1064 | 647 | + This class provides way for safety (re)allocation | 472 | @@ -766,6 +769,9 @@ |
1065 | 648 | + a memory for a query without comments. | 473 | statement lifetime. FIXME: must be const |
1066 | 649 | +*/ | 474 | */ |
1067 | 650 | +class Query_Without_Comments | 475 | ulong id; |
1068 | 651 | +{ | 476 | +#ifdef HAVE_QUERY_CACHE |
1069 | 652 | +private: | 477 | + QueryStripComments query_strip_comments; // see sql_cache.cc |
1070 | 653 | + /* | 478 | +#endif //HAVE_QUERY_CACHE |
1071 | 654 | + Denied copy and assigment for object of this class. | 479 | |
1072 | 655 | + */ | 480 | /* |
1073 | 656 | + Query_Without_Comments(const Query_Without_Comments&); | 481 | MARK_COLUMNS_NONE: Means mark_used_colums is not set and no indicator to |
991 | 657 | + Query_Without_Comments& operator=(const Query_Without_Comments&); | ||
992 | 658 | + | ||
993 | 659 | + | ||
994 | 660 | +public: | ||
995 | 661 | + /* | ||
996 | 662 | + Constructor is filling fields by zero (no allocation). | ||
997 | 663 | + */ | ||
998 | 664 | + Query_Without_Comments(); | ||
999 | 665 | + | ||
1000 | 666 | + | ||
1001 | 667 | + /* | ||
1002 | 668 | + Destructor clean allocated memory | ||
1003 | 669 | + */ | ||
1004 | 670 | + ~Query_Without_Comments(); | ||
1005 | 671 | +public: | ||
1006 | 672 | + | ||
1007 | 673 | + | ||
1008 | 674 | +/* | ||
1009 | 675 | + (Re)allocate memory for query. Query length after that is 0. | ||
1010 | 676 | + */ | ||
1011 | 677 | + bool allocate(size_t query_length, size_t db_length); | ||
1012 | 678 | + | ||
1013 | 679 | + | ||
1014 | 680 | + /* | ||
1015 | 681 | + Set result query length, when query | ||
1016 | 682 | + without comments is copied to buffer. | ||
1017 | 683 | + */ | ||
1018 | 684 | + void set_length(size_t query_length); | ||
1019 | 685 | + | ||
1020 | 686 | + | ||
1021 | 687 | +public: | ||
1022 | 688 | + /* | ||
1023 | 689 | + Result query. | ||
1024 | 690 | + */ | ||
1025 | 691 | + char* query(); | ||
1026 | 692 | + | ||
1027 | 693 | + | ||
1028 | 694 | + /* | ||
1029 | 695 | + Result query length | ||
1030 | 696 | + */ | ||
1031 | 697 | + size_t length(); | ||
1032 | 698 | + | ||
1033 | 699 | + | ||
1034 | 700 | +private: | ||
1035 | 701 | + char* buffer; | ||
1036 | 702 | + size_t q_length; | ||
1037 | 703 | + size_t b_length; | ||
1038 | 704 | +}; | ||
1039 | 705 | + | ||
1040 | 706 | + | ||
1041 | 707 | +#endif /* HAVE_QUERY_CACHE */ | ||
1042 | 708 | + | ||
1043 | 709 | /** | ||
1044 | 710 | @class THD | ||
1045 | 711 | For each client connection we create a separate thread with THD serving as | ||
1046 | 712 | @@ -1542,6 +1610,7 @@ | ||
1047 | 713 | struct st_mysql_stmt *current_stmt; | ||
1048 | 714 | #endif | ||
1049 | 715 | #ifdef HAVE_QUERY_CACHE | ||
1050 | 716 | + Query_Without_Comments query_without_comments; | ||
1051 | 717 | Query_cache_tls query_cache_tls; | ||
1052 | 718 | #endif | ||
1053 | 719 | NET net; // client connection descriptor | ||
1074 | 720 | --- a/sql/sys_vars.cc | 482 | --- a/sql/sys_vars.cc |
1075 | 721 | +++ b/sql/sys_vars.cc | 483 | +++ b/sql/sys_vars.cc |
1077 | 722 | @@ -1888,6 +1888,11 @@ | 484 | @@ -1895,6 +1895,11 @@ |
1078 | 723 | NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), | 485 | NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), |
1079 | 724 | ON_UPDATE(fix_query_cache_size)); | 486 | ON_UPDATE(fix_query_cache_size)); |
1080 | 725 | 487 | ||
1081 | @@ -733,7 +495,7 @@ | |||
1082 | 733 | "Don't cache results that are bigger than this", | 495 | "Don't cache results that are bigger than this", |
1083 | 734 | --- /dev/null | 496 | --- /dev/null |
1084 | 735 | +++ b/mysql-test/include/percona_query_cache_with_comments.inc | 497 | +++ b/mysql-test/include/percona_query_cache_with_comments.inc |
1086 | 736 | @@ -0,0 +1,117 @@ | 498 | @@ -0,0 +1,95 @@ |
1087 | 737 | +--source include/percona_query_cache_with_comments_clear.inc | 499 | +--source include/percona_query_cache_with_comments_clear.inc |
1088 | 738 | +let $query=/* with comment first */select * from t1; | 500 | +let $query=/* with comment first */select * from t1; |
1089 | 739 | +eval $query; | 501 | +eval $query; |
1090 | @@ -827,30 +589,8 @@ | |||
1091 | 827 | +; | 589 | +; |
1092 | 828 | +--source include/percona_query_cache_with_comments_eval.inc | 590 | +--source include/percona_query_cache_with_comments_eval.inc |
1093 | 829 | + | 591 | + |
1094 | 830 | +let $query=select */* a comment \*/from t1; | ||
1095 | 831 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1096 | 832 | + | ||
1097 | 833 | +let $query=select *# a comment \\ | ||
1098 | 834 | +from t1; | ||
1099 | 835 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1100 | 836 | + | ||
1101 | 837 | +let $query=select *-- a comment \\ | ||
1102 | 838 | +from t1; | ||
1103 | 839 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1104 | 840 | + | ||
1105 | 841 | +let $query=select "\\\\"" /* not a comment */" from t1; | ||
1106 | 842 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1107 | 843 | + | ||
1108 | 844 | +let $query=select "\\\\"" /*! not a comment */" from t1; | ||
1109 | 845 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1110 | 846 | + | ||
1111 | 847 | +# following two queries related to bug #856404. | ||
1112 | 848 | +# There are different queries, but opt_query_cache_strip_comments thinks that they are equal. | ||
1113 | 849 | +let $query=select ' \' ' from t1; | 592 | +let $query=select ' \' ' from t1; |
1114 | 850 | +--source include/percona_query_cache_with_comments_eval.inc | 593 | +--source include/percona_query_cache_with_comments_eval.inc |
1115 | 851 | + | ||
1116 | 852 | +let $query=select ' \' /* comment inside quotes with internal backslash quote */' from t1; | ||
1117 | 853 | +--source include/percona_query_cache_with_comments_eval.inc | ||
1118 | 854 | --- /dev/null | 594 | --- /dev/null |
1119 | 855 | +++ b/mysql-test/include/percona_query_cache_with_comments_begin.inc | 595 | +++ b/mysql-test/include/percona_query_cache_with_comments_begin.inc |
1120 | 856 | @@ -0,0 +1,12 @@ | 596 | @@ -0,0 +1,12 @@ |
1121 | @@ -903,7 +643,7 @@ | |||
1122 | 903 | + | 643 | + |
1123 | 904 | --- /dev/null | 644 | --- /dev/null |
1124 | 905 | +++ b/mysql-test/r/percona_query_cache_with_comments.result | 645 | +++ b/mysql-test/r/percona_query_cache_with_comments.result |
1126 | 906 | @@ -0,0 +1,1058 @@ | 646 | @@ -0,0 +1,866 @@ |
1127 | 907 | +set global query_cache_strip_comments=ON; | 647 | +set global query_cache_strip_comments=ON; |
1128 | 908 | +set GLOBAL query_cache_size=1355776; | 648 | +set GLOBAL query_cache_size=1355776; |
1129 | 909 | +drop table if exists t1; | 649 | +drop table if exists t1; |
1130 | @@ -1737,228 +1477,36 @@ | |||
1131 | 1737 | +Variable_name Value | 1477 | +Variable_name Value |
1132 | 1738 | +Qcache_hits 50 | 1478 | +Qcache_hits 50 |
1133 | 1739 | +----------------------------------------------------- | 1479 | +----------------------------------------------------- |
1134 | 1740 | +select */* a comment \*/from t1 | ||
1135 | 1741 | +----------------------------------------------------- | ||
1136 | 1742 | +show status like "Qcache_queries_in_cache"; | ||
1137 | 1743 | +Variable_name Value | ||
1138 | 1744 | +Qcache_queries_in_cache 1 | ||
1139 | 1745 | +show status like "Qcache_inserts"; | ||
1140 | 1746 | +Variable_name Value | ||
1141 | 1747 | +Qcache_inserts 1 | ||
1142 | 1748 | +show status like "Qcache_hits"; | ||
1143 | 1749 | +Variable_name Value | ||
1144 | 1750 | +Qcache_hits 50 | ||
1145 | 1751 | +select */* a comment \*/from t1; | ||
1146 | 1752 | +a | ||
1147 | 1753 | +1 | ||
1148 | 1754 | +2 | ||
1149 | 1755 | +3 | ||
1150 | 1756 | +select */* a comment \*/from t1; | ||
1151 | 1757 | +a | ||
1152 | 1758 | +1 | ||
1153 | 1759 | +2 | ||
1154 | 1760 | +3 | ||
1155 | 1761 | +show status like "Qcache_queries_in_cache"; | ||
1156 | 1762 | +Variable_name Value | ||
1157 | 1763 | +Qcache_queries_in_cache 1 | ||
1158 | 1764 | +show status like "Qcache_inserts"; | ||
1159 | 1765 | +Variable_name Value | ||
1160 | 1766 | +Qcache_inserts 1 | ||
1161 | 1767 | +show status like "Qcache_hits"; | ||
1162 | 1768 | +Variable_name Value | ||
1163 | 1769 | +Qcache_hits 52 | ||
1164 | 1770 | +----------------------------------------------------- | ||
1165 | 1771 | +select *# a comment \ | ||
1166 | 1772 | +from t1 | ||
1167 | 1773 | +----------------------------------------------------- | ||
1168 | 1774 | +show status like "Qcache_queries_in_cache"; | ||
1169 | 1775 | +Variable_name Value | ||
1170 | 1776 | +Qcache_queries_in_cache 1 | ||
1171 | 1777 | +show status like "Qcache_inserts"; | ||
1172 | 1778 | +Variable_name Value | ||
1173 | 1779 | +Qcache_inserts 1 | ||
1174 | 1780 | +show status like "Qcache_hits"; | ||
1175 | 1781 | +Variable_name Value | ||
1176 | 1782 | +Qcache_hits 52 | ||
1177 | 1783 | +select *# a comment \ | ||
1178 | 1784 | +from t1; | ||
1179 | 1785 | +a | ||
1180 | 1786 | +1 | ||
1181 | 1787 | +2 | ||
1182 | 1788 | +3 | ||
1183 | 1789 | +select *# a comment \ | ||
1184 | 1790 | +from t1; | ||
1185 | 1791 | +a | ||
1186 | 1792 | +1 | ||
1187 | 1793 | +2 | ||
1188 | 1794 | +3 | ||
1189 | 1795 | +show status like "Qcache_queries_in_cache"; | ||
1190 | 1796 | +Variable_name Value | ||
1191 | 1797 | +Qcache_queries_in_cache 1 | ||
1192 | 1798 | +show status like "Qcache_inserts"; | ||
1193 | 1799 | +Variable_name Value | ||
1194 | 1800 | +Qcache_inserts 1 | ||
1195 | 1801 | +show status like "Qcache_hits"; | ||
1196 | 1802 | +Variable_name Value | ||
1197 | 1803 | +Qcache_hits 54 | ||
1198 | 1804 | +----------------------------------------------------- | ||
1199 | 1805 | +select *-- a comment \ | ||
1200 | 1806 | +from t1 | ||
1201 | 1807 | +----------------------------------------------------- | ||
1202 | 1808 | +show status like "Qcache_queries_in_cache"; | ||
1203 | 1809 | +Variable_name Value | ||
1204 | 1810 | +Qcache_queries_in_cache 1 | ||
1205 | 1811 | +show status like "Qcache_inserts"; | ||
1206 | 1812 | +Variable_name Value | ||
1207 | 1813 | +Qcache_inserts 1 | ||
1208 | 1814 | +show status like "Qcache_hits"; | ||
1209 | 1815 | +Variable_name Value | ||
1210 | 1816 | +Qcache_hits 54 | ||
1211 | 1817 | +select *-- a comment \ | ||
1212 | 1818 | +from t1; | ||
1213 | 1819 | +a | ||
1214 | 1820 | +1 | ||
1215 | 1821 | +2 | ||
1216 | 1822 | +3 | ||
1217 | 1823 | +select *-- a comment \ | ||
1218 | 1824 | +from t1; | ||
1219 | 1825 | +a | ||
1220 | 1826 | +1 | ||
1221 | 1827 | +2 | ||
1222 | 1828 | +3 | ||
1223 | 1829 | +show status like "Qcache_queries_in_cache"; | ||
1224 | 1830 | +Variable_name Value | ||
1225 | 1831 | +Qcache_queries_in_cache 1 | ||
1226 | 1832 | +show status like "Qcache_inserts"; | ||
1227 | 1833 | +Variable_name Value | ||
1228 | 1834 | +Qcache_inserts 1 | ||
1229 | 1835 | +show status like "Qcache_hits"; | ||
1230 | 1836 | +Variable_name Value | ||
1231 | 1837 | +Qcache_hits 56 | ||
1232 | 1838 | +----------------------------------------------------- | ||
1233 | 1839 | +select "\\"" /* not a comment */" from t1 | ||
1234 | 1840 | +----------------------------------------------------- | ||
1235 | 1841 | +show status like "Qcache_queries_in_cache"; | ||
1236 | 1842 | +Variable_name Value | ||
1237 | 1843 | +Qcache_queries_in_cache 1 | ||
1238 | 1844 | +show status like "Qcache_inserts"; | ||
1239 | 1845 | +Variable_name Value | ||
1240 | 1846 | +Qcache_inserts 1 | ||
1241 | 1847 | +show status like "Qcache_hits"; | ||
1242 | 1848 | +Variable_name Value | ||
1243 | 1849 | +Qcache_hits 56 | ||
1244 | 1850 | +select "\\"" /* not a comment */" from t1; | ||
1245 | 1851 | +\" /* not a comment */ | ||
1246 | 1852 | +\" /* not a comment */ | ||
1247 | 1853 | +\" /* not a comment */ | ||
1248 | 1854 | +\" /* not a comment */ | ||
1249 | 1855 | +select "\\"" /* not a comment */" from t1; | ||
1250 | 1856 | +\" /* not a comment */ | ||
1251 | 1857 | +\" /* not a comment */ | ||
1252 | 1858 | +\" /* not a comment */ | ||
1253 | 1859 | +\" /* not a comment */ | ||
1254 | 1860 | +show status like "Qcache_queries_in_cache"; | ||
1255 | 1861 | +Variable_name Value | ||
1256 | 1862 | +Qcache_queries_in_cache 2 | ||
1257 | 1863 | +show status like "Qcache_inserts"; | ||
1258 | 1864 | +Variable_name Value | ||
1259 | 1865 | +Qcache_inserts 2 | ||
1260 | 1866 | +show status like "Qcache_hits"; | ||
1261 | 1867 | +Variable_name Value | ||
1262 | 1868 | +Qcache_hits 57 | ||
1263 | 1869 | +----------------------------------------------------- | ||
1264 | 1870 | +select "\\"" /*! not a comment */" from t1 | ||
1265 | 1871 | +----------------------------------------------------- | ||
1266 | 1872 | +show status like "Qcache_queries_in_cache"; | ||
1267 | 1873 | +Variable_name Value | ||
1268 | 1874 | +Qcache_queries_in_cache 2 | ||
1269 | 1875 | +show status like "Qcache_inserts"; | ||
1270 | 1876 | +Variable_name Value | ||
1271 | 1877 | +Qcache_inserts 2 | ||
1272 | 1878 | +show status like "Qcache_hits"; | ||
1273 | 1879 | +Variable_name Value | ||
1274 | 1880 | +Qcache_hits 57 | ||
1275 | 1881 | +select "\\"" /*! not a comment */" from t1; | ||
1276 | 1882 | +\" /*! not a comment */ | ||
1277 | 1883 | +\" /*! not a comment */ | ||
1278 | 1884 | +\" /*! not a comment */ | ||
1279 | 1885 | +\" /*! not a comment */ | ||
1280 | 1886 | +select "\\"" /*! not a comment */" from t1; | ||
1281 | 1887 | +\" /*! not a comment */ | ||
1282 | 1888 | +\" /*! not a comment */ | ||
1283 | 1889 | +\" /*! not a comment */ | ||
1284 | 1890 | +\" /*! not a comment */ | ||
1285 | 1891 | +show status like "Qcache_queries_in_cache"; | ||
1286 | 1892 | +Variable_name Value | ||
1287 | 1893 | +Qcache_queries_in_cache 3 | ||
1288 | 1894 | +show status like "Qcache_inserts"; | ||
1289 | 1895 | +Variable_name Value | ||
1290 | 1896 | +Qcache_inserts 3 | ||
1291 | 1897 | +show status like "Qcache_hits"; | ||
1292 | 1898 | +Variable_name Value | ||
1293 | 1899 | +Qcache_hits 58 | ||
1294 | 1900 | +----------------------------------------------------- | ||
1295 | 1901 | +select ' \' ' from t1 | 1480 | +select ' \' ' from t1 |
1296 | 1902 | +----------------------------------------------------- | 1481 | +----------------------------------------------------- |
1297 | 1903 | +show status like "Qcache_queries_in_cache"; | 1482 | +show status like "Qcache_queries_in_cache"; |
1298 | 1904 | +Variable_name Value | 1483 | +Variable_name Value |
1356 | 1905 | +Qcache_queries_in_cache 3 | 1484 | +Qcache_queries_in_cache 1 |
1357 | 1906 | +show status like "Qcache_inserts"; | 1485 | +show status like "Qcache_inserts"; |
1358 | 1907 | +Variable_name Value | 1486 | +Variable_name Value |
1359 | 1908 | +Qcache_inserts 3 | 1487 | +Qcache_inserts 1 |
1360 | 1909 | +show status like "Qcache_hits"; | 1488 | +show status like "Qcache_hits"; |
1361 | 1910 | +Variable_name Value | 1489 | +Variable_name Value |
1362 | 1911 | +Qcache_hits 58 | 1490 | +Qcache_hits 50 |
1363 | 1912 | +select ' \' ' from t1; | 1491 | +select ' \' ' from t1; |
1364 | 1913 | +' | 1492 | +' |
1365 | 1914 | + ' | 1493 | + ' |
1366 | 1915 | + ' | 1494 | + ' |
1367 | 1916 | + ' | 1495 | + ' |
1368 | 1917 | +select ' \' ' from t1; | 1496 | +select ' \' ' from t1; |
1369 | 1918 | +' | 1497 | +' |
1370 | 1919 | + ' | 1498 | + ' |
1371 | 1920 | + ' | 1499 | + ' |
1372 | 1921 | + ' | 1500 | + ' |
1373 | 1922 | +show status like "Qcache_queries_in_cache"; | 1501 | +show status like "Qcache_queries_in_cache"; |
1374 | 1923 | +Variable_name Value | 1502 | +Variable_name Value |
1375 | 1924 | +Qcache_queries_in_cache 4 | 1503 | +Qcache_queries_in_cache 2 |
1376 | 1925 | +show status like "Qcache_inserts"; | 1504 | +show status like "Qcache_inserts"; |
1377 | 1926 | +Variable_name Value | 1505 | +Variable_name Value |
1378 | 1927 | +Qcache_inserts 4 | 1506 | +Qcache_inserts 2 |
1379 | 1928 | +show status like "Qcache_hits"; | 1507 | +show status like "Qcache_hits"; |
1380 | 1929 | +Variable_name Value | 1508 | +Variable_name Value |
1381 | 1930 | +Qcache_hits 59 | 1509 | +Qcache_hits 51 |
1325 | 1931 | +----------------------------------------------------- | ||
1326 | 1932 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1 | ||
1327 | 1933 | +----------------------------------------------------- | ||
1328 | 1934 | +show status like "Qcache_queries_in_cache"; | ||
1329 | 1935 | +Variable_name Value | ||
1330 | 1936 | +Qcache_queries_in_cache 4 | ||
1331 | 1937 | +show status like "Qcache_inserts"; | ||
1332 | 1938 | +Variable_name Value | ||
1333 | 1939 | +Qcache_inserts 4 | ||
1334 | 1940 | +show status like "Qcache_hits"; | ||
1335 | 1941 | +Variable_name Value | ||
1336 | 1942 | +Qcache_hits 59 | ||
1337 | 1943 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1; | ||
1338 | 1944 | +' /* comment inside quotes with internal backslash quote */ | ||
1339 | 1945 | + ' /* comment inside quotes with internal backslash quote */ | ||
1340 | 1946 | + ' /* comment inside quotes with internal backslash quote */ | ||
1341 | 1947 | + ' /* comment inside quotes with internal backslash quote */ | ||
1342 | 1948 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1; | ||
1343 | 1949 | +' /* comment inside quotes with internal backslash quote */ | ||
1344 | 1950 | + ' /* comment inside quotes with internal backslash quote */ | ||
1345 | 1951 | + ' /* comment inside quotes with internal backslash quote */ | ||
1346 | 1952 | + ' /* comment inside quotes with internal backslash quote */ | ||
1347 | 1953 | +show status like "Qcache_queries_in_cache"; | ||
1348 | 1954 | +Variable_name Value | ||
1349 | 1955 | +Qcache_queries_in_cache 5 | ||
1350 | 1956 | +show status like "Qcache_inserts"; | ||
1351 | 1957 | +Variable_name Value | ||
1352 | 1958 | +Qcache_inserts 5 | ||
1353 | 1959 | +show status like "Qcache_hits"; | ||
1354 | 1960 | +Variable_name Value | ||
1355 | 1961 | +Qcache_hits 60 | ||
1382 | 1962 | +DROP TABLE t1; | 1510 | +DROP TABLE t1; |
1383 | 1963 | +SET GLOBAL query_cache_size=default; | 1511 | +SET GLOBAL query_cache_size=default; |
1384 | 1964 | +set global query_cache_strip_comments=OFF; | 1512 | +set global query_cache_strip_comments=OFF; |
1385 | @@ -1988,7 +1536,7 @@ | |||
1386 | 1988 | +SET GLOBAL query_cache_size= default; | 1536 | +SET GLOBAL query_cache_size= default; |
1387 | 1989 | --- /dev/null | 1537 | --- /dev/null |
1388 | 1990 | +++ b/mysql-test/r/percona_query_cache_with_comments_disable.result | 1538 | +++ b/mysql-test/r/percona_query_cache_with_comments_disable.result |
1390 | 1991 | @@ -0,0 +1,1057 @@ | 1539 | @@ -0,0 +1,865 @@ |
1391 | 1992 | +set GLOBAL query_cache_size=1355776; | 1540 | +set GLOBAL query_cache_size=1355776; |
1392 | 1993 | +drop table if exists t1; | 1541 | +drop table if exists t1; |
1393 | 1994 | +create table t1 (a int not null); | 1542 | +create table t1 (a int not null); |
1394 | @@ -2821,228 +2369,36 @@ | |||
1395 | 2821 | +Variable_name Value | 2369 | +Variable_name Value |
1396 | 2822 | +Qcache_hits 25 | 2370 | +Qcache_hits 25 |
1397 | 2823 | +----------------------------------------------------- | 2371 | +----------------------------------------------------- |
1398 | 2824 | +select */* a comment \*/from t1 | ||
1399 | 2825 | +----------------------------------------------------- | ||
1400 | 2826 | +show status like "Qcache_queries_in_cache"; | ||
1401 | 2827 | +Variable_name Value | ||
1402 | 2828 | +Qcache_queries_in_cache 20 | ||
1403 | 2829 | +show status like "Qcache_inserts"; | ||
1404 | 2830 | +Variable_name Value | ||
1405 | 2831 | +Qcache_inserts 20 | ||
1406 | 2832 | +show status like "Qcache_hits"; | ||
1407 | 2833 | +Variable_name Value | ||
1408 | 2834 | +Qcache_hits 25 | ||
1409 | 2835 | +select */* a comment \*/from t1; | ||
1410 | 2836 | +a | ||
1411 | 2837 | +1 | ||
1412 | 2838 | +2 | ||
1413 | 2839 | +3 | ||
1414 | 2840 | +select */* a comment \*/from t1; | ||
1415 | 2841 | +a | ||
1416 | 2842 | +1 | ||
1417 | 2843 | +2 | ||
1418 | 2844 | +3 | ||
1419 | 2845 | +show status like "Qcache_queries_in_cache"; | ||
1420 | 2846 | +Variable_name Value | ||
1421 | 2847 | +Qcache_queries_in_cache 21 | ||
1422 | 2848 | +show status like "Qcache_inserts"; | ||
1423 | 2849 | +Variable_name Value | ||
1424 | 2850 | +Qcache_inserts 21 | ||
1425 | 2851 | +show status like "Qcache_hits"; | ||
1426 | 2852 | +Variable_name Value | ||
1427 | 2853 | +Qcache_hits 26 | ||
1428 | 2854 | +----------------------------------------------------- | ||
1429 | 2855 | +select *# a comment \ | ||
1430 | 2856 | +from t1 | ||
1431 | 2857 | +----------------------------------------------------- | ||
1432 | 2858 | +show status like "Qcache_queries_in_cache"; | ||
1433 | 2859 | +Variable_name Value | ||
1434 | 2860 | +Qcache_queries_in_cache 21 | ||
1435 | 2861 | +show status like "Qcache_inserts"; | ||
1436 | 2862 | +Variable_name Value | ||
1437 | 2863 | +Qcache_inserts 21 | ||
1438 | 2864 | +show status like "Qcache_hits"; | ||
1439 | 2865 | +Variable_name Value | ||
1440 | 2866 | +Qcache_hits 26 | ||
1441 | 2867 | +select *# a comment \ | ||
1442 | 2868 | +from t1; | ||
1443 | 2869 | +a | ||
1444 | 2870 | +1 | ||
1445 | 2871 | +2 | ||
1446 | 2872 | +3 | ||
1447 | 2873 | +select *# a comment \ | ||
1448 | 2874 | +from t1; | ||
1449 | 2875 | +a | ||
1450 | 2876 | +1 | ||
1451 | 2877 | +2 | ||
1452 | 2878 | +3 | ||
1453 | 2879 | +show status like "Qcache_queries_in_cache"; | ||
1454 | 2880 | +Variable_name Value | ||
1455 | 2881 | +Qcache_queries_in_cache 22 | ||
1456 | 2882 | +show status like "Qcache_inserts"; | ||
1457 | 2883 | +Variable_name Value | ||
1458 | 2884 | +Qcache_inserts 22 | ||
1459 | 2885 | +show status like "Qcache_hits"; | ||
1460 | 2886 | +Variable_name Value | ||
1461 | 2887 | +Qcache_hits 27 | ||
1462 | 2888 | +----------------------------------------------------- | ||
1463 | 2889 | +select *-- a comment \ | ||
1464 | 2890 | +from t1 | ||
1465 | 2891 | +----------------------------------------------------- | ||
1466 | 2892 | +show status like "Qcache_queries_in_cache"; | ||
1467 | 2893 | +Variable_name Value | ||
1468 | 2894 | +Qcache_queries_in_cache 22 | ||
1469 | 2895 | +show status like "Qcache_inserts"; | ||
1470 | 2896 | +Variable_name Value | ||
1471 | 2897 | +Qcache_inserts 22 | ||
1472 | 2898 | +show status like "Qcache_hits"; | ||
1473 | 2899 | +Variable_name Value | ||
1474 | 2900 | +Qcache_hits 27 | ||
1475 | 2901 | +select *-- a comment \ | ||
1476 | 2902 | +from t1; | ||
1477 | 2903 | +a | ||
1478 | 2904 | +1 | ||
1479 | 2905 | +2 | ||
1480 | 2906 | +3 | ||
1481 | 2907 | +select *-- a comment \ | ||
1482 | 2908 | +from t1; | ||
1483 | 2909 | +a | ||
1484 | 2910 | +1 | ||
1485 | 2911 | +2 | ||
1486 | 2912 | +3 | ||
1487 | 2913 | +show status like "Qcache_queries_in_cache"; | ||
1488 | 2914 | +Variable_name Value | ||
1489 | 2915 | +Qcache_queries_in_cache 23 | ||
1490 | 2916 | +show status like "Qcache_inserts"; | ||
1491 | 2917 | +Variable_name Value | ||
1492 | 2918 | +Qcache_inserts 23 | ||
1493 | 2919 | +show status like "Qcache_hits"; | ||
1494 | 2920 | +Variable_name Value | ||
1495 | 2921 | +Qcache_hits 28 | ||
1496 | 2922 | +----------------------------------------------------- | ||
1497 | 2923 | +select "\\"" /* not a comment */" from t1 | ||
1498 | 2924 | +----------------------------------------------------- | ||
1499 | 2925 | +show status like "Qcache_queries_in_cache"; | ||
1500 | 2926 | +Variable_name Value | ||
1501 | 2927 | +Qcache_queries_in_cache 23 | ||
1502 | 2928 | +show status like "Qcache_inserts"; | ||
1503 | 2929 | +Variable_name Value | ||
1504 | 2930 | +Qcache_inserts 23 | ||
1505 | 2931 | +show status like "Qcache_hits"; | ||
1506 | 2932 | +Variable_name Value | ||
1507 | 2933 | +Qcache_hits 28 | ||
1508 | 2934 | +select "\\"" /* not a comment */" from t1; | ||
1509 | 2935 | +\" /* not a comment */ | ||
1510 | 2936 | +\" /* not a comment */ | ||
1511 | 2937 | +\" /* not a comment */ | ||
1512 | 2938 | +\" /* not a comment */ | ||
1513 | 2939 | +select "\\"" /* not a comment */" from t1; | ||
1514 | 2940 | +\" /* not a comment */ | ||
1515 | 2941 | +\" /* not a comment */ | ||
1516 | 2942 | +\" /* not a comment */ | ||
1517 | 2943 | +\" /* not a comment */ | ||
1518 | 2944 | +show status like "Qcache_queries_in_cache"; | ||
1519 | 2945 | +Variable_name Value | ||
1520 | 2946 | +Qcache_queries_in_cache 24 | ||
1521 | 2947 | +show status like "Qcache_inserts"; | ||
1522 | 2948 | +Variable_name Value | ||
1523 | 2949 | +Qcache_inserts 24 | ||
1524 | 2950 | +show status like "Qcache_hits"; | ||
1525 | 2951 | +Variable_name Value | ||
1526 | 2952 | +Qcache_hits 29 | ||
1527 | 2953 | +----------------------------------------------------- | ||
1528 | 2954 | +select "\\"" /*! not a comment */" from t1 | ||
1529 | 2955 | +----------------------------------------------------- | ||
1530 | 2956 | +show status like "Qcache_queries_in_cache"; | ||
1531 | 2957 | +Variable_name Value | ||
1532 | 2958 | +Qcache_queries_in_cache 24 | ||
1533 | 2959 | +show status like "Qcache_inserts"; | ||
1534 | 2960 | +Variable_name Value | ||
1535 | 2961 | +Qcache_inserts 24 | ||
1536 | 2962 | +show status like "Qcache_hits"; | ||
1537 | 2963 | +Variable_name Value | ||
1538 | 2964 | +Qcache_hits 29 | ||
1539 | 2965 | +select "\\"" /*! not a comment */" from t1; | ||
1540 | 2966 | +\" /*! not a comment */ | ||
1541 | 2967 | +\" /*! not a comment */ | ||
1542 | 2968 | +\" /*! not a comment */ | ||
1543 | 2969 | +\" /*! not a comment */ | ||
1544 | 2970 | +select "\\"" /*! not a comment */" from t1; | ||
1545 | 2971 | +\" /*! not a comment */ | ||
1546 | 2972 | +\" /*! not a comment */ | ||
1547 | 2973 | +\" /*! not a comment */ | ||
1548 | 2974 | +\" /*! not a comment */ | ||
1549 | 2975 | +show status like "Qcache_queries_in_cache"; | ||
1550 | 2976 | +Variable_name Value | ||
1551 | 2977 | +Qcache_queries_in_cache 25 | ||
1552 | 2978 | +show status like "Qcache_inserts"; | ||
1553 | 2979 | +Variable_name Value | ||
1554 | 2980 | +Qcache_inserts 25 | ||
1555 | 2981 | +show status like "Qcache_hits"; | ||
1556 | 2982 | +Variable_name Value | ||
1557 | 2983 | +Qcache_hits 30 | ||
1558 | 2984 | +----------------------------------------------------- | ||
1559 | 2985 | +select ' \' ' from t1 | 2372 | +select ' \' ' from t1 |
1560 | 2986 | +----------------------------------------------------- | 2373 | +----------------------------------------------------- |
1561 | 2987 | +show status like "Qcache_queries_in_cache"; | 2374 | +show status like "Qcache_queries_in_cache"; |
1562 | 2988 | +Variable_name Value | 2375 | +Variable_name Value |
1620 | 2989 | +Qcache_queries_in_cache 25 | 2376 | +Qcache_queries_in_cache 20 |
1621 | 2990 | +show status like "Qcache_inserts"; | 2377 | +show status like "Qcache_inserts"; |
1622 | 2991 | +Variable_name Value | 2378 | +Variable_name Value |
1623 | 2992 | +Qcache_inserts 25 | 2379 | +Qcache_inserts 20 |
1624 | 2993 | +show status like "Qcache_hits"; | 2380 | +show status like "Qcache_hits"; |
1625 | 2994 | +Variable_name Value | 2381 | +Variable_name Value |
1626 | 2995 | +Qcache_hits 30 | 2382 | +Qcache_hits 25 |
1627 | 2996 | +select ' \' ' from t1; | 2383 | +select ' \' ' from t1; |
1628 | 2997 | +' | 2384 | +' |
1629 | 2998 | + ' | 2385 | + ' |
1630 | 2999 | + ' | 2386 | + ' |
1631 | 3000 | + ' | 2387 | + ' |
1632 | 3001 | +select ' \' ' from t1; | 2388 | +select ' \' ' from t1; |
1633 | 3002 | +' | 2389 | +' |
1634 | 3003 | + ' | 2390 | + ' |
1635 | 3004 | + ' | 2391 | + ' |
1636 | 3005 | + ' | 2392 | + ' |
1637 | 3006 | +show status like "Qcache_queries_in_cache"; | 2393 | +show status like "Qcache_queries_in_cache"; |
1638 | 3007 | +Variable_name Value | 2394 | +Variable_name Value |
1639 | 3008 | +Qcache_queries_in_cache 26 | 2395 | +Qcache_queries_in_cache 21 |
1640 | 3009 | +show status like "Qcache_inserts"; | 2396 | +show status like "Qcache_inserts"; |
1641 | 3010 | +Variable_name Value | 2397 | +Variable_name Value |
1642 | 3011 | +Qcache_inserts 26 | 2398 | +Qcache_inserts 21 |
1643 | 3012 | +show status like "Qcache_hits"; | 2399 | +show status like "Qcache_hits"; |
1644 | 3013 | +Variable_name Value | 2400 | +Variable_name Value |
1645 | 3014 | +Qcache_hits 31 | 2401 | +Qcache_hits 26 |
1589 | 3015 | +----------------------------------------------------- | ||
1590 | 3016 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1 | ||
1591 | 3017 | +----------------------------------------------------- | ||
1592 | 3018 | +show status like "Qcache_queries_in_cache"; | ||
1593 | 3019 | +Variable_name Value | ||
1594 | 3020 | +Qcache_queries_in_cache 26 | ||
1595 | 3021 | +show status like "Qcache_inserts"; | ||
1596 | 3022 | +Variable_name Value | ||
1597 | 3023 | +Qcache_inserts 26 | ||
1598 | 3024 | +show status like "Qcache_hits"; | ||
1599 | 3025 | +Variable_name Value | ||
1600 | 3026 | +Qcache_hits 31 | ||
1601 | 3027 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1; | ||
1602 | 3028 | +' /* comment inside quotes with internal backslash quote */ | ||
1603 | 3029 | + ' /* comment inside quotes with internal backslash quote */ | ||
1604 | 3030 | + ' /* comment inside quotes with internal backslash quote */ | ||
1605 | 3031 | + ' /* comment inside quotes with internal backslash quote */ | ||
1606 | 3032 | +select ' \' /* comment inside quotes with internal backslash quote */' from t1; | ||
1607 | 3033 | +' /* comment inside quotes with internal backslash quote */ | ||
1608 | 3034 | + ' /* comment inside quotes with internal backslash quote */ | ||
1609 | 3035 | + ' /* comment inside quotes with internal backslash quote */ | ||
1610 | 3036 | + ' /* comment inside quotes with internal backslash quote */ | ||
1611 | 3037 | +show status like "Qcache_queries_in_cache"; | ||
1612 | 3038 | +Variable_name Value | ||
1613 | 3039 | +Qcache_queries_in_cache 27 | ||
1614 | 3040 | +show status like "Qcache_inserts"; | ||
1615 | 3041 | +Variable_name Value | ||
1616 | 3042 | +Qcache_inserts 27 | ||
1617 | 3043 | +show status like "Qcache_hits"; | ||
1618 | 3044 | +Variable_name Value | ||
1619 | 3045 | +Qcache_hits 32 | ||
1646 | 3046 | +DROP TABLE t1; | 2402 | +DROP TABLE t1; |
1647 | 3047 | +SET GLOBAL query_cache_size=default; | 2403 | +SET GLOBAL query_cache_size=default; |
1648 | 3048 | +set global query_cache_strip_comments=OFF; | 2404 | +set global query_cache_strip_comments=OFF; |
1649 | @@ -3735,7 +3091,7 @@ | |||
1650 | 3735 | +SET GLOBAL query_cache_size=0; | 3091 | +SET GLOBAL query_cache_size=0; |
1651 | 3736 | --- a/mysql-test/r/mysqld--help-notwin.result | 3092 | --- a/mysql-test/r/mysqld--help-notwin.result |
1652 | 3737 | +++ b/mysql-test/r/mysqld--help-notwin.result | 3093 | +++ b/mysql-test/r/mysqld--help-notwin.result |
1654 | 3738 | @@ -493,6 +493,10 @@ | 3094 | @@ -500,6 +500,10 @@ |
1655 | 3739 | The minimum size for blocks allocated by the query cache | 3095 | The minimum size for blocks allocated by the query cache |
1656 | 3740 | --query-cache-size=# | 3096 | --query-cache-size=# |
1657 | 3741 | The memory allocated to store results from old queries | 3097 | The memory allocated to store results from old queries |
1658 | @@ -3746,7 +3102,7 @@ | |||
1659 | 3746 | --query-cache-type=name | 3102 | --query-cache-type=name |
1660 | 3747 | OFF = Don't cache or retrieve results. ON = Cache all | 3103 | OFF = Don't cache or retrieve results. ON = Cache all |
1661 | 3748 | results except SELECT SQL_NO_CACHE ... queries. DEMAND = | 3104 | results except SELECT SQL_NO_CACHE ... queries. DEMAND = |
1663 | 3749 | @@ -931,6 +935,7 @@ | 3105 | @@ -942,6 +946,7 @@ |
1664 | 3750 | query-cache-limit 1048576 | 3106 | query-cache-limit 1048576 |
1665 | 3751 | query-cache-min-res-unit 4096 | 3107 | query-cache-min-res-unit 4096 |
1666 | 3752 | query-cache-size 0 | 3108 | query-cache-size 0 |
1667 | @@ -3778,7 +3134,7 @@ | |||
1668 | 3778 | +try_lock_mutex_query | 3134 | +try_lock_mutex_query |
1669 | 3779 | +SET GLOBAL query_cache_size=0; | 3135 | +SET GLOBAL query_cache_size=0; |
1670 | 3780 | --- /dev/null | 3136 | --- /dev/null |
1672 | 3781 | +++ b/mysql-test/r/percona_query_cache_with_comments_crash_2.result | 3137 | +++ b/mysql-test/r/percona_bug856404.result |
1673 | 3782 | @@ -0,0 +1,8 @@ | 3138 | @@ -0,0 +1,8 @@ |
1674 | 3783 | +DROP TABLE IF EXISTS table17_int; | 3139 | +DROP TABLE IF EXISTS table17_int; |
1675 | 3784 | +DROP TABLE IF EXISTS table30_int; | 3140 | +DROP TABLE IF EXISTS table30_int; |
1676 | @@ -3789,120 +3145,24 @@ | |||
1677 | 3789 | +DROP TABLE table17_int; | 3145 | +DROP TABLE table17_int; |
1678 | 3790 | +DROP TABLE table30_int; | 3146 | +DROP TABLE table30_int; |
1679 | 3791 | --- /dev/null | 3147 | --- /dev/null |
1681 | 3792 | +++ b/mysql-test/t/percona_query_cache_with_comments_crash_2-master.opt | 3148 | +++ b/mysql-test/t/percona_bug856404-master.opt |
1682 | 3793 | @@ -0,0 +1 @@ | 3149 | @@ -0,0 +1 @@ |
1683 | 3794 | +--query-cache-size=10M --query-cache-strip-comments | 3150 | +--query-cache-size=10M --query-cache-strip-comments |
1684 | 3795 | --- /dev/null | 3151 | --- /dev/null |
1687 | 3796 | +++ b/mysql-test/t/percona_query_cache_with_comments_crash_2.test | 3152 | +++ b/mysql-test/t/percona_bug856404.test |
1688 | 3797 | @@ -0,0 +1,9 @@ | 3153 | @@ -0,0 +1,15 @@ |
1689 | 3154 | +######################################################################## | ||
1690 | 3155 | +# Bug #856404: Crash when query_cache_strip_comments enabled | ||
1691 | 3156 | +######################################################################## | ||
1692 | 3157 | + | ||
1693 | 3798 | +--disable_warnings | 3158 | +--disable_warnings |
1694 | 3799 | +DROP TABLE IF EXISTS table17_int; | 3159 | +DROP TABLE IF EXISTS table17_int; |
1695 | 3800 | +DROP TABLE IF EXISTS table30_int; | 3160 | +DROP TABLE IF EXISTS table30_int; |
1696 | 3801 | +--enable_warnings | 3161 | +--enable_warnings |
1697 | 3162 | + | ||
1698 | 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); | 3163 | +CREATE TABLE `table17_int` (pk integer auto_increment primary key, `col_char_10_not_null_key` char(10), `col_enum_not_null_key` int); |
1699 | 3803 | +CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int); | 3164 | +CREATE TABLE `table30_int` (pk integer auto_increment primary key, `col_enum_not_null_key` int); |
1700 | 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*/; | 3165 | +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*/; |
1701 | 3166 | + | ||
1702 | 3805 | +DROP TABLE table17_int; | 3167 | +DROP TABLE table17_int; |
1703 | 3806 | +DROP TABLE table30_int; | 3168 | +DROP TABLE table30_int; |
1704 | 3807 | --- a/sql/sql_class.cc | ||
1705 | 3808 | +++ b/sql/sql_class.cc | ||
1706 | 3809 | @@ -807,6 +807,99 @@ | ||
1707 | 3810 | sql_errno == ER_TRG_NO_DEFINER); | ||
1708 | 3811 | } | ||
1709 | 3812 | |||
1710 | 3813 | +#ifdef HAVE_QUERY_CACHE | ||
1711 | 3814 | + | ||
1712 | 3815 | + | ||
1713 | 3816 | +Query_Without_Comments::Query_Without_Comments() : | ||
1714 | 3817 | + buffer(0), | ||
1715 | 3818 | + q_length(0), | ||
1716 | 3819 | + b_length(0) | ||
1717 | 3820 | +{ | ||
1718 | 3821 | +} | ||
1719 | 3822 | + | ||
1720 | 3823 | + | ||
1721 | 3824 | +Query_Without_Comments::~Query_Without_Comments() | ||
1722 | 3825 | +{ | ||
1723 | 3826 | + if(buffer) | ||
1724 | 3827 | + { | ||
1725 | 3828 | + my_free(buffer); | ||
1726 | 3829 | + } | ||
1727 | 3830 | +} | ||
1728 | 3831 | + | ||
1729 | 3832 | + | ||
1730 | 3833 | +bool Query_Without_Comments::allocate(size_t query_length, size_t db_length) | ||
1731 | 3834 | +{ | ||
1732 | 3835 | + DBUG_ENTER("Query_Without_Comments::allocate"); | ||
1733 | 3836 | + DBUG_PRINT("info", ("old buffer: %p " | ||
1734 | 3837 | + "old query: '%-.4096s' " | ||
1735 | 3838 | + "old buffer length: %u " | ||
1736 | 3839 | + "old query length: %u", | ||
1737 | 3840 | + buffer, | ||
1738 | 3841 | + buffer, | ||
1739 | 3842 | + (uint) b_length, | ||
1740 | 3843 | + (uint) q_length)); | ||
1741 | 3844 | + /* save maximum query length for check in the set_length */ | ||
1742 | 3845 | + q_length= query_length; | ||
1743 | 3846 | + /* according to sql_parse.cc memory allocation */ | ||
1744 | 3847 | + size_t new_b_length= (query_length + 1) + sizeof(size_t) + db_length + | ||
1745 | 3848 | + QUERY_CACHE_FLAGS_SIZE; | ||
1746 | 3849 | + if (b_length < new_b_length) | ||
1747 | 3850 | + { | ||
1748 | 3851 | + b_length= new_b_length; | ||
1749 | 3852 | + if (buffer) | ||
1750 | 3853 | + { | ||
1751 | 3854 | + buffer= (char*) my_realloc(buffer, b_length, MYF(0)); | ||
1752 | 3855 | + } | ||
1753 | 3856 | + else | ||
1754 | 3857 | + { | ||
1755 | 3858 | + buffer= (char *) my_malloc(b_length, MYF(0)); | ||
1756 | 3859 | + } | ||
1757 | 3860 | + } | ||
1758 | 3861 | + buffer[0]= 0; | ||
1759 | 3862 | + DBUG_PRINT("info", ("buffer: %p " | ||
1760 | 3863 | + "buffer length: %u " | ||
1761 | 3864 | + "query maximum length: %u", | ||
1762 | 3865 | + buffer, | ||
1763 | 3866 | + (uint) b_length, | ||
1764 | 3867 | + (uint) q_length)); | ||
1765 | 3868 | + DBUG_RETURN(buffer); | ||
1766 | 3869 | +} | ||
1767 | 3870 | + | ||
1768 | 3871 | + | ||
1769 | 3872 | +void Query_Without_Comments::set_length(size_t query_length) | ||
1770 | 3873 | +{ | ||
1771 | 3874 | + DBUG_ENTER("Query_Without_Comments::set_length"); | ||
1772 | 3875 | + DBUG_ASSERT(query_length <= q_length); | ||
1773 | 3876 | + buffer[query_length]= 0; | ||
1774 | 3877 | + DBUG_PRINT("info", ("buffer: %p " | ||
1775 | 3878 | + "query: '%-.4096s' " | ||
1776 | 3879 | + "buffer length: %u " | ||
1777 | 3880 | + "query maximum length: %u " | ||
1778 | 3881 | + "query length: %u", | ||
1779 | 3882 | + buffer, | ||
1780 | 3883 | + buffer, | ||
1781 | 3884 | + (uint) b_length, | ||
1782 | 3885 | + (uint) q_length, | ||
1783 | 3886 | + (uint) query_length)); | ||
1784 | 3887 | + q_length= query_length; | ||
1785 | 3888 | + DBUG_VOID_RETURN; | ||
1786 | 3889 | +} | ||
1787 | 3890 | + | ||
1788 | 3891 | + | ||
1789 | 3892 | +char* Query_Without_Comments::query() | ||
1790 | 3893 | +{ | ||
1791 | 3894 | + return buffer; | ||
1792 | 3895 | +} | ||
1793 | 3896 | + | ||
1794 | 3897 | + | ||
1795 | 3898 | +size_t Query_Without_Comments::length() | ||
1796 | 3899 | +{ | ||
1797 | 3900 | + return q_length; | ||
1798 | 3901 | +} | ||
1799 | 3902 | + | ||
1800 | 3903 | + | ||
1801 | 3904 | +#endif // HAVE_QUERY_CACHE | ||
1802 | 3905 | + | ||
1803 | 3906 | |||
1804 | 3907 | THD::THD() | ||
1805 | 3908 | :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, |
http:// jenkins. percona. com/view/ Percona% 20Server% 205.5/job/ percona- server- 5.5-param/ 303/