1 | /* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software |
14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | |
16 | #ifndef _SQL_CACHE_H |
17 | #define _SQL_CACHE_H |
18 | |
19 | #include "hash.h" |
20 | #include "my_base.h" /* ha_rows */ |
21 | |
22 | class MY_LOCALE; |
23 | struct TABLE_LIST; |
24 | class Time_zone; |
25 | struct LEX; |
26 | struct TABLE; |
27 | typedef struct st_changed_table_list CHANGED_TABLE_LIST; |
28 | |
29 | /* Query cache */ |
30 | |
31 | /* |
32 | Can't create new free memory block if unused memory in block less |
33 | then QUERY_CACHE_MIN_ALLOCATION_UNIT. |
34 | if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then |
35 | QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly |
36 | */ |
37 | #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512 |
38 | |
39 | /* inittial size of hashes */ |
40 | #define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024 |
41 | #define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024 |
42 | |
43 | /* minimal result data size when data allocated */ |
44 | #define QUERY_CACHE_MIN_RESULT_DATA_SIZE (1024*4) |
45 | |
46 | /* |
47 | start estimation of first result block size only when number of queries |
48 | bigger then: |
49 | */ |
50 | #define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3 |
51 | |
52 | |
53 | |
54 | /* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */ |
55 | #define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4 |
56 | #define QUERY_CACHE_MEM_BIN_STEP_PWR2 2 |
57 | #define QUERY_CACHE_MEM_BIN_PARTS_INC 1 |
58 | #define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2 |
59 | #define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3 |
60 | |
61 | /* how many free blocks check when finding most suitable before other 'end' |
62 | of list of free blocks */ |
63 | #define QUERY_CACHE_MEM_BIN_TRY 5 |
64 | |
65 | /* packing parameters */ |
66 | #define QUERY_CACHE_PACK_ITERATION 2 |
67 | #define QUERY_CACHE_PACK_LIMIT (512*1024L) |
68 | |
69 | #define TABLE_COUNTER_TYPE uint |
70 | |
71 | struct Query_cache_block; |
72 | struct Query_cache_block_table; |
73 | struct Query_cache_table; |
74 | struct Query_cache_query; |
75 | struct Query_cache_result; |
76 | class Query_cache; |
77 | struct Query_cache_tls; |
78 | struct LEX; |
79 | class THD; |
80 | |
81 | typedef my_bool (*qc_engine_callback)(THD *thd, const char *table_key, |
82 | uint key_length, |
83 | ulonglong *engine_data); |
84 | |
85 | /** |
86 | This class represents a node in the linked chain of queries |
87 | belonging to one table. |
88 | |
89 | @note The root of this linked list is not a query-type block, but the table- |
90 | type block which all queries has in common. |
91 | */ |
92 | struct Query_cache_block_table |
93 | { |
94 | Query_cache_block_table() {} /* Remove gcc warning */ |
95 | |
96 | /** |
97 | This node holds a position in a static table list belonging |
98 | to the associated query (base 0). |
99 | */ |
100 | TABLE_COUNTER_TYPE n; |
101 | |
102 | /** |
103 | Pointers to the next and previous node, linking all queries with |
104 | a common table. |
105 | */ |
106 | Query_cache_block_table *next, *prev; |
107 | |
108 | /** |
109 | A pointer to the table-type block which all |
110 | linked queries has in common. |
111 | */ |
112 | Query_cache_table *parent; |
113 | |
114 | /** |
115 | A method to calculate the address of the query cache block |
116 | owning this node. The purpose of this calculation is to |
117 | make it easier to move the query cache block without having |
118 | to modify all the pointer addresses. |
119 | */ |
120 | inline Query_cache_block *block(); |
121 | }; |
122 | |
123 | struct Query_cache_block |
124 | { |
125 | Query_cache_block() {} /* Remove gcc warning */ |
126 | enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG, |
127 | RES_INCOMPLETE, TABLE, INCOMPLETE}; |
128 | |
129 | size_t length; // length of all block |
130 | size_t used; // length of data |
131 | /* |
132 | Not used **pprev, **prev because really needed access to pervious block: |
133 | *pprev to join free blocks |
134 | *prev to access to opposite side of list in cyclic sorted list |
135 | */ |
136 | Query_cache_block *pnext,*pprev, // physical next/previous block |
137 | *next,*prev; // logical next/previous block |
138 | block_type type; |
139 | TABLE_COUNTER_TYPE n_tables; // number of tables in query |
140 | |
141 | inline bool is_free(void) { return type == FREE; } |
142 | void init(size_t length); |
143 | void destroy(); |
144 | uint (); |
145 | uchar* data(void); |
146 | Query_cache_query *query(); |
147 | Query_cache_table *table(); |
148 | Query_cache_result *result(); |
149 | Query_cache_block_table *table(TABLE_COUNTER_TYPE n); |
150 | }; |
151 | |
152 | struct Query_cache_query |
153 | { |
154 | ulonglong limit_found_rows; |
155 | mysql_rwlock_t lock; |
156 | Query_cache_block *res; |
157 | Query_cache_tls *wri; |
158 | size_t len; |
159 | unsigned int last_pkt_nr; |
160 | uint8 tbls_type; |
161 | uint8 ready; |
162 | ulonglong hit_count; |
163 | |
164 | Query_cache_query() {} /* Remove gcc warning */ |
165 | inline void init_n_lock(); |
166 | void unlock_n_destroy(); |
167 | inline ulonglong found_rows() { return limit_found_rows; } |
168 | inline void found_rows(ulonglong rows) { limit_found_rows= rows; } |
169 | inline Query_cache_block *result() { return res; } |
170 | inline void result(Query_cache_block *p) { res= p; } |
171 | inline Query_cache_tls *writer() { return wri; } |
172 | inline void writer(Query_cache_tls *p) { wri= p; } |
173 | inline uint8 tables_type() { return tbls_type; } |
174 | inline void tables_type(uint8 type) { tbls_type= type; } |
175 | inline size_t length() { return len; } |
176 | inline size_t add(size_t packet_len) { return(len+= packet_len); } |
177 | inline void length(size_t length_arg) { len= length_arg; } |
178 | inline uchar* query() |
179 | { |
180 | return (((uchar*)this) + ALIGN_SIZE(sizeof(Query_cache_query))); |
181 | } |
182 | /** |
183 | following used to check if result ready in plugin without |
184 | locking rw_lock of the query. |
185 | */ |
186 | inline void set_results_ready() { ready= 1; } |
187 | inline bool is_results_ready() { return ready; } |
188 | inline void increment_hits() { hit_count++; } |
189 | inline ulonglong hits() { return hit_count; } |
190 | void lock_writing(); |
191 | void lock_reading(); |
192 | bool try_lock_writing(); |
193 | void unlock_writing(); |
194 | void unlock_reading(); |
195 | }; |
196 | |
197 | |
198 | struct Query_cache_table |
199 | { |
200 | Query_cache_table() {} /* Remove gcc warning */ |
201 | char *tbl; |
202 | uint32 key_len; |
203 | uint8 suffix_len; /* For partitioned tables */ |
204 | uint8 table_type; |
205 | /* unique for every engine reference */ |
206 | qc_engine_callback callback_func; |
207 | /* data need by some engines */ |
208 | ulonglong engine_data_buff; |
209 | |
210 | /** |
211 | The number of queries depending of this table. |
212 | */ |
213 | int32 m_cached_query_count; |
214 | /** |
215 | If table included in the table hash to be found by other queries |
216 | */ |
217 | my_bool hashed; |
218 | |
219 | inline char *db() { return (char *) data(); } |
220 | inline char *table() { return tbl; } |
221 | inline void table(char *table_arg) { tbl= table_arg; } |
222 | inline uint32 key_length() { return key_len; } |
223 | inline void key_length(uint32 len) { key_len= len; } |
224 | inline uint8 suffix_length() { return suffix_len; } |
225 | inline void suffix_length(uint8 len) { suffix_len= len; } |
226 | inline uint8 type() { return table_type; } |
227 | inline void type(uint8 t) { table_type= t; } |
228 | inline qc_engine_callback callback() { return callback_func; } |
229 | inline void callback(qc_engine_callback fn){ callback_func= fn; } |
230 | inline ulonglong engine_data() { return engine_data_buff; } |
231 | inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; } |
232 | inline my_bool is_hashed() { return hashed; } |
233 | inline void set_hashed(my_bool hash) { hashed= hash; } |
234 | inline uchar* data() |
235 | { |
236 | return (uchar*)(((uchar*)this)+ |
237 | ALIGN_SIZE(sizeof(Query_cache_table))); |
238 | } |
239 | }; |
240 | |
241 | struct Query_cache_result |
242 | { |
243 | Query_cache_result() {} /* Remove gcc warning */ |
244 | Query_cache_block *query; |
245 | |
246 | inline uchar* data() |
247 | { |
248 | return (uchar*)(((uchar*) this)+ |
249 | ALIGN_SIZE(sizeof(Query_cache_result))); |
250 | } |
251 | /* data_continue (if not whole packet contained by this block) */ |
252 | inline Query_cache_block *parent() { return query; } |
253 | inline void parent (Query_cache_block *p) { query=p; } |
254 | }; |
255 | |
256 | |
257 | extern "C" |
258 | { |
259 | uchar *query_cache_query_get_key(const uchar *record, size_t *length, |
260 | my_bool not_used); |
261 | uchar *query_cache_table_get_key(const uchar *record, size_t *length, |
262 | my_bool not_used); |
263 | } |
264 | extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename); |
265 | |
266 | |
267 | struct Query_cache_memory_bin |
268 | { |
269 | Query_cache_memory_bin() {} /* Remove gcc warning */ |
270 | #ifndef DBUG_OFF |
271 | size_t size; |
272 | #endif |
273 | uint number; |
274 | Query_cache_block *free_blocks; |
275 | |
276 | inline void init(size_t size_arg) |
277 | { |
278 | #ifndef DBUG_OFF |
279 | size = size_arg; |
280 | #endif |
281 | number = 0; |
282 | free_blocks = 0; |
283 | } |
284 | }; |
285 | |
286 | struct Query_cache_memory_bin_step |
287 | { |
288 | Query_cache_memory_bin_step() {} /* Remove gcc warning */ |
289 | size_t size; |
290 | size_t increment; |
291 | size_t idx; |
292 | inline void init(size_t size_arg, size_t idx_arg, size_t increment_arg) |
293 | { |
294 | size = size_arg; |
295 | idx = idx_arg; |
296 | increment = increment_arg; |
297 | } |
298 | }; |
299 | |
300 | class Query_cache |
301 | { |
302 | public: |
303 | /* Info */ |
304 | size_t query_cache_size, query_cache_limit; |
305 | /* statistics */ |
306 | size_t free_memory, queries_in_cache, hits, inserts, refused, |
307 | free_memory_blocks, total_blocks, lowmem_prunes; |
308 | |
309 | |
310 | private: |
311 | #ifndef DBUG_OFF |
312 | my_thread_id m_cache_lock_thread_id; |
313 | #endif |
314 | mysql_cond_t COND_cache_status_changed; |
315 | uint m_requests_in_progress; |
316 | enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED }; |
317 | Cache_lock_status m_cache_lock_status; |
318 | enum Cache_staus {OK, DISABLE_REQUEST, DISABLED}; |
319 | Cache_staus m_cache_status; |
320 | |
321 | void free_query_internal(Query_cache_block *point); |
322 | void invalidate_table_internal(THD *thd, uchar *key, size_t key_length); |
323 | |
324 | protected: |
325 | /* |
326 | The following mutex is locked when searching or changing global |
327 | query, tables lists or hashes. When we are operating inside the |
328 | query structure we locked an internal query block mutex. |
329 | LOCK SEQUENCE (to prevent deadlocks): |
330 | 1. structure_guard_mutex |
331 | 2. query block (for operation inside query (query block/results)) |
332 | |
333 | Thread doing cache flush releases the mutex once it sets |
334 | m_cache_lock_status flag, so other threads may bypass the cache as |
335 | if it is disabled, not waiting for reset to finish. The exception |
336 | is other threads that were going to do cache flush---they'll wait |
337 | till the end of a flush operation. |
338 | */ |
339 | mysql_mutex_t structure_guard_mutex; |
340 | size_t additional_data_size; |
341 | uchar *cache; // cache memory |
342 | Query_cache_block *first_block; // physical location block list |
343 | Query_cache_block *queries_blocks; // query list (LIFO) |
344 | Query_cache_block *tables_blocks; |
345 | |
346 | Query_cache_memory_bin *bins; // free block lists |
347 | Query_cache_memory_bin_step *steps; // bins spacing info |
348 | HASH queries, tables; |
349 | /* options */ |
350 | size_t min_allocation_unit, min_result_data_size; |
351 | uint def_query_hash_size, def_table_hash_size; |
352 | |
353 | size_t mem_bin_num, mem_bin_steps; // See at init_cache & find_bin |
354 | |
355 | bool initialized; |
356 | |
357 | /* Exclude/include from cyclic double linked list */ |
358 | static void double_linked_list_exclude(Query_cache_block *point, |
359 | Query_cache_block **list_pointer); |
360 | static void double_linked_list_simple_include(Query_cache_block *point, |
361 | Query_cache_block ** |
362 | list_pointer); |
363 | static void double_linked_list_join(Query_cache_block *head_tail, |
364 | Query_cache_block *tail_head); |
365 | |
366 | /* The following functions require that structure_guard_mutex is locked */ |
367 | void flush_cache(); |
368 | my_bool free_old_query(); |
369 | void free_query(Query_cache_block *point); |
370 | my_bool allocate_data_chain(Query_cache_block **result_block, |
371 | size_t data_len, |
372 | Query_cache_block *query_block, |
373 | my_bool first_block); |
374 | void invalidate_table(THD *thd, TABLE_LIST *table); |
375 | void invalidate_table(THD *thd, TABLE *table); |
376 | void invalidate_table(THD *thd, uchar *key, size_t key_length); |
377 | void invalidate_table(THD *thd, Query_cache_block *table_block); |
378 | void invalidate_query_block_list(THD *thd, |
379 | Query_cache_block_table *list_root); |
380 | |
381 | TABLE_COUNTER_TYPE |
382 | register_tables_from_list(THD *thd, TABLE_LIST *tables_used, |
383 | TABLE_COUNTER_TYPE counter, |
384 | Query_cache_block_table **block_table); |
385 | my_bool register_all_tables(THD *thd, Query_cache_block *block, |
386 | TABLE_LIST *tables_used, |
387 | TABLE_COUNTER_TYPE tables); |
388 | void unlink_table(Query_cache_block_table *node); |
389 | Query_cache_block *get_free_block (size_t len, my_bool not_less, |
390 | size_t min); |
391 | void free_memory_block(Query_cache_block *point); |
392 | void split_block(Query_cache_block *block, size_t len); |
393 | Query_cache_block *join_free_blocks(Query_cache_block *first_block, |
394 | Query_cache_block *block_in_list); |
395 | my_bool append_next_free_block(Query_cache_block *block, |
396 | size_t add_size); |
397 | void exclude_from_free_memory_list(Query_cache_block *free_block); |
398 | void insert_into_free_memory_list(Query_cache_block *new_block); |
399 | my_bool move_by_type(uchar **border, Query_cache_block **before, |
400 | size_t *gap, Query_cache_block *i); |
401 | uint find_bin(size_t size); |
402 | void move_to_query_list_end(Query_cache_block *block); |
403 | void insert_into_free_memory_sorted_list(Query_cache_block *new_block, |
404 | Query_cache_block **list); |
405 | void pack_cache(); |
406 | void relink(Query_cache_block *oblock, |
407 | Query_cache_block *nblock, |
408 | Query_cache_block *next, |
409 | Query_cache_block *prev, |
410 | Query_cache_block *pnext, |
411 | Query_cache_block *pprev); |
412 | my_bool join_results(size_t join_limit); |
413 | |
414 | /* |
415 | Following function control structure_guard_mutex |
416 | by themself or don't need structure_guard_mutex |
417 | */ |
418 | size_t init_cache(); |
419 | void make_disabled(); |
420 | void free_cache(); |
421 | Query_cache_block *write_block_data(size_t data_len, uchar* data, |
422 | size_t , |
423 | Query_cache_block::block_type type, |
424 | TABLE_COUNTER_TYPE ntab = 0); |
425 | my_bool append_result_data(Query_cache_block **result, |
426 | size_t data_len, uchar* data, |
427 | Query_cache_block *parent); |
428 | my_bool write_result_data(Query_cache_block **result, |
429 | size_t data_len, uchar* data, |
430 | Query_cache_block *parent, |
431 | Query_cache_block::block_type |
432 | type=Query_cache_block::RESULT); |
433 | inline size_t get_min_first_result_data_size(); |
434 | inline size_t get_min_append_result_data_size(); |
435 | Query_cache_block *allocate_block(size_t len, my_bool not_less, |
436 | size_t min); |
437 | /* |
438 | If query is cacheable return number tables in query |
439 | (query without tables not cached) |
440 | */ |
441 | TABLE_COUNTER_TYPE is_cacheable(THD *thd, |
442 | LEX *lex, TABLE_LIST *tables_used, |
443 | uint8 *tables_type); |
444 | TABLE_COUNTER_TYPE process_and_count_tables(THD *thd, |
445 | TABLE_LIST *tables_used, |
446 | uint8 *tables_type); |
447 | |
448 | static my_bool ask_handler_allowance(THD *thd, TABLE_LIST *tables_used); |
449 | public: |
450 | |
451 | Query_cache(size_t query_cache_limit = ULONG_MAX, |
452 | size_t min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT, |
453 | size_t min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE, |
454 | uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, |
455 | uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); |
456 | |
457 | inline bool is_disabled(void) { return m_cache_status != OK; } |
458 | inline bool is_disable_in_progress(void) |
459 | { return m_cache_status == DISABLE_REQUEST; } |
460 | |
461 | /* initialize cache (mutex) */ |
462 | void init(); |
463 | /* resize query cache (return real query size, 0 if disabled) */ |
464 | size_t resize(size_t query_cache_size); |
465 | /* set limit on result size */ |
466 | inline void result_size_limit(size_t limit){query_cache_limit=limit;} |
467 | /* set minimal result data allocation unit size */ |
468 | size_t set_min_res_unit(size_t size); |
469 | |
470 | /* register query in cache */ |
471 | void store_query(THD *thd, TABLE_LIST *used_tables); |
472 | |
473 | /* |
474 | Check if the query is in the cache and if this is true send the |
475 | data to client. |
476 | */ |
477 | int send_result_to_client(THD *thd, char *query, uint query_length); |
478 | |
479 | /* Remove all queries that uses any of the listed following tables */ |
480 | void invalidate(THD *thd, TABLE_LIST *tables_used, |
481 | my_bool using_transactions); |
482 | void invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used); |
483 | void invalidate_locked_for_write(THD *thd, TABLE_LIST *tables_used); |
484 | void invalidate(THD *thd, TABLE *table, my_bool using_transactions); |
485 | void invalidate(THD *thd, const char *key, size_t key_length, |
486 | my_bool using_transactions); |
487 | |
488 | /* Remove all queries that uses any of the tables in following database */ |
489 | void invalidate(THD *thd, const char *db); |
490 | |
491 | /* Remove all queries that uses any of the listed following table */ |
492 | void invalidate_by_MyISAM_filename(const char *filename); |
493 | |
494 | void flush(); |
495 | void pack(THD *thd, |
496 | size_t join_limit = QUERY_CACHE_PACK_LIMIT, |
497 | uint iteration_limit = QUERY_CACHE_PACK_ITERATION); |
498 | |
499 | void destroy(); |
500 | |
501 | void insert(THD *thd, Query_cache_tls *query_cache_tls, |
502 | const char *packet, |
503 | size_t length, |
504 | unsigned pkt_nr); |
505 | my_bool insert_table(THD *thd, size_t key_len, const char *key, |
506 | Query_cache_block_table *node, |
507 | size_t db_length, uint8 suffix_length_arg, |
508 | uint8 cache_type, |
509 | qc_engine_callback callback, |
510 | ulonglong engine_data, |
511 | my_bool hash); |
512 | |
513 | void end_of_result(THD *thd); |
514 | void abort(THD *thd, Query_cache_tls *query_cache_tls); |
515 | |
516 | /* |
517 | The following functions are only used when debugging |
518 | We don't protect these with ifndef DBUG_OFF to not have to recompile |
519 | everything if we want to add checks of the cache at some places. |
520 | */ |
521 | void wreck(uint line, const char *message); |
522 | void bins_dump(); |
523 | void cache_dump(); |
524 | void queries_dump(); |
525 | void tables_dump(); |
526 | my_bool check_integrity(bool not_locked); |
527 | my_bool in_list(Query_cache_block * root, Query_cache_block * point, |
528 | const char *name); |
529 | my_bool in_table_list(Query_cache_block_table * root, |
530 | Query_cache_block_table * point, |
531 | const char *name); |
532 | my_bool in_blocks(Query_cache_block * point); |
533 | |
534 | /* Table key generation */ |
535 | static uint filename_2_table_key (char *key, const char *filename, |
536 | uint32 *db_langth); |
537 | |
538 | enum Cache_try_lock_mode {WAIT, TIMEOUT, TRY}; |
539 | bool try_lock(THD *thd, Cache_try_lock_mode mode= WAIT); |
540 | void lock(THD *thd); |
541 | void lock_and_suspend(void); |
542 | void unlock(void); |
543 | |
544 | void disable_query_cache(THD *thd); |
545 | }; |
546 | |
547 | #ifdef HAVE_QUERY_CACHE |
548 | struct Query_cache_query_flags |
549 | { |
550 | unsigned int client_long_flag:1; |
551 | unsigned int client_protocol_41:1; |
552 | unsigned int client_depr_eof:1; |
553 | unsigned int protocol_type:2; |
554 | unsigned int more_results_exists:1; |
555 | unsigned int in_trans:1; |
556 | unsigned int autocommit:1; |
557 | unsigned int pkt_nr; |
558 | uint character_set_client_num; |
559 | uint character_set_results_num; |
560 | uint collation_connection_num; |
561 | ha_rows limit; |
562 | Time_zone *time_zone; |
563 | sql_mode_t sql_mode; |
564 | ulonglong max_sort_length; |
565 | ulonglong group_concat_max_len; |
566 | size_t default_week_format; |
567 | size_t div_precision_increment; |
568 | MY_LOCALE *lc_time_names; |
569 | }; |
570 | #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags) |
571 | #define QUERY_CACHE_DB_LENGTH_SIZE 2 |
572 | #include "sql_cache.h" |
573 | #define query_cache_abort(A,B) query_cache.abort(A,B) |
574 | #define query_cache_end_of_result(A) query_cache.end_of_result(A) |
575 | #define query_cache_store_query(A, B) query_cache.store_query(A, B) |
576 | #define query_cache_destroy() query_cache.destroy() |
577 | #define query_cache_result_size_limit(A) query_cache.result_size_limit(A) |
578 | #define query_cache_init() query_cache.init() |
579 | #define query_cache_resize(A) query_cache.resize(A) |
580 | #define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A) |
581 | #define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C) |
582 | #define query_cache_invalidate1(A, B) query_cache.invalidate(A, B) |
583 | #define query_cache_send_result_to_client(A, B, C) \ |
584 | query_cache.send_result_to_client(A, B, C) |
585 | #define query_cache_invalidate_by_MyISAM_filename_ref \ |
586 | &query_cache_invalidate_by_MyISAM_filename |
587 | /* note the "maybe": it's a read without mutex */ |
588 | #define query_cache_maybe_disabled(T) \ |
589 | (T->variables.query_cache_type == 0 || query_cache.query_cache_size == 0) |
590 | #define query_cache_is_cacheable_query(L) \ |
591 | (((L)->sql_command == SQLCOM_SELECT) && (L)->safe_to_cache_query) |
592 | #else |
593 | #define QUERY_CACHE_FLAGS_SIZE 0 |
594 | #define query_cache_store_query(A, B) do { } while(0) |
595 | #define query_cache_destroy() do { } while(0) |
596 | #define query_cache_result_size_limit(A) do { } while(0) |
597 | #define query_cache_init() do { } while(0) |
598 | #define query_cache_resize(A) do { } while(0) |
599 | #define query_cache_set_min_res_unit(A) do { } while(0) |
600 | #define query_cache_invalidate3(A, B, C) do { } while(0) |
601 | #define query_cache_invalidate1(A,B) do { } while(0) |
602 | #define query_cache_send_result_to_client(A, B, C) 0 |
603 | #define query_cache_invalidate_by_MyISAM_filename_ref NULL |
604 | |
605 | #define query_cache_abort(A,B) do { } while(0) |
606 | #define query_cache_end_of_result(A) do { } while(0) |
607 | #define query_cache_maybe_disabled(T) 1 |
608 | #define query_cache_is_cacheable_query(L) 0 |
609 | #endif /*HAVE_QUERY_CACHE*/ |
610 | |
611 | extern Query_cache query_cache; |
612 | #endif |
613 | |